Avoid needlessly calling evthread_notify_base() when the loop is not running

Also make sure that we always hold the base lock when calling evthread_notify_base.
This commit is contained in:
Nick Mathewson 2010-09-08 13:02:58 -04:00
parent 495ed66705
commit c7a06bfaee
2 changed files with 20 additions and 9 deletions

16
event.c
View File

@ -471,7 +471,7 @@ static void
notify_base_cbq_callback(struct deferred_cb_queue *cb, void *baseptr) notify_base_cbq_callback(struct deferred_cb_queue *cb, void *baseptr)
{ {
struct event_base *base = baseptr; struct event_base *base = baseptr;
if (!EVBASE_IN_THREAD(base)) if (EVBASE_NEED_NOTIFY(base))
evthread_notify_base(base); evthread_notify_base(base);
} }
@ -1390,18 +1390,20 @@ event_loopbreak(void)
int int
event_base_loopbreak(struct event_base *event_base) event_base_loopbreak(struct event_base *event_base)
{ {
int r = 0;
if (event_base == NULL) if (event_base == NULL)
return (-1); return (-1);
EVBASE_ACQUIRE_LOCK(event_base, th_base_lock); EVBASE_ACQUIRE_LOCK(event_base, th_base_lock);
event_base->event_break = 1; event_base->event_break = 1;
EVBASE_RELEASE_LOCK(event_base, th_base_lock);
if (!EVBASE_IN_THREAD(event_base)) { if (EVBASE_NEED_NOTIFY(event_base)) {
return evthread_notify_base(event_base); r = evthread_notify_base(event_base);
} else { } else {
return (0); r = (0);
} }
EVBASE_RELEASE_LOCK(event_base, th_base_lock);
return r;
} }
int int
@ -2050,7 +2052,7 @@ event_add_internal(struct event *ev, const struct timeval *tv,
} }
/* if we are not in the right thread, we need to wake up the loop */ /* if we are not in the right thread, we need to wake up the loop */
if (res != -1 && notify && !EVBASE_IN_THREAD(base)) if (res != -1 && notify && EVBASE_NEED_NOTIFY(base))
evthread_notify_base(base); evthread_notify_base(base);
_event_debug_note_add(ev); _event_debug_note_add(ev);
@ -2144,7 +2146,7 @@ event_del_internal(struct event *ev)
} }
/* if we are not in the right thread, we need to wake up the loop */ /* if we are not in the right thread, we need to wake up the loop */
if (res != -1 && notify && !EVBASE_IN_THREAD(base)) if (res != -1 && notify && EVBASE_NEED_NOTIFY(base))
evthread_notify_base(base); evthread_notify_base(base);
_event_debug_note_del(ev); _event_debug_note_del(ev);

View File

@ -48,12 +48,20 @@ extern int _evthread_lock_debugging_enabled;
#define EVTHREAD_GET_ID() \ #define EVTHREAD_GET_ID() \
(_evthread_id_fn ? _evthread_id_fn() : 1) (_evthread_id_fn ? _evthread_id_fn() : 1)
/** Return true iff we're in the thread that is currently running a given /** Return true iff we're in the thread that is currently (or most recently)
* event_base's loop. */ * running a given event_base's loop. Requires lock. */
#define EVBASE_IN_THREAD(base) \ #define EVBASE_IN_THREAD(base) \
(_evthread_id_fn == NULL || \ (_evthread_id_fn == NULL || \
(base)->th_owner_id == _evthread_id_fn()) (base)->th_owner_id == _evthread_id_fn())
/** Return true iff we need to notify the base's main thread about changes to
* its state, because it's currently running the main loop in another
* thread. Requires lock. */
#define EVBASE_NEED_NOTIFY(base) \
(_evthread_id_fn != NULL && \
(base)->running_loop && \
(base)->th_owner_id != _evthread_id_fn())
/** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to /** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to
NULL if locking is not enabled. */ NULL if locking is not enabled. */
#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ #define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \
@ -196,6 +204,7 @@ EVLOCK_TRY_LOCK(void *lock)
#define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT #define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT
#define EVBASE_IN_THREAD(base) 1 #define EVBASE_IN_THREAD(base) 1
#define EVBASE_NEED_NOTIFY(base) 0
#define EVBASE_ACQUIRE_LOCK(base, lock) _EVUTIL_NIL_STMT #define EVBASE_ACQUIRE_LOCK(base, lock) _EVUTIL_NIL_STMT
#define EVBASE_RELEASE_LOCK(base, lock) _EVUTIL_NIL_STMT #define EVBASE_RELEASE_LOCK(base, lock) _EVUTIL_NIL_STMT
#define EVLOCK_ASSERT_LOCKED(lock) _EVUTIL_NIL_STMT #define EVLOCK_ASSERT_LOCKED(lock) _EVUTIL_NIL_STMT