From: Erik van der Kouwe Date: Sun, 16 Aug 2009 12:13:33 +0000 (+0000) Subject: Function nanosleep now checks arguments X-Git-Tag: v3.1.5~191 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=3573bc1abe1c26e167cc68984f1018c06bebdf91;p=minix.git Function nanosleep now checks arguments --- diff --git a/lib/posix/_sleep.c b/lib/posix/_sleep.c index e1f721e0f..21dfc633c 100755 --- a/lib/posix/_sleep.c +++ b/lib/posix/_sleep.c @@ -1,18 +1,97 @@ -/* sleep() - Sleep for a number of seconds. Author: Erik van der Kouwe +/* sleep() - Sleep for a number of seconds. Author: Erik van der Kouwe * 25 July 2009 + * (Avoids interfering with alarm/setitimer by using select, like usleep) */ #include #define sleep _sleep +#define nanosleep _nanosleep +#include +#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; + + /* check parameters */ + if (!rqtp) + return EFAULT; + + if (rqtp->tv_sec < 0 || + rqtp->tv_nsec < 0 || + rqtp->tv_nsec >= NSEC_PER_SEC) + return EINVAL; + + /* 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; +} unsigned sleep(unsigned sleep_seconds) { struct timespec rqtp, rmtp; - /* nanosleep implements this call; - * ignore failure, it cannot be reported - */ + /* nanosleep implements this call; ignore failure, it cannot be reported */ rqtp.tv_sec = sleep_seconds; rqtp.tv_nsec = 0; nanosleep(&rqtp, &rmtp);