gettime: use pthread_{set,get}specific() for TLS
authorJens Axboe <axboe@kernel.dk>
Tue, 18 Dec 2012 08:12:27 +0000 (09:12 +0100)
committerJens Axboe <axboe@kernel.dk>
Tue, 18 Dec 2012 08:12:27 +0000 (09:12 +0100)
__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 <axboe@kernel.dk>
backend.c
gettime.c
gettime.h

index a71d768d22d89437e4a6cde828c24c36bb28ecbf..225d8a36ec66a427a996a8f14fe48717fba67b6f 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1011,6 +1011,8 @@ static void *thread_main(void *data)
        } else
                td->pid = gettid();
 
        } 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);
        dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid);
 
        INIT_FLIST_HEAD(&td->io_u_freelist);
index 1a7af377eb24b1aadb31652884ffb312b4235783..921c171fdef80a414e8fdf039c9c09faefa30e02 100644 (file)
--- 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 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;
 
 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
 {
 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);
 #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 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
 }
 
 #ifdef ARCH_HAVE_CPU_CLOCK
@@ -262,12 +271,28 @@ static void calibrate_cpu_clock(void)
 }
 #endif
 
 }
 #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;
 
 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();
 
        fio_clock_source_inited = fio_clock_source;
        calibrate_cpu_clock();
 
index 8ca379116a4bad23ff6c0c9e9086d2b88b2b020f..f0ad20c8a2927437cc49eb2a4adf9fb28f4b247f 100644 (file)
--- 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_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;
 
 
 extern struct timeval *fio_tv;