From: Jim Meyering Date: Thu, 8 May 2003 09:26:34 +0000 (+0000) Subject: (timespec_subtract): Don't modify the 2nd arg. X-Git-Tag: v5.0.1~569 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de261015e86e6311e078330da6a6627ecec1d255;p=thirdparty%2Fcoreutils.git (timespec_subtract): Don't modify the 2nd arg. Work even if X-Y overflows when subtracting. Make explicit the assumption that tv_nsec must be in range. (clock_get_realtime): Remove. All callers changed to invoke gettime, for simplicity. (xnanosleep): Check for gettime failure every time. --- diff --git a/lib/xnanosleep.c b/lib/xnanosleep.c index 097466e127..c4e9b469b4 100644 --- a/lib/xnanosleep.c +++ b/lib/xnanosleep.c @@ -49,48 +49,40 @@ #include "xnanosleep.h" #include "xstrtod.h" -/* Subtract the `struct timespec' values X and Y, - storing the difference in DIFF. - Return 1 if the difference is positive, otherwise 0. - Derived from code in the GNU libc manual. */ +/* Subtract the `struct timespec' values X and Y by computing X - Y. + If the difference is negative or zero, return 0. + Otherwise, return 1 and store the difference in DIFF. + X and Y must have valid ts_nsec values, in the range 0 to 999999999. + If the difference would overflow, store the maximum possible difference. */ static int timespec_subtract (struct timespec *diff, - const struct timespec *x, struct timespec *y) + struct timespec const *x, struct timespec const *y) { - /* Perform the carry for the later subtraction by updating Y. */ - if (x->tv_nsec < y->tv_nsec) + time_t sec = x->tv_sec - y->tv_sec; + long int nsec = x->tv_nsec - y->tv_nsec; + + if (x->tv_sec < y->tv_sec) + return 0; + + if (sec < 0) { - int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1; - y->tv_nsec -= 1000000000 * nsec; - y->tv_sec += nsec; + /* The difference has overflowed. */ + sec = TIME_T_MAX; + nsec = 999999999; } + else if (sec == 0 && nsec <= 0) + return 0; - if (1000000000 < x->tv_nsec - y->tv_nsec) + if (nsec < 0) { - int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000; - y->tv_nsec += 1000000000 * nsec; - y->tv_sec -= nsec; + sec--; + nsec += 1000000000; } - /* Compute the time remaining to wait. - `tv_nsec' is certainly positive. */ - diff->tv_sec = x->tv_sec - y->tv_sec; - diff->tv_nsec = x->tv_nsec - y->tv_nsec; - - /* Return 1 if result is positive. */ - return y->tv_sec < x->tv_sec; -} - -struct timespec * -clock_get_realtime (struct timespec *ts) -{ - int fail = gettime (ts); - - if (fail) - return NULL; - - return ts; + diff->tv_sec = sec; + diff->tv_nsec = nsec; + return 1; } /* Sleep until the time (call it WAKE_UP_TIME) specified as @@ -111,7 +103,7 @@ xnanosleep (double seconds) assert (0 <= seconds); - if (clock_get_realtime (&ts_start) == NULL) + if (gettime (&ts_start) != 0) return -1; /* Separate whole seconds from nanoseconds. @@ -163,7 +155,7 @@ xnanosleep (double seconds) while (nanosleep (&ts_sleep, NULL) != 0) { - if (errno != EINTR) + if (errno != EINTR || gettime (&ts_start) != 0) return -1; /* POSIX.1-2001 requires that when a process is suspended, then @@ -174,8 +166,7 @@ xnanosleep (double seconds) this bug by computing the remaining time here, rather than by relying on nanosleep's computation. */ - if (! timespec_subtract (&ts_sleep, &ts_stop, - clock_get_realtime (&ts_start))) + if (! timespec_subtract (&ts_sleep, &ts_stop, &ts_start)) break; }