/* Start the timeout after which we'll receive a SIGALRM. Round DURATION up to the next representable value. Treat out-of-range values as if they were maximal, as that's more useful in practice than reporting an error. '0' means don't timeout. */ static void settimeout (double duration, bool warn) { /* timer_settime() provides potentially nanosecond resolution. setitimer() is more portable (to Darwin for example), but only provides microsecond resolution and thus is a little more awkward to use with timespecs, as well as being deprecated by POSIX. Instead we fallback to single second resolution provided by alarm(). */ #if HAVE_TIMER_SETTIME struct timespec ts = dtotimespec (duration); struct itimerspec its = { {0, 0}, ts }; timer_t timerid; if (timer_create (CLOCK_REALTIME, NULL, &timerid) == 0) { if (timer_settime (timerid, 0, &its, NULL) == 0) return; else { if (warn) error (0, errno, _("warning: timer_settime")); timer_delete (timerid); } } else if (warn && errno != ENOSYS) error (0, errno, _("warning: timer_create")); #endif unsigned int timeint; if (UINT_MAX <= duration) timeint = UINT_MAX; else { unsigned int duration_floor = duration; timeint = duration_floor + (duration_floor < duration); } alarm (timeint); }
int xnanosleep (double seconds) { struct timespec ts_sleep = dtotimespec (seconds); for (;;) { /* Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno when resumed after being suspended. Earlier versions would set errno to EINTR. nanosleep from linux-2.6.10, as well as implementations by (all?) other vendors, doesn't return -1 in that case; either it continues sleeping (if time remains) or it returns zero (if the wake-up time has passed). */ errno = 0; if (nanosleep (&ts_sleep, NULL) == 0) break; if (errno != EINTR && errno != 0) return -1; } return 0; }