diff --git a/configure.ac b/configure.ac index fad99ec23..4d7437d6d 100644 --- a/configure.ac +++ b/configure.ac @@ -399,7 +399,7 @@ AC_CHECK_FUNCS([mach_port_construct]) # # Find functions and declarations we care about. # -AC_CHECK_DECLS([CLOCK_UPTIME, CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_UPTIME_FAST], [], [], +AC_CHECK_DECLS([CLOCK_UPTIME, CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_UPTIME_FAST, CLOCK_MONOTONIC_COARSE], [], [], [[#include ]]) AC_CHECK_DECLS([NOTE_NONE, NOTE_REAP, NOTE_REVOKE, NOTE_SIGNAL, NOTE_LOWAT], [], [], [[#include ]]) diff --git a/src/shims/time.h b/src/shims/time.h index 0b8e92617..6cc5a1603 100644 --- a/src/shims/time.h +++ b/src/shims/time.h @@ -121,6 +121,19 @@ _dispatch_get_nanoseconds(void) #endif } +/* On the use of clock sources in the CLOCK_MONOTONIC family + * + * The code below requires monotonic clock sources that only tick + * while the machine is running. + * + * Per POSIX, the CLOCK_MONOTONIC family is supposed to tick during + * machine sleep; this is not the case on Linux, and that behavior + * became part of the Linux ABI. + * + * Using the CLOCK_MONOTONIC family on POSIX-compliant platforms + * will lead to bugs, hence its use is restricted to Linux. + */ + static inline uint64_t _dispatch_absolute_time(void) { @@ -130,7 +143,7 @@ _dispatch_absolute_time(void) struct timespec ts; dispatch_assume_zero(clock_gettime(CLOCK_UPTIME, &ts)); return _dispatch_timespec_to_nano(ts); -#elif HAVE_DECL_CLOCK_MONOTONIC +#elif HAVE_DECL_CLOCK_MONOTONIC && defined(__linux__) struct timespec ts; dispatch_assume_zero(clock_gettime(CLOCK_MONOTONIC, &ts)); return _dispatch_timespec_to_nano(ts); @@ -152,9 +165,9 @@ _dispatch_approximate_time(void) struct timespec ts; dispatch_assume_zero(clock_gettime(CLOCK_UPTIME_FAST, &ts)); return _dispatch_timespec_to_nano(ts); -#elif defined(__linux__) +#elif HAVE_DECL_CLOCK_MONOTONIC_COARSE && defined(__linux__) struct timespec ts; - dispatch_assume_zero(clock_gettime(CLOCK_REALTIME_COARSE, &ts)); + dispatch_assume_zero(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts)); return _dispatch_timespec_to_nano(ts); #else return _dispatch_absolute_time();