From 03589ccb12c61e4ec9879298ddcceb80c930c008 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Mon, 24 Dec 2007 22:49:30 +0000 Subject: [PATCH] rollback r594: restructuring to make event activation independent. changes are going to wait for api design svn:r612 --- ChangeLog | 1 - event-internal.h | 5 +- event.c | 202 ++++++++++++++++------------------------------- event.h | 52 ++++-------- 4 files changed, 84 insertions(+), 176 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5793e9e6..d4f473b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,7 +25,6 @@ Changes in current version: o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures. o prefix {encode,decode}_tag functions with evtag to avoid collisions o fix a bug with event_rpcgen for integers - o restructure the code to make event activation independent of regular event logic o Correctly handle DNS replies with no answers set (Fixes bug 1846282) o add -Wstrict-aliasing to warnings and more cleanup o removed linger from http server socket; reported by Ilya Martynov diff --git a/event-internal.h b/event-internal.h index c1f4a2dc..f61757c1 100644 --- a/event-internal.h +++ b/event-internal.h @@ -57,7 +57,7 @@ struct event_base { int event_break; /* Set to terminate loop immediately */ /* active event management */ - TAILQ_HEAD (eventhead_list, event_head) **activequeues; + struct event_list **activequeues; int nactivequeues; /* signal handling info */ @@ -69,9 +69,6 @@ struct event_base { struct min_heap timeheap; }; -#define EVENT_CB(x) \ - (void (*)(struct event_base *, struct event_head *, int, void *))(x) - /* Internal use only: Functions that might be missing from */ #ifndef HAVE_TAILQFOREACH #define TAILQ_FIRST(head) ((head)->tqh_first) diff --git a/event.c b/event.c index 4c199152..9b54cfcc 100644 --- a/event.c +++ b/event.c @@ -155,80 +155,6 @@ gettime(struct timeval *tp) return (gettimeofday(tp, NULL)); } -/* glue stuff */ - -static int -event_is_active(struct event_head *ev) -{ - return (ev->ev_flags & EVLIST_ACTIVE); -} - -static int -event_active_events(struct event_head *ev) -{ - return (ev->ev_res); -} - -static void -event_head_set(struct event_head *ev, - void (*cb)(struct event_base *, struct event_head *, int, void *), - void *cb_arg) -{ - ev->ev_pri = 0; - ev->ev_res = 0; - ev->ev_flags = EVLIST_INIT; - - ev->ev_cb = cb; - ev->ev_cb_arg = cb_arg; -} - -static void -event_make_active(struct event_base *base, struct event_head *ev, int events) -{ - if (ev->ev_flags & EVLIST_ACTIVE) { - ev->ev_res |= events; - return; - } - - if (~ev->ev_flags & EVLIST_INTERNAL) - base->event_count++; - base->event_count_active++; - - TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri], ev, ev_active_next); - ev->ev_flags |= EVLIST_ACTIVE; - ev->ev_res = events; -} - -static void -event_remove_active(struct event_base *base, struct event_head *ev) -{ - if (!(ev->ev_flags & EVLIST_ACTIVE)) - event_errx(1, "%s: %p not on active queue", __func__, ev); - if (~ev->ev_flags & EVLIST_INTERNAL) - base->event_count--; - base->event_count_active--; - - TAILQ_REMOVE(base->activequeues[ev->ev_pri], ev, ev_active_next); - ev->ev_flags &= ~EVLIST_ACTIVE; -} - -static int -event_head_priority_set(struct event_base *base, - struct event_head *ev, int pri) -{ - if (event_is_active(ev)) - return (-1); - - if (pri < 0 || pri >= base->nactivequeues) - return (-1); - - ev->ev_pri = pri; - - return (0); -} - -/* back to normal stuff */ - struct event_base * event_init(void) { @@ -375,9 +301,9 @@ event_base_priority_init(struct event_base *base, int npriorities) /* Allocate our priority queues */ base->nactivequeues = npriorities; - base->activequeues = (struct eventhead_list **)event_calloc( + base->activequeues = (struct event_list **)event_calloc( base->nactivequeues, - npriorities * sizeof(struct eventhead_list *)); + npriorities * sizeof(struct event_list *)); if (base->activequeues == NULL) event_err(1, "%s: calloc", __func__); @@ -397,32 +323,6 @@ event_haveevents(struct event_base *base) return (base->event_count > 0); } -/* - * Traditional libevent events get deleted when they become active - * unless they have specifically been set to be persistent. - */ - -static void -event_legacy_handler(struct event_base *base, struct event *ev, - int events, void *arg) -{ - short ncalls; - - if (!(ev->ev_events & EV_PERSIST)) - event_del(ev); - - /* Allows deletes to work */ - ncalls = ev->ev_ncalls; - ev->ev_pncalls = &ncalls; - while (ncalls) { - ncalls--; - ev->ev_ncalls = ncalls; - (*ev->ev_callback)((int)ev->ev_fd, events, ev->ev_arg); - if (event_gotsig || base->event_break) - return; - } -} - /* * Active events are stored in priority queues. Lower priorities are always * process before higher priorities. Low priority events can starve high @@ -432,9 +332,10 @@ event_legacy_handler(struct event_base *base, struct event *ev, static void event_process_active(struct event_base *base) { - struct event_head *ev; - struct eventhead_list *activeq = NULL; + struct event *ev; + struct event_list *activeq = NULL; int i; + short ncalls; for (i = 0; i < base->nactivequeues; ++i) { if (TAILQ_FIRST(base->activequeues[i]) != NULL) { @@ -446,11 +347,21 @@ event_process_active(struct event_base *base) assert(activeq != NULL); for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) { - event_remove_active(base, ev); + if (ev->ev_events & EV_PERSIST) + event_queue_remove(base, ev, EVLIST_ACTIVE); + else + event_del(ev); - (*ev->ev_cb)(base, ev, ev->ev_res, ev->ev_cb_arg); - if (event_gotsig || base->event_break) - return; + /* Allows deletes to work */ + ncalls = ev->ev_ncalls; + ev->ev_pncalls = &ncalls; + while (ncalls) { + ncalls--; + ev->ev_ncalls = ncalls; + (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg); + if (event_gotsig || base->event_break) + return; + } } } @@ -674,35 +585,34 @@ void event_set(struct event *ev, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg) { - event_head_set(EVHEAD(ev), EVENT_CB(event_legacy_handler), NULL); - /* Take the current base - caller needs to set the real base later */ ev->ev_base = current_base; - ev->ev_flags = 0; ev->ev_callback = callback; ev->ev_arg = arg; ev->ev_fd = fd; ev->ev_events = events; + ev->ev_res = 0; + ev->ev_flags = EVLIST_INIT; ev->ev_ncalls = 0; ev->ev_pncalls = NULL; min_heap_elem_init(ev); /* by default, we put new events into the middle priority */ - if (current_base) - event_priority_set(ev, current_base->nactivequeues/2); + if(current_base) + 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 (event_is_active(EVHEAD(ev)) || ev->ev_flags != 0) + if (ev->ev_flags != EVLIST_INIT) return (-1); ev->ev_base = base; - event_head_priority_set(base, EVHEAD(ev), base->nactivequeues/2); + ev->ev_pri = base->nactivequeues/2; return (0); } @@ -715,7 +625,14 @@ event_base_set(struct event_base *base, struct event *ev) int event_priority_set(struct event *ev, int pri) { - return (event_head_priority_set(ev->ev_base, EVHEAD(ev), pri)); + if (ev->ev_flags & EVLIST_ACTIVE) + return (-1); + if (pri < 0 || pri >= ev->ev_base->nactivequeues) + return (-1); + + ev->ev_pri = pri; + + return (0); } /* @@ -730,8 +647,8 @@ event_pending(struct event *ev, short event, struct timeval *tv) if (ev->ev_flags & EVLIST_INSERTED) flags |= (ev->ev_events & (EV_READ|EV_WRITE)); - if (event_is_active(EVHEAD(ev))) - flags |= event_active_events(EVHEAD(ev)); + if (ev->ev_flags & EVLIST_ACTIVE) + flags |= ev->ev_res; if (ev->ev_flags & EVLIST_TIMEOUT) flags |= EV_TIMEOUT; if (ev->ev_flags & EVLIST_SIGNAL) @@ -780,8 +697,8 @@ event_add(struct event *ev, struct timeval *tv) /* Check if it is active due to a timeout. Rescheduling * this timeout before the callback can be executed * removes it from the active list. */ - if (event_is_active(EVHEAD(ev)) && - (event_active_events(EVHEAD(ev)) & EV_TIMEOUT)) { + if ((ev->ev_flags & EVLIST_ACTIVE) && + (ev->ev_res & EV_TIMEOUT)) { /* See if we are just active executing this * event in a loop */ @@ -790,7 +707,7 @@ event_add(struct event *ev, struct timeval *tv) *ev->ev_pncalls = 0; } - event_remove_active(base, EVHEAD(ev)); + event_queue_remove(base, ev, EVLIST_ACTIVE); } gettime(&now); @@ -803,13 +720,11 @@ event_add(struct event *ev, struct timeval *tv) event_queue_insert(base, ev, EVLIST_TIMEOUT); } - if (ev->ev_events & (EV_READ|EV_WRITE)) { - if ((ev->ev_flags & EVLIST_INSERTED) == 0 && - !event_is_active(EVHEAD(ev))) { - event_queue_insert(base, ev, EVLIST_INSERTED); + if ((ev->ev_events & (EV_READ|EV_WRITE)) && + !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { + event_queue_insert(base, ev, EVLIST_INSERTED); - return (evsel->add(evbase, ev)); - } + return (evsel->add(evbase, ev)); } else if ((ev->ev_events & EV_SIGNAL) && !(ev->ev_flags & EVLIST_SIGNAL)) { event_queue_insert(base, ev, EVLIST_SIGNAL); @@ -849,8 +764,8 @@ event_del(struct event *ev) if (ev->ev_flags & EVLIST_TIMEOUT) event_queue_remove(base, ev, EVLIST_TIMEOUT); - if (event_is_active(EVHEAD(ev))) - event_remove_active(base, EVHEAD(ev)); + if (ev->ev_flags & EVLIST_ACTIVE) + event_queue_remove(base, ev, EVLIST_ACTIVE); if (ev->ev_flags & EVLIST_INSERTED) { event_queue_remove(base, ev, EVLIST_INSERTED); @@ -866,16 +781,16 @@ event_del(struct event *ev) void event_active(struct event *ev, int res, short ncalls) { - /* If we get different kinds of events, add them together */ - int was_active = event_is_active(EVHEAD(ev)); - - event_make_active(ev->ev_base, EVHEAD(ev), res); - - if (was_active) + /* We get different kinds of events, add them together */ + if (ev->ev_flags & EVLIST_ACTIVE) { + ev->ev_res |= res; return; + } + ev->ev_res = res; ev->ev_ncalls = ncalls; ev->ev_pncalls = NULL; + event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE); } static int @@ -983,6 +898,11 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue) ev->ev_flags &= ~queue; switch (queue) { + 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; @@ -1000,15 +920,25 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue) void event_queue_insert(struct event_base *base, struct event *ev, int queue) { - if (ev->ev_flags & queue) + if (ev->ev_flags & queue) { + /* Double insertion is possible for active events */ + if (queue & EVLIST_ACTIVE) + return; + event_errx(1, "%s: %p(fd %d) already on queue %x", __func__, ev, ev->ev_fd, queue); + } if (~ev->ev_flags & EVLIST_INTERNAL) base->event_count++; ev->ev_flags |= queue; switch (queue) { + 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; diff --git a/event.h b/event.h index 9e5c4eaa..cbc8f1b7 100644 --- a/event.h +++ b/event.h @@ -192,11 +192,11 @@ typedef unsigned short u_short; /* EVLIST_X_ Private space: 0x1000-0xf000 */ #define EVLIST_ALL (0xf000 | 0x9f) -#define EV_TIMEOUT 0x0001 -#define EV_READ 0x0002 -#define EV_WRITE 0x0004 -#define EV_SIGNAL 0x0008 -#define EV_PERSIST 0x0800 /* Persistant event */ +#define EV_TIMEOUT 0x01 +#define EV_READ 0x02 +#define EV_WRITE 0x04 +#define EV_SIGNAL 0x08 +#define EV_PERSIST 0x10 /* Persistant event */ /* Fix so that ppl dont have to run with */ #ifndef TAILQ_ENTRY @@ -208,36 +208,13 @@ struct { \ } #endif /* !TAILQ_ENTRY */ -#define EVHEAD(x) ((struct event_head *)(x)) - struct event_base; - -/** a structure common to all events - * - * struct event_head contains elements common to all event types. - * it needs to be the first element of any structure that defines - * a new event type. - */ -struct event_head { - TAILQ_ENTRY (event_head) (ev_active_next); - int ev_pri; /*!< smaller numbers are higher priority */ - int ev_res; /*!< result passed to event callback */ - int ev_flags; /*!< keeps track of initialization and activation */ - - void (*ev_cb)(struct event_base *, struct event_head *, - int events, void *); - void *ev_cb_arg; -}; - struct event { - struct event_head head; - - TAILQ_ENTRY (event) (ev_next); + TAILQ_ENTRY (event) ev_next; + TAILQ_ENTRY (event) ev_active_next; TAILQ_ENTRY (event) ev_signal_next; unsigned int min_heap_idx; /* for managing timeouts */ - int ev_flags; - struct event_base *ev_base; evutil_socket_t ev_fd; @@ -247,8 +224,13 @@ struct event { struct timeval ev_timeout; + int ev_pri; /* smaller numbers are higher priority */ + void (*ev_callback)(evutil_socket_t, short, void *arg); void *ev_arg; + + int ev_res; /* result passed to event callback */ + int ev_flags; }; #define EVENT_SIGNAL(ev) (int)(ev)->ev_fd @@ -482,7 +464,7 @@ int event_base_loopbreak(struct event_base *); */ #define evtimer_del(ev) event_del(ev) #define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define evtimer_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT) +#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) /** * Add a timeout event. @@ -511,14 +493,14 @@ int event_base_loopbreak(struct event_base *); #define timeout_del(ev) event_del(ev) #define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define timeout_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT) +#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) #define signal_add(ev, tv) event_add(ev, tv) #define signal_set(ev, x, cb, arg) \ event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) #define signal_del(ev) event_del(ev) #define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv) -#define signal_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT) +#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) /** Prepare an event structure to be added. @@ -659,9 +641,9 @@ int event_pending(struct event *, short, struct timeval *); initialized */ #ifdef WIN32 -#define event_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE) +#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE) #else -#define event_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT) +#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) #endif