diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-08-12 10:49:19 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-08-18 08:56:23 -0400 |
commit | 9ec94f1d22a87fbf86f721c6106f78f85b8be33c (patch) | |
tree | 9f2e36dad0208158c77be8a986e49973a4401988 /src/or/control.c | |
parent | e2a6a7ec6178834c3de7a3be614679120e2c00c8 (diff) | |
download | tor-9ec94f1d22a87fbf86f721c6106f78f85b8be33c.tar.gz tor-9ec94f1d22a87fbf86f721c6106f78f85b8be33c.zip |
Use thread-local storage to block event_queue recursion.
Diffstat (limited to 'src/or/control.c')
-rw-r--r-- | src/or/control.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/src/or/control.c b/src/or/control.c index 2be99d5d7a..c80546529e 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -594,9 +594,9 @@ typedef struct queued_event_s { char *msg; } queued_event_t; -/** If this is greater than 0, we don't allow new events to be queued. - * XXXX This should be thread-local. */ -static int block_event_queue = 0; +/** Pointer to int. If this is greater than 0, we don't allow new events to be + * queued. */ +static tor_threadlocal_t block_event_queue; /** Holds a smartlist of queued_event_t objects that may need to be sent * to one or more controllers */ @@ -631,9 +631,21 @@ control_initialize_event_queue(void) if (queued_control_events_lock == NULL) { queued_control_events_lock = tor_mutex_new(); + tor_threadlocal_init(&block_event_queue); } } +static int * +get_block_event_queue(void) +{ + int *val = tor_threadlocal_get(&block_event_queue); + if (PREDICT_UNLIKELY(val == NULL)) { + val = tor_malloc_zero(sizeof(int)); + tor_threadlocal_set(&block_event_queue, val); + } + return val; +} + /** Helper: inserts an event on the list of events queued to be sent to * one or more controllers, and schedules the events to be flushed if needed. * @@ -655,21 +667,20 @@ queue_control_event_string,(uint16_t event, char *msg)) return; } - queued_event_t *ev = tor_malloc(sizeof(*ev)); - ev->event = event; - ev->msg = msg; - - tor_mutex_acquire(queued_control_events_lock); - if (block_event_queue) { /* XXXX This should be thread-specific. */ - tor_mutex_release(queued_control_events_lock); + int *block_event_queue = get_block_event_queue(); + if (*block_event_queue) { tor_free(msg); - tor_free(ev); return; } + queued_event_t *ev = tor_malloc(sizeof(*ev)); + ev->event = event; + ev->msg = msg; + /* No queueing an event while queueing an event */ - ++block_event_queue; + ++*block_event_queue; + tor_mutex_acquire(queued_control_events_lock); tor_assert(queued_control_events); smartlist_add(queued_control_events, ev); @@ -679,10 +690,10 @@ queue_control_event_string,(uint16_t event, char *msg)) flush_queued_event_pending = 1; } - --block_event_queue; - tor_mutex_release(queued_control_events_lock); + --*block_event_queue; + /* We just put an event on the queue; mark the queue to be * flushed. We only do this from the main thread for now; otherwise, * we'd need to incur locking overhead in Libevent or use a socket. @@ -718,9 +729,11 @@ queued_events_flush_all(int force) smartlist_t *controllers = smartlist_new(); smartlist_t *queued_events; + int *block_event_queue = get_block_event_queue(); + ++*block_event_queue; + tor_mutex_acquire(queued_control_events_lock); /* No queueing an event while flushing events. */ - ++block_event_queue; flush_queued_event_pending = 0; queued_events = queued_control_events; queued_control_events = smartlist_new(); @@ -760,9 +773,7 @@ queued_events_flush_all(int force) smartlist_free(queued_events); smartlist_free(controllers); - tor_mutex_acquire(queued_control_events_lock); - --block_event_queue; - tor_mutex_release(queued_control_events_lock); + --*block_event_queue; } /** Libevent callback: Flushes pending events to controllers that are |