From: Niels Provos Date: Thu, 25 Nov 2004 09:50:18 +0000 (+0000) Subject: make libevent thread-safe; first cut X-Git-Tag: release-1.1b~47 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8773c4c96c47078ee502030daef36078bc0e75a4;p=libevent make libevent thread-safe; first cut svn:r122 --- diff --git a/devpoll.c b/devpoll.c index 183db85d..3532d59a 100644 --- a/devpoll.c +++ b/devpoll.c @@ -57,8 +57,6 @@ #include "event.h" #include "evsignal.h" -extern struct event_list eventqueue; - extern volatile sig_atomic_t evsignal_caught; /* due to limitations in the devpoll interface, we need to keep track of @@ -81,8 +79,8 @@ struct devpollop { void *devpoll_init (void); int devpoll_add (void *, struct event *); int devpoll_del (void *, struct event *); -int devpoll_recalc (void *, int); -int devpoll_dispatch (void *, struct timeval *); +int devpoll_recalc (struct event_base *, void *, int); +int devpoll_dispatch (struct event_base *, void *, struct timeval *); struct eventop devpollops = { "devpoll", @@ -139,7 +137,7 @@ devpoll_init(void) } int -devpoll_recalc(void *arg, int max) +devpoll_recalc(struct event_base *base, void *arg, int max) { struct devpollop *devpollop = arg; @@ -166,7 +164,7 @@ devpoll_recalc(void *arg, int max) } int -devpoll_dispatch(void *arg, struct timeval *tv) +devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { struct devpollop *devpollop = arg; struct pollfd *events = devpollop->events; @@ -257,7 +255,7 @@ devpoll_add(void *arg, struct event *ev) fd = ev->ev_fd; if (fd >= devpollop->nfds) { /* Extent the file descriptor array as necessary */ - if (devpoll_recalc(devpollop, fd) == -1) + if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1) return (-1); } evdp = &devpollop->fds[fd]; diff --git a/epoll.c b/epoll.c index 9924d0fb..2ffc2335 100644 --- a/epoll.c +++ b/epoll.c @@ -59,8 +59,6 @@ #include "event.h" #include "evsignal.h" -extern struct event_list eventqueue; - extern volatile sig_atomic_t evsignal_caught; /* due to limitations in the epoll interface, we need to keep track of @@ -83,8 +81,8 @@ struct epollop { void *epoll_init (void); int epoll_add (void *, struct event *); int epoll_del (void *, struct event *); -int epoll_recalc (void *, int); -int epoll_dispatch (void *, struct timeval *); +int epoll_recalc (struct event_base *, void *, int); +int epoll_dispatch (struct event_base *, void *, struct timeval *); struct eventop epollops = { "epoll", @@ -152,7 +150,7 @@ epoll_init(void) } int -epoll_recalc(void *arg, int max) +epoll_recalc(struct event_base *base, void *arg, int max) { struct epollop *epollop = arg; @@ -179,7 +177,7 @@ epoll_recalc(void *arg, int max) } int -epoll_dispatch(void *arg, struct timeval *tv) +epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { struct epollop *epollop = arg; struct epoll_event *events = epollop->events; @@ -263,7 +261,7 @@ epoll_add(void *arg, struct event *ev) fd = ev->ev_fd; if (fd >= epollop->nfds) { /* Extent the file descriptor array as necessary */ - if (epoll_recalc(epollop, fd) == -1) + if (epoll_recalc(ev->ev_base, epollop, fd) == -1) return (-1); } evep = &epollop->fds[fd]; diff --git a/event-internal.h b/event-internal.h new file mode 100644 index 00000000..4f365955 --- /dev/null +++ b/event-internal.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2000-2004 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _EVENT_INTERNAL_H_ +#define _EVENT_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct event_base { + const struct eventop *evsel; + void *evbase; + int event_count; /* counts number of total events */ + int event_count_active; /* counts number of active events */ + + /* Handle signals - This is a deprecated interface */ + int (*event_sigcb)(void); /* Signal callback when gotsig is set */ + int event_gotsig; /* Set in signal handler */ + int event_gotterm; /* Set to terminate loop */ + + /* active event management */ + struct event_list **activequeues; + int nactivequeues; + + struct event_list eventqueue; + struct timeval event_tv; + + RB_HEAD(event_tree, event) timetree; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT_INTERNAL_H_ */ diff --git a/event.c b/event.c index c62574e3..cc5b1640 100644 --- a/event.c +++ b/event.c @@ -60,6 +60,7 @@ #endif #include "event.h" +#include "event-internal.h" #ifdef HAVE_SELECT extern const struct eventop selectops; @@ -110,33 +111,20 @@ const struct eventop *eventops[] = { }; /* Global state */ +struct event_list signalqueue; -const struct eventop *evsel; -void *evbase; -static int event_count; /* counts number of total events */ -static int event_count_active; /* counts number of active events */ - -/* Handle signals - This is a deprecated interface */ -int (*event_sigcb)(void); /* Signal callback when gotsig is set */ -int event_gotsig; /* Set in signal handler */ -int event_gotterm; /* Set to terminate loop */ +struct event_base *current_base = NULL; /* Prototypes */ -void event_queue_insert(struct event *, int); -void event_queue_remove(struct event *, int); -int event_haveevents(void); +static void event_queue_insert(struct event_base *, struct event *, int); +static void event_queue_remove(struct event_base *, struct event *, int); +static int event_haveevents(struct event_base *); -static void event_process_active(void); +static void event_process_active(struct event_base *); -static RB_HEAD(event_tree, event) timetree; - -/* active event management */ -static struct event_list **activequeues; -static int nactivequeues; - -struct event_list signalqueue; -struct event_list eventqueue; -static struct timeval event_tv; +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 *); static int compare(struct event *a, struct event *b) @@ -157,77 +145,83 @@ RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare); RB_GENERATE(event_tree, event, ev_timeout_node, compare); -void +void * event_init(void) { int i; - event_sigcb = NULL; - event_gotsig = 0; - gettimeofday(&event_tv, NULL); + if ((current_base = calloc(1, sizeof(struct event_base))) == NULL) + err(1, "%s: calloc"); + + current_base->event_sigcb = NULL; + current_base->event_gotsig = 0; + gettimeofday(¤t_base->event_tv, NULL); #if defined(USE_LOG) && defined(USE_DEBUG) log_to(stderr); log_debug_cmd(LOG_MISC, 80); #endif - RB_INIT(&timetree); - TAILQ_INIT(&eventqueue); + RB_INIT(¤t_base->timetree); + TAILQ_INIT(¤t_base->eventqueue); TAILQ_INIT(&signalqueue); - evbase = NULL; - for (i = 0; eventops[i] && !evbase; i++) { - evsel = eventops[i]; + current_base->evbase = NULL; + for (i = 0; eventops[i] && !current_base->evbase; i++) { + current_base->evsel = eventops[i]; - evbase = evsel->init(); + current_base->evbase = current_base->evsel->init(); } - if (evbase == NULL) + if (current_base->evbase == NULL) errx(1, "%s: no event mechanism available", __func__); if (getenv("EVENT_SHOW_METHOD")) - fprintf(stderr, "libevent using: %s\n", evsel->name); + fprintf(stderr, "libevent using: %s\n", + current_base->evsel->name); /* allocate a single active event queue */ - event_priority_init(1); + event_priority_init(current_base, 1); + + return (current_base); } int -event_priority_init(int npriorities) +event_priority_init(struct event_base *base, int npriorities) { int i; - if (event_count_active) + if (base->event_count_active) return (-1); - if (nactivequeues && npriorities != nactivequeues) { - for (i = 0; i < nactivequeues; ++i) { - free(activequeues[i]); + if (base->nactivequeues && npriorities != base->nactivequeues) { + for (i = 0; i < base->nactivequeues; ++i) { + free(base->activequeues[i]); } - free(activequeues); + free(base->activequeues); } /* Allocate our priority queues */ - nactivequeues = npriorities; - activequeues = (struct event_list **)calloc(nactivequeues, + base->nactivequeues = npriorities; + base->activequeues = (struct event_list **)calloc(base->nactivequeues, npriorities * sizeof(struct event_list *)); - if (activequeues == NULL) + if (base->activequeues == NULL) err(1, "%s: calloc", __func__); - for (i = 0; i < nactivequeues; ++i) { - activequeues[i] = malloc(sizeof(struct event_list)); - if (activequeues[i] == NULL) + for (i = 0; i < base->nactivequeues; ++i) { + base->activequeues[i] = malloc(sizeof(struct event_list)); + if (base->activequeues[i] == NULL) err(1, "%s: malloc", __func__); - TAILQ_INIT(activequeues[i]); + TAILQ_INIT(base->activequeues[i]); } return (0); } int -event_haveevents(void) +event_haveevents(struct event_base *base) { - return (event_count > 0); + return (base->event_count > 0); } /* @@ -237,25 +231,25 @@ event_haveevents(void) */ static void -event_process_active(void) +event_process_active(struct event_base *base) { struct event *ev; struct event_list *activeq = NULL; int i; short ncalls; - if (!event_count_active) + if (!base->event_count_active) return; - for (i = 0; i < nactivequeues; ++i) { - if (TAILQ_FIRST(activequeues[i]) != NULL) { - activeq = activequeues[i]; + for (i = 0; i < base->nactivequeues; ++i) { + if (TAILQ_FIRST(base->activequeues[i]) != NULL) { + activeq = base->activequeues[i]; break; } } for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) { - event_queue_remove(ev, EVLIST_ACTIVE); + event_queue_remove(base, ev, EVLIST_ACTIVE); /* Allows deletes to work */ ncalls = ev->ev_ncalls; @@ -281,37 +275,51 @@ event_dispatch(void) static void event_loopexit_cb(int fd, short what, void *arg) { - event_gotterm = 1; + struct event_base *base = arg; + base->event_gotterm = 1; } +/* not thread safe */ + int event_loopexit(struct timeval *tv) { - return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, NULL, tv)); + return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, + current_base, tv)); } +/* not thread safe */ + int event_loop(int flags) { + return event_loop_base(current_base, flags); +} + +int +event_loop_base(struct event_base *base, int flags) +{ + const struct eventop *evsel = base->evsel; + void *evbase = base->evbase; struct timeval tv; int res, done; /* Calculate the initial events that we are waiting for */ - if (evsel->recalc(evbase, 0) == -1) + if (evsel->recalc(base, evbase, 0) == -1) return (-1); done = 0; while (!done) { /* Terminate the loop if we have been asked to */ - if (event_gotterm) { - event_gotterm = 0; + if (base->event_gotterm) { + base->event_gotterm = 0; break; } - while (event_gotsig) { - event_gotsig = 0; - if (event_sigcb) { - res = (*event_sigcb)(); + while (base->event_gotsig) { + base->event_gotsig = 0; + if (base->event_sigcb) { + res = (*base->event_sigcb)(); if (res == -1) { errno = EINTR; return (-1); @@ -321,41 +329,41 @@ event_loop(int flags) /* Check if time is running backwards */ gettimeofday(&tv, NULL); - if (timercmp(&tv, &event_tv, <)) { + if (timercmp(&tv, &base->event_tv, <)) { struct timeval off; LOG_DBG((LOG_MISC, 10, "%s: time is running backwards, corrected", __func__)); - timersub(&event_tv, &tv, &off); - timeout_correct(&off); + timersub(&base->event_tv, &tv, &off); + timeout_correct(base, &off); } - event_tv = tv; + base->event_tv = tv; - if (!event_count_active && !(flags & EVLOOP_NONBLOCK)) - timeout_next(&tv); + if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) + timeout_next(base, &tv); else timerclear(&tv); /* If we have no events, we just exit */ - if (!event_haveevents()) + if (!event_haveevents(base)) return (1); - res = evsel->dispatch(evbase, &tv); + res = evsel->dispatch(base, evbase, &tv); if (res == -1) return (-1); - timeout_process(); + timeout_process(base); - if (event_count_active) { - event_process_active(); - if (!event_count_active && (flags & EVLOOP_ONCE)) + if (base->event_count_active) { + event_process_active(base); + if (!base->event_count_active && (flags & EVLOOP_ONCE)) done = 1; } else if (flags & EVLOOP_NONBLOCK) done = 1; - if (evsel->recalc(evbase, 0) == -1) + if (evsel->recalc(base, evbase, 0) == -1) return (-1); } @@ -426,6 +434,9 @@ void event_set(struct event *ev, int fd, short events, void (*callback)(int, short, void *), void *arg) { + /* Take the current base - caller needs to set the real base later */ + ev->ev_base = current_base; + ev->ev_callback = callback; ev->ev_arg = arg; #ifdef WIN32 @@ -440,7 +451,20 @@ event_set(struct event *ev, int fd, short events, ev->ev_pncalls = NULL; /* by default, we put new events into the middle priority */ - ev->ev_pri = nactivequeues/2; + ev->ev_pri = current_base->nactivequeues/2; +} + +int +event_base_set(struct event_base *base, struct event *ev) +{ + /* Only innocent events may be assigned to a different base */ + if (ev->ev_flags != EVLIST_INIT) + return (-1); + + ev->ev_base = base; + ev->ev_pri = current_base->nactivequeues/2; + + return (0); } /* @@ -453,7 +477,7 @@ event_priority_set(struct event *ev, int pri) { if (ev->ev_flags & EVLIST_ACTIVE) return (-1); - if (pri < 0 || pri >= nactivequeues) + if (pri < 0 || pri >= ev->ev_base->nactivequeues) return (-1); ev->ev_pri = pri; @@ -491,6 +515,10 @@ event_pending(struct event *ev, short event, struct timeval *tv) int event_add(struct event *ev, struct timeval *tv) { + struct event_base *base = ev->ev_base; + const struct eventop *evsel = base->evsel; + void *evbase = base->evbase; + LOG_DBG((LOG_MISC, 55, "event_add: event: %p, %s%s%scall %p", ev, @@ -505,7 +533,7 @@ event_add(struct event *ev, struct timeval *tv) struct timeval now; if (ev->ev_flags & EVLIST_TIMEOUT) - event_queue_remove(ev, EVLIST_TIMEOUT); + event_queue_remove(base, ev, EVLIST_TIMEOUT); /* Check if it is active due to a timeout. Rescheduling * this timeout before the callback can be executed @@ -520,7 +548,7 @@ event_add(struct event *ev, struct timeval *tv) *ev->ev_pncalls = 0; } - event_queue_remove(ev, EVLIST_ACTIVE); + event_queue_remove(base, ev, EVLIST_ACTIVE); } gettimeofday(&now, NULL); @@ -530,17 +558,17 @@ event_add(struct event *ev, struct timeval *tv) "event_add: timeout in %d seconds, call %p", tv->tv_sec, ev->ev_callback)); - event_queue_insert(ev, EVLIST_TIMEOUT); + event_queue_insert(base, ev, EVLIST_TIMEOUT); } if ((ev->ev_events & (EV_READ|EV_WRITE)) && !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { - event_queue_insert(ev, EVLIST_INSERTED); + event_queue_insert(base, ev, EVLIST_INSERTED); return (evsel->add(evbase, ev)); } else if ((ev->ev_events & EV_SIGNAL) && !(ev->ev_flags & EVLIST_SIGNAL)) { - event_queue_insert(ev, EVLIST_SIGNAL); + event_queue_insert(base, ev, EVLIST_SIGNAL); return (evsel->add(evbase, ev)); } @@ -551,6 +579,10 @@ event_add(struct event *ev, struct timeval *tv) int event_del(struct event *ev) { + struct event_base *base = ev->ev_base; + const struct eventop *evsel = base->evsel; + void *evbase = base->evbase; + LOG_DBG((LOG_MISC, 80, "event_del: %p, callback %p", ev, ev->ev_callback)); @@ -563,16 +595,16 @@ event_del(struct event *ev) } if (ev->ev_flags & EVLIST_TIMEOUT) - event_queue_remove(ev, EVLIST_TIMEOUT); + event_queue_remove(base, ev, EVLIST_TIMEOUT); if (ev->ev_flags & EVLIST_ACTIVE) - event_queue_remove(ev, EVLIST_ACTIVE); + event_queue_remove(base, ev, EVLIST_ACTIVE); if (ev->ev_flags & EVLIST_INSERTED) { - event_queue_remove(ev, EVLIST_INSERTED); + event_queue_remove(base, ev, EVLIST_INSERTED); return (evsel->del(evbase, ev)); } else if (ev->ev_flags & EVLIST_SIGNAL) { - event_queue_remove(ev, EVLIST_SIGNAL); + event_queue_remove(base, ev, EVLIST_SIGNAL); return (evsel->del(evbase, ev)); } @@ -591,18 +623,18 @@ event_active(struct event *ev, int res, short ncalls) ev->ev_res = res; ev->ev_ncalls = ncalls; ev->ev_pncalls = NULL; - event_queue_insert(ev, EVLIST_ACTIVE); + event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE); } int -timeout_next(struct timeval *tv) +timeout_next(struct event_base *base, struct timeval *tv) { struct timeval dflt = TIMEOUT_DEFAULT; struct timeval now; struct event *ev; - if ((ev = RB_MIN(event_tree, &timetree)) == NULL) { + if ((ev = RB_MIN(event_tree, &base->timetree)) == NULL) { *tv = dflt; return (0); } @@ -624,8 +656,8 @@ timeout_next(struct timeval *tv) return (0); } -void -timeout_correct(struct timeval *off) +static void +timeout_correct(struct event_base *base, struct timeval *off) { struct event *ev; @@ -633,24 +665,24 @@ timeout_correct(struct timeval *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, &timetree) + RB_FOREACH(ev, event_tree, &base->timetree) timersub(&ev->ev_timeout, off, &ev->ev_timeout); } void -timeout_process(void) +timeout_process(struct event_base *base) { struct timeval now; struct event *ev, *next; gettimeofday(&now, NULL); - for (ev = RB_MIN(event_tree, &timetree); ev; ev = next) { + for (ev = RB_MIN(event_tree, &base->timetree); ev; ev = next) { if (timercmp(&ev->ev_timeout, &now, >)) break; - next = RB_NEXT(event_tree, &timetree, ev); + next = RB_NEXT(event_tree, &base->timetree, ev); - event_queue_remove(ev, EVLIST_TIMEOUT); + event_queue_remove(base, ev, EVLIST_TIMEOUT); /* delete this event from the I/O queues */ event_del(ev); @@ -662,7 +694,7 @@ timeout_process(void) } void -event_queue_remove(struct event *ev, int queue) +event_queue_remove(struct event_base *base, struct event *ev, int queue) { int docount = 1; @@ -674,23 +706,24 @@ event_queue_remove(struct event *ev, int queue) docount = 0; if (docount) - event_count--; + base->event_count--; ev->ev_flags &= ~queue; switch (queue) { case EVLIST_ACTIVE: if (docount) - event_count_active--; - TAILQ_REMOVE(activequeues[ev->ev_pri], ev, ev_active_next); + base->event_count_active--; + TAILQ_REMOVE(base->activequeues[ev->ev_pri], + ev, ev_active_next); break; case EVLIST_SIGNAL: TAILQ_REMOVE(&signalqueue, ev, ev_signal_next); break; case EVLIST_TIMEOUT: - RB_REMOVE(event_tree, &timetree, ev); + RB_REMOVE(event_tree, &base->timetree, ev); break; case EVLIST_INSERTED: - TAILQ_REMOVE(&eventqueue, ev, ev_next); + TAILQ_REMOVE(&base->eventqueue, ev, ev_next); break; default: errx(1, "%s: unknown queue %x", __func__, queue); @@ -698,7 +731,7 @@ event_queue_remove(struct event *ev, int queue) } void -event_queue_insert(struct event *ev, int queue) +event_queue_insert(struct event_base *base, struct event *ev, int queue) { int docount = 1; @@ -715,25 +748,26 @@ event_queue_insert(struct event *ev, int queue) docount = 0; if (docount) - event_count++; + base->event_count++; ev->ev_flags |= queue; switch (queue) { case EVLIST_ACTIVE: if (docount) - event_count_active++; - TAILQ_INSERT_TAIL(activequeues[ev->ev_pri], ev,ev_active_next); + base->event_count_active++; + TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri], + ev,ev_active_next); break; case EVLIST_SIGNAL: TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next); break; case EVLIST_TIMEOUT: { - struct event *tmp = RB_INSERT(event_tree, &timetree, ev); + struct event *tmp = RB_INSERT(event_tree, &base->timetree, ev); assert(tmp == NULL); break; } case EVLIST_INSERTED: - TAILQ_INSERT_TAIL(&eventqueue, ev, ev_next); + TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next); break; default: errx(1, "%s: unknown queue %x", __func__, queue); diff --git a/event.h b/event.h index 83230bf7..bb4019de 100644 --- a/event.h +++ b/event.h @@ -71,12 +71,14 @@ struct { \ } #endif /* !RB_ENTRY */ +struct event_base; struct event { TAILQ_ENTRY (event) ev_next; TAILQ_ENTRY (event) ev_active_next; TAILQ_ENTRY (event) ev_signal_next; RB_ENTRY (event) ev_timeout_node; + struct event_base *ev_base; #ifdef WIN32 HANDLE ev_fd; OVERLAPPED overlap; @@ -117,24 +119,21 @@ struct eventop { void *(*init)(void); int (*add)(void *, struct event *); int (*del)(void *, struct event *); - int (*recalc)(void *, int); - int (*dispatch)(void *, struct timeval *); + int (*recalc)(struct event_base *, void *, int); + int (*dispatch)(struct event_base *, void *, struct timeval *); }; #define TIMEOUT_DEFAULT {5, 0} -void event_init(void); +void *event_init(void); int event_dispatch(void); #define EVLOOP_ONCE 0x01 #define EVLOOP_NONBLOCK 0x02 int event_loop(int); +int event_loop_base(struct event_base *, int); int event_loopexit(struct timeval *); /* Causes the loop to exit */ -int timeout_next(struct timeval *); -void timeout_correct(struct timeval *); -void timeout_process(void); - #define evtimer_add(ev, tv) event_add(ev, tv) #define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) #define evtimer_del(ev) event_del(ev) @@ -171,7 +170,7 @@ int event_pending(struct event *, short, struct timeval *); /* These functions deal with event priorities */ -int event_priority_init(int); +int event_priority_init(struct event_base *, int); int event_priority_set(struct event *, int); /* These functions deal with buffering input and output */ diff --git a/kqueue.c b/kqueue.c index a17e69bb..68d6cb03 100644 --- a/kqueue.c +++ b/kqueue.c @@ -64,10 +64,6 @@ #include "event.h" -extern struct event_list timequeue; -extern struct event_list eventqueue; -extern struct event_list addqueue; - #define EVLIST_X_KQINKERNEL 0x1000 #define NEVENT 64 @@ -83,8 +79,8 @@ struct kqop { void *kq_init (void); int kq_add (void *, struct event *); int kq_del (void *, struct event *); -int kq_recalc (void *, int); -int kq_dispatch (void *, struct timeval *); +int kq_recalc (struct event_base *, void *, int); +int kq_dispatch (struct event_base *, void *, struct timeval *); int kq_insert (struct kqop *, struct kevent *); const struct eventop kqops = { @@ -131,7 +127,7 @@ kq_init(void) } int -kq_recalc(void *arg, int max) +kq_recalc(struct event_base *base, void *arg, int max) { return (0); } @@ -188,7 +184,7 @@ kq_sighandler(int sig) } int -kq_dispatch(void *arg, struct timeval *tv) +kq_dispatch(struct event_base *base, void *arg, struct timeval *tv) { struct kqop *kqop = arg; struct kevent *changes = kqop->changes; diff --git a/poll.c b/poll.c index bba594d4..ec2366d8 100644 --- a/poll.c +++ b/poll.c @@ -37,6 +37,7 @@ #include #endif #include +#include #include #include #include @@ -54,10 +55,9 @@ #endif #include "event.h" +#include "event-internal.h" #include "evsignal.h" -extern struct event_list eventqueue; - extern volatile sig_atomic_t evsignal_caught; struct pollop { @@ -70,8 +70,8 @@ struct pollop { void *poll_init (void); int poll_add (void *, struct event *); int poll_del (void *, struct event *); -int poll_recalc (void *, int); -int poll_dispatch (void *, struct timeval *); +int poll_recalc (struct event_base *, void *, int); +int poll_dispatch (struct event_base *, void *, struct timeval *); struct eventop pollops = { "poll", @@ -102,7 +102,7 @@ poll_init(void) */ int -poll_recalc(void *arg, int max) +poll_recalc(struct event_base *base, void *arg, int max) { struct pollop *pop = arg; @@ -110,7 +110,7 @@ poll_recalc(void *arg, int max) } int -poll_dispatch(void *arg, struct timeval *tv) +poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { int res, i, count, sec, nfds; struct event *ev; @@ -118,7 +118,7 @@ poll_dispatch(void *arg, struct timeval *tv) count = pop->event_count; nfds = 0; - TAILQ_FOREACH(ev, &eventqueue, ev_next) { + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { if (nfds + 1 >= count) { if (count < 32) count = 32; diff --git a/rtsig.c b/rtsig.c index 59d1ceaa..54e5cdf6 100644 --- a/rtsig.c +++ b/rtsig.c @@ -28,7 +28,6 @@ #define EVLIST_X_NORT 0x1000 /* Skip RT signals (internal) */ #include "event.h" -extern struct event_list eventqueue; extern struct event_list signalqueue; struct rtsigop { @@ -122,8 +121,8 @@ activate(struct event *ev, int flags) void *rtsig_init(void); int rtsig_add(void *, struct event *); int rtsig_del(void *, struct event *); -int rtsig_recalc(void *, int); -int rtsig_dispatch(void *, struct timeval *); +int rtsig_recalc(struct event_base *, void *, int); +int rtsig_dispatch(struct event_base *, void *, struct timeval *); struct eventop rtsigops = { "rtsig", @@ -251,13 +250,13 @@ rtsig_del(void *arg, struct event *ev) } int -rtsig_recalc(void *arg, int max) +rtsig_recalc(struct event_base *base, void *arg, int max) { return (0); } int -rtsig_dispatch(void *arg, struct timeval *tv) +rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv) { struct rtsigop *op = (struct rtsigop *) arg; struct timespec ts; @@ -311,7 +310,7 @@ rtsig_dispatch(void *arg, struct timeval *tv) return (-1); } - TAILQ_FOREACH(ev, &eventqueue, ev_next) + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) if (!(ev->ev_flags & EVLIST_X_NORT)) poll_add(op, ev); @@ -339,8 +338,8 @@ rtsig_dispatch(void *arg, struct timeval *tv) } } - for (ev = TAILQ_FIRST(&eventqueue); - flags && ev != TAILQ_END(&eventqueue); + for (ev = TAILQ_FIRST(&base->eventqueue); + flags && ev != TAILQ_END(&base->eventqueue); ev = TAILQ_NEXT(ev, ev_next)) { if (ev->ev_fd == info.si_fd) { if (flags & ev->ev_events) { diff --git a/select.c b/select.c index 2a1c6f33..865f2427 100644 --- a/select.c +++ b/select.c @@ -37,6 +37,7 @@ #include #endif #include +#include #include #include #include @@ -53,10 +54,9 @@ #endif #include "event.h" +#include "event-internal.h" #include "evsignal.h" -extern struct event_list eventqueue; - #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif @@ -74,8 +74,8 @@ struct selectop { void *select_init (void); int select_add (void *, struct event *); int select_del (void *, struct event *); -int select_recalc (void *, int); -int select_dispatch (void *, struct timeval *); +int select_recalc (struct event_base *, void *, int); +int select_dispatch (struct event_base *, void *, struct timeval *); const struct eventop selectops = { "select", @@ -106,7 +106,7 @@ select_init(void) */ int -select_recalc(void *arg, int max) +select_recalc(struct event_base *base, void *arg, int max) { struct selectop *sop = arg; fd_set *readset, *writeset; @@ -117,7 +117,7 @@ select_recalc(void *arg, int max) sop->event_fds = max; if (!sop->event_fds) { - TAILQ_FOREACH(ev, &eventqueue, ev_next) + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) if (ev->ev_fd > sop->event_fds) sop->event_fds = ev->ev_fd; } @@ -149,7 +149,7 @@ select_recalc(void *arg, int max) } int -select_dispatch(void *arg, struct timeval *tv) +select_dispatch(struct event_base *base, void *arg, struct timeval *tv) { int maxfd, res; struct event *ev, *next; @@ -158,7 +158,7 @@ select_dispatch(void *arg, struct timeval *tv) memset(sop->event_readset, 0, sop->event_fdsz); memset(sop->event_writeset, 0, sop->event_fdsz); - TAILQ_FOREACH(ev, &eventqueue, ev_next) { + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { if (ev->ev_events & EV_WRITE) FD_SET(ev->ev_fd, sop->event_writeset); if (ev->ev_events & EV_READ) @@ -188,7 +188,7 @@ select_dispatch(void *arg, struct timeval *tv) LOG_DBG((LOG_MISC, 80, "%s: select reports %d", __func__, res)); maxfd = 0; - for (ev = TAILQ_FIRST(&eventqueue); ev != NULL; ev = next) { + for (ev = TAILQ_FIRST(&base->eventqueue); ev != NULL; ev = next) { next = TAILQ_NEXT(ev, ev_next); res = 0; diff --git a/test/regress.c b/test/regress.c index 20ef0b40..f12b9231 100644 --- a/test/regress.c +++ b/test/regress.c @@ -63,6 +63,7 @@ static int roff; static int usepersist; static struct timeval tset; static struct timeval tcalled; +static struct event_base *event_base; #define TEST1 "this is a test" #define SECONDS 1 @@ -561,7 +562,7 @@ test_priorities(int npriorities) snprintf(buf, sizeof(buf), "Priorities %d: ", npriorities); setup_test(buf); - event_priority_init(npriorities); + event_priority_init(event_base, npriorities); memset(&one, 0, sizeof(one)); memset(&two, 0, sizeof(two)); @@ -621,7 +622,7 @@ main (int argc, char **argv) setvbuf(stdout, NULL, _IONBF, 0); /* Initalize the event library */ - event_init(); + event_base = event_init(); test1();