X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=gettime.c;h=b1431f329bec2e3ef9e32439035d896e9f8545ca;hp=533ec97b50b6e9c1baf84e82a012090a06214be2;hb=983b770d547c11d8b0a4ef9e1ac75ffce1d4e46d;hpb=7e326f3bbc7e6f23f2b4c99282f73a7948d02637 diff --git a/gettime.c b/gettime.c index 533ec97b..b1431f32 100644 --- a/gettime.c +++ b/gettime.c @@ -6,22 +6,28 @@ #include #include "fio.h" -#include "os.h" +#include "smalloc.h" #include "hash.h" -static int clock_gettime_works = 1; +static int clock_gettime_works; +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 #define HASH_BITS 8 #define HASH_SIZE (1 << HASH_BITS) -static struct list_head hash[HASH_SIZE]; +static struct flist_head hash[HASH_SIZE]; static int gtod_inited; struct gtod_log { - struct list_head list; + struct flist_head list; void *caller; unsigned long calls; }; @@ -29,10 +35,11 @@ struct gtod_log { static struct gtod_log *find_hash(void *caller) { unsigned long h = hash_ptr(caller, HASH_BITS); - struct list_head *entry; + struct flist_head *entry; - list_for_each(entry, &hash[h]) { - struct gtod_log *log = list_entry(entry, struct gtod_log, list); + flist_for_each(entry, &hash[h]) { + struct gtod_log *log = flist_entry(entry, struct gtod_log, + list); if (log->caller == caller) return log; @@ -49,12 +56,12 @@ static struct gtod_log *find_log(void *caller) unsigned long h; log = malloc(sizeof(*log)); - INIT_LIST_HEAD(&log->list); + INIT_FLIST_HEAD(&log->list); log->caller = caller; log->calls = 0; h = hash_ptr(caller, HASH_BITS); - list_add_tail(&log->list, &hash[h]); + flist_add_tail(&log->list, &hash[h]); } return log; @@ -75,13 +82,14 @@ static void fio_exit fio_dump_gtod(void) int i; for (i = 0; i < HASH_SIZE; i++) { - struct list_head *entry; + struct flist_head *entry; struct gtod_log *log; - list_for_each(entry, &hash[i]) { - log = list_entry(entry, struct gtod_log, list); + flist_for_each(entry, &hash[i]) { + log = flist_entry(entry, struct gtod_log, list); - printf("function %p, calls %lu\n", log->caller, log->calls); + printf("function %p, calls %lu\n", log->caller, + log->calls); total_calls += log->calls; } } @@ -94,7 +102,7 @@ static void fio_init gtod_init(void) int i; for (i = 0; i < HASH_SIZE; i++) - INIT_LIST_HEAD(&hash[i]); + INIT_FLIST_HEAD(&hash[i]); gtod_inited = 1; } @@ -113,7 +121,10 @@ 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 { @@ -127,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); }