etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / nanosleep.c
blobc69c4cf6831c20b965aeb966ca95169f076b92c7
1 /* nanosleep() - Sleep for a number of seconds. Author: Erik van der Kouwe
2 * 25 July 2009
3 */
5 #include <sys/cdefs.h>
6 #include "namespace.h"
7 #include <lib.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <time.h>
12 #include <sys/select.h>
13 #include <sys/time.h>
15 #define MSEC_PER_SEC 1000
16 #define USEC_PER_MSEC 1000
17 #define NSEC_PER_USEC 1000
19 #define USEC_PER_SEC (USEC_PER_MSEC * MSEC_PER_SEC)
20 #define NSEC_PER_SEC (NSEC_PER_USEC * USEC_PER_SEC)
22 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
24 struct timeval timeout, timestart = { 0, 0 }, timeend;
25 int errno_select, r;
26 struct timespec rqt;
28 /* check parameters */
29 if (!rqtp) {
30 errno = EFAULT;
31 return -1;
34 if (rqtp->tv_sec < 0 ||
35 rqtp->tv_nsec < 0 ||
36 rqtp->tv_nsec >= NSEC_PER_SEC) {
37 errno = EINVAL;
38 return -1;
41 /* store *rqtp to make sure it is not overwritten */
42 rqt = *rqtp;
44 /* keep track of start time if needed */
45 if (rmtp)
47 rmtp->tv_sec = 0;
48 rmtp->tv_nsec = 0;
49 if (gettimeofday(&timestart, NULL) < 0)
50 return -1;
53 /* use select to wait */
54 timeout.tv_sec = rqt.tv_sec;
55 timeout.tv_usec = (rqt.tv_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC;
56 r = select(0, NULL, NULL, NULL, &timeout);
58 /* return remaining time only if requested */
59 /* if select succeeded then we slept all time */
60 if (!rmtp || r >= 0)
61 return r;
63 /* measure end time; preserve errno */
64 errno_select = errno;
65 if (gettimeofday(&timeend, NULL) < 0)
66 return -1;
68 errno = errno_select;
70 /* compute remaining time */
71 rmtp->tv_sec = rqt.tv_sec - (timeend.tv_sec - timestart.tv_sec);
72 rmtp->tv_nsec = rqt.tv_nsec - (timeend.tv_usec - timestart.tv_usec) * NSEC_PER_USEC;
74 /* bring remaining time into canonical form */
75 while (rmtp->tv_nsec < 0)
77 rmtp->tv_sec -= 1;
78 rmtp->tv_nsec += NSEC_PER_SEC;
81 while (rmtp->tv_nsec > NSEC_PER_SEC)
83 rmtp->tv_sec += 1;
84 rmtp->tv_nsec -= NSEC_PER_SEC;
87 /* remaining time must not be negative */
88 if (rmtp->tv_sec < 0)
90 rmtp->tv_sec = 0;
91 rmtp->tv_nsec = 0;
94 return r;
98 #if defined(__minix) && defined(__weak_alias)
99 __weak_alias(nanosleep, __nanosleep50)
100 #endif