from trunk: cache clock_gettime/gettimeofday values in base

svn:r759
This commit is contained in:
Niels Provos 2008-05-03 18:27:24 +00:00
parent 2a69a5ea9a
commit bfdf56c22e
3 changed files with 32 additions and 17 deletions

View File

@ -7,6 +7,7 @@ Changes in 1.4.4-stable:
o fix a bug in bufferevent read water marks and add a test for them
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
o reduce system calls for getting current time by caching it.
Changes in 1.4.3-stable:

View File

@ -66,6 +66,8 @@ struct event_base {
struct timeval event_tv;
struct min_heap timeheap;
struct timeval tv_cache;
};
/* Internal use only: Functions that might be missing from <sys/queue.h> */

46
event.c
View File

@ -137,8 +137,13 @@ detect_monotonic(void)
}
static int
gettime(struct timeval *tp)
gettime(struct event_base *base, struct timeval *tp)
{
if (base->tv_cache.tv_sec) {
*tp = base->tv_cache;
return (0);
}
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec ts;
@ -179,7 +184,7 @@ event_base_new(void)
event_gotsig = 0;
detect_monotonic();
gettime(&base->event_tv);
gettime(base, &base->event_tv);
min_heap_ctor(&base->timeheap);
TAILQ_INIT(&base->eventqueue);
@ -497,10 +502,17 @@ event_base_loop(struct event_base *base, int flags)
return (1);
}
/* update last old time */
gettime(base, &base->event_tv);
/* clear time cache */
base->tv_cache.tv_sec = 0;
res = evsel->dispatch(base, evbase, tv_p);
if (res == -1)
return (-1);
gettime(base, &base->tv_cache);
timeout_process(base);
@ -668,7 +680,7 @@ event_pending(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)) {
gettime(&now);
gettime(ev->ev_base, &now);
evutil_timersub(&ev->ev_timeout, &now, &res);
/* correctly remap to real time */
gettimeofday(&now, NULL);
@ -720,7 +732,7 @@ event_add(struct event *ev, struct timeval *tv)
event_queue_remove(base, ev, EVLIST_ACTIVE);
}
gettime(&now);
gettime(base, &now);
evutil_timeradd(&now, tv, &ev->ev_timeout);
event_debug((
@ -820,7 +832,7 @@ timeout_next(struct event_base *base, struct timeval **tv_p)
return (0);
}
if (gettime(&now) == -1)
if (gettime(base, &now) == -1)
return (-1);
if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
@ -854,7 +866,7 @@ timeout_correct(struct event_base *base, struct timeval *tv)
return;
/* Check if time is running backwards */
gettime(tv);
gettime(base, tv);
if (evutil_timercmp(tv, &base->event_tv, >=)) {
base->event_tv = *tv;
return;
@ -885,7 +897,7 @@ timeout_process(struct event_base *base)
if (min_heap_empty(&base->timeheap))
return;
gettime(&now);
gettime(base, &now);
while ((ev = min_heap_top(&base->timeheap))) {
if (evutil_timercmp(&ev->ev_timeout, &now, >))
@ -912,19 +924,19 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
ev->ev_flags &= ~queue;
switch (queue) {
case EVLIST_INSERTED:
TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
break;
case EVLIST_ACTIVE:
base->event_count_active--;
TAILQ_REMOVE(base->activequeues[ev->ev_pri],
ev, ev_active_next);
break;
case EVLIST_SIGNAL:
TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT:
min_heap_erase(&base->timeheap, ev);
break;
case EVLIST_INSERTED:
TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
case EVLIST_SIGNAL:
TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
default:
event_errx(1, "%s: unknown queue %x", __func__, queue);
@ -948,20 +960,20 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue)
ev->ev_flags |= queue;
switch (queue) {
case EVLIST_INSERTED:
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
break;
case EVLIST_ACTIVE:
base->event_count_active++;
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
ev,ev_active_next);
break;
case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT: {
min_heap_push(&base->timeheap, ev);
break;
}
case EVLIST_INSERTED:
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
default:
event_errx(1, "%s: unknown queue %x", __func__, queue);