-/* $OpenBSD: nanosleep.c,v 1.8 2024/02/29 18:17:41 bluhm Exp $ */
+/* $OpenBSD: nanosleep.c,v 1.9 2024/02/29 21:47:02 bluhm Exp $ */
/*
* Written by Artur Grabowski <art@openbsd.org> 2002 Public Domain.
*/
break;
case 'S':
ret |= short_time();
+ break;
default:
fprintf(stderr, "Usage: nanosleep [-itseSE]\n");
exit(1);
int
trivial(void)
{
- struct timespec ts, rts;
-
- ts.tv_sec = 0;
- ts.tv_nsec = 30000000;
- rts.tv_sec = 4711; /* Just add to the confusion */
- rts.tv_nsec = 4711;
- if (nanosleep(&ts, &rts) < 0) {
- warn("trivial: nanosleep");
+ struct timespec timeout, remainder;
+
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 30000000;
+ remainder.tv_sec = 4711; /* Just add to the confusion */
+ remainder.tv_nsec = 4711;
+ if (nanosleep(&timeout, &remainder) < 0) {
+ warn("%s: nanosleep", __func__);
return 1;
}
* amount of time we want to sleep.
* If we receive any signal, something is wrong anyway.
*/
- if (rts.tv_sec != 0 || rts.tv_nsec != 0) {
- warnx("trivial: non-zero time? %lld/%ld", (long long)rts.tv_sec,
- rts.tv_nsec);
+ if (remainder.tv_sec != 0 || remainder.tv_nsec != 0) {
+ warnx("%s: non-zero time: %lld.%09ld", __func__,
+ (long long)remainder.tv_sec, remainder.tv_nsec);
return 1;
}
int
with_signal(void)
{
- struct timespec ts, rts;
+ struct timespec timeout, remainder;
pid_t pid;
int status;
switch(fork()) {
case -1:
err(1, "fork");
- default:
- ts.tv_sec = 1;
- ts.tv_nsec = 0;
- nanosleep(&ts, NULL);
+ case 0:
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+ nanosleep(&timeout, NULL);
kill(pid, SIGUSR1);
- exit(0);
+ _exit(0);
+ default:
+ break;
}
- ts.tv_sec = 10;
- ts.tv_nsec = 0;
- rts.tv_sec = 0;
- rts.tv_nsec = 0;
- if (nanosleep(&ts, &rts) == 0) {
- warnx("with-signal: nanosleep");
+ timeout.tv_sec = 10;
+ timeout.tv_nsec = 0;
+ remainder.tv_sec = 0;
+ remainder.tv_nsec = 0;
+ if (nanosleep(&timeout, &remainder) == 0) {
+ warnx("%s: nanosleep", __func__);
return 1;
}
- if (rts.tv_sec == 0 && rts.tv_nsec == 0) {
- warnx("with-signal: zero time");
+
+ if (remainder.tv_sec == 0 && remainder.tv_nsec == 0) {
+ warnx("%s: zero time", __func__);
return 1;
}
if (wait(&status) < 0)
err(1, "wait");
+ if (status != 0)
+ errx(1, "status");
return 0;
}
int
time_elapsed(void)
{
- struct timespec ts;
- struct timespec stv, etv;
+ struct timespec timeout;
+ struct timespec start, end, duration;
- ts.tv_sec = 0;
- ts.tv_nsec = 500000000;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 500000000;
- if (clock_gettime(CLOCK_MONOTONIC, &stv) < 0) {
- warn("clock_gettime");
+ if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) {
+ warn("%s: clock_gettime", __func__);
return 1;
}
- if (nanosleep(&ts, NULL) < 0) {
- warn("nanosleep");
+ if (nanosleep(&timeout, NULL) < 0) {
+ warn("%s: nanosleep", __func__);
return 1;
}
- if (clock_gettime(CLOCK_MONOTONIC, &etv) < 0) {
- warn("clock_gettime");
+ if (clock_gettime(CLOCK_MONOTONIC, &end) < 0) {
+ warn("%s: clock_gettime", __func__);
return 1;
}
- timespecsub(&etv, &stv, &stv);
+ timespecsub(&end, &start, &duration);
- if (stv.tv_sec == 0 && stv.tv_nsec < 500000000) {
- warnx("slept less than 0.5 sec");
+ if (duration.tv_sec == 0 && duration.tv_nsec < 500000000) {
+ warnx("%s: slept less than 0.5 sec: %lld.%09ld", __func__,
+ (long long)duration.tv_sec, duration.tv_nsec);
return 1;
}
int
time_elapsed_with_signal(void)
{
- struct timespec ts, rts;
- struct timespec stv, etv;
+ struct timespec timeout, remainder;
+ struct timespec start, end, duration;
pid_t pid;
int status;
switch(fork()) {
case -1:
err(1, "fork");
- default:
- ts.tv_sec = 1;
- ts.tv_nsec = 0;
- nanosleep(&ts, NULL);
+ case 0:
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+ nanosleep(&timeout, NULL);
kill(pid, SIGUSR1);
- exit(0);
+ _exit(0);
+ default:
+ break;
}
- ts.tv_sec = 10;
- ts.tv_nsec = 0;
- rts.tv_sec = 0;
- rts.tv_nsec = 0;
-
- if (clock_gettime(CLOCK_MONOTONIC, &stv) < 0) {
- warn("clock_gettime");
+ if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) {
+ warn("%s: clock_gettime", __func__);
return 1;
}
- if (nanosleep(&ts, &rts) == 0) {
- warnx("nanosleep");
+ timeout.tv_sec = 10;
+ timeout.tv_nsec = 0;
+ remainder.tv_sec = 0;
+ remainder.tv_nsec = 0;
+ if (nanosleep(&timeout, &remainder) == 0) {
+ warnx("%s: nanosleep", __func__);
return 1;
}
- if (clock_gettime(CLOCK_MONOTONIC, &etv) < 0) {
- warn("clock_gettime");
+ if (clock_gettime(CLOCK_MONOTONIC, &end) < 0) {
+ warn("%s: clock_gettime", __func__);
return 1;
}
- timespecsub(&etv, &stv, &stv);
-
- etv.tv_sec = rts.tv_sec;
- etv.tv_nsec = rts.tv_nsec;
-
- timespecadd(&etv, &stv, &stv);
+ timespecsub(&end, &start, &duration);
+ timespecadd(&duration, &remainder, &timeout);
+ /* XXX remainder may be one tick too small */
+ remainder.tv_sec = 0;
+ remainder.tv_nsec = 10000000;
+ timespecadd(&timeout, &remainder, &timeout);
- if (stv.tv_sec < 10) {
- warnx("slept time + leftover time < 10 sec");
+ if (timeout.tv_sec < 10) {
+ warnx("%s: slept time + leftover time < 10 sec: %lld.%09ld",
+ __func__, (long long)timeout.tv_sec, timeout.tv_nsec);
return 1;
}
-
if (wait(&status) < 0)
err(1, "wait");
+ if (status != 0)
+ errx(1, "status");
return 0;
}
int
short_time(void)
{
- struct timespec ts, rts;
+ struct timespec timeout;
pid_t pid;
int status;
switch(fork()) {
case -1:
err(1, "fork");
- default:
+ case 0:
/* Sleep two seconds, then shoot parent. */
- ts.tv_sec = 2;
- ts.tv_nsec = 0;
- nanosleep(&ts, NULL);
+ timeout.tv_sec = 2;
+ timeout.tv_nsec = 0;
+ nanosleep(&timeout, NULL);
kill(pid, SIGUSR1);
- exit(0);
+ _exit(0);
+ default:
+ break;
}
- ts.tv_sec = 0;
- ts.tv_nsec = 1;
- if (nanosleep(&ts, NULL) <= 0) {
- warn("short_time: nanosleep");
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 1;
+ if (nanosleep(&timeout, NULL) < 0) {
+ warn("%s: nanosleep", __func__);
return 1;
}
if (wait(&status) < 0)
err(1, "wait");
+ if (status != 0)
+ errx(1, "status");
return 0;
}
int
invalid_time(void)
{
- struct timespec ts[3] = { {-1, 0}, {0, -1}, {0, 1000000000L} };
+ struct timespec timeout[3] = { {-1, 0}, {0, -1}, {0, 1000000000L} };
int i, status;
for (i = 0; i < 3; i++) {
- status = nanosleep(&ts[i], NULL);
+ status = nanosleep(&timeout[i], NULL);
if (status != -1 || errno != EINVAL) {
- warnx("invalid-time: nanosleep %lld %ld",
- (long long)ts[i].tv_sec, ts[i].tv_nsec);
+ warnx("%s: nanosleep %lld %ld", __func__,
+ (long long)timeout[i].tv_sec, timeout[i].tv_nsec);
return 1;
}
}