use monotonic time source in convar->timed_wait, and in the scheduler using it
authorMartin Willi <martin@strongswan.org>
Mon, 31 Aug 2009 13:13:48 +0000 (15:13 +0200)
committerMartin Willi <martin@strongswan.org>
Mon, 31 Aug 2009 13:13:48 +0000 (15:13 +0200)
configure.in
src/charon/processing/scheduler.c
src/charon/processing/scheduler.h
src/libstrongswan/utils.c
src/libstrongswan/utils/mutex.c
src/libstrongswan/utils/mutex.h

index 7caa8c1..903d742 100644 (file)
@@ -927,6 +927,20 @@ AC_TRY_COMPILE(
        [AC_MSG_RESULT([no])]
 )
 
+dnl check if pthread_condattr_setclock(CLOCK_MONOTONE) is supported
+saved_LIBS=$LIBS
+LIBS="-lpthread"
+AC_MSG_CHECKING([for pthread_condattr_setclock(CLOCK_MONOTONE)])
+AC_TRY_RUN(
+       [#include <pthread.h>
+        int main() { pthread_condattr_t attr;
+               pthread_condattr_init(&attr);
+               return pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);}],
+       [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_CONDATTR_CLOCK_MONOTONIC])],
+       [AC_MSG_RESULT([no])]
+)
+LIBS=$saved_LIBS
+
 AC_CHECK_FUNCS(prctl)
 
 AC_CHECK_HEADERS(sys/sockio.h)
index 1f59205..f53ccb9 100644 (file)
@@ -190,7 +190,7 @@ static job_requeue_t schedule(private_scheduler_t * this)
        
        this->mutex->lock(this->mutex);
        
-       gettimeofday(&now, NULL);
+       time_monotonic(&now);
        
        if ((event = peek_event(this)) != NULL)
        {
@@ -290,7 +290,7 @@ static void schedule_job(private_scheduler_t *this, job_t *job, u_int32_t s)
 {
        timeval_t tv;
        
-       gettimeofday(&tv, NULL);
+       time_monotonic(&tv);
        tv.tv_sec += s;
        
        schedule_job_tv(this, job, tv);
@@ -303,7 +303,7 @@ static void schedule_job_ms(private_scheduler_t *this, job_t *job, u_int32_t ms)
 {
        timeval_t tv, add;
        
-       gettimeofday(&tv, NULL);
+       time_monotonic(&tv);
        add.tv_sec = ms / 1000;
        add.tv_usec = (ms % 1000) * 1000;
        
index 502f70b..927b561 100644 (file)
@@ -101,6 +101,9 @@ struct scheduler_t {
        /**
         * Adds a event to the queue, using an absolut time.
         *
+        * The passed timeval should be calculated based on the time_monotonic()
+        * function.
+        *
         * @param job                   job to schedule
         * @param time                  absolut time to schedule job
         */
index 91242da..2d5ff3d 100644 (file)
@@ -167,7 +167,9 @@ bool mkdir_p(const char *path, mode_t mode)
  */
 time_t time_monotonic(timeval_t *tv)
 {
-#if defined(HAVE_CLOCK_GETTIME)
+#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CONDATTR_CLOCK_MONOTONIC)
+       /* as we use time_monotonic() for condvar operations, we use the
+        * monotonic time source only if it is also supported by pthread. */
        timespec_t ts;
        
        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
@@ -179,11 +181,12 @@ time_t time_monotonic(timeval_t *tv)
                }
                return ts.tv_sec;
        }
-#endif /* HAVE_CLOCK_MONOTONIC */
+#endif /* HAVE_CLOCK_MONOTONIC && HAVE_CONDATTR_CLOCK_MONOTONIC */
        /* Fallback to non-monotonic timestamps:
         * On MAC OS X, creating monotonic timestamps is rather difficult. We
         * could use mach_absolute_time() and catch sleep/wakeup notifications.
-        * We stick to the simpler (non-monotonic) gettimeofday() for now. */
+        * We stick to the simpler (non-monotonic) gettimeofday() for now.
+        * But keep in mind: we need the same time source here as in condvar! */
        if (!tv)
        {
                return time(NULL);
index a6c39e9..fef2570 100644 (file)
@@ -47,7 +47,7 @@ struct lock_profile_t {
        /**
         * how long threads have waited for the lock in this mutex so far
         */
-       struct timeval waited;
+       timeval_t waited;
        
        /**
         * backtrace where mutex has been created
@@ -81,10 +81,10 @@ static void profiler_init(lock_profile_t *profile)
 
 #define profiler_start(profile) { \
        struct timeval _start, _end, _diff; \
-       gettimeofday(&_start, NULL);
+       time_monotonic(&_start);
        
 #define profiler_end(profile) \
-       gettimeofday(&_end, NULL); \
+       time_monotonic(&_end); \
        timersub(&_end, &_start, &_diff); \
        timeradd(&(profile)->waited, &_diff, &(profile)->waited); }
 
@@ -368,7 +368,7 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex,
        timeval_t tv;
        u_int s, ms;
        
-       gettimeofday(&tv, NULL);
+       time_monotonic(&tv);
        
        s = timeout / 1000;
        ms = timeout % 1000;
@@ -419,17 +419,23 @@ condvar_t *condvar_create(condvar_type_t type)
                case CONDVAR_TYPE_DEFAULT:
                default:
                {
+                       pthread_condattr_t condattr;
                        private_condvar_t *this = malloc_thing(private_condvar_t);
-               
+                       
                        this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))_wait;
                        this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait;
                        this->public.timed_wait_abs = (bool(*)(condvar_t*, mutex_t *mutex, timeval_t time))timed_wait_abs;
                        this->public.signal = (void(*)(condvar_t*))_signal;
                        this->public.broadcast = (void(*)(condvar_t*))broadcast;
                        this->public.destroy = (void(*)(condvar_t*))condvar_destroy;
-               
-                       pthread_cond_init(&this->condvar, NULL);
-               
+                       
+                       pthread_condattr_init(&condattr);
+#ifdef HAVE_CONDATTR_CLOCK_MONOTONIC
+                       pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
+#endif
+                       pthread_cond_init(&this->condvar, &condattr);
+                       pthread_condattr_destroy(&condattr);
+                       
                        return &this->public;
                }
        }
index 273f56b..39763f9 100644 (file)
@@ -98,11 +98,11 @@ struct mutex_t {
         * Release the lock on the mutex.
         */
        void (*unlock)(mutex_t *this);
-                       
+       
        /**
-     * Destroy a mutex instance.
-     */
-    void (*destroy)(mutex_t *this);
+        * Destroy a mutex instance.
+        */
+       void (*destroy)(mutex_t *this);
 };
 
 /**
@@ -128,12 +128,15 @@ struct condvar_t {
        
        /**
         * Wait on a condvar until it gets signalized, or times out.
-        * 
+        *
+        * The passed timeval should be calculated based on the time_monotonic()
+        * function.
+        *
         * @param mutex                 mutex to release while waiting
-        * @param time                  absolute time until timeout
+        * @param tv                    absolute time until timeout
         * @return                              TRUE if timed out, FALSE otherwise
         */
-       bool (*timed_wait_abs)(condvar_t *this, mutex_t *mutex, timeval_t timeout);
+       bool (*timed_wait_abs)(condvar_t *this, mutex_t *mutex, timeval_t tv);
        
        /**
         * Wake up a single thread in a condvar.