From 4632b78e01a312ae716bc17322c462be53182eca Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 8 Sep 2010 13:22:55 -0400 Subject: [PATCH] Minimize calls to base_notify implementation functions, thereby avoiding needless syscalls The trick here is that if we already told the base to wake up, and it hasn't woken up yet, we don't need to tell it to wake up again. This should help lots with inherently multithreaded code like IOCP. --- event-internal.h | 3 +++ event.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/event-internal.h b/event-internal.h index e52c129b..122195b3 100644 --- a/event-internal.h +++ b/event-internal.h @@ -262,6 +262,9 @@ struct event_base { enum event_base_config_flag flags; /* Notify main thread to wake up break, etc. */ + /** True if the base already has a pending notify, and we don't need + * to add any more. */ + int is_notify_pending; /** A socketpair used by some th_notify functions to wake up the main * thread. */ int th_notify_fd[2]; diff --git a/event.c b/event.c index 0c8238d7..902aed54 100644 --- a/event.c +++ b/event.c @@ -1902,8 +1902,12 @@ evthread_notify_base_eventfd(struct event_base *base) static int evthread_notify_base(struct event_base *base) { + EVENT_BASE_ASSERT_LOCKED(base); if (!base->th_notify_fn) return -1; + if (base->is_notify_pending) + return 0; + base->is_notify_pending = 1; return base->th_notify_fn(base); } @@ -2247,8 +2251,6 @@ event_deferred_cb_schedule(struct deferred_cb_queue *queue, cb->queued = 1; TAILQ_INSERT_TAIL(&queue->deferred_cb_list, cb, cb_next); ++queue->active_count; - /* XXXX Can we get away with doing this only when adding - * the first active deferred_cb to the queue? */ if (queue->notify_fn) queue->notify_fn(queue, queue->notify_arg); } @@ -2594,11 +2596,15 @@ evthread_notify_drain_eventfd(evutil_socket_t fd, short what, void *arg) { ev_uint64_t msg; ev_ssize_t r; + struct event_base *base = arg; r = read(fd, (void*) &msg, sizeof(msg)); if (r<0 && errno != EAGAIN) { event_sock_warn(fd, "Error reading from eventfd"); } + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + base->is_notify_pending = 0; + EVBASE_RELEASE_LOCK(base, th_base_lock); } #endif @@ -2606,6 +2612,7 @@ static void evthread_notify_drain_default(evutil_socket_t fd, short what, void *arg) { unsigned char buf[1024]; + struct event_base *base = arg; #ifdef WIN32 while (recv(fd, (char*)buf, sizeof(buf), 0) > 0) ; @@ -2613,6 +2620,10 @@ evthread_notify_drain_default(evutil_socket_t fd, short what, void *arg) while (read(fd, (char*)buf, sizeof(buf)) > 0) ; #endif + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + base->is_notify_pending = 0; + EVBASE_RELEASE_LOCK(base, th_base_lock); } int