Browse Source

Timer-based gettimeofday substitute for systems with poor time-of-day clocks (Windows)

Luke Dashjr 12 years ago
parent
commit
b81e7a23bd
3 changed files with 58 additions and 2 deletions
  1. 2 2
      logging.c
  2. 44 0
      util.c
  3. 12 0
      util.h

+ 2 - 2
logging.c

@@ -75,8 +75,8 @@ void _applog(int prio, const char *str)
 			struct timeval tv;
 			struct timeval tv;
 			struct tm tm;
 			struct tm tm;
 			
 			
-			// NOTE: cgtime is for timers, not time of day!
-			gettimeofday(&tv, NULL);
+			bfg_init_time();
+			bfg_gettimeofday(&tv);
 			localtime_r(&tv.tv_sec, &tm);
 			localtime_r(&tv.tv_sec, &tm);
 			
 			
 			sprintf(datetime, "[%d-%02d-%02d %02d:%02d:%02d.%06ld]",
 			sprintf(datetime, "[%d-%02d-%02d %02d:%02d:%02d.%06ld]",

+ 44 - 0
util.c

@@ -1111,6 +1111,42 @@ void _now_gettimeofday(struct timeval *tv)
 #endif
 #endif
 }
 }
 
 
+#ifdef HAVE_POOR_GETTIMEOFDAY
+static struct timeval tv_timeofday_offset;
+static struct timeval _tv_timeofday_lastchecked;
+static pthread_mutex_t _tv_timeofday_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static
+void bfg_calibrate_timeofday(struct timeval *expected, char *buf)
+{
+	struct timeval actual, delta;
+	timeradd(expected, &tv_timeofday_offset, expected);
+	_now_gettimeofday(&actual);
+	if (expected->tv_sec >= actual.tv_sec - 1 && expected->tv_sec <= actual.tv_sec + 1)
+		// Within reason - no change necessary
+		return;
+	
+	timersub(&actual, expected, &delta);
+	timeradd(&tv_timeofday_offset, &delta, &tv_timeofday_offset);
+	sprintf(buf, "Recalibrating timeofday offset (delta %ld.%06lds)", (long)delta.tv_sec, (long)delta.tv_usec);
+	*expected = actual;
+}
+
+void bfg_gettimeofday(struct timeval *out)
+{
+	char buf[64] = "";
+	timer_set_now(out);
+	mutex_lock(&_tv_timeofday_mutex);
+	if (_tv_timeofday_lastchecked.tv_sec < out->tv_sec - 21)
+		bfg_calibrate_timeofday(out, buf);
+	else
+		timeradd(out, &tv_timeofday_offset, out);
+	mutex_unlock(&_tv_timeofday_mutex);
+	if (unlikely(buf[0]))
+		applog(LOG_WARNING, "%s", buf);
+}
+#endif
+
 #ifdef WIN32
 #ifdef WIN32
 static LARGE_INTEGER _perffreq;
 static LARGE_INTEGER _perffreq;
 
 
@@ -1193,6 +1229,14 @@ void bfg_init_time()
 		timer_set_now = _now_gettimeofday;
 		timer_set_now = _now_gettimeofday;
 		applog(LOG_DEBUG, "Timers: Using gettimeofday");
 		applog(LOG_DEBUG, "Timers: Using gettimeofday");
 	}
 	}
+	
+#ifdef HAVE_POOR_GETTIMEOFDAY
+	char buf[64] = "";
+	struct timeval tv;
+	timer_set_now(&tv);
+	bfg_calibrate_timeofday(&tv, buf);
+	applog(LOG_DEBUG, "%s", buf);
+#endif
 }
 }
 
 
 void subtime(struct timeval *a, struct timeval *b)
 void subtime(struct timeval *a, struct timeval *b)

+ 12 - 0
util.h

@@ -13,6 +13,8 @@
 #ifndef __UTIL_H__
 #ifndef __UTIL_H__
 #define __UTIL_H__
 #define __UTIL_H__
 
 
+#include <sys/time.h>
+
 #include <curl/curl.h>
 #include <curl/curl.h>
 #include <jansson.h>
 #include <jansson.h>
 
 
@@ -274,6 +276,16 @@ bool timer_passed(const struct timeval *tvp_timer, const struct timeval *tvp_now
 	return timercmp(tvp_timer, _tvp_now, <);
 	return timercmp(tvp_timer, _tvp_now, <);
 }
 }
 
 
+#if defined(WIN32) && !defined(HAVE_POOR_GETTIMEOFDAY)
+#define HAVE_POOR_GETTIMEOFDAY
+#endif
+
+#ifdef HAVE_POOR_GETTIMEOFDAY
+extern void bfg_gettimeofday(struct timeval *);
+#else
+#define bfg_gettimeofday(out)  gettimeofday(out, NULL)
+#endif
+
 static inline
 static inline
 void reduce_timeout_to(struct timeval *tvp_timeout, struct timeval *tvp_time)
 void reduce_timeout_to(struct timeval *tvp_timeout, struct timeval *tvp_time)
 {
 {