diff options
author | Matt Johnston <matt@ucc.asn.au> | 2014-07-28 22:48:48 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2014-07-28 22:48:48 +0800 |
commit | ad1d48e07b7f846fd584c23d3eb15aa44d30a1ad (patch) | |
tree | 927f6334358ee79b68783066c6cdb2e63a803481 /dbutil.c | |
parent | ac98aae16026dd3d02e98b5a12bce1d40982977b (diff) |
Fix clock_gettime handling
Diffstat (limited to 'dbutil.c')
-rw-r--r-- | dbutil.c | 46 |
1 files changed, 34 insertions, 12 deletions
@@ -945,22 +945,45 @@ int constant_time_memcmp(const void* a, const void *b, size_t n) return c; } -time_t monotonic_now() { - #if defined(__linux__) && defined(SYS_clock_gettime) - /* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32. Probably cheaper. */ +/* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32 but took a while to +reach userspace include headers */ #ifndef CLOCK_MONOTONIC_COARSE #define CLOCK_MONOTONIC_COARSE 6 #endif - static clockid_t clock_source = CLOCK_MONOTONIC_COARSE; +static clockid_t get_linux_clock_source() { struct timespec ts; + if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE, &ts) == 0) { + return CLOCK_MONOTONIC_COARSE; + } + if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) { + return CLOCK_MONOTONIC; + } + return -1; +} +#endif + +time_t monotonic_now() { +#if defined(__linux__) && defined(SYS_clock_gettime) + static clockid_t clock_source = -2; - if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) { - clock_source = CLOCK_MONOTONIC; - syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts); + if (clock_source == -2) { + /* First time, find out which one works. + -1 will fall back to time() */ + clock_source = get_linux_clock_source(); } - return ts.tv_sec; -#elif defined(HAVE_MACH_ABSOLUTE_TIME) + + if (clock_source >= 0) { + struct timespec ts; + if (syscall(SYS_clock_gettime, clock_source, &ts) != 0) { + /* Intermittent clock failures should not happen */ + dropbear_exit("Clock broke"); + } + return ts.tv_sec; + } +#endif /* linux clock_gettime */ + +#if defined(HAVE_MACH_ABSOLUTE_TIME) /* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */ static mach_timebase_info_data_t timebase_info; if (timebase_info.denom == 0) { @@ -968,10 +991,9 @@ time_t monotonic_now() { } return mach_absolute_time() * timebase_info.numer / timebase_info.denom / 1e9; -#else +#endif /* osx mach_absolute_time */ + /* Fallback for everything else - this will sometimes go backwards */ return time(NULL); -#endif - } |