esp_wifi: fix occasional test failure due to memory leak indications
Ensure that newly spawned task stack (dynamic) is getting freed up before test completion and thus preventing false memory leak indication failure. unit-test-app: add an API test_utils_task_delete This API ensures that dynamic memory of deleted task gets freed up before return. This helps for preventing false memory leak detections in test failures.
This commit is contained in:
parent
e8ca5e6f21
commit
8ae05e6547
3 changed files with 82 additions and 9 deletions
|
@ -96,24 +96,27 @@ static void wifi_driver_can_start_on_APP_CPU_task(void* arg)
|
|||
TEST_ESP_OK(event_deinit());
|
||||
ESP_LOGI(TAG, EMPH_STR("nvs_flash_deinit..."));
|
||||
TEST_ESP_OK(nvs_flash_deinit());
|
||||
xSemaphoreGive(*sema);
|
||||
ESP_LOGI(TAG, "exit task...");
|
||||
vTaskDelete(NULL);
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("wifi driver can start on APP CPU", "[wifi_init]")
|
||||
{
|
||||
TaskHandle_t th;
|
||||
TaskHandle_t th = NULL;
|
||||
SemaphoreHandle_t sema = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(sema);
|
||||
printf("Creating tasks\n");
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(wifi_driver_can_start_on_APP_CPU_task, "wifi_driver_can_start_on_APP_CPU_task", 2048*2, &sema, 3, &th, 1);
|
||||
#else
|
||||
xTaskCreate(wifi_driver_can_start_on_APP_CPU_task, "wifi_driver_can_start_on_APP_CPU_task", 2048*2, &sema, 3, &th);
|
||||
#endif
|
||||
TEST_ASSERT_NOT_NULL(th);
|
||||
xSemaphoreTake(sema, portMAX_DELAY);
|
||||
vSemaphoreDelete(sema);
|
||||
sema = NULL;
|
||||
test_utils_task_delete(th);
|
||||
}
|
||||
|
||||
static void wifi_start_stop_task(void* arg)
|
||||
|
@ -148,22 +151,25 @@ static void wifi_start_stop_task(void* arg)
|
|||
nvs_flash_deinit();
|
||||
ESP_LOGI(TAG, "test passed...");
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling esp_wifi_stop() with start", "[wifi_init]")
|
||||
{
|
||||
TaskHandle_t th;
|
||||
TaskHandle_t th = NULL;
|
||||
SemaphoreHandle_t sema = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(sema);
|
||||
printf("Creating tasks\n");
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(wifi_start_stop_task, "wifi_start_stop_task", 2048*2, &sema, 3, &th, 0);
|
||||
#else
|
||||
xTaskCreate(wifi_start_stop_task, "wifi_start_stop_task", 2048*2, &sema, 3, &th);
|
||||
#endif
|
||||
TEST_ASSERT_NOT_NULL(th);
|
||||
xSemaphoreTake(sema, portMAX_DELAY);
|
||||
vSemaphoreDelete(sema);
|
||||
sema = NULL;
|
||||
test_utils_task_delete(th);
|
||||
}
|
||||
|
||||
static void wifi_stop_task(void* arg)
|
||||
|
@ -194,20 +200,23 @@ static void wifi_stop_task(void* arg)
|
|||
nvs_flash_deinit();
|
||||
ESP_LOGI(TAG, "test passed...");
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling esp_wifi_stop() without start", "[wifi_init]")
|
||||
{
|
||||
TaskHandle_t th;
|
||||
TaskHandle_t th = NULL;
|
||||
SemaphoreHandle_t sema = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(sema);
|
||||
printf("Creating tasks\n");
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(wifi_stop_task, "wifi_stop_task", 2048*2, &sema, 3, &th, 0);
|
||||
#else
|
||||
xTaskCreate(wifi_stop_task, "wifi_stop_task", 2048*2, &sema, 3, &th);
|
||||
#endif
|
||||
TEST_ASSERT_NOT_NULL(th);
|
||||
xSemaphoreTake(sema, portMAX_DELAY);
|
||||
vSemaphoreDelete(sema);
|
||||
sema = NULL;
|
||||
test_utils_task_delete(th);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <stdint.h>
|
||||
#include <esp_partition.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/* include performance pass standards header file */
|
||||
#include "idf_performance.h"
|
||||
|
@ -259,7 +261,6 @@ esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type, esp
|
|||
size_t test_utils_get_leak_level(esp_type_leak_t type, esp_comp_leak_t component);
|
||||
|
||||
|
||||
|
||||
typedef struct test_utils_exhaust_memory_record_s *test_utils_exhaust_memory_rec;
|
||||
|
||||
/**
|
||||
|
@ -285,3 +286,9 @@ test_utils_exhaust_memory_rec test_utils_exhaust_memory(uint32_t caps, size_t li
|
|||
void test_utils_free_exhausted_memory(test_utils_exhaust_memory_rec rec);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Delete task ensuring dynamic memory (for stack, tcb etc.) gets freed up immediately
|
||||
*
|
||||
* @param[in] thandle Handle of task to be deleted (should not be NULL or self handle)
|
||||
*/
|
||||
void test_utils_task_delete(TaskHandle_t thandle);
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
#include "freertos/task.h"
|
||||
#include "esp_netif.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "sdkconfig.h"
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#include "esp_ipc.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#endif
|
||||
|
||||
const esp_partition_t *get_test_data_partition(void)
|
||||
{
|
||||
|
@ -142,7 +147,6 @@ size_t test_utils_get_leak_level(esp_type_leak_t type_of_leak, esp_comp_leak_t c
|
|||
return leak_level;
|
||||
}
|
||||
|
||||
|
||||
#define EXHAUST_MEMORY_ENTRIES 100
|
||||
|
||||
struct test_utils_exhaust_memory_record_s {
|
||||
|
@ -179,3 +183,56 @@ void test_utils_free_exhausted_memory(test_utils_exhaust_memory_rec rec)
|
|||
free(rec);
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
static SemaphoreHandle_t test_sem;
|
||||
|
||||
static bool test_idle_hook_func(void)
|
||||
{
|
||||
if (test_sem) {
|
||||
xSemaphoreGive(test_sem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void test_task_delete_func(void *arg)
|
||||
{
|
||||
vTaskDelete(arg);
|
||||
}
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
|
||||
void test_utils_task_delete(TaskHandle_t thandle)
|
||||
{
|
||||
/* Self deletion can not free up associated task dynamic memory immediately,
|
||||
* hence not recommended for test scenarios */
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(thandle, "test_utils_task_delete: handle is NULL");
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(thandle, xTaskGetCurrentTaskHandle(), "test_utils_task_delete: handle is of currently executing task");
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
vTaskDelete(thandle);
|
||||
#else // CONFIG_FREERTOS_UNICORE
|
||||
const BaseType_t tsk_affinity = xTaskGetAffinity(thandle);
|
||||
const uint32_t core_id = xPortGetCoreID();
|
||||
|
||||
printf("Task_affinity: 0x%x, current_core: %d\n", tsk_affinity, core_id);
|
||||
|
||||
if (tsk_affinity == tskNO_AFFINITY) {
|
||||
/* For no affinity case, we wait for idle hook to trigger on different core */
|
||||
esp_err_t ret = esp_register_freertos_idle_hook_for_cpu(test_idle_hook_func, !core_id);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(ret, ESP_OK, "test_utils_task_delete: failed to register idle hook");
|
||||
vTaskDelete(thandle);
|
||||
test_sem = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(test_sem, "test_utils_task_delete: failed to create semaphore");
|
||||
xSemaphoreTake(test_sem, portMAX_DELAY);
|
||||
esp_deregister_freertos_idle_hook_for_cpu(test_idle_hook_func, !core_id);
|
||||
vSemaphoreDelete(test_sem);
|
||||
test_sem = NULL;
|
||||
} else if (tsk_affinity != core_id) {
|
||||
/* Task affinity and current core are differnt, schedule IPC call (to delete task)
|
||||
* on core where task is pinned to */
|
||||
esp_ipc_call_blocking(tsk_affinity, test_task_delete_func, thandle);
|
||||
} else {
|
||||
/* Task affinity and current core are same, so we can safely proceed for deletion */
|
||||
vTaskDelete(thandle);
|
||||
}
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue