From 8b6a404cdd2c40715885e562416c3db039912773 Mon Sep 17 00:00:00 2001 From: Vincent Fu Date: Tue, 14 Mar 2017 14:41:26 -0400 Subject: [PATCH] nanosecond: initial commit changing timeval to timespec struct timeval has usec resolution whereas struct timespec has nsec resolution. This commit changes several dozen instances of struct timeval to struct timespec. All of the output is unchanged. The ticks to nsec conversion in this patch is broken but fixed in a later patch. --- backend.c | 42 +++++++++++------------ client.c | 22 ++++++------ crc/test.c | 6 ++-- diskutil.c | 2 +- diskutil.h | 2 +- engines/guasi.c | 2 +- engines/libaio.c | 8 ++--- engines/rdma.c | 2 +- eta.c | 6 ++-- fio.h | 24 ++++++------- fio_time.h | 15 +++++---- gettime-thread.c | 14 ++++---- gettime.c | 84 ++++++++++++++++++++++++++++------------------ gettime.h | 14 ++++---- helper_thread.c | 32 +++++++++--------- idletime.c | 14 +++----- idletime.h | 4 +-- io_u.c | 4 +-- io_u.h | 4 +-- ioengines.c | 4 +-- iolog.c | 6 ++-- libfio.c | 8 ++--- mutex.c | 12 ++++--- options.c | 2 +- os/windows/posix.c | 6 ++-- profiles/act.c | 2 +- server.c | 2 +- server.h | 2 +- stat.c | 26 +++++++------- steadystate.c | 2 +- steadystate.h | 2 +- t/debug.c | 2 +- t/dedupe.c | 2 +- t/lfsr-test.c | 2 +- time.c | 36 +++++++++----------- verify.c | 2 +- 36 files changed, 218 insertions(+), 201 deletions(-) diff --git a/backend.c b/backend.c index 9a684edb..fe159970 100644 --- a/backend.c +++ b/backend.c @@ -136,7 +136,7 @@ static void set_sig_handlers(void) /* * Check if we are above the minimum rate given. */ -static bool __check_min_rate(struct thread_data *td, struct timeval *now, +static bool __check_min_rate(struct thread_data *td, struct timespec *now, enum fio_ddir ddir) { unsigned long long bytes = 0; @@ -223,7 +223,7 @@ static bool __check_min_rate(struct thread_data *td, struct timeval *now, return false; } -static bool check_min_rate(struct thread_data *td, struct timeval *now) +static bool check_min_rate(struct thread_data *td, struct timespec *now) { bool ret = false; @@ -335,18 +335,18 @@ static int fio_file_fsync(struct thread_data *td, struct fio_file *f) return ret; } -static inline void __update_tv_cache(struct thread_data *td) +static inline void __update_ts_cache(struct thread_data *td) { - fio_gettime(&td->tv_cache, NULL); + fio_gettime(&td->ts_cache, NULL); } -static inline void update_tv_cache(struct thread_data *td) +static inline void update_ts_cache(struct thread_data *td) { - if ((++td->tv_cache_nr & td->tv_cache_mask) == td->tv_cache_mask) - __update_tv_cache(td); + if ((++td->ts_cache_nr & td->ts_cache_mask) == td->ts_cache_mask) + __update_ts_cache(td); } -static inline bool runtime_exceeded(struct thread_data *td, struct timeval *t) +static inline bool runtime_exceeded(struct thread_data *td, struct timespec *t) { if (in_ramp_time(td)) return false; @@ -430,7 +430,7 @@ static void check_update_rusage(struct thread_data *td) } } -static int wait_for_completions(struct thread_data *td, struct timeval *time) +static int wait_for_completions(struct thread_data *td, struct timespec *time) { const int full = queue_full(td); int min_evts = 0; @@ -462,7 +462,7 @@ static int wait_for_completions(struct thread_data *td, struct timeval *time) int io_queue_event(struct thread_data *td, struct io_u *io_u, int *ret, enum fio_ddir ddir, uint64_t *bytes_issued, int from_verify, - struct timeval *comp_time) + struct timespec *comp_time) { int ret2; @@ -633,12 +633,12 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes) enum fio_ddir ddir; int full; - update_tv_cache(td); + update_ts_cache(td); check_update_rusage(td); - if (runtime_exceeded(td, &td->tv_cache)) { - __update_tv_cache(td); - if (runtime_exceeded(td, &td->tv_cache)) { + if (runtime_exceeded(td, &td->ts_cache)) { + __update_ts_cache(td); + if (runtime_exceeded(td, &td->ts_cache)) { fio_mark_td_terminate(td); break; } @@ -874,7 +874,7 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done) while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) || (!flist_empty(&td->trim_list)) || !io_issue_bytes_exceeded(td) || td->o.time_based) { - struct timeval comp_time; + struct timespec comp_time; struct io_u *io_u; int full; enum fio_ddir ddir; @@ -884,11 +884,11 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done) if (td->terminate || td->done) break; - update_tv_cache(td); + update_ts_cache(td); - if (runtime_exceeded(td, &td->tv_cache)) { - __update_tv_cache(td); - if (runtime_exceeded(td, &td->tv_cache)) { + if (runtime_exceeded(td, &td->ts_cache)) { + __update_ts_cache(td); + if (runtime_exceeded(td, &td->ts_cache)) { fio_mark_td_terminate(td); break; } @@ -1686,7 +1686,7 @@ static void *thread_main(void *data) uint64_t verify_bytes; fio_gettime(&td->start, NULL); - memcpy(&td->tv_cache, &td->start, sizeof(td->start)); + memcpy(&td->ts_cache, &td->start, sizeof(td->start)); if (clear_state) { clear_io_state(td, 0); @@ -2202,7 +2202,7 @@ reap: while (todo) { struct thread_data *map[REAL_MAX_JOBS]; - struct timeval this_start; + struct timespec this_start; int this_jobs = 0, left; struct fork_data *fd; diff --git a/client.c b/client.c index 80096bf8..42ccbef0 100644 --- a/client.c +++ b/client.c @@ -48,7 +48,7 @@ struct client_ops fio_client_ops = { .client_type = FIO_CLIENT_TYPE_CLI, }; -static struct timeval eta_tv; +static struct timespec eta_ts; static FLIST_HEAD(client_list); static FLIST_HEAD(eta_list); @@ -1869,7 +1869,7 @@ static int handle_cmd_timeout(struct fio_client *client, } static int client_check_cmd_timeout(struct fio_client *client, - struct timeval *now) + struct timespec *now) { struct fio_net_cmd_reply *reply; struct flist_head *entry, *tmp; @@ -1878,7 +1878,7 @@ static int client_check_cmd_timeout(struct fio_client *client, flist_for_each_safe(entry, tmp, &client->cmd_list) { reply = flist_entry(entry, struct fio_net_cmd_reply, list); - if (mtime_since(&reply->tv, now) < FIO_NET_CLIENT_TIMEOUT) + if (mtime_since(&reply->ts, now) < FIO_NET_CLIENT_TIMEOUT) continue; if (!handle_cmd_timeout(client, reply)) @@ -1896,10 +1896,10 @@ static int fio_check_clients_timed_out(void) { struct fio_client *client; struct flist_head *entry, *tmp; - struct timeval tv; + struct timespec ts; int ret = 0; - fio_gettime(&tv, NULL); + fio_gettime(&ts, NULL); flist_for_each_safe(entry, tmp, &client_list) { client = flist_entry(entry, struct fio_client, list); @@ -1907,7 +1907,7 @@ static int fio_check_clients_timed_out(void) if (flist_empty(&client->cmd_list)) continue; - if (!client_check_cmd_timeout(client, &tv)) + if (!client_check_cmd_timeout(client, &ts)) continue; if (client->ops->timed_out) @@ -1928,7 +1928,7 @@ int fio_handle_clients(struct client_ops *ops) struct pollfd *pfds; int i, ret = 0, retval = 0; - fio_gettime(&eta_tv, NULL); + fio_gettime(&eta_ts, NULL); pfds = malloc(nr_clients * sizeof(struct pollfd)); @@ -1960,13 +1960,13 @@ int fio_handle_clients(struct client_ops *ops) assert(i == nr_clients); do { - struct timeval tv; + struct timespec ts; int timeout; - fio_gettime(&tv, NULL); - if (mtime_since(&eta_tv, &tv) >= 900) { + fio_gettime(&ts, NULL); + if (mtime_since(&eta_ts, &ts) >= 900) { request_client_etas(ops); - memcpy(&eta_tv, &tv, sizeof(tv)); + memcpy(&eta_ts, &ts, sizeof(ts)); if (fio_check_clients_timed_out()) break; diff --git a/crc/test.c b/crc/test.c index 368229e7..b1198726 100644 --- a/crc/test.c +++ b/crc/test.c @@ -392,7 +392,7 @@ int fio_crctest(const char *type) fill_random_buf(&state, buf, CHUNK); for (i = 0; t[i].name; i++) { - struct timeval tv; + struct timespec ts; double mb_sec; uint64_t usec; char pre[3]; @@ -409,9 +409,9 @@ int fio_crctest(const char *type) t[i].fn(&t[i], buf, CHUNK); } - fio_gettime(&tv, NULL); + fio_gettime(&ts, NULL); t[i].fn(&t[i], buf, CHUNK); - usec = utime_since_now(&tv); + usec = utime_since_now(&ts); if (usec) { mb_sec = (double) mb / (double) usec; diff --git a/diskutil.c b/diskutil.c index 9767ea25..4fe554f5 100644 --- a/diskutil.c +++ b/diskutil.c @@ -84,7 +84,7 @@ static int get_io_ticks(struct disk_util *du, struct disk_util_stat *dus) static void update_io_tick_disk(struct disk_util *du) { struct disk_util_stat __dus, *dus, *ldus; - struct timeval t; + struct timespec t; if (!du->users) return; diff --git a/diskutil.h b/diskutil.h index f7730667..91b42020 100644 --- a/diskutil.h +++ b/diskutil.h @@ -64,7 +64,7 @@ struct disk_util { */ struct flist_head slaves; - struct timeval time; + struct timespec time; struct fio_mutex *lock; unsigned long users; diff --git a/engines/guasi.c b/engines/guasi.c index eb12c899..9644ee59 100644 --- a/engines/guasi.c +++ b/engines/guasi.c @@ -132,7 +132,7 @@ static void fio_guasi_queued(struct thread_data *td, struct io_u **io_us, int nr { int i; struct io_u *io_u; - struct timeval now; + struct timespec now; if (!fio_fill_issue_time(td)) return; diff --git a/engines/libaio.c b/engines/libaio.c index e15c519e..e0d7cbba 100644 --- a/engines/libaio.c +++ b/engines/libaio.c @@ -220,7 +220,7 @@ static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u) static void fio_libaio_queued(struct thread_data *td, struct io_u **io_us, unsigned int nr) { - struct timeval now; + struct timespec now; unsigned int i; if (!fio_fill_issue_time(td)) @@ -241,7 +241,7 @@ static int fio_libaio_commit(struct thread_data *td) struct libaio_data *ld = td->io_ops_data; struct iocb **iocbs; struct io_u **io_us; - struct timeval tv; + struct timespec ts; int ret, wait_start = 0; if (!ld->queued) @@ -282,9 +282,9 @@ static int fio_libaio_commit(struct thread_data *td) break; } if (!wait_start) { - fio_gettime(&tv, NULL); + fio_gettime(&ts, NULL); wait_start = 1; - } else if (mtime_since_now(&tv) > 30000) { + } else if (mtime_since_now(&ts) > 30000) { log_err("fio: aio appears to be stalled, giving up\n"); break; } diff --git a/engines/rdma.c b/engines/rdma.c index 10e60dc8..8d31ff30 100644 --- a/engines/rdma.c +++ b/engines/rdma.c @@ -802,7 +802,7 @@ static void fio_rdmaio_queued(struct thread_data *td, struct io_u **io_us, unsigned int nr) { struct rdmaio_data *rd = td->io_ops_data; - struct timeval now; + struct timespec now; unsigned int i; if (!fio_fill_issue_time(td)) diff --git a/eta.c b/eta.c index adf7f94c..baaa6815 100644 --- a/eta.c +++ b/eta.c @@ -358,12 +358,12 @@ bool calc_thread_status(struct jobs_eta *je, int force) uint64_t rate_time, disp_time, bw_avg_time, *eta_secs; unsigned long long io_bytes[DDIR_RWDIR_CNT]; unsigned long long io_iops[DDIR_RWDIR_CNT]; - struct timeval now; + struct timespec now; static unsigned long long rate_io_bytes[DDIR_RWDIR_CNT]; static unsigned long long disp_io_bytes[DDIR_RWDIR_CNT]; static unsigned long long disp_io_iops[DDIR_RWDIR_CNT]; - static struct timeval rate_prev_time, disp_prev_time; + static struct timespec rate_prev_time, disp_prev_time; if (!force) { if (!(output_format & FIO_OUTPUT_NORMAL) && @@ -511,7 +511,7 @@ bool calc_thread_status(struct jobs_eta *je, int force) void display_thread_status(struct jobs_eta *je) { - static struct timeval disp_eta_new_line; + static struct timespec disp_eta_new_line; static int eta_new_line_init, eta_new_line_pending; static int linelen_last; static int eta_good; diff --git a/fio.h b/fio.h index 6c06a0cd..d5d6bfe4 100644 --- a/fio.h +++ b/fio.h @@ -165,10 +165,10 @@ struct thread_data { struct thread_data *parent; uint64_t stat_io_bytes[DDIR_RWDIR_CNT]; - struct timeval bw_sample_time; + struct timespec bw_sample_time; uint64_t stat_io_blocks[DDIR_RWDIR_CNT]; - struct timeval iops_sample_time; + struct timespec iops_sample_time; volatile int update_rusage; struct fio_mutex *rusage_sem; @@ -287,7 +287,7 @@ struct thread_data { unsigned long rate_bytes[DDIR_RWDIR_CNT]; unsigned long rate_blocks[DDIR_RWDIR_CNT]; unsigned long long rate_io_issue_bytes[DDIR_RWDIR_CNT]; - struct timeval lastrate[DDIR_RWDIR_CNT]; + struct timespec lastrate[DDIR_RWDIR_CNT]; int64_t last_usec[DDIR_RWDIR_CNT]; struct frand_state poisson_state[DDIR_RWDIR_CNT]; @@ -323,21 +323,21 @@ struct thread_data { */ struct frand_state random_state; - struct timeval start; /* start of this loop */ - struct timeval epoch; /* time job was started */ + struct timespec start; /* start of this loop */ + struct timespec epoch; /* time job was started */ unsigned long long unix_epoch; /* Time job was started, unix epoch based. */ - struct timeval last_issue; + struct timespec last_issue; long time_offset; - struct timeval tv_cache; - struct timeval terminate_time; - unsigned int tv_cache_nr; - unsigned int tv_cache_mask; + struct timespec ts_cache; + struct timespec terminate_time; + unsigned int ts_cache_nr; + unsigned int ts_cache_mask; unsigned int ramp_time_over; /* * Time since last latency_window was started */ - struct timeval latency_ts; + struct timespec latency_ts; unsigned int latency_qd; unsigned int latency_qd_high; unsigned int latency_qd_low; @@ -642,7 +642,7 @@ extern void reset_all_stats(struct thread_data *); extern int io_queue_event(struct thread_data *td, struct io_u *io_u, int *ret, enum fio_ddir ddir, uint64_t *bytes_issued, int from_verify, - struct timeval *comp_time); + struct timespec *comp_time); /* * Latency target helpers diff --git a/fio_time.h b/fio_time.h index b49cc828..3a5848e7 100644 --- a/fio_time.h +++ b/fio_time.h @@ -4,22 +4,23 @@ #include "lib/types.h" struct thread_data; -extern uint64_t utime_since(const struct timeval *,const struct timeval *); -extern uint64_t utime_since_now(const struct timeval *); -extern uint64_t mtime_since(const struct timeval *, const struct timeval *); -extern uint64_t mtime_since_now(const struct timeval *); -extern uint64_t time_since_now(const struct timeval *); +extern uint64_t utime_since(const struct timespec *,const struct timespec *); +extern uint64_t utime_since_now(const struct timespec *); +extern uint64_t mtime_since(const struct timespec *, const struct timespec *); +extern uint64_t mtime_since_now(const struct timespec *); +extern uint64_t mtime_since_tv(const struct timeval *, const struct timeval *); +extern uint64_t time_since_now(const struct timespec *); extern uint64_t time_since_genesis(void); extern uint64_t mtime_since_genesis(void); extern uint64_t utime_since_genesis(void); extern uint64_t usec_spin(unsigned int); extern uint64_t usec_sleep(struct thread_data *, unsigned long); -extern void fill_start_time(struct timeval *); +extern void fill_start_time(struct timespec *); extern void set_genesis_time(void); extern bool ramp_time_over(struct thread_data *); extern bool in_ramp_time(struct thread_data *); extern void fio_time_init(void); -extern void timeval_add_msec(struct timeval *, unsigned int); +extern void timespec_add_msec(struct timespec *, unsigned int); extern void set_epoch_time(struct thread_data *, int); #endif diff --git a/gettime-thread.c b/gettime-thread.c index 19541b47..cbb81dc8 100644 --- a/gettime-thread.c +++ b/gettime-thread.c @@ -6,30 +6,30 @@ #include "fio.h" #include "smalloc.h" -struct timeval *fio_tv = NULL; +struct timespec *fio_ts = NULL; int fio_gtod_offload = 0; static pthread_t gtod_thread; static os_cpu_mask_t fio_gtod_cpumask; void fio_gtod_init(void) { - if (fio_tv) + if (fio_ts) return; - fio_tv = smalloc(sizeof(struct timeval)); - if (!fio_tv) + fio_ts = smalloc(sizeof(*fio_ts)); + if (!fio_ts) log_err("fio: smalloc pool exhausted\n"); } static void fio_gtod_update(void) { - if (fio_tv) { + if (fio_ts) { struct timeval __tv; gettimeofday(&__tv, NULL); - fio_tv->tv_sec = __tv.tv_sec; + fio_ts->tv_sec = __tv.tv_sec; write_barrier(); - fio_tv->tv_usec = __tv.tv_usec; + fio_ts->tv_nsec = __tv.tv_usec * 1000; write_barrier(); } } diff --git a/gettime.c b/gettime.c index 628aad64..a4ee20df 100644 --- a/gettime.c +++ b/gettime.c @@ -16,8 +16,9 @@ #if defined(ARCH_HAVE_CPU_CLOCK) #ifndef ARCH_CPU_CLOCK_CYCLES_PER_USEC static unsigned long cycles_per_usec; -static unsigned long inv_cycles_per_usec; +static unsigned long inv_cycles_per_nsec; static uint64_t max_cycles_for_mult; +#define NSEC_INV_FACTOR 4096 #endif #ifdef ARCH_CPU_CLOCK_WRAPS static unsigned long long cycles_start, cycles_wrap; @@ -143,31 +144,31 @@ static int fill_clock_gettime(struct timespec *ts) } #endif -static void __fio_gettime(struct timeval *tp) +static void __fio_gettime(struct timespec *tp) { switch (fio_clock_source) { #ifdef CONFIG_GETTIMEOFDAY - case CS_GTOD: - gettimeofday(tp, NULL); + case CS_GTOD: { + struct timeval tv; + gettimeofday(&tv, NULL); + + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000; break; + } #endif #ifdef CONFIG_CLOCK_GETTIME case CS_CGETTIME: { - struct timespec ts; - - if (fill_clock_gettime(&ts) < 0) { + if (fill_clock_gettime(tp) < 0) { log_err("fio: clock_gettime fails\n"); assert(0); } - - tp->tv_sec = ts.tv_sec; - tp->tv_usec = ts.tv_nsec / 1000; break; } #endif #ifdef ARCH_HAVE_CPU_CLOCK case CS_CPUCLOCK: { - uint64_t usecs, t; + uint64_t nsecs, t; struct tv_valid *tv; #ifdef CONFIG_TLS_THREAD @@ -190,15 +191,15 @@ static void __fio_gettime(struct timeval *tp) tv->last_cycles = t; tv->last_tv_valid = 1; #ifdef ARCH_CPU_CLOCK_CYCLES_PER_USEC - usecs = t / ARCH_CPU_CLOCK_CYCLES_PER_USEC; + nsecs = t * 1000 / ARCH_CPU_CLOCK_CYCLES_PER_USEC; #else if (t < max_cycles_for_mult) - usecs = (t * inv_cycles_per_usec) / 16777216UL; + nsecs = (t * inv_cycles_per_nsec) / NSEC_INV_FACTOR; else - usecs = t / cycles_per_usec; + nsecs = (t / NSEC_INV_FACTOR) * inv_cycles_per_nsec; #endif - tp->tv_sec = usecs / 1000000; - tp->tv_usec = usecs % 1000000; + tp->tv_sec = nsecs / 1000000000ULL; + tp->tv_nsec = nsecs % 1000000000ULL; break; } #endif @@ -209,9 +210,9 @@ static void __fio_gettime(struct timeval *tp) } #ifdef FIO_DEBUG_TIME -void fio_gettime(struct timeval *tp, void *caller) +void fio_gettime(struct timespec *tp, void *caller) #else -void fio_gettime(struct timeval *tp, void fio_unused *caller) +void fio_gettime(struct timespec *tp, void fio_unused *caller) #endif { #ifdef FIO_DEBUG_TIME @@ -229,7 +230,7 @@ void fio_gettime(struct timeval *tp, void fio_unused *caller) #if defined(ARCH_HAVE_CPU_CLOCK) && !defined(ARCH_CPU_CLOCK_CYCLES_PER_USEC) static unsigned long get_cycles_per_usec(void) { - struct timeval s, e; + struct timespec s, e; uint64_t c_s, c_e; enum fio_cs old_cs = fio_clock_source; uint64_t elapsed; @@ -310,9 +311,9 @@ static int calibrate_cpu_clock(void) (unsigned long long) maxc, mean, S); cycles_per_usec = avg; - inv_cycles_per_usec = 16777216UL / cycles_per_usec; - max_cycles_for_mult = ~0ULL / inv_cycles_per_usec; - dprint(FD_TIME, "inv_cycles_per_usec=%lu\n", inv_cycles_per_usec); + inv_cycles_per_nsec = NSEC_INV_FACTOR * 1000 / cycles_per_usec; + max_cycles_for_mult = ~0ULL / inv_cycles_per_nsec; + dprint(FD_TIME, "inv_cycles_per_nsec=%lu\n", inv_cycles_per_nsec); #ifdef ARCH_CPU_CLOCK_WRAPS cycles_start = get_cpu_clock(); dprint(FD_TIME, "cycles_start=%llu\n", cycles_start); @@ -379,12 +380,12 @@ void fio_clock_init(void) log_info("fio: clocksource=cpu may not be reliable\n"); } -uint64_t utime_since(const struct timeval *s, const struct timeval *e) +uint64_t utime_since(const struct timespec *s, const struct timespec *e) { int64_t sec, usec; sec = e->tv_sec - s->tv_sec; - usec = e->tv_usec - s->tv_usec; + usec = (e->tv_nsec - s->tv_nsec) / 1000; if (sec > 0 && usec < 0) { sec--; usec += 1000000; @@ -399,9 +400,9 @@ uint64_t utime_since(const struct timeval *s, const struct timeval *e) return usec + (sec * 1000000); } -uint64_t utime_since_now(const struct timeval *s) +uint64_t utime_since_now(const struct timespec *s) { - struct timeval t; + struct timespec t; #ifdef FIO_DEBUG_TIME void *p = __builtin_return_address(0); @@ -413,12 +414,12 @@ uint64_t utime_since_now(const struct timeval *s) return utime_since(s, &t); } -uint64_t mtime_since(const struct timeval *s, const struct timeval *e) +uint64_t mtime_since_tv(const struct timeval *s, const struct timeval *e) { - long sec, usec; + int64_t sec, usec; sec = e->tv_sec - s->tv_sec; - usec = e->tv_usec - s->tv_usec; + usec = (e->tv_usec - s->tv_usec); if (sec > 0 && usec < 0) { sec--; usec += 1000000; @@ -432,9 +433,9 @@ uint64_t mtime_since(const struct timeval *s, const struct timeval *e) return sec + usec; } -uint64_t mtime_since_now(const struct timeval *s) +uint64_t mtime_since_now(const struct timespec *s) { - struct timeval t; + struct timespec t; #ifdef FIO_DEBUG_TIME void *p = __builtin_return_address(0); @@ -446,7 +447,26 @@ uint64_t mtime_since_now(const struct timeval *s) return mtime_since(s, &t); } -uint64_t time_since_now(const struct timeval *s) +uint64_t mtime_since(const struct timespec *s, const struct timespec *e) +{ + int64_t sec, usec; + + sec = e->tv_sec - s->tv_sec; + usec = (e->tv_nsec - s->tv_nsec) / 1000; + if (sec > 0 && usec < 0) { + sec--; + usec += 1000000; + } + + if (sec < 0 || (sec == 0 && usec < 0)) + return 0; + + sec *= 1000; + usec /= 1000; + return sec + usec; +} + +uint64_t time_since_now(const struct timespec *s) { return mtime_since_now(s) / 1000; } diff --git a/gettime.h b/gettime.h index 86d55bd9..11e2a7b9 100644 --- a/gettime.h +++ b/gettime.h @@ -13,27 +13,27 @@ enum fio_cs { CS_INVAL, }; -extern void fio_gettime(struct timeval *, void *); +extern void fio_gettime(struct timespec *, void *); extern void fio_gtod_init(void); extern void fio_clock_init(void); extern int fio_start_gtod_thread(void); extern int fio_monotonic_clocktest(int debug); extern void fio_local_clock_init(int); -extern struct timeval *fio_tv; +extern struct timespec *fio_ts; -static inline int fio_gettime_offload(struct timeval *tv) +static inline int fio_gettime_offload(struct timespec *ts) { time_t last_sec; - if (!fio_tv) + if (!fio_ts) return 0; do { read_barrier(); - last_sec = tv->tv_sec = fio_tv->tv_sec; - tv->tv_usec = fio_tv->tv_usec; - } while (fio_tv->tv_sec != last_sec); + last_sec = ts->tv_sec = fio_ts->tv_sec; + ts->tv_nsec = fio_ts->tv_nsec; + } while (fio_ts->tv_sec != last_sec); return 1; } diff --git a/helper_thread.c b/helper_thread.c index 47ec728c..9c6e0a2b 100644 --- a/helper_thread.c +++ b/helper_thread.c @@ -71,45 +71,45 @@ static void *helper_thread_main(void *data) { struct helper_data *hd = data; unsigned int msec_to_next_event, next_log, next_ss = STEADYSTATE_MSEC; - struct timeval tv, last_du, last_ss; + struct timeval tv; + struct timespec ts, last_du, last_ss; int ret = 0; sk_out_assign(hd->sk_out); gettimeofday(&tv, NULL); - memcpy(&last_du, &tv, sizeof(tv)); - memcpy(&last_ss, &tv, sizeof(tv)); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + memcpy(&last_du, &ts, sizeof(ts)); + memcpy(&last_ss, &ts, sizeof(ts)); fio_mutex_up(hd->startup_mutex); msec_to_next_event = DISK_UTIL_MSEC; while (!ret && !hd->exit) { - struct timespec ts; - struct timeval now; uint64_t since_du, since_ss = 0; - timeval_add_msec(&tv, msec_to_next_event); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; + timespec_add_msec(&ts, msec_to_next_event); pthread_mutex_lock(&hd->lock); pthread_cond_timedwait(&hd->cond, &hd->lock, &ts); - gettimeofday(&now, NULL); + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; if (hd->reset) { - memcpy(&tv, &now, sizeof(tv)); - memcpy(&last_du, &now, sizeof(last_du)); - memcpy(&last_ss, &now, sizeof(last_ss)); + memcpy(&last_du, &ts, sizeof(ts)); + memcpy(&last_ss, &ts, sizeof(ts)); hd->reset = 0; } pthread_mutex_unlock(&hd->lock); - since_du = mtime_since(&last_du, &now); + since_du = mtime_since(&last_du, &ts); if (since_du >= DISK_UTIL_MSEC || DISK_UTIL_MSEC - since_du < 10) { ret = update_io_ticks(); - timeval_add_msec(&last_du, DISK_UTIL_MSEC); + timespec_add_msec(&last_du, DISK_UTIL_MSEC); msec_to_next_event = DISK_UTIL_MSEC; if (since_du >= DISK_UTIL_MSEC) msec_to_next_event -= (since_du - DISK_UTIL_MSEC); @@ -126,10 +126,10 @@ static void *helper_thread_main(void *data) next_log = DISK_UTIL_MSEC; if (steadystate_enabled) { - since_ss = mtime_since(&last_ss, &now); + since_ss = mtime_since(&last_ss, &ts); if (since_ss >= STEADYSTATE_MSEC || STEADYSTATE_MSEC - since_ss < 10) { steadystate_check(); - timeval_add_msec(&last_ss, since_ss); + timespec_add_msec(&last_ss, since_ss); if (since_ss > STEADYSTATE_MSEC) next_ss = STEADYSTATE_MSEC - (since_ss - STEADYSTATE_MSEC); else diff --git a/idletime.c b/idletime.c index 4c00d80d..90bc1d9e 100644 --- a/idletime.c +++ b/idletime.c @@ -11,7 +11,7 @@ static volatile struct idle_prof_common ipc; static double calibrate_unit(unsigned char *data) { unsigned long t, i, j, k; - struct timeval tps; + struct timespec tps; double tunit = 0.0; for (i = 0; i < CALIBRATE_RUNS; i++) { @@ -183,7 +183,6 @@ static void calibration_stats(void) void fio_idle_prof_init(void) { int i, ret; - struct timeval tp; struct timespec ts; pthread_attr_t tattr; struct idle_prof_thread *ipt; @@ -282,9 +281,8 @@ void fio_idle_prof_init(void) pthread_mutex_lock(&ipt->init_lock); while ((ipt->state != TD_EXITED) && (ipt->state!=TD_INITIALIZED)) { - fio_gettime(&tp, NULL); - ts.tv_sec = tp.tv_sec + 1; - ts.tv_nsec = tp.tv_usec * 1000; + fio_gettime(&ts, NULL); + ts.tv_sec += 1; pthread_cond_timedwait(&ipt->cond, &ipt->init_lock, &ts); } pthread_mutex_unlock(&ipt->init_lock); @@ -325,7 +323,6 @@ void fio_idle_prof_stop(void) { int i; uint64_t runt; - struct timeval tp; struct timespec ts; struct idle_prof_thread *ipt; @@ -343,9 +340,8 @@ void fio_idle_prof_stop(void) pthread_mutex_lock(&ipt->start_lock); while ((ipt->state != TD_EXITED) && (ipt->state!=TD_NOT_CREATED)) { - fio_gettime(&tp, NULL); - ts.tv_sec = tp.tv_sec + 1; - ts.tv_nsec = tp.tv_usec * 1000; + fio_gettime(&ts, NULL); + ts.tv_sec += 1; /* timed wait in case a signal is not received */ pthread_cond_timedwait(&ipt->cond, &ipt->start_lock, &ts); } diff --git a/idletime.h b/idletime.h index 84c1fbbe..b8376c2c 100644 --- a/idletime.h +++ b/idletime.h @@ -26,8 +26,8 @@ struct idle_prof_thread { pthread_t thread; int cpu; int state; - struct timeval tps; - struct timeval tpe; + struct timespec tps; + struct timespec tpe; double cali_time; /* microseconds to finish a unit work */ double loops; double idleness; diff --git a/io_u.c b/io_u.c index fd631198..51d6e958 100644 --- a/io_u.c +++ b/io_u.c @@ -20,7 +20,7 @@ struct io_completion_data { int error; /* output */ uint64_t bytes_done[DDIR_RWDIR_CNT]; /* output */ - struct timeval time; /* output */ + struct timespec time; /* output */ }; /* @@ -1572,7 +1572,7 @@ static void small_content_scramble(struct io_u *io_u) * the buffer, given by the product of the usec time * and the actual offset. */ - offset = (io_u->start_time.tv_usec ^ boffset) & 511; + offset = ((io_u->start_time.tv_nsec/1000) ^ boffset) & 511; offset &= ~(sizeof(uint64_t) - 1); if (offset >= 512 - sizeof(uint64_t)) offset -= sizeof(uint64_t); diff --git a/io_u.h b/io_u.h index 155344d4..b228e2e8 100644 --- a/io_u.h +++ b/io_u.h @@ -31,8 +31,8 @@ enum { * The io unit */ struct io_u { - struct timeval start_time; - struct timeval issue_time; + struct timespec start_time; + struct timespec issue_time; struct fio_file *file; unsigned int flags; diff --git a/ioengines.c b/ioengines.c index 2d55065b..abbaa9a7 100644 --- a/ioengines.c +++ b/ioengines.c @@ -281,7 +281,7 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u) */ if (td->o.read_iolog_file) memcpy(&td->last_issue, &io_u->issue_time, - sizeof(struct timeval)); + sizeof(io_u->issue_time)); } if (ddir_rw(ddir)) { @@ -356,7 +356,7 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u) */ if (td->o.read_iolog_file) memcpy(&td->last_issue, &io_u->issue_time, - sizeof(struct timeval)); + sizeof(io_u->issue_time)); } return ret; diff --git a/iolog.c b/iolog.c index 01b82e8d..45a95aa4 100644 --- a/iolog.c +++ b/iolog.c @@ -65,7 +65,7 @@ static void iolog_delay(struct thread_data *td, unsigned long delay) { uint64_t usec = utime_since_now(&td->last_issue); uint64_t this_delay; - struct timeval tv; + struct timespec ts; if (delay < td->time_offset) { td->time_offset = 0; @@ -78,7 +78,7 @@ static void iolog_delay(struct thread_data *td, unsigned long delay) delay -= usec; - fio_gettime(&tv, NULL); + fio_gettime(&ts, NULL); while (delay && !td->terminate) { this_delay = delay; if (this_delay > 500000) @@ -88,7 +88,7 @@ static void iolog_delay(struct thread_data *td, unsigned long delay) delay -= this_delay; } - usec = utime_since_now(&tv); + usec = utime_since_now(&ts); if (usec > delay) td->time_offset = usec - delay; else diff --git a/libfio.c b/libfio.c index da22456e..14ddc4d0 100644 --- a/libfio.c +++ b/libfio.c @@ -144,10 +144,10 @@ void reset_all_stats(struct thread_data *td) } set_epoch_time(td, td->o.log_unix_epoch); - memcpy(&td->start, &td->epoch, sizeof(struct timeval)); - memcpy(&td->iops_sample_time, &td->epoch, sizeof(struct timeval)); - memcpy(&td->bw_sample_time, &td->epoch, sizeof(struct timeval)); - memcpy(&td->ss.prev_time, &td->epoch, sizeof(struct timeval)); + memcpy(&td->start, &td->epoch, sizeof(td->epoch)); + memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch)); + memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch)); + memcpy(&td->ss.prev_time, &td->epoch, sizeof(td->epoch)); lat_target_reset(td); clear_rusage_stat(td); diff --git a/mutex.c b/mutex.c index d8c48251..9fab715b 100644 --- a/mutex.c +++ b/mutex.c @@ -141,11 +141,15 @@ struct fio_mutex *fio_mutex_init(int value) return NULL; } -static bool mutex_timed_out(struct timeval *t, unsigned int msecs) +static bool mutex_timed_out(struct timespec *t, unsigned int msecs) { - struct timeval now; + struct timeval tv; + struct timespec now; + + gettimeofday(&tv, NULL); + now.tv_sec = tv.tv_sec; + now.tv_nsec = tv.tv_usec * 1000; - gettimeofday(&now, NULL); return mtime_since(t, &now) >= msecs; } @@ -177,7 +181,7 @@ int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int msecs) * way too early, double check. */ ret = pthread_cond_timedwait(&mutex->cond, &mutex->lock, &t); - if (ret == ETIMEDOUT && !mutex_timed_out(&tv_s, msecs)) + if (ret == ETIMEDOUT && !mutex_timed_out(&t, msecs)) ret = 0; } mutex->waiters--; diff --git a/options.c b/options.c index a8fdde44..7431ed8c 100644 --- a/options.c +++ b/options.c @@ -1381,7 +1381,7 @@ static int str_gtod_reduce_cb(void *data, int *il) td->o.disable_bw = !!val; td->o.clat_percentiles = !val; if (val) - td->tv_cache_mask = 63; + td->ts_cache_mask = 63; return 0; } diff --git a/os/windows/posix.c b/os/windows/posix.c index eae8c861..488d0ed2 100755 --- a/os/windows/posix.c +++ b/os/windows/posix.c @@ -25,8 +25,8 @@ #include "../os-windows.h" #include "../../lib/hweight.h" -extern unsigned long mtime_since_now(struct timeval *); -extern void fio_gettime(struct timeval *, void *); +extern unsigned long mtime_since_now(struct timespec *); +extern void fio_gettime(struct timespec *, void *); /* These aren't defined in the MinGW headers */ HRESULT WINAPI StringCchCopyA( @@ -852,7 +852,7 @@ int poll(struct pollfd fds[], nfds_t nfds, int timeout) int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { - struct timeval tv; + struct timespec tv; DWORD ms_remaining; DWORD ms_total = (rqtp->tv_sec * 1000) + (rqtp->tv_nsec / 1000000.0); diff --git a/profiles/act.c b/profiles/act.c index 643f8a87..59e50052 100644 --- a/profiles/act.c +++ b/profiles/act.c @@ -47,7 +47,7 @@ struct act_run_data { static struct act_run_data *act_run_data; struct act_prof_data { - struct timeval sample_tv; + struct timespec sample_tv; struct act_slice *slices; unsigned int cur_slice; unsigned int nr_slices; diff --git a/server.c b/server.c index 8a5e75d3..017ab130 100644 --- a/server.c +++ b/server.c @@ -438,7 +438,7 @@ static uint64_t alloc_reply(uint64_t tag, uint16_t opcode) reply = calloc(1, sizeof(*reply)); INIT_FLIST_HEAD(&reply->list); - fio_gettime(&reply->tv, NULL); + fio_gettime(&reply->ts, NULL); reply->saved_tag = tag; reply->opcode = opcode; diff --git a/server.h b/server.h index f002f3bd..0b31df75 100644 --- a/server.h +++ b/server.h @@ -43,7 +43,7 @@ struct fio_net_cmd { struct fio_net_cmd_reply { struct flist_head list; - struct timeval tv; + struct timespec ts; uint64_t saved_tag; uint16_t opcode; }; diff --git a/stat.c b/stat.c index fd3ad5aa..6ffcad93 100644 --- a/stat.c +++ b/stat.c @@ -37,9 +37,9 @@ void update_rusage_stat(struct thread_data *td) struct thread_stat *ts = &td->ts; fio_getrusage(&td->ru_end); - ts->usr_time += mtime_since(&td->ru_start.ru_utime, + ts->usr_time += mtime_since_tv(&td->ru_start.ru_utime, &td->ru_end.ru_utime); - ts->sys_time += mtime_since(&td->ru_start.ru_stime, + ts->sys_time += mtime_since_tv(&td->ru_start.ru_stime, &td->ru_end.ru_stime); ts->ctx += td->ru_end.ru_nvcsw + td->ru_end.ru_nivcsw - (td->ru_start.ru_nvcsw + td->ru_start.ru_nivcsw); @@ -1849,22 +1849,22 @@ void __show_running_run_stats(void) { struct thread_data *td; unsigned long long *rt; - struct timeval tv; + struct timespec ts; int i; fio_mutex_down(stat_mutex); rt = malloc(thread_number * sizeof(unsigned long long)); - fio_gettime(&tv, NULL); + fio_gettime(&ts, NULL); for_each_td(td, i) { td->update_rusage = 1; td->ts.io_bytes[DDIR_READ] = td->io_bytes[DDIR_READ]; td->ts.io_bytes[DDIR_WRITE] = td->io_bytes[DDIR_WRITE]; td->ts.io_bytes[DDIR_TRIM] = td->io_bytes[DDIR_TRIM]; - td->ts.total_run_time = mtime_since(&td->epoch, &tv); + td->ts.total_run_time = mtime_since(&td->epoch, &ts); - rt[i] = mtime_since(&td->start, &tv); + rt[i] = mtime_since(&td->start, &ts); if (td_read(td) && td->ts.io_bytes[DDIR_READ]) td->ts.runtime[DDIR_READ] += rt[i]; if (td_write(td) && td->ts.io_bytes[DDIR_WRITE]) @@ -1899,7 +1899,7 @@ void __show_running_run_stats(void) } static int status_interval_init; -static struct timeval status_time; +static struct timespec status_time; static int status_file_disabled; #define FIO_STATUS_FILE "fio-dump-status" @@ -2430,8 +2430,8 @@ void add_bw_sample(struct thread_data *td, struct io_u *io_u, td_io_u_unlock(td); } -static int __add_samples(struct thread_data *td, struct timeval *parent_tv, - struct timeval *t, unsigned int avg_time, +static int __add_samples(struct thread_data *td, struct timespec *parent_tv, + struct timespec *t, unsigned int avg_time, uint64_t *this_io_bytes, uint64_t *stat_io_bytes, struct io_stat *stat, struct io_log *log, bool is_kb) @@ -2481,7 +2481,7 @@ static int __add_samples(struct thread_data *td, struct timeval *parent_tv, stat_io_bytes[ddir] = this_io_bytes[ddir]; } - timeval_add_msec(parent_tv, avg_time); + timespec_add_msec(parent_tv, avg_time); td_io_u_unlock(td); @@ -2493,7 +2493,7 @@ static int __add_samples(struct thread_data *td, struct timeval *parent_tv, return min(next, next_log); } -static int add_bw_samples(struct thread_data *td, struct timeval *t) +static int add_bw_samples(struct thread_data *td, struct timespec *t) { return __add_samples(td, &td->bw_sample_time, t, td->o.bw_avg_time, td->this_io_bytes, td->stat_io_bytes, @@ -2517,7 +2517,7 @@ void add_iops_sample(struct thread_data *td, struct io_u *io_u, td_io_u_unlock(td); } -static int add_iops_samples(struct thread_data *td, struct timeval *t) +static int add_iops_samples(struct thread_data *td, struct timespec *t) { return __add_samples(td, &td->iops_sample_time, t, td->o.iops_avg_time, td->this_io_blocks, td->stat_io_blocks, @@ -2531,7 +2531,7 @@ int calc_log_samples(void) { struct thread_data *td; unsigned int next = ~0U, tmp; - struct timeval now; + struct timespec now; int i; fio_gettime(&now, NULL); diff --git a/steadystate.c b/steadystate.c index 98f027ce..45d4f5d2 100644 --- a/steadystate.c +++ b/steadystate.c @@ -196,7 +196,7 @@ void steadystate_check(void) int i, j, ddir, prev_groupid, group_ramp_time_over = 0; unsigned long rate_time; struct thread_data *td, *td2; - struct timeval now; + struct timespec now; uint64_t group_bw = 0, group_iops = 0; uint64_t td_iops, td_bytes; bool ret; diff --git a/steadystate.h b/steadystate.h index 20ccd303..bbc3945c 100644 --- a/steadystate.h +++ b/steadystate.h @@ -35,7 +35,7 @@ struct steadystate_data { uint64_t sum_xy; uint64_t oldest_y; - struct timeval prev_time; + struct timespec prev_time; uint64_t prev_iops; uint64_t prev_bytes; }; diff --git a/t/debug.c b/t/debug.c index bf6f4605..8965cfbc 100644 --- a/t/debug.c +++ b/t/debug.c @@ -1,7 +1,7 @@ #include FILE *f_err; -struct timeval *fio_tv = NULL; +struct timespec *fio_ts = NULL; unsigned long fio_debug = 0; void __dprint(int type, const char *str, ...) diff --git a/t/dedupe.c b/t/dedupe.c index 1f172a26..c3b837f7 100644 --- a/t/dedupe.c +++ b/t/dedupe.c @@ -334,7 +334,7 @@ static void *thread_fn(void *data) static void show_progress(struct worker_thread *threads, unsigned long total) { unsigned long last_nitems = 0; - struct timeval last_tv; + struct timespec last_tv; fio_gettime(&last_tv, NULL); diff --git a/t/lfsr-test.c b/t/lfsr-test.c index 7016f268..4009b62e 100644 --- a/t/lfsr-test.c +++ b/t/lfsr-test.c @@ -27,7 +27,7 @@ void usage() int main(int argc, char *argv[]) { int r; - struct timeval start, end; + struct timespec start, end; struct fio_lfsr *fl; int verify = 0; unsigned int spin = 0; diff --git a/time.c b/time.c index 279ee484..edfe779b 100644 --- a/time.c +++ b/time.c @@ -3,23 +3,23 @@ #include "fio.h" -static struct timeval genesis; +static struct timespec genesis; static unsigned long ns_granularity; -void timeval_add_msec(struct timeval *tv, unsigned int msec) +void timespec_add_msec(struct timespec *ts, unsigned int msec) { - unsigned long adj_usec = 1000 * msec; + unsigned long adj_nsec = 1000000 * msec; - tv->tv_usec += adj_usec; - if (adj_usec >= 1000000) { - unsigned long adj_sec = adj_usec / 1000000; + ts->tv_nsec += adj_nsec; + if (adj_nsec >= 1000000000) { + unsigned long adj_sec = adj_nsec / 1000000000UL; - tv->tv_usec -= adj_sec * 1000000; - tv->tv_sec += adj_sec; + ts->tv_nsec -= adj_sec * 1000000000UL; + ts->tv_sec += adj_sec; } - if (tv->tv_usec >= 1000000){ - tv->tv_usec -= 1000000; - tv->tv_sec++; + if (ts->tv_nsec >= 1000000000UL){ + ts->tv_nsec -= 1000000000UL; + ts->tv_sec++; } } @@ -28,7 +28,7 @@ void timeval_add_msec(struct timeval *tv, unsigned int msec) */ uint64_t usec_spin(unsigned int usec) { - struct timeval start; + struct timespec start; uint64_t t; fio_gettime(&start, NULL); @@ -41,7 +41,7 @@ uint64_t usec_spin(unsigned int usec) uint64_t usec_sleep(struct thread_data *td, unsigned long usec) { struct timespec req; - struct timeval tv; + struct timespec tv; uint64_t t = 0; do { @@ -111,13 +111,10 @@ static void parent_update_ramp(struct thread_data *td) bool ramp_time_over(struct thread_data *td) { - struct timeval tv; - if (!td->o.ramp_time || td->ramp_time_over) return true; - fio_gettime(&tv, NULL); - if (utime_since(&td->epoch, &tv) >= td->o.ramp_time) { + if (utime_since_now(&td->epoch) >= td->o.ramp_time) { td->ramp_time_over = 1; reset_all_stats(td); td_set_runstate(td, TD_RAMP); @@ -138,8 +135,7 @@ void fio_time_init(void) * Check the granularity of the nanosleep function */ for (i = 0; i < 10; i++) { - struct timeval tv; - struct timespec ts; + struct timespec tv, ts; unsigned long elapsed; fio_gettime(&tv, NULL); @@ -170,7 +166,7 @@ void set_epoch_time(struct thread_data *td, int log_unix_epoch) } } -void fill_start_time(struct timeval *t) +void fill_start_time(struct timespec *t) { memcpy(t, &genesis, sizeof(genesis)); } diff --git a/verify.c b/verify.c index 1c39fa2e..ffd8707f 100644 --- a/verify.c +++ b/verify.c @@ -1167,7 +1167,7 @@ static void __fill_hdr(struct thread_data *td, struct io_u *io_u, hdr->rand_seed = rand_seed; hdr->offset = io_u->offset + header_num * td->o.verify_interval; hdr->time_sec = io_u->start_time.tv_sec; - hdr->time_usec = io_u->start_time.tv_usec; + hdr->time_usec = io_u->start_time.tv_nsec / 1000; hdr->thread = td->thread_number; hdr->numberio = io_u->numberio; hdr->crc32 = fio_crc32c(p, offsetof(struct verify_header, crc32)); -- 2.25.1