From 733b46022bae0385e9fb33e29c16eee67a5a5110 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Tue, 31 Jul 2012 20:33:57 +0000 Subject: [PATCH] Move event cache updates into event processing thread. Prior to this patch, updating the device state cache was done by the thread that originated the event. It would update the cache and then queue the event up for another thread to dispatch. This thread moves the cache updating part to be in the same thread as event dispatching. I was working with someone on a heavily loaded Asterisk system and while reviewing backtraces of the system while it was having problems, I noticed that there were a lot of threads contending for the lock on the event cache. By simply moving this into a single thread, this helped performance *a lot* and alleviated some deadlock-like symptoms. Review: https://reviewboard.asterisk.org/r/2066/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370664 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/event.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/main/event.c b/main/event.c index 23e20f333e..12d3abb7fd 100644 --- a/main/event.c +++ b/main/event.c @@ -103,6 +103,7 @@ struct ast_event { */ struct ast_event_ref { struct ast_event *event; + unsigned int cache; }; struct ast_event_ie_val { @@ -1470,23 +1471,6 @@ static void event_update_cache(struct ao2_container *cache, struct ast_event *ev ao2_unlock(cache); } -int ast_event_queue_and_cache(struct ast_event *event) -{ - struct ao2_container *container; - - container = ast_event_cache[ast_event_get_type(event)].container; - if (!container) { - ast_log(LOG_WARNING, "cache requested for non-cached event type\n"); - } else { - event_update_cache(container, event); - } - - if (ast_event_queue(event)) { - ast_event_destroy(event); - } - return 0; -} - static int handle_event(void *data) { struct ast_event_ref *event_ref = data; @@ -1497,6 +1481,16 @@ static int handle_event(void *data) }; int i; + if (event_ref->cache) { + struct ao2_container *container; + container = ast_event_cache[ast_event_get_type(event_ref->event)].container; + if (!container) { + ast_log(LOG_WARNING, "cache requested for non-cached event type\n"); + } else { + event_update_cache(container, event_ref->event); + } + } + for (i = 0; i < ARRAY_LEN(event_types); i++) { AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]); AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) { @@ -1522,7 +1516,7 @@ static int handle_event(void *data) return 0; } -int ast_event_queue(struct ast_event *event) +static int _ast_event_queue(struct ast_event *event, unsigned int cache) { struct ast_event_ref *event_ref; uint16_t host_event_type; @@ -1549,6 +1543,7 @@ int ast_event_queue(struct ast_event *event) } event_ref->event = event; + event_ref->cache = cache; res = ast_taskprocessor_push(event_dispatcher, handle_event, event_ref); if (res) { @@ -1558,6 +1553,16 @@ int ast_event_queue(struct ast_event *event) return res; } +int ast_event_queue(struct ast_event *event) +{ + return _ast_event_queue(event, 0); +} + +int ast_event_queue_and_cache(struct ast_event *event) +{ + return _ast_event_queue(event, 1); +} + static int ast_event_hash_mwi(const void *obj, const int flags) { const struct ast_event *event = obj;