mutex: down_timeout: check against the base time
authorYasushi SHOJI <yasushi.shoji@gmail.com>
Thu, 28 Dec 2017 01:53:47 +0000 (10:53 +0900)
committerYasushi SHOJI <yasushi.shoji@gmail.com>
Thu, 28 Dec 2017 01:53:47 +0000 (10:53 +0900)
When the commit 8b6a404cdd2c40715885e562416c3db039912773 changed
timeval to timespec, it accsidentally picked timeout time `t' instead
of the current `base' time for checking timewait() really timed out.

t is base + msecs as follows:

      base = gettimeofday()
      t = base + msecs
      pthread_cond_timedwait()
      while (!done)
         if (timedout)
    if (mutex_timed_out(t, msecs))
       done = true

Thus, after a good timedout, it burns the cpu for the given msecs
seconds doing tight loop in the while shown above.  This causes 30 to
40 % CPU load on my i5-3360M 2.80GHz while fio server is running.

mutex.c

diff --git a/mutex.c b/mutex.c
index 9fab715bd7429e87b2690000d49a69bbaea3785a..63229eda09d62084f2b3e7a4cb076fcdf2e0dc88 100644 (file)
--- a/mutex.c
+++ b/mutex.c
@@ -156,14 +156,15 @@ static bool mutex_timed_out(struct timespec *t, unsigned int msecs)
 int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int msecs)
 {
        struct timeval tv_s;
+       struct timespec base;
        struct timespec t;
        int ret = 0;
 
        assert(mutex->magic == FIO_MUTEX_MAGIC);
 
        gettimeofday(&tv_s, NULL);
-       t.tv_sec = tv_s.tv_sec;
-       t.tv_nsec = tv_s.tv_usec * 1000;
+       base.tv_sec = t.tv_sec = tv_s.tv_sec;
+       base.tv_nsec = t.tv_nsec = tv_s.tv_usec * 1000;
 
        t.tv_sec += msecs / 1000;
        t.tv_nsec += ((msecs * 1000000ULL) % 1000000000);
@@ -181,7 +182,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(&t, msecs))
+               if (ret == ETIMEDOUT && !mutex_timed_out(&base, msecs))
                        ret = 0;
        }
        mutex->waiters--;