From c5892a4c96ce6138bbc89c83fe9055441a6fc82f Mon Sep 17 00:00:00 2001 From: aditi Date: Wed, 21 Aug 2024 17:54:02 +0530 Subject: [PATCH] fix(wpa_supplicant): Add few fixes in eloop task --- components/wpa_supplicant/port/eloop.c | 552 +++++++++++++------------ 1 file changed, 278 insertions(+), 274 deletions(-) diff --git a/components/wpa_supplicant/port/eloop.c b/components/wpa_supplicant/port/eloop.c index 74eacb5804..c1c71f274b 100644 --- a/components/wpa_supplicant/port/eloop.c +++ b/components/wpa_supplicant/port/eloop.c @@ -6,7 +6,7 @@ * See README for more details. */ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,21 +19,21 @@ #include "esp_wifi_driver.h" struct eloop_timeout { - struct dl_list list; - struct os_reltime time; - void *eloop_data; - void *user_data; - eloop_timeout_handler handler; + struct dl_list list; + struct os_reltime time; + void *eloop_data; + void *user_data; + eloop_timeout_handler handler; #ifdef ELOOP_DEBUG - char func_name[100]; - int line; + char func_name[100]; + int line; #endif }; struct eloop_data { - struct dl_list timeout; - ETSTimer eloop_timer; - bool eloop_started; + struct dl_list timeout; + ETSTimer eloop_timer; + bool eloop_started; }; #define ELOOP_LOCK() os_mutex_lock(eloop_data_lock) @@ -45,364 +45,368 @@ static struct eloop_data eloop; static int eloop_run_wrapper(void *data) { - eloop_run(); - return 0; + eloop_run(); + return 0; } static void eloop_run_timer(void *args) { - /* Execute timers in pptask context to make it thread safe */ - wifi_ipc_config_t cfg; + /* Execute timers in pptask context to make it thread safe */ + wifi_ipc_config_t cfg; - cfg.fn = eloop_run_wrapper; - cfg.arg = NULL; - cfg.arg_size = 0; - esp_wifi_ipc_internal(&cfg, false); + cfg.fn = eloop_run_wrapper; + cfg.arg = NULL; + cfg.arg_size = 0; + esp_wifi_ipc_internal(&cfg, false); } int eloop_init(void) { - os_memset(&eloop, 0, sizeof(eloop)); - dl_list_init(&eloop.timeout); - os_timer_disarm(&eloop.eloop_timer); - os_timer_setfn(&eloop.eloop_timer, (ETSTimerFunc *)eloop_run_timer, NULL); + os_memset(&eloop, 0, sizeof(eloop)); + dl_list_init(&eloop.timeout); + os_timer_disarm(&eloop.eloop_timer); + os_timer_setfn(&eloop.eloop_timer, (ETSTimerFunc *)eloop_run_timer, NULL); - eloop_data_lock = os_recursive_mutex_create(); + eloop_data_lock = os_recursive_mutex_create(); - if (!eloop_data_lock) { - wpa_printf(MSG_ERROR, "failed to create eloop data loop"); - return -1; - } - eloop.eloop_started = true; + if (!eloop_data_lock) { + wpa_printf(MSG_ERROR, "failed to create eloop data loop"); + return -1; + } + eloop.eloop_started = true; - return 0; + return 0; } #ifdef ELOOP_DEBUG int eloop_register_timeout_debug(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, void *eloop_data, - void *user_data, const char *func, int line) + eloop_timeout_handler handler, void *eloop_data, + void *user_data, const char *func, int line) #else int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data) + eloop_timeout_handler handler, + void *eloop_data, void *user_data) #endif { - struct eloop_timeout *timeout, *tmp; - os_time_t now_sec; + struct eloop_timeout *timeout, *tmp; + os_time_t now_sec; #ifdef ELOOP_DEBUG - int count = 0; + int count = 0; #endif - timeout = os_zalloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - if (os_get_reltime(&timeout->time) < 0) { - os_free(timeout); - return -1; - } - now_sec = timeout->time.sec; - timeout->time.sec += secs; - if (timeout->time.sec < now_sec) - goto overflow; - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - if (timeout->time.sec < now_sec) - goto overflow; - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; + timeout = os_zalloc(sizeof(*timeout)); + if (timeout == NULL) { + return -1; + } + if (os_get_reltime(&timeout->time) < 0) { + os_free(timeout); + return -1; + } + now_sec = timeout->time.sec; + timeout->time.sec += secs; + if (timeout->time.sec < now_sec) { + goto overflow; + } + timeout->time.usec += usecs; + while (timeout->time.usec >= 1000000) { + timeout->time.sec++; + timeout->time.usec -= 1000000; + } + if (timeout->time.sec < now_sec) { + goto overflow; + } + timeout->eloop_data = eloop_data; + timeout->user_data = user_data; + timeout->handler = handler; #ifdef ELOOP_DEBUG - os_strlcpy(timeout->func_name, func, 100); - timeout->line = line; + os_strlcpy(timeout->func_name, func, 100); + timeout->line = line; #endif - /* Maintain timeouts in order of increasing time */ - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (os_reltime_before(&timeout->time, &tmp->time)) { - ELOOP_LOCK(); - dl_list_add(tmp->list.prev, &timeout->list); - ELOOP_UNLOCK(); - goto run; - } + /* Maintain timeouts in order of increasing time */ + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (os_reltime_before(&timeout->time, &tmp->time)) { + ELOOP_LOCK(); + dl_list_add(tmp->list.prev, &timeout->list); + ELOOP_UNLOCK(); + goto run; + } #ifdef ELOOP_DEBUG - count++; + count++; #endif - } - ELOOP_LOCK(); - dl_list_add_tail(&eloop.timeout, &timeout->list); - ELOOP_UNLOCK(); + } + ELOOP_LOCK(); + dl_list_add_tail(&eloop.timeout, &timeout->list); + ELOOP_UNLOCK(); run: #ifdef ELOOP_DEBUG - wpa_printf(MSG_DEBUG, "ELOOP: Added one timer from %s:%d to call %p, current order=%d", - timeout->func_name, line, timeout->handler, count); + wpa_printf(MSG_DEBUG, "ELOOP: Added one timer from %s:%d to call %p, current order=%d", + timeout->func_name, line, timeout->handler, count); #endif - ELOOP_LOCK(); - os_timer_disarm(&eloop.eloop_timer); - os_timer_arm(&eloop.eloop_timer, 0, 0); - ELOOP_UNLOCK(); + ELOOP_LOCK(); + os_timer_disarm(&eloop.eloop_timer); + os_timer_arm(&eloop.eloop_timer, 0, 0); + ELOOP_UNLOCK(); - return 0; + return 0; overflow: - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - wpa_printf(MSG_DEBUG, - "ELOOP: Too long timeout (secs=%u usecs=%u) to ever happen - ignore it", - secs,usecs); - os_free(timeout); - return 0; + /* + * Integer overflow - assume long enough timeout to be assumed + * to be infinite, i.e., the timeout would never happen. + */ + wpa_printf(MSG_DEBUG, + "ELOOP: Too long timeout (secs=%u usecs=%u) to ever happen - ignore it", + secs, usecs); + os_free(timeout); + return 0; } static bool timeout_exists(struct eloop_timeout *old) { - struct eloop_timeout *timeout, *prev; - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - if (old == timeout) - return true; - } + struct eloop_timeout *timeout, *prev; + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + if (old == timeout) { + return true; + } + } - return false; + return false; } static void eloop_remove_timeout(struct eloop_timeout *timeout) { - bool timeout_present = false; - ELOOP_LOCK(); - /* Make sure timeout still exists(Another context may have deleted this) */ - timeout_present = timeout_exists(timeout); - if (timeout_present) - dl_list_del(&timeout->list); - ELOOP_UNLOCK(); - if (timeout_present) - os_free(timeout); + bool timeout_present = false; + ELOOP_LOCK(); + /* Make sure timeout still exists(Another context may have deleted this) */ + timeout_present = timeout_exists(timeout); + if (timeout_present) { + dl_list_del(&timeout->list); + } + ELOOP_UNLOCK(); + if (timeout_present) { + os_free(timeout); + } } #ifdef ELOOP_DEBUG int eloop_cancel_timeout_debug(eloop_timeout_handler handler, void *eloop_data, - void *user_data, const char *func, int line) + void *user_data, const char *func, int line) #else int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data) + void *eloop_data, void *user_data) #endif { - struct eloop_timeout *timeout, *prev; - int removed = 0; + struct eloop_timeout *timeout, *prev; + int removed = 0; - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - eloop_remove_timeout(timeout); - removed++; - } - } + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + if (timeout->handler == handler && + (timeout->eloop_data == eloop_data || + eloop_data == ELOOP_ALL_CTX) && + (timeout->user_data == user_data || + user_data == ELOOP_ALL_CTX)) { + eloop_remove_timeout(timeout); + removed++; + } + } #ifdef ELOOP_DEBUG - wpa_printf(MSG_DEBUG, "ELOOP: %s:%d called to remove timer handler=%p, removed count=%d", - func, line, handler, removed); + wpa_printf(MSG_DEBUG, "ELOOP: %s:%d called to remove timer handler=%p, removed count=%d", + func, line, handler, removed); #endif - return removed; + return removed; } - int eloop_cancel_timeout_one(eloop_timeout_handler handler, - void *eloop_data, void *user_data, - struct os_reltime *remaining) + void *eloop_data, void *user_data, + struct os_reltime *remaining) { - struct eloop_timeout *timeout, *prev; - int removed = 0; - struct os_reltime now; + struct eloop_timeout *timeout, *prev; + int removed = 0; + struct os_reltime now; - os_get_reltime(&now); - remaining->sec = remaining->usec = 0; + os_get_reltime(&now); + remaining->sec = remaining->usec = 0; - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data) && - (timeout->user_data == user_data)) { - removed = 1; - if (os_reltime_before(&now, &timeout->time)) - os_reltime_sub(&timeout->time, &now, remaining); - eloop_remove_timeout(timeout); - break; - } - } - return removed; + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + if (timeout->handler == handler && + (timeout->eloop_data == eloop_data) && + (timeout->user_data == user_data)) { + removed = 1; + if (os_reltime_before(&now, &timeout->time)) { + os_reltime_sub(&timeout->time, &now, remaining); + } + eloop_remove_timeout(timeout); + break; + } + } + return removed; } - int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data) + void *eloop_data, void *user_data) { - struct eloop_timeout *tmp; + struct eloop_timeout *tmp; - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - } + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + return 1; + } + } - return 0; + return 0; } - int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, - eloop_timeout_handler handler, void *eloop_data, - void *user_data) + eloop_timeout_handler handler, void *eloop_data, + void *user_data) { - struct os_reltime now, requested, remaining; - struct eloop_timeout *tmp; + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) { - requested.sec = req_secs; - requested.usec = req_usecs; - os_get_reltime(&now); - os_reltime_sub(&tmp->time, &now, &remaining); - if (os_reltime_before(&requested, &remaining)) { - eloop_cancel_timeout(handler, eloop_data, - user_data); - eloop_register_timeout(requested.sec, - requested.usec, - handler, eloop_data, - user_data); - return 1; - } - return 0; - } - } + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&requested, &remaining)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } - return -1; + return -1; } - int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, - eloop_timeout_handler handler, void *eloop_data, - void *user_data) + eloop_timeout_handler handler, void *eloop_data, + void *user_data) { - struct os_reltime now, requested, remaining; - struct eloop_timeout *tmp; + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) { - requested.sec = req_secs; - requested.usec = req_usecs; - os_get_reltime(&now); - os_reltime_sub(&tmp->time, &now, &remaining); - if (os_reltime_before(&remaining, &requested)) { - eloop_cancel_timeout(handler, eloop_data, - user_data); - eloop_register_timeout(requested.sec, - requested.usec, - handler, eloop_data, - user_data); - return 1; - } - return 0; - } - } + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&remaining, &requested)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } - return -1; + return -1; } void eloop_run(void) { - struct os_reltime tv, now; + struct os_reltime tv, now; - while (!dl_list_empty(&eloop.timeout)) { - struct eloop_timeout *timeout; + while (!dl_list_empty(&eloop.timeout)) { + struct eloop_timeout *timeout; - timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, - list); - if (timeout) { - os_get_reltime(&now); - if (os_reltime_before(&now, &timeout->time)) { - /* we don't need to process it rn, do it later */ - uint32_t ms; - os_reltime_sub(&timeout->time, &now, &tv); - ms = tv.sec * 1000 + tv.usec / 1000; - ELOOP_LOCK(); - os_timer_disarm(&eloop.eloop_timer); - os_timer_arm(&eloop.eloop_timer, ms, 0); - ELOOP_UNLOCK(); - goto out; - } - } + timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, + list); + if (timeout) { + os_get_reltime(&now); + if (os_reltime_before(&now, &timeout->time)) { + /* we don't need to process it rn, do it later */ + uint32_t ms; + os_reltime_sub(&timeout->time, &now, &tv); + ms = tv.sec * 1000 + tv.usec / 1000; + ELOOP_LOCK(); + os_timer_disarm(&eloop.eloop_timer); + os_timer_arm(&eloop.eloop_timer, ms, 0); + ELOOP_UNLOCK(); + goto out; + } + } - /* check if some registered timeouts have occurred */ - timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, - list); - if (timeout) { - os_get_reltime(&now); - if (!os_reltime_before(&now, &timeout->time)) { - void *eloop_data = timeout->eloop_data; - void *user_data = timeout->user_data; - eloop_timeout_handler handler = - timeout->handler; + /* check if some registered timeouts have occurred */ + timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, + list); + if (timeout) { + os_get_reltime(&now); + if (!os_reltime_before(&now, &timeout->time)) { + void *eloop_data = timeout->eloop_data; + void *user_data = timeout->user_data; + eloop_timeout_handler handler = + timeout->handler; #ifdef ELOOP_DEBUG - char fn_name[100] = {0}; - int line = timeout->line; - os_strlcpy(fn_name, timeout->func_name, 100); + char fn_name[100] = {0}; + int line = timeout->line; + os_strlcpy(fn_name, timeout->func_name, 100); #endif - eloop_remove_timeout(timeout); + eloop_remove_timeout(timeout); #ifdef ELOOP_DEBUG - wpa_printf(MSG_DEBUG, "ELOOP: Running timer fn:%p scheduled by %s:%d ", - handler, fn_name, line); + wpa_printf(MSG_DEBUG, "ELOOP: Running timer fn:%p scheduled by %s:%d ", + handler, fn_name, line); #endif - handler(eloop_data, user_data); - } - } - } + handler(eloop_data, user_data); + } + } + } out: - return; + return; } void eloop_destroy(void) { - struct eloop_timeout *timeout, *prev; - struct os_reltime now; + struct eloop_timeout *timeout, *prev; + struct os_reltime now; - if (!eloop.eloop_started) { - return; - } - os_get_reltime(&now); - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - int sec, usec; - sec = timeout->time.sec - now.sec; - usec = timeout->time.usec - now.usec; - if (timeout->time.usec < now.usec) { - sec--; - usec += 1000000; - } - wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " - "eloop_data=%p user_data=%p handler=%p", - sec, usec, timeout->eloop_data, timeout->user_data, - timeout->handler); - eloop_remove_timeout(timeout); - } - if (eloop_data_lock) { - os_semphr_delete(eloop_data_lock); - eloop_data_lock = NULL; - } - os_timer_disarm(&eloop.eloop_timer); - os_timer_done(&eloop.eloop_timer); - os_memset(&eloop, 0, sizeof(eloop)); + if (!eloop.eloop_started) { + return; + } + os_get_reltime(&now); + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + int sec, usec; + sec = timeout->time.sec - now.sec; + usec = timeout->time.usec - now.usec; + if (timeout->time.usec < now.usec) { + sec--; + usec += 1000000; + } + wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " + "eloop_data=%p user_data=%p handler=%p", + sec, usec, timeout->eloop_data, timeout->user_data, + timeout->handler); + eloop_remove_timeout(timeout); + } + if (eloop_data_lock) { + os_mutex_delete(eloop_data_lock); + eloop_data_lock = NULL; + } + os_timer_disarm(&eloop.eloop_timer); + os_timer_done(&eloop.eloop_timer); + os_memset(&eloop, 0, sizeof(eloop)); }