From: Bart Van Assche Date: Sun, 21 Jun 2020 21:31:08 +0000 (-0700) Subject: Optimize fio_gettime_offload() X-Git-Tag: fio-3.21~28^2 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=817a1d8301824effbf9ea3352e6e722a3515473c Optimize fio_gettime_offload() This patch not only an optimization but also a bug fix because it guarantees that fio_gettime_offload() never returns an inconsistent timestamp, something that could happen before. In this context inconsistent means returning the .tv_sec value from one gettimeofday() call and the .tv_usec value from another gettimeofday() call. Signed-off-by: Bart Van Assche --- diff --git a/gettime-thread.c b/gettime-thread.c index 0a2cc6c4..953e4e67 100644 --- a/gettime-thread.c +++ b/gettime-thread.c @@ -2,9 +2,10 @@ #include #include "fio.h" +#include "lib/seqlock.h" #include "smalloc.h" -struct timespec *fio_ts = NULL; +struct fio_ts *fio_ts; int fio_gtod_offload = 0; static pthread_t gtod_thread; static os_cpu_mask_t fio_gtod_cpumask; @@ -19,15 +20,17 @@ void fio_gtod_init(void) static void fio_gtod_update(void) { - if (fio_ts) { - struct timeval __tv; - - gettimeofday(&__tv, NULL); - fio_ts->tv_sec = __tv.tv_sec; - write_barrier(); - fio_ts->tv_nsec = __tv.tv_usec * 1000; - write_barrier(); - } + struct timeval __tv; + + if (!fio_ts) + return; + + gettimeofday(&__tv, NULL); + + write_seqlock_begin(&fio_ts->seqlock); + fio_ts->ts.tv_sec = __tv.tv_sec; + fio_ts->ts.tv_nsec = __tv.tv_usec * 1000; + write_seqlock_end(&fio_ts->seqlock); } struct gtod_cpu_data { diff --git a/gettime.h b/gettime.h index f92ee8c4..c55f5cba 100644 --- a/gettime.h +++ b/gettime.h @@ -4,6 +4,7 @@ #include #include "arch/arch.h" +#include "lib/seqlock.h" /* * Clock sources @@ -22,20 +23,22 @@ extern int fio_start_gtod_thread(void); extern int fio_monotonic_clocktest(int debug); extern void fio_local_clock_init(void); -extern struct timespec *fio_ts; +extern struct fio_ts { + struct seqlock seqlock; + struct timespec ts; +} *fio_ts; static inline int fio_gettime_offload(struct timespec *ts) { - time_t last_sec; + unsigned int seq; if (!fio_ts) return 0; do { - read_barrier(); - last_sec = ts->tv_sec = fio_ts->tv_sec; - ts->tv_nsec = fio_ts->tv_nsec; - } while (fio_ts->tv_sec != last_sec); + seq = read_seqlock_begin(&fio_ts->seqlock); + *ts = fio_ts->ts; + } while (read_seqlock_retry(&fio_ts->seqlock, seq)); return 1; } diff --git a/t/debug.c b/t/debug.c index 8965cfbc..0c913368 100644 --- a/t/debug.c +++ b/t/debug.c @@ -1,7 +1,7 @@ #include FILE *f_err; -struct timespec *fio_ts = NULL; +void *fio_ts; unsigned long fio_debug = 0; void __dprint(int type, const char *str, ...)