From 5d879392c0e4025e508cce8118f6fc13ee57cc0e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 18 Dec 2012 09:12:27 +0100 Subject: [PATCH] gettime: use pthread_{set,get}specific() for TLS __thread doesn't work on OSX at least (thanks...), so resort to using the pthread functions to maintaining a per-thread clock check. Signed-off-by: Jens Axboe --- backend.c | 2 ++ gettime.c | 47 ++++++++++++++++++++++++++++++++++++----------- gettime.h | 1 + 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/backend.c b/backend.c index a71d768d..225d8a36 100644 --- a/backend.c +++ b/backend.c @@ -1011,6 +1011,8 @@ static void *thread_main(void *data) } else td->pid = gettid(); + fio_local_clock_init(td->o.use_thread); + dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid); INIT_FLIST_HEAD(&td->io_u_freelist); diff --git a/gettime.c b/gettime.c index 1a7af377..921c171f 100644 --- a/gettime.c +++ b/gettime.c @@ -18,8 +18,12 @@ static unsigned long cycles_per_usec; static unsigned long last_cycles; int tsc_reliable = 0; #endif -static __thread struct timeval last_tv; -static __thread int last_tv_valid; + +struct tv_valid { + struct timeval last_tv; + int last_tv_valid; +}; +static pthread_key_t tv_tls_key; enum fio_cs fio_clock_source = FIO_PREFERRED_CLOCK_SOURCE; int fio_clock_source_set = 0; @@ -122,6 +126,8 @@ void fio_gettime(struct timeval *tp, void *caller) void fio_gettime(struct timeval *tp, void fio_unused *caller) #endif { + struct tv_valid *t; + #ifdef FIO_DEBUG_TIME if (!caller) caller = __builtin_return_address(0); @@ -179,15 +185,18 @@ void fio_gettime(struct timeval *tp, void fio_unused *caller) * 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; + t = pthread_getspecific(tv_tls_key); + if (t) { + if (t->last_tv_valid) { + if (tp->tv_sec < t->last_tv.tv_sec) + tp->tv_sec = t->last_tv.tv_sec; + else if (t->last_tv.tv_sec == tp->tv_sec && + tp->tv_usec < t->last_tv.tv_usec) + tp->tv_usec = t->last_tv.tv_usec; + } + t->last_tv_valid = 1; + memcpy(&t->last_tv, tp, sizeof(*tp)); } - last_tv_valid = 1; - memcpy(&last_tv, tp, sizeof(*tp)); } #ifdef ARCH_HAVE_CPU_CLOCK @@ -262,12 +271,28 @@ static void calibrate_cpu_clock(void) } #endif +void fio_local_clock_init(int is_thread) +{ + struct tv_valid *t; + + t = calloc(sizeof(*t), 1); + if (pthread_setspecific(tv_tls_key, t)) + log_err("fio: can't set TLS key\n"); +} + +static void kill_tv_tls_key(void *data) +{ + free(data); +} + void fio_clock_init(void) { if (fio_clock_source == fio_clock_source_inited) return; - last_tv_valid = 0; + if (pthread_key_create(&tv_tls_key, kill_tv_tls_key)) + log_err("fio: can't create TLS key\n"); + fio_clock_source_inited = fio_clock_source; calibrate_cpu_clock(); diff --git a/gettime.h b/gettime.h index 8ca37911..f0ad20c8 100644 --- a/gettime.h +++ b/gettime.h @@ -16,6 +16,7 @@ extern void fio_gtod_init(void); extern void fio_clock_init(void); extern int fio_start_gtod_thread(void); extern int fio_monotonic_clocktest(void); +extern void fio_local_clock_init(int); extern struct timeval *fio_tv; -- 2.25.1