]> Zhao Yanbai Git Server - minix.git/commitdiff
nanosleep(3), and sleep(3) rewrite, by Erik van der Kouwe
authorDavid van Moolenbroek <david@minix3.org>
Sat, 15 Aug 2009 22:14:48 +0000 (22:14 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Sat, 15 Aug 2009 22:14:48 +0000 (22:14 +0000)
include/time.h
lib/posix/Makefile.in
lib/posix/_nanosleep.c [new file with mode: 0644]
lib/posix/_sleep.c
lib/syscall/Makefile.in
lib/syscall/nanosleep.s [new file with mode: 0644]

index 6915480e2eef03660ec2f2f307764eb2edd41734..e17c42f4e25440c938b6f463a6788c8c1e892539 100755 (executable)
@@ -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 */
index 2c5014aea52f4813602eeef3e2179385afa27356..7c77efd0b291364c6e81bde9693a852c5cc6c3ff 100644 (file)
@@ -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 (file)
index 0000000..b687dda
--- /dev/null
@@ -0,0 +1,77 @@
+/* nanosleep() - Sleep for a number of nanoseconds. Author: Erik van der Kouwe
+ *                                                               25 July 2009
+ */
+
+#include <lib.h>
+#define nanosleep _nanosleep
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/select.h>
+#include <sys/time.h>
+
+#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(&timestart, 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;
+}
index 2be6fa58f74c32ea873b37e79ac8ac7ada669f60..e1f721e0f886fb423292b1efa41d25f891fafd0a 100755 (executable)
@@ -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 <lib.h>
 #define sleep _sleep
-#include <signal.h>
-#include <unistd.h>
 #include <time.h>
 
-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);
 }
index b25f193d825040c0cc21e359c5b1ae6da254950d..d5b27e0d6125c7683d2fb77ba9699106e0daf5ea 100644 (file)
@@ -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 (file)
index 0000000..2d8b4e7
--- /dev/null
@@ -0,0 +1,6 @@
+.sect .text
+.extern        __nanosleep
+.define        _nanosleep
+
+_nanosleep:
+       jmp     __nanosleep