mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 12:28:19 -04:00
Merge branch '21_choose_monotonic'
This commit is contained in:
commit
5595a79ff1
@ -36,6 +36,10 @@ extern "C" {
|
||||
|
||||
#include <time.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 "minheap-internal.h"
|
||||
#include "evsignal-internal.h"
|
||||
@ -64,6 +68,8 @@ extern "C" {
|
||||
#define HAVE_ANY_MONOTONIC 1
|
||||
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
|
||||
#define HAVE_ANY_MONOTONIC 1
|
||||
#elif defined(_WIN32)
|
||||
#define HAVE_ANY_MONOTONIC 1
|
||||
#endif
|
||||
|
||||
/** Structure to define the backend of a given event_base. */
|
||||
@ -251,7 +257,21 @@ struct event_base {
|
||||
* too often. */
|
||||
struct timeval tv_cache;
|
||||
|
||||
#if defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
|
||||
struct mach_timebase_info mach_timebase_units;
|
||||
#endif
|
||||
#if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) && defined(CLOCK_MONOTONIC_COARSE)
|
||||
#define CLOCK_IS_SELECTED
|
||||
int monotonic_clock;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
DWORD last_tick_count;
|
||||
struct timeval adjust_tick_count;
|
||||
#endif
|
||||
#if defined(HAVE_ANY_MONOTONIC)
|
||||
/** True iff we should use our system's monotonic time implementation */
|
||||
/* TODO: Support systems where we don't need to detct monotonic time */
|
||||
int use_monotonic;
|
||||
/** Difference between internal time (maybe from clock_gettime) and
|
||||
* gettimeofday. */
|
||||
struct timeval tv_clock_diff;
|
||||
|
74
event.c
74
event.c
@ -46,9 +46,6 @@
|
||||
#ifdef EVENT__HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
@ -131,10 +128,6 @@ struct event_base *event_global_current_base_ = NULL;
|
||||
|
||||
/* Global state */
|
||||
|
||||
#ifdef HAVE_ANY_MONOTONIC
|
||||
static int use_monotonic;
|
||||
#endif
|
||||
|
||||
static void *event_self_cbarg_ptr_ = NULL;
|
||||
|
||||
/* Prototypes */
|
||||
@ -345,19 +338,11 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
|
||||
#define EVENT_BASE_ASSERT_LOCKED(base) \
|
||||
EVLOCK_ASSERT_LOCKED((base)->th_base_lock)
|
||||
|
||||
#if defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
|
||||
struct mach_timebase_info mach_timebase_units;
|
||||
#endif
|
||||
|
||||
/* The first time this function is called, it sets use_monotonic to 1
|
||||
* if we have a clock function that supports monotonic time */
|
||||
/* Set base->use_monotonic to 1 if we have a clock function that supports
|
||||
* monotonic time */
|
||||
static void
|
||||
detect_monotonic(void)
|
||||
detect_monotonic(struct event_base *base, const struct event_config *cfg)
|
||||
{
|
||||
static int use_monotonic_initialized = 0;
|
||||
if (use_monotonic_initialized)
|
||||
return;
|
||||
|
||||
#if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
{
|
||||
/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.
|
||||
@ -365,25 +350,34 @@ detect_monotonic(void)
|
||||
* versions won't have it working. */
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||
use_monotonic = 1;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||
base->use_monotonic = 1;
|
||||
#ifdef CLOCK_IS_SELECTED
|
||||
base->monotonic_clock = CLOCK_MONOTONIC;
|
||||
if (cfg == NULL ||
|
||||
!(cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER)) {
|
||||
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0)
|
||||
base->monotonic_clock = CLOCK_MONOTONIC_COARSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
|
||||
{
|
||||
struct mach_timebase_info mi;
|
||||
/* OSX has mach_absolute_time() */
|
||||
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_absolute_time() into nanoseconds, but we
|
||||
* want to use microseconds instead. */
|
||||
mi.denom *= 1000;
|
||||
memcpy(&mach_timebase_units, &mi, sizeof(mi));
|
||||
memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
base->use_monotonic = 1;
|
||||
#endif
|
||||
use_monotonic_initialized = 1;
|
||||
|
||||
}
|
||||
|
||||
/* How often (in seconds) do we check for changes in wall clock time relative
|
||||
@ -406,21 +400,43 @@ gettime(struct event_base *base, struct timeval *tp)
|
||||
}
|
||||
|
||||
#ifdef HAVE_ANY_MONOTONIC
|
||||
if (use_monotonic) {
|
||||
if (base->use_monotonic) {
|
||||
#if defined(EVENT__HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
#ifdef CLOCK_IS_SELECTED
|
||||
if (clock_gettime(base->monotonic_clock, &ts) == -1)
|
||||
return (-1);
|
||||
#else
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
tp->tv_sec = ts.tv_sec;
|
||||
tp->tv_usec = ts.tv_nsec / 1000;
|
||||
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
|
||||
uint64_t abstime = mach_absolute_time();
|
||||
uint64_t usec;
|
||||
usec = (abstime * mach_timebase_units.numer)
|
||||
/ (mach_timebase_units.denom);
|
||||
usec = (abstime * base->mach_timebase_units.numer)
|
||||
/ (base->mach_timebase_units.denom);
|
||||
tp->tv_sec = usec / 1000000;
|
||||
tp->tv_usec = usec % 1000000;
|
||||
#elif defined(_WIN32)
|
||||
/* TODO: Support GetTickCount64. */
|
||||
/* TODO: Support alternate timer backends if the user asked
|
||||
* for a high-precision timer. QueryPerformanceCounter is
|
||||
* possibly a good idea, but it is also supposed to have
|
||||
* reliability issues under various circumstances. */
|
||||
DWORD ticks = GetTickCount();
|
||||
if (ticks < base->last_tick_count) {
|
||||
/* The 32-bit timer rolled over. Let's assume it only
|
||||
* happened once. Add 2**32 msec to adjust_tick_count. */
|
||||
const struct timeval tv_rollover = { 4294967, 296000 };
|
||||
evutil_timeradd(&tv_rollover, &base->adjust_tick_count, &base->adjust_tick_count);
|
||||
}
|
||||
base->last_tick_count = ticks;
|
||||
tp->tv_sec = ticks / 1000;
|
||||
tp->tv_usec = (ticks % 1000) * 1000;
|
||||
evutil_timeradd(tp, &base->adjust_tick_count, tp);
|
||||
#else
|
||||
#error "Missing monotonic time implementation."
|
||||
#endif
|
||||
@ -631,7 +647,7 @@ event_base_new_with_config(const struct event_config *cfg)
|
||||
event_warn("%s: calloc", __func__);
|
||||
return NULL;
|
||||
}
|
||||
detect_monotonic();
|
||||
detect_monotonic(base, cfg);
|
||||
gettime(base, &base->event_tv);
|
||||
|
||||
min_heap_ctor_(&base->timeheap);
|
||||
@ -2621,7 +2637,7 @@ timeout_correct(struct event_base *base, struct timeval *tv)
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_ANY_MONOTONIC
|
||||
if (use_monotonic)
|
||||
if (base->use_monotonic)
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -481,7 +481,14 @@ enum event_base_config_flag {
|
||||
This flag has no effect if you wind up using a backend other than
|
||||
epoll.
|
||||
*/
|
||||
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10
|
||||
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,
|
||||
|
||||
/** Ordinarily, Libevent implements its time and timeout code using
|
||||
the fastest monotonic timer that we have. If this flag is set,
|
||||
however, we use less efficient more precise timer, assuming one is
|
||||
present.
|
||||
*/
|
||||
EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user