]> granicus.if.org Git - libevent/commitdiff
Have event_base_gettimeofday_cached() always return wall-clock time
authorNick Mathewson <nickm@torproject.org>
Thu, 3 Mar 2011 20:34:22 +0000 (15:34 -0500)
committerNick Mathewson <nickm@torproject.org>
Thu, 3 Mar 2011 20:48:26 +0000 (15:48 -0500)
Based on code by Dave Hart

event-internal.h
event.c

index e3da33da724ed8ac21f68b30931ee00682d19e3e..12ca8bc194d09a9498cdb7c4c85c98620d7fdc9f 100644 (file)
@@ -32,6 +32,7 @@ extern "C" {
 #endif
 
 #include "event2/event-config.h"
+#include <time.h>
 #include <sys/queue.h>
 #include "event2/event_struct.h"
 #include "minheap-internal.h"
@@ -235,9 +236,18 @@ struct event_base {
        /** Priority queue of events with timeouts. */
        struct min_heap timeheap;
 
-       /** Stored timeval: used to avoid calling gettimeofday too often. */
+       /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
+        * too often. */
        struct timeval tv_cache;
 
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+       /** Difference between internal time (maybe from clock_gettime) and
+        * gettimeofday. */
+       struct timeval tv_clock_diff;
+       /** Second in which we last updated tv_clock_diff, in monotonic time. */
+       time_t last_updated_clock_diff;
+#endif
+
 #ifndef _EVENT_DISABLE_THREAD_SUPPORT
        /* threading support */
        /** The thread currently running the event_loop for this base */
diff --git a/event.c b/event.c
index fedb9c73cfa293adb776bc3e6815669699880f90..2469c44aeb69e9aa5a03ccd457b78b1b95352fa2 100644 (file)
--- a/event.c
+++ b/event.c
@@ -330,6 +330,10 @@ detect_monotonic(void)
 #endif
 }
 
+/* How often (in seconds) do we check for changes in wall clock time relative
+ * to monotonic time?  Set this to -1 for 'never.' */
+#define CLOCK_SYNC_INTERVAL 5
+
 /** Set 'tp' to the current time according to 'base'.  We must hold the lock
  * on 'base'.  If there is a cached time, return it.  Otherwise, use
  * clock_gettime or gettimeofday as appropriate to find out the right time.
@@ -354,6 +358,14 @@ gettime(struct event_base *base, struct timeval *tp)
 
                tp->tv_sec = ts.tv_sec;
                tp->tv_usec = ts.tv_nsec / 1000;
+               if (base->last_updated_clock_diff + CLOCK_SYNC_INTERVAL
+                   < ts.tv_sec) {
+                       struct timeval tv;
+                       evutil_gettimeofday(&tv,NULL);
+                       evutil_timersub(&tv, tp, &base->tv_clock_diff);
+                       base->last_updated_clock_diff = ts.tv_sec;
+               }
+
                return (0);
        }
 #endif
@@ -372,7 +384,16 @@ event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv)
        }
 
        EVBASE_ACQUIRE_LOCK(base, th_base_lock);
-       r = gettime(base, tv);
+       if (base->tv_cache.tv_sec == 0) {
+               r = evutil_gettimeofday(tv, NULL);
+       } else {
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+               evutil_timeradd(&base->tv_cache, &base->tv_clock_diff, tv);
+#else
+               *tv = base->tv_cache;
+#endif
+               r = 0;
+       }
        EVBASE_RELEASE_LOCK(base, th_base_lock);
        return r;
 }
@@ -1778,7 +1799,6 @@ event_priority_set(struct event *ev, int pri)
 int
 event_pending(const struct event *ev, short event, struct timeval *tv)
 {
-       struct timeval  now, res;
        int flags = 0;
 
        _event_debug_assert_is_setup(ev);
@@ -1795,12 +1815,13 @@ event_pending(const struct event *ev, short event, struct timeval *tv)
        /* See if there is a timeout that we should report */
        if (tv != NULL && (flags & event & EV_TIMEOUT)) {
                struct timeval tmp = ev->ev_timeout;
-               event_base_gettimeofday_cached(ev->ev_base, &now);
                tmp.tv_usec &= MICROSECONDS_MASK;
-               evutil_timersub(&tmp, &now, &res);
-               /* correctly remap to real time */
-               evutil_gettimeofday(&now, NULL);
-               evutil_timeradd(&now, &res, tv);
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+               /* correctly remamp to real time */
+               evutil_timeradd(&ev->ev_base->tv_clock_diff, &tmp, tv);
+#else
+               *tv = tmp;
+#endif
        }
 
        return (flags & event);