summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1999-12-23 14:34:38 +0000
committerJim Meyering <jim@meyering.net>1999-12-23 14:34:38 +0000
commit0ecbb73025629fd0d6fc4a57d5c40ced4634bfe5 (patch)
treec61170254dc58a064b68edade909e13263470ff5 /src
parentfc7ceba21b5239ce0d654b8dbc6caa51c6df95fb (diff)
downloadcoreutils-0ecbb73025629fd0d6fc4a57d5c40ced4634bfe5.tar.xz
(USE_CLOCK_GETTIME): Define.
[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.
Diffstat (limited to 'src')
-rw-r--r--src/sleep.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/src/sleep.c b/src/sleep.c
index ec64098be..f1e778109 100644
--- a/src/sleep.c
+++ b/src/sleep.c
@@ -22,6 +22,11 @@
#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);