(USE_CLOCK_GETTIME): Define.
authorJim Meyering <jim@meyering.net>
Thu, 23 Dec 1999 14:34:38 +0000 (14:34 +0000)
committerJim Meyering <jim@meyering.net>
Thu, 23 Dec 1999 14:34:38 +0000 (14:34 +0000)
[USE_CLOCK_GETTIME]: Include sys/time.h.
(timespec_subtract): New function.
(clock_get_realtime): New function.
(sighandler): Remove function.
(main): Reimplement again, using nanosleep and clock_gettime.

src/sleep.c

index ec64098..f1e7781 100644 (file)
 #include <time.h>
 #include <getopt.h>
 
+#define USE_CLOCK_GETTIME (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME)
+#if ! USE_CLOCK_GETTIME
+# include <sys/time.h>
+#endif
+
 #ifndef TIME_T_MAX
 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
 #endif
@@ -104,6 +109,59 @@ apply_suffix (double *s, char suffix_char)
   return 0;
 }
 
+/* Subtract the `struct timespec' values X and Y,
+   storing the difference in DIFF.
+   Return 1 if the difference is negative, otherwise 0.
+   From the GNU libc manual.  */
+
+static int
+timespec_subtract (struct timespec *diff,
+                  const struct timespec *x, struct timespec *y)
+{
+  /* Perform the carry for the later subtraction by updating Y. */
+  if (x->tv_nsec < y->tv_nsec)
+    {
+      int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
+      y->tv_nsec -= 1000000000 * nsec;
+      y->tv_sec += nsec;
+    }
+
+  if (x->tv_nsec - y->tv_nsec > 1000000000)
+    {
+      int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000;
+      y->tv_nsec += 1000000000 * nsec;
+      y->tv_sec -= nsec;
+    }
+
+  /* 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 negative. */
+  return x->tv_sec < y->tv_sec;
+}
+
+static void
+clock_get_realtime (struct timespec *ts)
+{
+  int fail;
+#if USE_CLOCK_GETTIME
+  fail = clock_gettime (CLOCK_REALTIME, &ts);
+#else
+  struct timeval tv;
+  fail = gettimeofday (&tv, NULL);
+  if (!fail)
+    {
+      ts->tv_sec = tv.tv_sec;
+      ts->tv_nsec = 1000 * tv.tv_usec;
+    }
+#endif
+
+  if (fail)
+    error (1, errno, _("cannot read realtime clock"));
+}
+
 int
 main (int argc, char **argv)
 {
@@ -111,8 +169,12 @@ main (int argc, char **argv)
   double seconds = 0.0;
   int c;
   int fail = 0;
-  int interrupted;
-  struct timespec ts;
+  struct timespec ts_start;
+  struct timespec ts_stop;
+  struct timespec ts_sleep;
+
+  /* Record start time.  */
+  clock_get_realtime (&ts_start);
 
   program_name = argv[0];
   setlocale (LC_ALL, "");
@@ -170,17 +232,24 @@ main (int argc, char **argv)
   seconds += .0000000005;
 
   /* Separate whole seconds from nanoseconds.  */
-  ts.tv_sec = seconds;
-  ts.tv_nsec = (seconds - ts.tv_sec) * 1000000000;
+  ts_sleep.tv_sec = seconds;
+  ts_sleep.tv_nsec = (seconds - ts_sleep.tv_sec) * 1000000000;
+
+  ts_stop.tv_sec = ts_start.tv_sec + ts_sleep.tv_sec;
+  ts_stop.tv_nsec = ts_start.tv_nsec + ts_sleep.tv_nsec;
 
   while (1)
     {
       struct timespec remaining;
-      interrupted = nanosleep (&ts, &remaining);
-      /* assert (!interrupted || errno == EINTR); */
+      struct timespec ts_now;
+      int negative;
+      int interrupted = nanosleep (&ts_sleep, &remaining);
       if (!interrupted)
        break;
-      ts = remaining;
+      clock_get_realtime (&ts_now);
+      negative = timespec_subtract (&ts_sleep, &ts_stop, &ts_now);
+      if (negative)
+       break;
     }
 
   exit (0);