From fd841467ce4a5875dba2d21da6851936b46fdb08 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 13 Jan 2007 12:20:30 +0100 Subject: [PATCH] [PATCH] Improve rate functionality usec_sleep() now takes into account the granularity of nanosleep(). Also stop using the remainder returned by nanosleep(), it doesn't appear to always be accurate. Instead just check the elapsed time manually. Signed-off-by: Jens Axboe --- fio.c | 2 +- time.c | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/fio.c b/fio.c index 84819d9f..225aaa4d 100644 --- a/fio.c +++ b/fio.c @@ -449,7 +449,7 @@ static void do_io(struct thread_data *td) if (check_min_rate(td, &icd.time)) { if (exitall_on_terminate) terminate_threads(td->groupid, 0); - td_verror(td, ENOMEM); + td_verror(td, ENODATA); break; } diff --git a/time.c b/time.c index d0ecbe5c..08ef0782 100644 --- a/time.c +++ b/time.c @@ -4,6 +4,7 @@ #include "fio.h" static struct timeval genesis; +static unsigned long ns_granularity; unsigned long utime_since(struct timeval *s, struct timeval *e) { @@ -74,28 +75,36 @@ void __usec_sleep(unsigned int usec) void usec_sleep(struct thread_data *td, unsigned long usec) { - struct timespec req, rem; - - req.tv_sec = usec / 1000000; - req.tv_nsec = usec * 1000 - req.tv_sec * 1000000; + struct timespec req; + struct timeval tv; do { - if (usec < 5000) { + unsigned long ts = usec; + + if (usec < ns_granularity) { __usec_sleep(usec); break; } - rem.tv_sec = rem.tv_nsec = 0; - if (nanosleep(&req, &rem) < 0) - break; + ts = usec - ns_granularity; - if ((rem.tv_sec + rem.tv_nsec) == 0) + if (ts >= 1000000) { + req.tv_sec = ts / 1000000; + ts -= 1000000 * req.tv_sec; + } else + req.tv_sec = 0; + + req.tv_nsec = ts * 1000; + fio_gettime(&tv, NULL); + + if (nanosleep(&req, NULL) < 0) break; - req.tv_nsec = rem.tv_nsec; - req.tv_sec = rem.tv_sec; + ts = utime_since_now(&tv); + if (ts >= usec) + break; - usec = rem.tv_sec * 1000000 + rem.tv_nsec / 1000; + usec -= ts; } while (!td->terminate); } @@ -131,7 +140,28 @@ unsigned long mtime_since_genesis(void) static void fio_init time_init(void) { + int i; + fio_gettime(&genesis, NULL); + + /* + * Check the granularity of the nanosleep function + */ + for (i = 0; i < 10; i++) { + struct timeval tv; + struct timespec ts; + unsigned long elapsed; + + fio_gettime(&tv, NULL); + ts.tv_sec = 0; + ts.tv_nsec = 1000; + + nanosleep(&ts, NULL); + elapsed = utime_since_now(&tv); + + if (elapsed > ns_granularity) + ns_granularity = elapsed; + } } void fill_start_time(struct timeval *t) -- 2.25.1