diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c index eba9bcc676..d9f65c4a2f 100644 --- a/components/esp_event/esp_event.c +++ b/components/esp_event/esp_event.c @@ -30,12 +30,10 @@ /* ---------------------------- Definitions --------------------------------- */ #ifdef CONFIG_EVENT_LOOP_PROFILING -// loop@ rx: dr: inv: run: -#define LOOP_DUMP_FORMAT "loop@%p,%s rx:%u dr:%u inv:%u run:%lld us\n" -// event@ proc: run: -#define EVENT_DUMP_FORMAT "\tevent@%s:%d proc:%u run:%lld us\n" - // handler@
inv: run: -#define HANDLER_DUMP_FORMAT "\t\thandler@%p inv:%u run:%lld us\n" +// LOOP @ rx: dr: +#define LOOP_DUMP_FORMAT "LOOP @%p,%s rx:%u dr:%u\n" + // handler @
ev: inv: time: +#define HANDLER_DUMP_FORMAT " HANDLER @%p ev:%s,%s inv:%u time:%lld us\n" #define PRINT_DUMP_INFO(dst, sz, ...) do { \ int cb = snprintf(dst, sz, __VA_ARGS__); \ @@ -63,33 +61,33 @@ static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED; static int esp_event_dump_prepare() { esp_event_loop_instance_t* loop_it; - esp_event_base_instance_t* base_it; - esp_event_id_instance_t* id_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; esp_event_handler_instance_t* handler_it; // Count the number of items to be printed. This is needed to compute how much memory to reserve. - int loops = 0, events = 0, handlers = 0; + int loops = 0, handlers = 0; portENTER_CRITICAL(&s_event_loops_spinlock); - SLIST_FOREACH(loop_it, &s_event_loops, loop_entry) { - SLIST_FOREACH(handler_it, &(loop_it->loop_handlers), handler_entry) { - handlers++; - } - SLIST_FOREACH(base_it, &(loop_it->event_bases), event_base_entry) { - SLIST_FOREACH(handler_it, &(base_it->base_handlers), handler_entry) { + SLIST_FOREACH(loop_it, &s_event_loops, next) { + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { handlers++; } - // Print event-level handlers - SLIST_FOREACH(id_it, &(base_it->event_ids), event_id_entry) { - SLIST_FOREACH(handler_it, &(id_it->handlers), handler_entry) { + + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { handlers++; } - events++; + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + handlers++; + } + } } - events++; } - events++; loops++; } @@ -97,9 +95,8 @@ static int esp_event_dump_prepare() // Reserve slightly more memory than computed int allowance = 3; - int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 3 * 11 + 20 )) + - ((events + allowance) * (sizeof(EVENT_DUMP_FORMAT) + 10 + 20 + 11 + 20)) + - ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 11 + 20))); + int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 2 * 11)) + + ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 2 * 20 + 11 + 20))); return size; } @@ -123,167 +120,257 @@ static void esp_event_loop_run_task(void* args) vTaskSuspend(NULL); } -// Functions that operate on handler instance -static esp_event_handler_instance_t* handler_instance_create(esp_event_handler_t event_handler, void* event_handler_arg) +static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_instance_t *handler, esp_event_post_instance_t post) +{ + ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, handler->handler, loop); + +#ifdef CONFIG_EVENT_LOOP_PROFILING + int64_t start, diff; + start = esp_timer_get_time(); +#endif + // Execute the handler + (*(handler->handler))(handler->arg, post.base, post.id, post.data); + +#ifdef CONFIG_EVENT_LOOP_PROFILING + diff = esp_timer_get_time() - start; + + xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); + + handler->invoked++; + handler->time += diff; + + xSemaphoreGive(loop->profiling_mutex); +#endif +} + +static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_t handler, void* handler_arg) { esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance)); - if (handler_instance != NULL) { - handler_instance->handler = event_handler; - handler_instance->arg = event_handler_arg; + if (!handler_instance) { + return ESP_ERR_NO_MEM; } - return handler_instance; + handler_instance->handler = handler; + handler_instance->arg = handler_arg; + + if(SLIST_EMPTY(handlers)) { + SLIST_INSERT_HEAD(handlers, handler_instance, next); + } + else { + esp_event_handler_instance_t *it = NULL, *last = NULL; + + SLIST_FOREACH(it, handlers, next) { + if (handler == it->handler) { + it->arg = handler_arg; + ESP_LOGW(TAG, "handler already registered, overwriting"); + return ESP_OK; + } + last = it; + } + + SLIST_INSERT_AFTER(last, handler_instance, next); + } + + return ESP_OK; } -static void handler_instance_delete(esp_event_handler_instance_t* handler_instance) +static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler, void* handler_arg) { - free(handler_instance); + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(base_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_id_node_t *it = NULL, *id_node = NULL, *last_id_node = NULL; + + SLIST_FOREACH(it, &(base_node->id_nodes), next) { + if (it->id == id) { + id_node = it; + } + last_id_node = it; + } + + if (!last_id_node || !id_node) { + id_node = (esp_event_id_node_t*) calloc(1, sizeof(*id_node)); + + if (!id_node) { + ESP_LOGI(TAG, "alloc for new id node failed"); + return ESP_ERR_NO_MEM; + } + + id_node->id = id; + + SLIST_INIT(&(id_node->handlers)); + + err = handler_instances_add(&(id_node->handlers), handler, handler_arg); + + if (err == ESP_OK) { + if (!last_id_node) { + SLIST_INSERT_HEAD(&(base_node->id_nodes), id_node, next); + } + else { + SLIST_INSERT_AFTER(last_id_node, id_node, next); + } + } + + return err; + } + else { + return handler_instances_add(&(id_node->handlers), handler, handler_arg); + } + } } -// Functions that operate on handler instance list -static esp_event_handler_instance_t* handler_instances_find(esp_event_handler_instances_t* handlers, esp_event_handler_t handler) +static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler, void* handler_arg) { - esp_event_handler_instance_t* it; + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(loop_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_base_node_t *it = NULL, *base_node = NULL, *last_base_node = NULL; - SLIST_FOREACH(it, handlers, handler_entry) { + SLIST_FOREACH(it, &(loop_node->base_nodes), next) { + if (it->base == base) { + base_node = it; + } + last_base_node = it; + } + + if (!last_base_node || + !base_node || + (base_node && !SLIST_EMPTY(&(base_node->id_nodes)) && id == ESP_EVENT_ANY_ID) || + (last_base_node && last_base_node->base != base && !SLIST_EMPTY(&(last_base_node->id_nodes)) && id == ESP_EVENT_ANY_ID)) { + base_node = (esp_event_base_node_t*) calloc(1, sizeof(*base_node)); + + if (!base_node) { + ESP_LOGE(TAG, "alloc mem for new base node failed"); + return ESP_ERR_NO_MEM; + } + + base_node->base = base; + + SLIST_INIT(&(base_node->handlers)); + SLIST_INIT(&(base_node->id_nodes)); + + err = base_node_add_handler(base_node, id, handler, handler_arg); + + if (err == ESP_OK) { + if (!last_base_node) { + SLIST_INSERT_HEAD(&(loop_node->base_nodes), base_node, next); + } + else { + SLIST_INSERT_AFTER(last_base_node, base_node, next); + } + } + + return err; + } else { + return base_node_add_handler(base_node, id, handler, handler_arg); + } + } +} + +static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_t handler) +{ + esp_event_handler_instance_t *it, *temp; + + SLIST_FOREACH_SAFE(it, handlers, next, temp) { if (it->handler == handler) { - break; + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); + return ESP_OK; } } - return it; + return ESP_ERR_NOT_FOUND; } -static void handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_instance_t* handler_instance) + +static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler) { - SLIST_INSERT_HEAD(handlers, handler_instance, handler_entry); + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(base_node->handlers), handler); + } + else { + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + if (it->id == id) { + esp_err_t res = handler_instances_remove(&(it->handlers), handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; } -static void handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_instance_t* handler_instance) +static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler) { - SLIST_REMOVE(handlers, handler_instance, esp_event_handler_instance, handler_entry); - handler_instance_delete(handler_instance); + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(loop_node->handlers), handler); + } + else { + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + if (it->base == base) { + esp_err_t res = base_node_remove_handler(it, id, handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers)) && SLIST_EMPTY(&(it->id_nodes))) { + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; } static void handler_instances_remove_all(esp_event_handler_instances_t* handlers) { - esp_event_handler_instance_t* it; - esp_event_handler_instance_t* temp; - - SLIST_FOREACH_SAFE(it, handlers, handler_entry, temp) { - handler_instances_remove(handlers, it); + esp_event_handler_instance_t *it, *temp; + SLIST_FOREACH_SAFE(it, handlers, next, temp) { + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); } } -// Functions that operate on event id instance -static void* event_id_instance_create(int32_t event_id) +static void base_node_remove_all_handler(esp_event_base_node_t* base_node) { - esp_event_id_instance_t* event_id_instance = calloc(1, sizeof(*event_id_instance)); + handler_instances_remove_all(&(base_node->handlers)); - if (event_id_instance != NULL) { - event_id_instance->id = event_id; - SLIST_INIT(&(event_id_instance->handlers)); - } - - return event_id_instance; -} - -static void event_id_instance_delete(esp_event_id_instance_t* event_id_instance) -{ - handler_instances_remove_all(&(event_id_instance->handlers)); - free(event_id_instance); -} - -// Functions that operate on event id instance list -static void event_id_instances_remove(esp_event_id_instances_t* head, esp_event_id_instance_t* event_id_instance) -{ - SLIST_REMOVE(head, event_id_instance, esp_event_id_instance, event_id_entry); - event_id_instance_delete(event_id_instance); -} - -// Functions that operate on event base instance -static esp_event_base_instance_t* event_base_instance_create(esp_event_base_t event_base) -{ - esp_event_base_instance_t* event_base_instance = calloc(1, sizeof(*event_base_instance)); - - if (event_base_instance != NULL) { - event_base_instance->base = event_base; - SLIST_INIT(&(event_base_instance->base_handlers)); - SLIST_INIT(&(event_base_instance->event_ids)); - } - - return event_base_instance; -} - -static void event_base_instance_delete(esp_event_base_instance_t* event_base_instance) -{ - esp_event_id_instance_t* it; - esp_event_id_instance_t* temp; - - handler_instances_remove_all(&(event_base_instance->base_handlers)); - - SLIST_FOREACH_SAFE(it, &(event_base_instance->event_ids), event_id_entry, temp) { - event_id_instances_remove(&(event_base_instance->event_ids), it); - } - - free(event_base_instance); -} - -static void event_base_instance_add_event_id_instance(esp_event_base_instance_t* event_base_instance, esp_event_id_instance_t* event_id_instance) -{ - SLIST_INSERT_HEAD(&(event_base_instance->event_ids), event_id_instance, event_id_entry); -} - -static esp_event_id_instance_t* event_base_instance_find_event_id_instance(esp_event_base_instance_t* event_base_instance, int32_t event_id) -{ - esp_event_id_instance_t* it; - - SLIST_FOREACH(it, &(event_base_instance->event_ids), event_id_entry) { - if (it->id == event_id) { - break; - } - } - - return it; -} - -// Functions that operate on event base instances list -static void event_base_instances_remove(esp_event_base_instances_t* head, esp_event_base_instance_t* event_base_instance) -{ - SLIST_REMOVE(head, event_base_instance, esp_event_base_instance, event_base_entry); - event_base_instance_delete(event_base_instance); -} - -// Functions that operate on loop instances -static void loop_add_event_base_instance(esp_event_loop_instance_t* loop, esp_event_base_instance_t* event_base_instance) { - SLIST_INSERT_HEAD(&(loop->event_bases), event_base_instance, event_base_entry); -} - -static void loop_remove_all_event_base_instance(esp_event_loop_instance_t* loop) -{ - esp_event_base_instance_t* it; - esp_event_base_instance_t* temp; - - SLIST_FOREACH_SAFE(it, &(loop->event_bases), event_base_entry, temp) { - event_base_instances_remove(&(loop->event_bases), it); + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + handler_instances_remove_all(&(it->handlers)); + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); } } -static esp_event_base_instance_t* loop_find_event_base_instance(esp_event_loop_instance_t* loop, esp_event_base_t event_base) +static void loop_node_remove_all_handler(esp_event_loop_node_t* loop_node) { - esp_event_base_instance_t* it; + handler_instances_remove_all(&(loop_node->handlers)); - SLIST_FOREACH(it, &(loop->event_bases), event_base_entry) { - if (it->base == event_base) { - break; - } + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + base_node_remove_all_handler(it); + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); } - - return it; } -// Functions that operate on post instance static esp_err_t post_instance_create(esp_event_base_t event_base, int32_t event_id, void* event_data, int32_t event_data_size, esp_event_post_instance_t* post) { void* event_data_copy = NULL; @@ -314,33 +401,6 @@ static void post_instance_delete(esp_event_post_instance_t* post) free(post->data); } -static esp_event_handler_instances_t* find_handlers_list(esp_event_loop_instance_t* loop, esp_event_base_t event_base, - int32_t event_id) -{ - esp_event_handler_instances_t* handlers = NULL; - - esp_event_base_instance_t* base = NULL; - esp_event_id_instance_t* event = NULL; - - if (event_base == esp_event_any_base && event_id == ESP_EVENT_ANY_ID) { - handlers = &(loop->loop_handlers); - } else { - base = loop_find_event_base_instance(loop, event_base); - if (base != NULL) { - if (event_id == ESP_EVENT_ANY_ID) { - handlers = &(base->base_handlers); - } else { - event = event_base_instance_find_event_id_instance(base, event_id); - if (event != NULL) { - handlers = &(event->handlers); - } - } - } - } - - return handlers; -} - /* ---------------------------- Public API --------------------------------- */ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop) @@ -376,8 +436,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es } #endif - SLIST_INIT(&(loop->loop_handlers)); - SLIST_INIT(&(loop->event_bases)); + SLIST_INIT(&(loop->loop_nodes)); // Create the loop task if requested if (event_loop_args->task_name != NULL) { @@ -403,7 +462,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es #ifdef CONFIG_EVENT_LOOP_PROFILING portENTER_CRITICAL(&s_event_loops_spinlock); - SLIST_INSERT_HEAD(&s_event_loops, loop, loop_entry); + SLIST_INSERT_HEAD(&s_event_loops, loop, next); portEXIT_CRITICAL(&s_event_loops_spinlock); #endif @@ -447,7 +506,6 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick esp_event_post_instance_t post; TickType_t marker = xTaskGetTickCount(); TickType_t end = 0; - esp_event_handler_instance_t* temp; #if( configUSE_16_BIT_TICKS == 1 ) int32_t remaining_ticks = ticks_to_run; @@ -456,76 +514,46 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick #endif while(xQueueReceive(loop->queue, &post, ticks_to_run) == pdTRUE) { - esp_event_base_instance_t* base = NULL; - esp_event_id_instance_t* event = NULL; - - // Reserve space for three possible matches: (1) the entry for handlers registered to all events in the loop, the - // (2) entry matching events with a specified base and (3) the entry matching both base and id. - #define LOOP_LEVEL_HANDLER 0 - #define BASE_LEVEL_HANDLER 1 - #define EVENT_LEVEL_HANDLER 2 - - esp_event_handler_instances_t* handlers_list[EVENT_LEVEL_HANDLER + 1] = {0}; - // The event has already been unqueued, so ensure it gets executed. xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); - - loop->running_task = xTaskGetCurrentTaskHandle(); - - handlers_list[LOOP_LEVEL_HANDLER] = &(loop->loop_handlers); - base = loop_find_event_base_instance(loop, post.base); - if (base) { - event = event_base_instance_find_event_id_instance(base, post.id); - handlers_list[BASE_LEVEL_HANDLER] = &(base->base_handlers); - if (event) { - handlers_list[EVENT_LEVEL_HANDLER] = &(event->handlers); - } - } + loop->running_task = xTaskGetCurrentTaskHandle(); bool exec = false; - for (int i = LOOP_LEVEL_HANDLER; i <= EVENT_LEVEL_HANDLER; i++) { - if (handlers_list[i] != NULL) { - esp_event_handler_instance_t* it; - - SLIST_FOREACH_SAFE(it, handlers_list[i], handler_entry, temp) { - ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, it->handler, event_loop); + esp_event_handler_instance_t *handler; + esp_event_loop_node_t *loop_node; + esp_event_base_node_t *base_node; + esp_event_id_node_t *id_node; -#ifdef CONFIG_EVENT_LOOP_PROFILING - int64_t start, diff; - start = esp_timer_get_time(); -#endif - // Execute the handler - (*(it->handler))(it->arg, post.base, post.id, post.data); + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + // Execute loop level handlers + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } -#ifdef CONFIG_EVENT_LOOP_PROFILING - diff = esp_timer_get_time() - start; - - xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); - - it->total_times_invoked++; - it->total_runtime += diff; - - if (i == LOOP_LEVEL_HANDLER) { - loop->loop_handlers_invoked++; - loop->loop_handlers_runtime += diff; - } else if (i == BASE_LEVEL_HANDLER) { - base->base_handlers_invoked++; - base->base_handlers_runtime += diff; - } else { - event->handlers_invoked++; - event->handlers_runtime += diff; + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == post.base) { + // Execute base level handlers + SLIST_FOREACH(handler, &(base_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; } - loop->total_handlers_invoked++; - loop->total_handlers_runtime += diff; - - xSemaphoreGive(loop->profiling_mutex); -#endif + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if(id_node->id == post.id) { + // Execute id level handlers + SLIST_FOREACH(handler, &(id_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + // Skip to next base node + break; + } + } } } - exec |= true; } post_instance_delete(&post); @@ -570,7 +598,7 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) #ifdef CONFIG_EVENT_LOOP_PROFILING xSemaphoreTakeRecursive(loop->profiling_mutex, portMAX_DELAY); portENTER_CRITICAL(&s_event_loops_spinlock); - SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, loop_entry); + SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, next); portEXIT_CRITICAL(&s_event_loops_spinlock); #endif @@ -579,9 +607,13 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) vTaskDelete(loop->task); } - // Remove all registered events in the loop - handler_instances_remove_all(&(loop->loop_handlers)); - loop_remove_all_event_base_instance(loop); + // Remove all registered events and handlers in the loop + esp_event_loop_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + loop_node_remove_all_handler(it); + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + } // Drop existing posts on the queue esp_event_post_instance_t post; @@ -618,89 +650,55 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, es esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; - esp_event_base_instance_t* base = NULL; - esp_event_id_instance_t* event = NULL; - esp_event_handler_instance_t* handler = NULL; - esp_event_handler_instances_t* handlers = NULL; - - bool base_created = false; - bool event_created = false; - if (event_base == ESP_EVENT_ANY_BASE) { event_base = esp_event_any_base; } + esp_err_t err = ESP_OK; + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); - if (event_base == esp_event_any_base && event_id == ESP_EVENT_ANY_ID) { - // Add to the loop-level handlers - handlers = &(loop->loop_handlers); - } else { - // If base instance does not exist, create one - if ((base = loop_find_event_base_instance(loop, event_base)) == NULL) { - base = event_base_instance_create(event_base); - if (base == NULL) { - xSemaphoreGiveRecursive(loop->mutex); - return ESP_ERR_NO_MEM; - } - base_created = true; - } - // Add to the event base instance level handlers - if (event_id == ESP_EVENT_ANY_ID) { - handlers = &(base->base_handlers); - } else { - if (base_created || - (event = event_base_instance_find_event_id_instance(base, event_id)) == NULL) { - event = event_id_instance_create(event_id); - // If it does not exist, create one - if (event == NULL) { - if (base_created) { - event_base_instance_delete(base); - } - xSemaphoreGiveRecursive(loop->mutex); - return ESP_ERR_NO_MEM; - } - event_created = true; - } - // Add to the event id instance level handlers - handlers = &(event->handlers); - } + esp_event_loop_node_t *loop_node = NULL, *last_loop_node = NULL; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + last_loop_node = loop_node; } - // Add handler to the list - if (base_created || event_created || - (handler = handler_instances_find(handlers, event_handler)) == NULL) { - handler = handler_instance_create(event_handler, event_handler_arg); - if (handler == NULL) { - if (event_created) { - event_id_instance_delete(event); + bool is_loop_level_handler = (event_base == esp_event_any_base) && (event_id == ESP_EVENT_ANY_ID); + + if (!last_loop_node || + (last_loop_node && !SLIST_EMPTY(&(last_loop_node->base_nodes)) && is_loop_level_handler)) { + loop_node = (esp_event_loop_node_t*) calloc(1, sizeof(*loop_node)); + + SLIST_INIT(&(loop_node->handlers)); + SLIST_INIT(&(loop_node->base_nodes)); + + if (!loop_node) { + ESP_LOGE(TAG, "alloc for new loop node failed"); + err = ESP_ERR_NO_MEM; + goto on_err; + } + + err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg); + + if (err == ESP_OK) { + if (!last_loop_node) { + SLIST_INSERT_HEAD(&(loop->loop_nodes), loop_node, next); } - if (base_created) { - event_base_instance_delete(base); + else { + SLIST_INSERT_AFTER(last_loop_node, loop_node, next); } - xSemaphoreGiveRecursive(loop->mutex); - return ESP_ERR_NO_MEM; } - handler_instances_add(handlers, handler); - // If a new event base/ event id instance was created, add them to the appropriate list - if (event_created) { - event_base_instance_add_event_id_instance(base, event); - } - if (base_created) { - loop_add_event_base_instance(loop, base); - } - ESP_LOGD(TAG, "registered handler %p for event %s:%d", event_handler, event_base, event_id); - } else { - handler->arg = event_handler_arg; - ESP_LOGW(TAG, "handler %p for event %s:%d already registered, overwriting", event_handler, event_base, event_id); + } + else { + err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg); } +on_err: xSemaphoreGiveRecursive(loop->mutex); - - return ESP_OK; + return err; } - esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler) { @@ -718,17 +716,18 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; - esp_event_handler_instance_t* handler = NULL; - esp_event_handler_instances_t* handlers = find_handlers_list(loop, event_base, event_id); - xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); - if (handlers != NULL && - (handler = handler_instances_find(handlers, event_handler)) != NULL) { - handler_instances_remove(handlers, handler); - ESP_LOGD(TAG, "unregistered handler %p from event %s:%d", event_handler, event_base, event_id); - } else { - ESP_LOGW(TAG, "handler %p for event %s:%d not registered, ignoring", event_handler, event_base, event_id); + esp_event_loop_node_t *it, *temp; + + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + esp_err_t res = loop_node_remove_handler(it, event_base, event_id, event_handler); + + if (res == ESP_OK && SLIST_EMPTY(&(it->base_nodes)) && SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + break; + } } xSemaphoreGiveRecursive(loop->mutex); @@ -804,14 +803,16 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t return ESP_OK; } + esp_err_t esp_event_dump(FILE* file) { #ifdef CONFIG_EVENT_LOOP_PROFILING assert(file); esp_event_loop_instance_t* loop_it; - esp_event_base_instance_t* base_it; - esp_event_id_instance_t* id_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; esp_event_handler_instance_t* handler_it; // Allocate memory for printing @@ -819,46 +820,52 @@ esp_err_t esp_event_dump(FILE* file) char* buf = calloc(sz, sizeof(char)); char* dst = buf; + char id_str_buf[20]; + // Print info to buffer portENTER_CRITICAL(&s_event_loops_spinlock); - SLIST_FOREACH(loop_it, &s_event_loops, loop_entry) { - PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->name, loop_it->events_recieved, - loop_it->events_dropped, loop_it->total_handlers_invoked, loop_it->total_handlers_runtime); - // Print loop-level handler - PRINT_DUMP_INFO(dst, sz, esp_event_any_base, ESP_EVENT_ANY_ID, loop_it->loop_handlers_invoked, - loop_it->loop_handlers_runtime); - SLIST_FOREACH(handler_it, &(loop_it->loop_handlers), handler_entry) { - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, handler_it->total_times_invoked, - handler_it->total_runtime); - } + SLIST_FOREACH(loop_it, &s_event_loops, next) { + PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->task != NULL ? loop_it->name : "none" , + loop_it->events_recieved, loop_it->events_dropped); - SLIST_FOREACH(base_it, &(loop_it->event_bases), event_base_entry) { - // Print base-level handler - PRINT_DUMP_INFO(dst, sz, EVENT_DUMP_FORMAT, base_it->base, ESP_EVENT_ANY_ID, - base_it->base_handlers_invoked, base_it->base_handlers_runtime); - SLIST_FOREACH(handler_it, &(base_it->base_handlers), handler_entry) { - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, - handler_it->total_times_invoked, handler_it->total_runtime); + int sz_bak = sz; + + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, "ESP_EVENT_ANY_BASE", + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); } - // Print event-level handlers - SLIST_FOREACH(id_it, &(base_it->event_ids), event_id_entry) { - PRINT_DUMP_INFO(dst, sz, EVENT_DUMP_FORMAT, base_it->base, id_it->id, - id_it->handlers_invoked, id_it->handlers_runtime); + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); + } - SLIST_FOREACH(handler_it, &(id_it->handlers), handler_entry) { - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, - handler_it->total_times_invoked, handler_it->total_runtime); + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + memset(id_str_buf, 0, sizeof(id_str_buf)); + snprintf(id_str_buf, sizeof(id_str_buf), "%d", id_node_it->id); + + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + id_str_buf, handler_it->invoked, handler_it->time); + } } } } + + // No handlers registered for this loop + if (sz == sz_bak) { + PRINT_DUMP_INFO(dst, sz, " NO HANDLERS REGISTERED\n"); + } } + portEXIT_CRITICAL(&s_event_loops_spinlock); - + // Print the contents of the buffer to the file fprintf(file, buf); - + // Free the allocated buffer free(buf); #endif diff --git a/components/esp_event/esp_event_private.c b/components/esp_event/esp_event_private.c index 8e14284c79..828e458c6d 100644 --- a/components/esp_event/esp_event_private.c +++ b/components/esp_event/esp_event_private.c @@ -22,17 +22,41 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; bool result = false; - xSemaphoreTake(loop->mutex, portMAX_DELAY); - esp_event_base_instance_t* base_it; - SLIST_FOREACH(base_it, &(loop->event_bases), event_base_entry) { - esp_event_id_instance_t* event_it; - SLIST_FOREACH(event_it, &(base_it->event_ids), event_id_entry) { - esp_event_handler_instance_t* handler_it; - SLIST_FOREACH(handler_it, &(event_it->handlers), handler_entry) { - if (base_it->base == event_base && event_it->id == event_id && handler_it->handler == event_handler) { - result = true; - goto out; + esp_event_loop_node_t* loop_node; + esp_event_base_node_t* base_node; + esp_event_id_node_t* id_node; + esp_event_handler_instance_t* handler; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == event_base) { + SLIST_FOREACH(handler, &(base_node->handlers), next) { + if(event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if(id_node->id == event_id) { + SLIST_FOREACH(handler, &(id_node->handlers), next) { + if(handler->handler == event_handler) + { + result = true; + goto out; + } + } + } } } } diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h index f095844a72..f97deaf8b4 100644 --- a/components/esp_event/include/esp_event.h +++ b/components/esp_event/include/esp_event.h @@ -33,11 +33,11 @@ extern "C" { /// Configuration for creating event loops typedef struct { int32_t queue_size; /**< size of the event loop queue */ - const char* task_name; /**< name of the event loop task; if NULL, + const char* task_name; /**< name of the event loop task; if NULL, a dedicated task is not created for event loop*/ UBaseType_t task_priority; /**< priority of the event loop task, ignored if task name is NULL */ uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ - BaseType_t task_core_id; /**< core to which the event loop task is pinned to, + BaseType_t task_core_id; /**< core to which the event loop task is pinned to, ignored if task name is NULL */ } esp_event_loop_args_t; @@ -47,7 +47,7 @@ typedef struct { * @param[in] event_loop_args configuration structure for the event loop to create * @param[out] event_loop handle to the created event loop * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - ESP_FAIL: Failed to create task loop @@ -60,7 +60,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es * * @param[in] event_loop event loop to delete * - * @return + * @return * - ESP_OK: Success * - Others: Fail */ @@ -68,8 +68,8 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop); /** * @brief Create default event loop - * - * @return + * + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - ESP_FAIL: Failed to create task loop @@ -79,8 +79,8 @@ esp_err_t esp_event_loop_create_default(); /** * @brief Delete the default event loop - * - * @return + * + * @return * - ESP_OK: Success * - Others: Fail */ @@ -89,18 +89,18 @@ esp_err_t esp_event_loop_delete_default(); /** * @brief Dispatch events posted to an event loop. * - * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL - * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time - * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee - * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have + * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL + * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time + * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee + * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have * been dispatched during the call, as the function might have spent all of the alloted time waiting on the event queue. - * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being - * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued - * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code + * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being + * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued + * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code * execution. The guaranteed time of exit is therefore the alloted time + amount of time required to dispatch * the last unqueued event. * - * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is + * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is * normal behavior. * * @param[in] event_loop event loop to dispatch posted events from @@ -108,7 +108,7 @@ esp_err_t esp_event_loop_delete_default(); * * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error. * - * @return + * @return * - ESP_OK: Success * - Others: Fail */ @@ -124,8 +124,8 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id * - * Registering multiple handlers to events is possible. Registering a single handler to multiple events is - * also possible. However, registering the same handler to the same event multiple times would cause the + * Registering multiple handlers to events is possible. Registering a single handler to multiple events is + * also possible. However, registering the same handler to the same event multiple times would cause the * previous registrations to be overwritten. * * @param[in] event_base the base id of the event to register the handler for @@ -133,24 +133,24 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick * @param[in] event_handler the handler function which gets called when the event is dispatched * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called * - * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should * ensure that event_handler_arg still points to a valid location by the time the handler gets called * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_register(esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, +esp_err_t esp_event_handler_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg); /** * @brief Register an event handler to a specific loop. * - * This function behaves in the same manner as esp_event_handler_register, except the additional + * This function behaves in the same manner as esp_event_handler_register, except the additional * specification of the event loop to register the handler to. * * @param[in] event_loop the event loop to register this handler function to @@ -159,23 +159,26 @@ esp_err_t esp_event_handler_register(esp_event_base_t event_base, * @param[in] event_handler the handler function which gets called when the event is dispatched * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called * - * @return + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg); /** * @brief Unregister a handler with the system event loop. * * This function can be used to unregister a handler so that it no longer gets called during dispatch. - * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, + * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, * or (3) all events known by the system event loop * * - specific events: specify exact event_base and event_id @@ -189,7 +192,7 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, * @param[in] event_handler the handler to unregister * * @return ESP_OK success - * @return ESP_ERR_INVALIG_ARG invalid combination of event base and event id + * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id * @return others fail */ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); @@ -197,7 +200,7 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even /** * @brief Unregister a handler with the system event loop. * - * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of + * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of * the event loop to unregister the handler with. * * @param[in] event_loop the event loop with which to unregister this handler function @@ -205,21 +208,21 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even * @param[in] event_id the id of the event with which to unregister the handler * @param[in] event_handler the handler to unregister * - * @return + * @return * - ESP_OK: Success - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler); /** - * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages - * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the * handler recieves is always valid. - * + * * @param[in] event_base the event base that identifies the event * @param[in] event_id the the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler @@ -228,21 +231,21 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, * * @note posting events from an ISR is not supported * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_post(esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, +esp_err_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, TickType_t ticks_to_wait); /** - * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages - * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the * handler recieves is always valid. * * This function behaves in the same manner as esp_event_post_to, except the additional specification of the event loop @@ -256,73 +259,60 @@ esp_err_t esp_event_post(esp_event_base_t event_base, * @param[in] ticks_to_wait number of ticks to block on a full event queue * * @note posting events from an ISR is not supported - * - * @return + * + * @return * - ESP_OK: Success * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired - * - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ -esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, TickType_t ticks_to_wait); /** * @brief Dumps statistics of all event loops. * * Dumps event loop info in the format: - * + * @verbatim event loop - event - handler - handler - event - handler - handler - event loop - event - handler - ... + handler + handler ... - ... - + event loop + handler + handler + ... + where: - + event loop - format: address,name rx:total_recieved dr:total_dropped inv:total_number_of_invocations run:total_runtime + format: address,name rx:total_recieved dr:total_dropped where: address - memory address of the event loop - name - name of the event loop + name - name of the event loop, 'none' if no dedicated task total_recieved - number of successfully posted events - total_number_of_invocations - total number of handler invocations performed so far - total_runtime - total runtime of all invocations so far - - event - format: base:id proc:total_processed run:total_runtime - where: - base - event base - id - event id - total_processed - number of instances of this event that has been processed - total_runtime - total amount of time in microseconds used for invoking handlers of this event - + total_dropped - number of events unsucessfully posted due to queue being full + handler - format: address inv:total_invoked run:total_runtime + format: address ev:base,id inv:total_invoked run:total_runtime where: address - address of the handler function + base,id - the event specified by event base and id this handler executes total_invoked - number of times this handler has been invoked total_runtime - total amount of time used for invoking this handler - + @endverbatim * * @param[in] file the file stream to output to * * @note this function is a noop when CONFIG_EVENT_LOOP_PROFILING is disabled * - * @return + * @return * - ESP_OK: Success * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - Others: Fail diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h index 8b29c8628b..734def5868 100644 --- a/components/esp_event/private_include/esp_event_internal.h +++ b/components/esp_event/private_include/esp_event_internal.h @@ -21,68 +21,66 @@ extern "C" { #endif +typedef SLIST_HEAD(base_nodes, base_node) base_nodes_t; + /// Event handler typedef struct esp_event_handler_instance { esp_event_handler_t handler; /**< event handler function*/ void* arg; /**< event handler argument */ #ifdef CONFIG_EVENT_LOOP_PROFILING - uint32_t total_times_invoked; /**< number of times this handler has been invoked */ - int64_t total_runtime; /**< total runtime of this handler across all calls */ + uint32_t invoked; /**< number of times this handler has been invoked */ + int64_t time; /**< total runtime of this handler across all calls */ #endif - SLIST_ENTRY(esp_event_handler_instance) handler_entry; /**< next event handler in the list */ + SLIST_ENTRY(esp_event_handler_instance) next; /**< next event handler in the list */ } esp_event_handler_instance_t; typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_instance) esp_event_handler_instances_t; -typedef struct esp_event_id_instance { - int32_t id; - esp_event_handler_instances_t handlers; /**< list of handlers to be executed when - this event is raised */ - SLIST_ENTRY(esp_event_id_instance) event_id_entry; /**< pointer to the next event node on the linked list */ -#ifdef CONFIG_EVENT_LOOP_PROFILING - uint32_t handlers_invoked; /**< total number of times the event has been - raised and processed in the loop */ - int64_t handlers_runtime; /**< total time spent in executing handlers */ -#endif -} esp_event_id_instance_t; - -typedef SLIST_HEAD(esp_event_id_instances, esp_event_id_instance) esp_event_id_instances_t; - /// Event -typedef struct esp_event_base_instance { - esp_event_base_t base; /**< base identifier of the event */ - esp_event_handler_instances_t base_handlers; /**< event base level handlers, handlers for - all events with this base */ - esp_event_id_instances_t event_ids; /**< list of event ids with this base */ - SLIST_ENTRY(esp_event_base_instance) event_base_entry; /**< pointer to the next event node on the linked list */ -#ifdef CONFIG_EVENT_LOOP_PROFILING - uint32_t base_handlers_invoked; /**< total number of base-level handlers invoked */ - int64_t base_handlers_runtime; /**< amount of time processing base-level handlers */ -#endif -} esp_event_base_instance_t; +typedef struct esp_event_id_node { + int32_t id; /**< id number of the event */ + esp_event_handler_instances_t handlers; /**< list of handlers to be executed when + this event is raised */ + SLIST_ENTRY(esp_event_id_node) next; /**< pointer to the next event node on the linked list */ +} esp_event_id_node_t; -typedef SLIST_HEAD(esp_event_base_instances, esp_event_base_instance) esp_event_base_instances_t; +typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t; + +typedef struct esp_event_base_node { + esp_event_base_t base; /**< base identifier of the event */ + esp_event_handler_instances_t handlers; /**< event base level handlers, handlers for + all events with this base */ + esp_event_id_nodes_t id_nodes; /**< list of event ids with this base */ + SLIST_ENTRY(esp_event_base_node) next; /**< pointer to the next base node on the linked list */ +} esp_event_base_node_t; + +typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t; + +typedef struct esp_event_loop_node { + esp_event_handler_instances_t handlers; /** event loop level handlers */ + esp_event_base_nodes_t base_nodes; /** list of event bases registered to the loop */ + SLIST_ENTRY(esp_event_loop_node) next; /** pointer to the next loop node containing + event loop level handlers and the rest of + event bases registered to the loop */ +} esp_event_loop_node_t; + +typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t; /// Event loop typedef struct esp_event_loop_instance { const char* name; /**< name of this event loop */ QueueHandle_t queue; /**< event queue */ TaskHandle_t task; /**< task that consumes the event queue */ - TaskHandle_t running_task; /**< for loops with no dedicated task, the + TaskHandle_t running_task; /**< for loops with no dedicated task, the task that consumes the queue */ SemaphoreHandle_t mutex; /**< mutex for updating the events linked list */ - esp_event_handler_instances_t loop_handlers; /**< loop level handlers, handlers for all events - registered in the loop */ - esp_event_base_instances_t event_bases; /**< events linked list head pointer */ + esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the + registered handlers for the loop */ #ifdef CONFIG_EVENT_LOOP_PROFILING uint32_t events_recieved; /**< number of events successfully posted to the loop */ uint32_t events_dropped; /**< number of events dropped due to queue being full */ - uint32_t loop_handlers_invoked; /**< total number of loop-level handlers invoked */ - int64_t loop_handlers_runtime; /**< amount of time processing loop-level handlers */ - uint32_t total_handlers_invoked; /**< total number of handlers invoked */ - int64_t total_handlers_runtime; /**< total amount of time dedicated to processing this loop */ - SLIST_ENTRY(esp_event_loop_instance) loop_entry; /**< next event loop in the list */ - SemaphoreHandle_t profiling_mutex; + SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */ + SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */ #endif } esp_event_loop_instance_t;