diff dbutil.c @ 928:7cd89d4e0335

Add new monotonic_now() wrapper so that timeouts are unaffected by system clock changes
author Matt Johnston <matt@ucc.asn.au>
date Thu, 13 Mar 2014 23:50:09 +0800
parents ff597bf2cfb0
children 8f04e36622c0
line wrap: on
line diff
--- a/dbutil.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/dbutil.c	Thu Mar 13 23:50:09 2014 +0800
@@ -48,6 +48,19 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
+#include "config.h"
+
+#ifdef __linux__
+#define _GNU_SOURCE
+/* To call clock_gettime() directly */
+#include <sys/syscall.h>
+#endif /* __linux */
+
+#ifdef HAVE_MACH_MACH_TIME_H
+#include <mach/mach_time.h>
+#include <mach/mach.h>
+#endif
+
 #include "includes.h"
 #include "dbutil.h"
 #include "buffer.h"
@@ -932,3 +945,33 @@
 	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. */
+#ifndef CLOCK_MONOTONIC_COARSE
+#define CLOCK_MONOTONIC_COARSE 6
+#endif
+	static clockid_t clock_source = CLOCK_MONOTONIC_COARSE;
+	struct timespec ts;
+
+	if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) {
+		clock_source = CLOCK_MONOTONIC;
+		syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts);
+	}
+	return ts.tv_sec;
+#elif defined(HAVE_MACH_ABSOLUTE_TIME)
+	/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
+	mach_timebase_info_data_t timebase_info;
+	if (timebase_info.denom == 0) {
+		mach_timebase_info(&timebase_info);
+	}
+	return mach_absolute_time() * timebase_info.numer / timebase_info.denom
+		/ 1e9;
+#else 
+	/* Fallback for everything else - this will sometimes go backwards */
+	return time(NULL);
+#endif
+
+}
+