From 8c750eaff8412b8387eeca1e75d62540ad725f00 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Sat, 3 May 2008 21:37:33 +0000 Subject: [PATCH] separate signal events from io events svn:r760 --- ChangeLog | 1 + event-internal.h | 10 +++++ event.c | 76 +++++++++++++++++++++++++---------- include/event2/event_struct.h | 23 ++++++++--- signal.c | 2 - 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8122ac15..b3bc09cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -86,6 +86,7 @@ Changes in current version: o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient. o reduce system calls for getting current time by caching it. + o separate signal events from io events; making the code less complex. Changes in 1.4.0: o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. diff --git a/event-internal.h b/event-internal.h index e80171ee..10fd5d5b 100644 --- a/event-internal.h +++ b/event-internal.h @@ -36,6 +36,16 @@ extern "C" { #include "evsignal.h" #include "mm-internal.h" +/* map union members back */ + +/* mutually exclusive */ +#define ev_next _ev.ev_io.ev_next +#define ev_signal_next _ev.ev_signal.ev_signal_next + +/* used only by signals */ +#define ev_ncalls _ev.ev_signal.ev_ncalls +#define ev_pncalls _ev.ev_signal.ev_pncalls + struct eventop { const char *name; void *(*init)(struct event_base *); diff --git a/event.c b/event.c index 0215deae..740d8f08 100644 --- a/event.c +++ b/event.c @@ -136,6 +136,8 @@ 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 void event_signal_closure(struct event_base *, struct event *ev); + static void detect_monotonic(void) { @@ -360,6 +362,23 @@ event_haveevents(struct event_base *base) return (base->event_count > 0); } +static void +event_signal_closure(struct event_base *base, struct event *ev) +{ + short ncalls; + + /* 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; + } +} + /* * Active events are stored in priority queues. Lower priorities are always * process before higher priorities. Low priority events can starve high @@ -372,7 +391,6 @@ event_process_active(struct event_base *base) struct event *ev; struct event_list *activeq = NULL; int i; - short ncalls; EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock); @@ -394,16 +412,13 @@ event_process_active(struct event_base *base) EVTHREAD_RELEASE_LOCK(base, EVTHREAD_WRITE, th_base_lock); - /* 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; - } + if (ev->ev_closure != NULL) + (*ev->ev_closure)(base, ev); + else + (*ev->ev_callback)( + (int)ev->ev_fd, ev->ev_res, ev->ev_arg); + if (event_gotsig || base->event_break) + return; EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock); } @@ -655,6 +670,15 @@ event_set(struct event *ev, evutil_socket_t fd, short events, ev->ev_ncalls = 0; ev->ev_pncalls = NULL; + if (events & EV_SIGNAL) { + if ((events & (EV_READ|EV_WRITE)) != 0) + event_errx(1, "%s: EV_SIGNAL incompatible use", + __func__); + ev->ev_closure = event_signal_closure; + } else { + ev->ev_closure = NULL; + } + min_heap_elem_init(ev); /* by default, we put new events into the middle priority */ @@ -804,12 +828,14 @@ event_add_internal(struct event *ev, struct timeval *tv) * removes it from the active list. */ if ((ev->ev_flags & EVLIST_ACTIVE) && (ev->ev_res & EV_TIMEOUT)) { - /* See if we are just active executing this - * event in a loop - */ - if (ev->ev_ncalls && ev->ev_pncalls) { - /* Abort loop */ - *ev->ev_pncalls = 0; + if (ev->ev_flags & EVLIST_SIGNAL) { + /* See if we are just active executing + * this event in a loop + */ + if (ev->ev_ncalls && ev->ev_pncalls) { + /* Abort loop */ + *ev->ev_pncalls = 0; + } } event_queue_remove(base, ev, EVLIST_ACTIVE); @@ -880,9 +906,11 @@ event_del_internal(struct event *ev) assert(!(ev->ev_flags & ~EVLIST_ALL)); /* See if we are just active executing this event in a loop */ - if (ev->ev_ncalls && ev->ev_pncalls) { - /* Abort loop */ - *ev->ev_pncalls = 0; + if (ev->ev_flags & EVLIST_SIGNAL) { + if (ev->ev_ncalls && ev->ev_pncalls) { + /* Abort loop */ + *ev->ev_pncalls = 0; + } } if (ev->ev_flags & EVLIST_TIMEOUT) @@ -931,8 +959,12 @@ event_active_internal(struct event *ev, int res, short ncalls) base = ev->ev_base; ev->ev_res = res; - ev->ev_ncalls = ncalls; - ev->ev_pncalls = NULL; + + if (ev->ev_flags & EVLIST_SIGNAL) { + ev->ev_ncalls = ncalls; + ev->ev_pncalls = NULL; + } + event_queue_insert(base, ev, EVLIST_ACTIVE); } diff --git a/include/event2/event_struct.h b/include/event2/event_struct.h index 4256d89f..b85e4528 100644 --- a/include/event2/event_struct.h +++ b/include/event2/event_struct.h @@ -85,22 +85,35 @@ struct { \ struct event_base; struct event { - TAILQ_ENTRY (event) ev_next; - TAILQ_ENTRY (event) ev_active_next; - TAILQ_ENTRY (event) ev_signal_next; + TAILQ_ENTRY (event) (ev_active_next); unsigned int min_heap_idx; /* for managing timeouts */ struct event_base *ev_base; evutil_socket_t ev_fd; + union { + /* used by io events */ + struct { + TAILQ_ENTRY (event) (ev_next); + } ev_io; + + /* used by signal events */ + struct { + TAILQ_ENTRY (event) (ev_signal_next); + short ev_ncalls; + /* Allows deletes in callback */ + short *ev_pncalls; + } ev_signal; + } _ev; + short ev_events; - short ev_ncalls; - short *ev_pncalls; /* Allows deletes in callback */ struct timeval ev_timeout; int ev_pri; /* smaller numbers are higher priority */ + /* allows us to adopt for different types of events */ + void (*ev_closure)(struct event_base *, struct event *); void (*ev_callback)(evutil_socket_t, short, void *arg); void *ev_arg; diff --git a/signal.c b/signal.c index 4bfe9bcd..e9b8664e 100644 --- a/signal.c +++ b/signal.c @@ -188,8 +188,6 @@ evsignal_add(struct event *ev) struct event_base *base = ev->ev_base; struct evsignal_info *sig = &ev->ev_base->sig; - if (ev->ev_events & (EV_READ|EV_WRITE)) - event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); evsignal = EVENT_SIGNAL(ev); event_debug(("%s: %p: changing signal handler", __func__, ev)); -- 2.40.0