summaryrefslogtreecommitdiff
path: root/lib/xnanosleep.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-05-08 09:26:34 +0000
committerJim Meyering <jim@meyering.net>2003-05-08 09:26:34 +0000
commitde261015e86e6311e078330da6a6627ecec1d255 (patch)
tree580747d0a484fcf33b765cfab06b843aef5d2cc7 /lib/xnanosleep.c
parentf197628cb2e7192a8a8ba9b841fca068b50dd96d (diff)
downloadcoreutils-de261015e86e6311e078330da6a6627ecec1d255.tar.xz
(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.
Diffstat (limited to 'lib/xnanosleep.c')
-rw-r--r--lib/xnanosleep.c63
1 files changed, 27 insertions, 36 deletions
diff --git a/lib/xnanosleep.c b/lib/xnanosleep.c
index 097466e12..c4e9b469b 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;
}