summaryrefslogtreecommitdiffhomepage
path: root/dbutil.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2014-07-28 22:48:48 +0800
committerMatt Johnston <matt@ucc.asn.au>2014-07-28 22:48:48 +0800
commitad1d48e07b7f846fd584c23d3eb15aa44d30a1ad (patch)
tree927f6334358ee79b68783066c6cdb2e63a803481 /dbutil.c
parentac98aae16026dd3d02e98b5a12bce1d40982977b (diff)
Fix clock_gettime handling
Diffstat (limited to 'dbutil.c')
-rw-r--r--dbutil.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/dbutil.c b/dbutil.c
index 2ea52ac..5826729 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -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
-
}