From: David van Moolenbroek Date: Sat, 15 Aug 2009 22:14:48 +0000 (+0000) Subject: nanosleep(3), and sleep(3) rewrite, by Erik van der Kouwe X-Git-Tag: v3.1.5~196 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=5a13b2eda89a602dc86fcafa9b9206edd4fb862a;p=minix.git nanosleep(3), and sleep(3) rewrite, by Erik van der Kouwe --- diff --git a/include/time.h b/include/time.h index 6915480e2..e17c42f4e 100755 --- a/include/time.h +++ b/include/time.h @@ -72,4 +72,14 @@ _PROTOTYPE( int stime, (time_t *_top) ); extern long timezone; +#ifdef _POSIX_SOURCE +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; + +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); +#endif + #endif /* _TIME_H */ diff --git a/lib/posix/Makefile.in b/lib/posix/Makefile.in index 2c5014aea..7c77efd0b 100644 --- a/lib/posix/Makefile.in +++ b/lib/posix/Makefile.in @@ -56,6 +56,7 @@ libc_FILES=" \ _mkfifo.c \ _mknod.c \ _mmap.c \ + _nanosleep.c \ _open.c \ _opendir.c \ _pathconf.c \ diff --git a/lib/posix/_nanosleep.c b/lib/posix/_nanosleep.c new file mode 100644 index 000000000..b687dda48 --- /dev/null +++ b/lib/posix/_nanosleep.c @@ -0,0 +1,77 @@ +/* nanosleep() - Sleep for a number of nanoseconds. Author: Erik van der Kouwe + * 25 July 2009 + */ + +#include +#define nanosleep _nanosleep +#include +#include +#include +#include +#include + +#define MSEC_PER_SEC 1000 +#define USEC_PER_MSEC 1000 +#define NSEC_PER_USEC 1000 + +#define USEC_PER_SEC (USEC_PER_MSEC * MSEC_PER_SEC) +#define NSEC_PER_SEC (NSEC_PER_USEC * USEC_PER_SEC) + +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + struct timeval timeout, timestart = { 0, 0 }, timeend; + int errno_select, r; + + /* keep track of start time if needed */ + if (rmtp) + { + rmtp->tv_sec = 0; + rmtp->tv_nsec = 0; + if (gettimeofday(×tart, NULL) < 0) + return -1; + } + + /* use select to wait */ + timeout.tv_sec = rqtp->tv_sec; + timeout.tv_usec = (rqtp->tv_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC; + r = select(0, NULL, NULL, NULL, &timeout); + + /* return remaining time only if requested */ + /* if select succeeded then we slept all time */ + if (!rmtp || r >= 0) + return r; + + /* measure end time; preserve errno */ + errno_select = errno; + if (gettimeofday(&timeend, NULL) < 0) + return -1; + + errno = errno_select; + + /* compute remaining time */ + rmtp->tv_sec = rqtp->tv_sec - (timeend.tv_sec - timestart.tv_sec); + rmtp->tv_nsec = rqtp->tv_nsec - + (timeend.tv_usec - timestart.tv_usec) * NSEC_PER_USEC; + + /* bring remaining time into canonical form */ + while (rmtp->tv_nsec < 0) + { + rmtp->tv_sec -= 1; + rmtp->tv_nsec += NSEC_PER_SEC; + } + + while (rmtp->tv_nsec > NSEC_PER_SEC) + { + rmtp->tv_sec += 1; + rmtp->tv_nsec -= NSEC_PER_SEC; + } + + /* remaining time must not be negative */ + if (rmtp->tv_sec < 0) + { + rmtp->tv_sec = 0; + rmtp->tv_nsec = 0; + } + + return r; +} diff --git a/lib/posix/_sleep.c b/lib/posix/_sleep.c index 2be6fa58f..e1f721e0f 100755 --- a/lib/posix/_sleep.c +++ b/lib/posix/_sleep.c @@ -1,69 +1,22 @@ -/* sleep() - Sleep for a number of seconds. Author: Kees J. Bot - * 24 Apr 2000 - * (Inspired by the Minix-vmd version of same, except that - * this implementation doesn't bother to check if all the signal - * functions succeed. Under Minix that is no problem.) +/* sleep() - Sleep for a number of seconds. Author: Erik van der Kouwe + * 25 July 2009 */ #include #define sleep _sleep -#include -#include #include -static void handler(int sig) -{ - /* Dummy signal handler. */ -} - unsigned sleep(unsigned sleep_seconds) { - sigset_t ss_full, ss_orig, ss_alarm; - struct sigaction action_alarm, action_orig; - unsigned alarm_seconds, nap_seconds; - - if (sleep_seconds == 0) return 0; /* No rest for the wicked */ - - /* Mask all signals. */ - sigfillset(&ss_full); - sigprocmask(SIG_BLOCK, &ss_full, &ss_orig); - - /* Cancel currently running alarm. */ - alarm_seconds= alarm(0); - - /* How long can we nap without interruptions? */ - nap_seconds= sleep_seconds; - if (alarm_seconds != 0 && alarm_seconds < sleep_seconds) { - nap_seconds= alarm_seconds; - } - - /* Now sleep. */ - action_alarm.sa_handler= handler; - sigemptyset(&action_alarm.sa_mask); - action_alarm.sa_flags= 0; - sigaction(SIGALRM, &action_alarm, &action_orig); - alarm(nap_seconds); - - /* Wait for a wakeup call, either our alarm, or some other signal. */ - ss_alarm= ss_orig; - sigdelset(&ss_alarm, SIGALRM); - sigsuspend(&ss_alarm); - - /* Cancel alarm, set mask and stuff back to normal. */ - nap_seconds -= alarm(0); - sigaction(SIGALRM, &action_orig, NULL); - sigprocmask(SIG_SETMASK, &ss_orig, NULL); + struct timespec rqtp, rmtp; - /* Restore alarm counter to the time remaining. */ - if (alarm_seconds != 0 && alarm_seconds >= nap_seconds) { - alarm_seconds -= nap_seconds; - if (alarm_seconds == 0) { - raise(SIGALRM); /* Alarm expires now! */ - } else { - alarm(alarm_seconds); /* Count time remaining. */ - } - } + /* nanosleep implements this call; + * ignore failure, it cannot be reported + */ + rqtp.tv_sec = sleep_seconds; + rqtp.tv_nsec = 0; + nanosleep(&rqtp, &rmtp); - /* Return time not slept. */ - return sleep_seconds - nap_seconds; + /* round remainder up to seconds */ + return rmtp.tv_sec + ((rmtp.tv_nsec > 0) ? 1 : 0); } diff --git a/lib/syscall/Makefile.in b/lib/syscall/Makefile.in index b25f193d8..d5b27e0d6 100644 --- a/lib/syscall/Makefile.in +++ b/lib/syscall/Makefile.in @@ -70,6 +70,7 @@ libc_FILES=" \ mknod.s \ mmap.s \ mount.s \ + nanosleep.s \ open.s \ opendir.s \ pathconf.s \ diff --git a/lib/syscall/nanosleep.s b/lib/syscall/nanosleep.s new file mode 100644 index 000000000..2d8b4e751 --- /dev/null +++ b/lib/syscall/nanosleep.s @@ -0,0 +1,6 @@ +.sect .text +.extern __nanosleep +.define _nanosleep + +_nanosleep: + jmp __nanosleep