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>
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, ENODATA);
#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)
{
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;
+ 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)
- 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;
} while (!td->terminate);
}
} while (!td->terminate);
}
static void fio_init time_init(void)
{
static void fio_init time_init(void)
{
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)