bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: sleep from coreutils-5.0 doesn't work on AIX 4.3.3


From: Paul Eggert
Subject: Re: sleep from coreutils-5.0 doesn't work on AIX 4.3.3
Date: 07 May 2003 13:27:08 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Jim Meyering <address@hidden> writes:

>       * xnanosleep.c (clock_get_realtime): Use gettime.c's gettime function,
>       rather than an inferior, open-coded version that would fail on
>       AIX systems due to clock_gettime failing with errno == ENOSYS.

I looked at that code a bit more and noticed that timespec_subtract
can misbehave in unusual situations where x->tv_sec - y->tv_sec
overflows.  Also, it seems to worry about nsec being out of range, but
that's not possible here and it makes it harder to follow the code
(and I'm not sure the extra complexity is correct anyway).  And the
xnanosleep code doesn't check for clock_get_realtime failing the
second time it's called.  Also, now that the code is cleaned up
there's little point to having a clock_get_realtime function at all.
So how about the following further patch?

2003-05-07  Paul Eggert  <address@hidden>

        * lib/xnanosleep.c (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.

--- old/xnanosleep.c    Wed May  7 13:08:02 2003
+++ new/xnanosleep.c    Wed May  7 13:25:28 2003
@@ -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 @@
 
   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 @@
 
   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 @@
         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;
     }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]