changeset 952:ef8d939de3dd

Fix clock_gettime handling
author Matt Johnston <matt@ucc.asn.au>
date Mon, 28 Jul 2014 22:48:48 +0800
parents 9a48d8bcfeed
children 356a25a108a3
files dbutil.c
diffstat 1 files changed, 34 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/dbutil.c	Sun Jul 27 23:11:52 2014 +0800
+++ b/dbutil.c	Mon Jul 28 22:48:48 2014 +0800
@@ -945,22 +945,45 @@
 	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 @@
 	}
 	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
-
 }