Move use_monotonic and friends into event_base

The use_monotonic field used to be a static field set up at library
setup.  Unfortunately, this makes it hard to give the user a way to
make speed/accuracy tradeoffs about time.  Moving it into event_base
should let the clock implementation become configurable.
This commit is contained in:
Nick Mathewson 2012-04-17 12:44:39 -04:00
parent b62b31f1f1
commit 1fbef7d538
2 changed files with 20 additions and 28 deletions

View File

@ -36,6 +36,10 @@ extern "C" {
#include <time.h> #include <time.h>
#include <sys/queue.h> #include <sys/queue.h>
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
/* For mach_timebase_info */
#include <mach/mach_time.h>
#endif
#include "event2/event_struct.h" #include "event2/event_struct.h"
#include "minheap-internal.h" #include "minheap-internal.h"
#include "evsignal-internal.h" #include "evsignal-internal.h"
@ -251,7 +255,12 @@ struct event_base {
* too often. */ * too often. */
struct timeval tv_cache; struct timeval tv_cache;
#if defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
struct mach_timebase_info mach_timebase_units;
#endif
#if defined(HAVE_ANY_MONOTONIC) #if defined(HAVE_ANY_MONOTONIC)
/** True iff we should use our system's monotonic time implementation */
int use_monotonic;
/** Difference between internal time (maybe from clock_gettime) and /** Difference between internal time (maybe from clock_gettime) and
* gettimeofday. */ * gettimeofday. */
struct timeval tv_clock_diff; struct timeval tv_clock_diff;

39
event.c
View File

@ -46,9 +46,6 @@
#ifdef EVENT__HAVE_UNISTD_H #ifdef EVENT__HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#endif
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
@ -131,10 +128,6 @@ struct event_base *event_global_current_base_ = NULL;
/* Global state */ /* Global state */
#ifdef HAVE_ANY_MONOTONIC
static int use_monotonic;
#endif
static void *event_self_cbarg_ptr_ = NULL; static void *event_self_cbarg_ptr_ = NULL;
/* Prototypes */ /* Prototypes */
@ -345,19 +338,11 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
#define EVENT_BASE_ASSERT_LOCKED(base) \ #define EVENT_BASE_ASSERT_LOCKED(base) \
EVLOCK_ASSERT_LOCKED((base)->th_base_lock) EVLOCK_ASSERT_LOCKED((base)->th_base_lock)
#if defined(EVENT__HAVE_MACH_ABSOLUTE_TIME) /* Set base->use_monotonic to 1 if we have a clock function that supports
struct mach_timebase_info mach_timebase_units; * monotonic time */
#endif
/* The first time this function is called, it sets use_monotonic to 1
* if we have a clock function that supports monotonic time */
static void static void
detect_monotonic(void) detect_monotonic(struct event_base *base)
{ {
static int use_monotonic_initialized = 0;
if (use_monotonic_initialized)
return;
#if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) #if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
{ {
/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris. /* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.
@ -366,24 +351,22 @@ detect_monotonic(void)
struct timespec ts; struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
use_monotonic = 1; base->use_monotonic = 1;
} }
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME) #elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
{ {
struct mach_timebase_info mi; struct mach_timebase_info mi;
/* OSX has mach_absolute_time() */ /* OSX has mach_absolute_time() */
if (mach_timebase_info(&mi) == 0 && mach_absolute_time() != 0) { if (mach_timebase_info(&mi) == 0 && mach_absolute_time() != 0) {
use_monotonic = 1; base->use_monotonic = 1;
/* mach_timebase_info tells us how to convert /* mach_timebase_info tells us how to convert
* mach_absolute_time() into nanoseconds, but we * mach_absolute_time() into nanoseconds, but we
* want to use microseconds instead. */ * want to use microseconds instead. */
mi.denom *= 1000; mi.denom *= 1000;
memcpy(&mach_timebase_units, &mi, sizeof(mi)); memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
} }
} }
#endif #endif
use_monotonic_initialized = 1;
} }
/* How often (in seconds) do we check for changes in wall clock time relative /* How often (in seconds) do we check for changes in wall clock time relative
@ -406,7 +389,7 @@ gettime(struct event_base *base, struct timeval *tp)
} }
#ifdef HAVE_ANY_MONOTONIC #ifdef HAVE_ANY_MONOTONIC
if (use_monotonic) { if (base->use_monotonic) {
#if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) #if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec ts; struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
@ -417,8 +400,8 @@ gettime(struct event_base *base, struct timeval *tp)
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME) #elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
uint64_t abstime = mach_absolute_time(); uint64_t abstime = mach_absolute_time();
uint64_t usec; uint64_t usec;
usec = (abstime * mach_timebase_units.numer) usec = (abstime * base->mach_timebase_units.numer)
/ (mach_timebase_units.denom); / (base->mach_timebase_units.denom);
tp->tv_sec = usec / 1000000; tp->tv_sec = usec / 1000000;
tp->tv_usec = usec % 1000000; tp->tv_usec = usec % 1000000;
#else #else
@ -631,7 +614,7 @@ event_base_new_with_config(const struct event_config *cfg)
event_warn("%s: calloc", __func__); event_warn("%s: calloc", __func__);
return NULL; return NULL;
} }
detect_monotonic(); detect_monotonic(base);
gettime(base, &base->event_tv); gettime(base, &base->event_tv);
min_heap_ctor_(&base->timeheap); min_heap_ctor_(&base->timeheap);
@ -2621,7 +2604,7 @@ timeout_correct(struct event_base *base, struct timeval *tv)
int i; int i;
#ifdef HAVE_ANY_MONOTONIC #ifdef HAVE_ANY_MONOTONIC
if (use_monotonic) if (base->use_monotonic)
return; return;
#endif #endif