[PATCH] Improve rate functionality
authorJens Axboe <jens.axboe@oracle.com>
Sat, 13 Jan 2007 11:20:30 +0000 (12:20 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Sat, 13 Jan 2007 11:20:30 +0000 (12:20 +0100)
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 <jens.axboe@oracle.com>
fio.c
time.c

diff --git a/fio.c b/fio.c
index 84819d9f51e996b2a25c35f1da29a62772b99e8b..225aaa4d4550c2ea385f8eaaee70b9b8d1bc321d 100644 (file)
--- 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);
                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;
                }
 
                        break;
                }
 
diff --git a/time.c b/time.c
index d0ecbe5c831af59f857164af9fa433d96eaceda0..08ef078277ba125d43d1ce956db2ea92091e0793 100644 (file)
--- a/time.c
+++ b/time.c
@@ -4,6 +4,7 @@
 #include "fio.h"
 
 static struct timeval genesis;
 #include "fio.h"
 
 static struct timeval genesis;
+static unsigned long ns_granularity;
 
 unsigned long utime_since(struct timeval *s, struct timeval *e)
 {
 
 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)
 {
 
 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 {
 
        do {
-               if (usec < 5000) {
+               unsigned long ts = usec;
+
+               if (usec < ns_granularity) {
                        __usec_sleep(usec);
                        break;
                }
 
                        __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;
 
                        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);
 }
 
        } while (!td->terminate);
 }
 
@@ -131,7 +140,28 @@ unsigned long mtime_since_genesis(void)
 
 static void fio_init time_init(void)
 {
 
 static void fio_init time_init(void)
 {
+       int i;
+
        fio_gettime(&genesis, NULL);
        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)
 }
 
 void fill_start_time(struct timeval *t)