mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
make clock_monotonic work; do not use default timeout;
from Scott Lamb, plus some fixes from me. svn:r371
This commit is contained in:
parent
d7918e7963
commit
3ad6b47e03
@ -37,6 +37,7 @@ AC_ARG_WITH(rtsig,
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB(socket, socket)
|
||||
AC_CHECK_LIB(resolv, inet_aton)
|
||||
AC_CHECK_LIB(rt, clock_gettime)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
|
@ -218,11 +218,12 @@ devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
struct pollfd *events = devpollop->events;
|
||||
struct dvpoll dvp;
|
||||
struct evdevpoll *evdp;
|
||||
int i, res, timeout;
|
||||
int i, res, timeout = -1;
|
||||
|
||||
if (devpollop->nchanges)
|
||||
devpoll_commit(devpollop);
|
||||
|
||||
if (tv != NULL)
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
dvp.dp_fds = devpollop->events;
|
||||
|
4
epoll.c
4
epoll.c
@ -187,9 +187,11 @@ epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event *events = epollop->events;
|
||||
struct evepoll *evep;
|
||||
int i, res, timeout;
|
||||
int i, res, timeout = -1;
|
||||
|
||||
if (tv != NULL)
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
|
||||
|
||||
if (res == -1) {
|
||||
|
92
event.c
92
event.c
@ -51,6 +51,7 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
@ -113,6 +114,7 @@ const struct eventop *eventops[] = {
|
||||
/* Global state */
|
||||
struct event_base *current_base = NULL;
|
||||
extern struct event_base *evsignal_base;
|
||||
static int use_monotonic;
|
||||
|
||||
/* Handle signals - This is a deprecated interface */
|
||||
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
|
||||
@ -125,7 +127,7 @@ static int event_haveevents(struct event_base *);
|
||||
|
||||
static void event_process_active(struct event_base *);
|
||||
|
||||
static int timeout_next(struct event_base *, struct timeval *);
|
||||
static int timeout_next(struct event_base *, struct timeval **);
|
||||
static void timeout_process(struct event_base *);
|
||||
static void timeout_correct(struct event_base *, struct timeval *);
|
||||
|
||||
@ -143,25 +145,34 @@ compare(struct event *a, struct event *b)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
detect_monotonic(void)
|
||||
{
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||
use_monotonic = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
gettime(struct timeval *tp)
|
||||
{
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
|
||||
#ifdef HAVE_CLOCK_MONOTONIC
|
||||
if (use_monotonic) {
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
|
||||
#else
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
|
||||
#endif
|
||||
return (-1);
|
||||
|
||||
tp->tv_sec = ts.tv_sec;
|
||||
tp->tv_usec = ts.tv_nsec / 1000;
|
||||
#else
|
||||
gettimeofday(tp, NULL);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
return (gettimeofday(tp, NULL));
|
||||
}
|
||||
|
||||
RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare);
|
||||
@ -180,6 +191,8 @@ event_init(void)
|
||||
|
||||
event_sigcb = NULL;
|
||||
event_gotsig = 0;
|
||||
|
||||
detect_monotonic();
|
||||
gettime(&base->event_tv);
|
||||
|
||||
RB_INIT(&base->timetree);
|
||||
@ -374,6 +387,7 @@ event_base_loop(struct event_base *base, int flags)
|
||||
const struct eventop *evsel = base->evsel;
|
||||
void *evbase = base->evbase;
|
||||
struct timeval tv;
|
||||
struct timeval *tv_p;
|
||||
int res, done;
|
||||
|
||||
if(!TAILQ_EMPTY(&base->sig.signalqueue))
|
||||
@ -402,21 +416,18 @@ event_base_loop(struct event_base *base, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if time is running backwards */
|
||||
gettime(&tv);
|
||||
if (timercmp(&tv, &base->event_tv, <)) {
|
||||
struct timeval off;
|
||||
event_debug(("%s: time is running backwards, corrected",
|
||||
__func__));
|
||||
timersub(&base->event_tv, &tv, &off);
|
||||
timeout_correct(base, &off);
|
||||
}
|
||||
base->event_tv = tv;
|
||||
timeout_correct(base, &tv);
|
||||
|
||||
if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK))
|
||||
timeout_next(base, &tv);
|
||||
else
|
||||
tv_p = &tv;
|
||||
if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
|
||||
timeout_next(base, &tv_p);
|
||||
} else {
|
||||
/*
|
||||
* if we have active events, we just poll new events
|
||||
* without waiting.
|
||||
*/
|
||||
timerclear(&tv);
|
||||
}
|
||||
|
||||
/* If we have no events, we just exit */
|
||||
if (!event_haveevents(base)) {
|
||||
@ -424,7 +435,7 @@ event_base_loop(struct event_base *base, int flags)
|
||||
return (1);
|
||||
}
|
||||
|
||||
res = evsel->dispatch(base, evbase, &tv);
|
||||
res = evsel->dispatch(base, evbase, tv_p);
|
||||
|
||||
|
||||
if (res == -1)
|
||||
@ -725,16 +736,16 @@ event_active(struct event *ev, int res, short ncalls)
|
||||
event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
int
|
||||
timeout_next(struct event_base *base, struct timeval *tv)
|
||||
static int
|
||||
timeout_next(struct event_base *base, struct timeval **tv_p)
|
||||
{
|
||||
struct timeval dflt = TIMEOUT_DEFAULT;
|
||||
|
||||
struct timeval now;
|
||||
struct event *ev;
|
||||
struct timeval *tv = *tv_p;
|
||||
|
||||
if ((ev = RB_MIN(event_tree, &base->timetree)) == NULL) {
|
||||
*tv = dflt;
|
||||
/* if no time-based events are active wait for I/O */
|
||||
*tv_p = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -755,17 +766,38 @@ timeout_next(struct event_base *base, struct timeval *tv)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if the time is running backwards by comparing the current
|
||||
* time against the last time we checked. Not needed when using clock
|
||||
* monotonic.
|
||||
*/
|
||||
|
||||
static void
|
||||
timeout_correct(struct event_base *base, struct timeval *off)
|
||||
timeout_correct(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
struct event *ev;
|
||||
struct timeval off;
|
||||
|
||||
if (use_monotonic)
|
||||
return;
|
||||
|
||||
/* Check if time is running backwards */
|
||||
gettime(tv);
|
||||
if (timercmp(tv, &base->event_tv, >=)) {
|
||||
base->event_tv = *tv;
|
||||
return;
|
||||
}
|
||||
|
||||
event_debug(("%s: time is running backwards, corrected",
|
||||
__func__));
|
||||
timersub(&base->event_tv, tv, &off);
|
||||
|
||||
/*
|
||||
* We can modify the key element of the node without destroying
|
||||
* the key, beause we apply it to all in the right order.
|
||||
*/
|
||||
RB_FOREACH(ev, event_tree, &base->timetree)
|
||||
timersub(&ev->ev_timeout, off, &ev->ev_timeout);
|
||||
timersub(&ev->ev_timeout, &off, &ev->ev_timeout);
|
||||
}
|
||||
|
||||
void
|
||||
|
2
event.h
2
event.h
@ -141,8 +141,6 @@ struct eventop {
|
||||
void (*dealloc)(struct event_base *, void *);
|
||||
};
|
||||
|
||||
#define TIMEOUT_DEFAULT {5, 0}
|
||||
|
||||
void *event_init(void);
|
||||
int event_dispatch(void);
|
||||
int event_base_dispatch(struct event_base *);
|
||||
|
2
http.c
2
http.c
@ -1247,7 +1247,7 @@ evhttp_get_body_length(struct evhttp_request *req)
|
||||
|
||||
event_debug(("%s: bytes to read: %d (in buffer %d)\n",
|
||||
__func__, req->ntoread,
|
||||
EVBUFFER_LENGTH(evcon->input_buffer)));
|
||||
EVBUFFER_LENGTH(req->evcon->input_buffer)));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
7
kqueue.c
7
kqueue.c
@ -212,13 +212,16 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
struct kevent *changes = kqop->changes;
|
||||
struct kevent *events = kqop->events;
|
||||
struct event *ev;
|
||||
struct timespec ts;
|
||||
struct timespec ts, *ts_p = NULL;
|
||||
int i, res;
|
||||
|
||||
if (tv != NULL) {
|
||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
res = kevent(kqop->kq, changes, kqop->nchanges,
|
||||
events, kqop->nevents, &ts);
|
||||
events, kqop->nevents, ts_p);
|
||||
kqop->nchanges = 0;
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
|
9
poll.c
9
poll.c
@ -148,13 +148,16 @@ poll_check_ok(struct pollop *pop)
|
||||
int
|
||||
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i, sec, nfds;
|
||||
int res, i, msec = -1, nfds;
|
||||
struct pollop *pop = arg;
|
||||
|
||||
poll_check_ok(pop);
|
||||
sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
if (tv != NULL)
|
||||
msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
nfds = pop->nfds;
|
||||
res = poll(pop->event_set, nfds, sec);
|
||||
res = poll(pop->event_set, nfds, msec);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
|
32
rtsig.c
32
rtsig.c
@ -750,7 +750,7 @@ rtsig_recalc(struct event_base *base, void *arg, int max)
|
||||
*/
|
||||
|
||||
static inline int
|
||||
do_poll(struct rtsigop *op, struct timespec *ts)
|
||||
do_poll(struct rtsigop *op, struct timespec *ts, struct timespec **ts_p)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
@ -758,7 +758,11 @@ do_poll(struct rtsigop *op, struct timespec *ts)
|
||||
if (op->cur > 1) {
|
||||
/* non-empty poll set (modulo the signalfd) */
|
||||
if (op->nonsock) {
|
||||
int timeout = ts->tv_nsec / 1000000 + ts->tv_sec * 1000;
|
||||
int timeout = -1;
|
||||
|
||||
if (*ts_p != NULL)
|
||||
timeout = (*ts_p)->tv_nsec / 1000000
|
||||
+ (*ts_p)->tv_sec * 1000;
|
||||
|
||||
sigprocmask(SIG_UNBLOCK, &(op->sigs), NULL);
|
||||
|
||||
@ -768,6 +772,7 @@ do_poll(struct rtsigop *op, struct timespec *ts)
|
||||
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
*ts_p = ts;
|
||||
} else {
|
||||
res = poll(op->poll, op->cur, 0);
|
||||
}
|
||||
@ -777,6 +782,7 @@ do_poll(struct rtsigop *op, struct timespec *ts)
|
||||
} else if (res) {
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
*ts_p = ts;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@ -894,17 +900,18 @@ do_siginfo_dispatch(struct event_base *base, struct rtsigop *op,
|
||||
* return -1 on error
|
||||
*/
|
||||
static inline int
|
||||
do_sigwait(struct event_base *base, struct rtsigop *op, struct timespec *ts,
|
||||
sigset_t *sigs)
|
||||
do_sigwait(struct event_base *base, struct rtsigop *op,
|
||||
struct timespec *ts, struct timespec **ts_p, sigset_t *sigs)
|
||||
{
|
||||
for (;;) {
|
||||
siginfo_t info;
|
||||
int signum;
|
||||
|
||||
signum = sigtimedwait(sigs, &info, ts);
|
||||
signum = sigtimedwait(sigs, &info, *ts_p);
|
||||
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
*ts_p = ts;
|
||||
|
||||
if (signum == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
@ -920,7 +927,7 @@ do_sigwait(struct event_base *base, struct rtsigop *op, struct timespec *ts,
|
||||
|
||||
static inline int
|
||||
do_signals_from_socket(struct event_base *base, struct rtsigop *op,
|
||||
struct timespec *ts)
|
||||
struct timespec *ts, struct timespec **ts_p)
|
||||
{
|
||||
int fd = op->signal_recv_fd;
|
||||
siginfo_t info;
|
||||
@ -937,6 +944,7 @@ do_signals_from_socket(struct event_base *base, struct rtsigop *op,
|
||||
} else {
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
*ts_p = ts;
|
||||
if (1 == do_siginfo_dispatch(base, op, &info))
|
||||
return (1);
|
||||
}
|
||||
@ -948,17 +956,21 @@ int
|
||||
rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct rtsigop *op = (struct rtsigop *) arg;
|
||||
struct timespec ts;
|
||||
struct timespec ts, *ts_p = NULL;
|
||||
int res;
|
||||
sigset_t sigs;
|
||||
|
||||
if (tv != NULL) {
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
*ts_p = ts;
|
||||
}
|
||||
|
||||
poll_for_level:
|
||||
res = do_poll(op, &ts); /* ts can be modified in do_XXX() */
|
||||
/* ts and ts_p can be modified in do_XXX() */
|
||||
res = do_poll(op, &ts, &ts_p);
|
||||
|
||||
res = do_signals_from_socket(base, op, &ts);
|
||||
res = do_signals_from_socket(base, op, &ts, &ts_p);
|
||||
if (res == 1)
|
||||
goto poll_for_level;
|
||||
else if (res == -1)
|
||||
@ -973,7 +985,7 @@ rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
signotset(&sigs);
|
||||
sigorset(&sigs, &sigs, &op->sigs);
|
||||
|
||||
res = do_sigwait(base, op, &ts, &sigs);
|
||||
res = do_sigwait(base, op, &ts, &ts_p, &sigs);
|
||||
|
||||
if (res == 1)
|
||||
goto poll_for_level;
|
||||
|
Loading…
x
Reference in New Issue
Block a user