Add generic arch include header
[fio.git] / gettime.c
index 2753faecb02d0596b1898346a46bf7f1d9e44873..8ec70b9f186aeb7d31ccedd82e64a1f284ba4759 100644 (file)
--- a/gettime.c
+++ b/gettime.c
@@ -6,10 +6,17 @@
 #include <sys/time.h>
 
 #include "fio.h"
+#include "smalloc.h"
 
 #include "hash.h"
 
-static int clock_gettime_works;
+static int clock_gettime_works = 0;
+static struct timeval last_tv;
+static int last_tv_valid;
+
+static struct timeval *fio_tv;
+int fio_gtod_offload = 0;
+int fio_gtod_cpu = -1;
 
 #ifdef FIO_DEBUG_TIME
 
@@ -114,13 +121,16 @@ void fio_gettime(struct timeval *tp, void fio_unused *caller)
 
        gtod_log_caller(caller);
 #endif
-       if (!clock_gettime_works) {
+       if (fio_tv) {
+               memcpy(tp, fio_tv, sizeof(*tp));
+               return;
+       } else if (!clock_gettime_works) {
 gtod:
                gettimeofday(tp, NULL);
        } else {
                struct timespec ts;
 
-               if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
+               if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
                        clock_gettime_works = 0;
                        goto gtod;
                }
@@ -128,4 +138,29 @@ gtod:
                tp->tv_sec = ts.tv_sec;
                tp->tv_usec = ts.tv_nsec / 1000;
        }
+
+       /*
+        * If Linux is using the tsc clock on non-synced processors,
+        * sometimes time can appear to drift backwards. Fix that up.
+        */
+       if (last_tv_valid) {
+               if (tp->tv_sec < last_tv.tv_sec)
+                       tp->tv_sec = last_tv.tv_sec;
+               else if (last_tv.tv_sec == tp->tv_sec &&
+                        tp->tv_usec < last_tv.tv_usec)
+                       tp->tv_usec = last_tv.tv_usec;
+       }
+       last_tv_valid = 1;
+       memcpy(&last_tv, tp, sizeof(*tp));
+}
+
+void fio_gtod_init(void)
+{
+       fio_tv = smalloc(sizeof(struct timeval));
+       assert(fio_tv);
+}
+
+void fio_gtod_update(void)
+{
+       gettimeofday(fio_tv, NULL);
 }