diff --git a/components/heap/heap_task_info.c b/components/heap/heap_task_info.c index 8349ad441d..880bf358fd 100644 --- a/components/heap/heap_task_info.c +++ b/components/heap/heap_task_info.c @@ -4,10 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include #include -#include #include "multi_heap_internal.h" #include "heap_private.h" #include "esp_heap_task_info.h" @@ -619,11 +620,15 @@ esp_err_t heap_caps_get_single_task_stat(heap_single_task_stat_t *task_stat, Tas return ESP_OK; } -static void heap_caps_print_task_info(task_info_t *task_info, bool is_last_task_info) +static void heap_caps_print_task_info(FILE *stream, task_info_t *task_info, bool is_last_task_info) { + if (stream == NULL) { + stream = stdout; + } + const char *task_info_visual = is_last_task_info ? " " : "│"; const char *task_info_visual_start = is_last_task_info ? "└" : "├"; - esp_rom_printf("%s %s: %s, CURRENT MEMORY USAGE %d, PEAK MEMORY USAGE %d, TOTAL HEAP USED %d:\n", task_info_visual_start, + fprintf(stream, "%s %s: %s, CURRENT MEMORY USAGE %d, PEAK MEMORY USAGE %d, TOTAL HEAP USED %d:\n", task_info_visual_start, task_info->task_stat.is_alive ? "ALIVE" : "DELETED", task_info->task_stat.name, task_info->task_stat.overall_current_usage, @@ -634,7 +639,7 @@ static void heap_caps_print_task_info(task_info_t *task_info, bool is_last_task_ STAILQ_FOREACH(heap_info, &task_info->heaps_stats, next_heap_stat) { char *next_heap_visual = !STAILQ_NEXT(heap_info, next_heap_stat) ? " " : "│"; char *next_heap_visual_start = !STAILQ_NEXT(heap_info, next_heap_stat) ? "└" : "├"; - esp_rom_printf("%s %s HEAP: %s, CAPS: 0x%08lx, SIZE: %d, USAGE: CURRENT %d (%d%%), PEAK %d (%d%%), ALLOC COUNT: %d\n", + fprintf(stream, "%s %s HEAP: %s, CAPS: 0x%08lx, SIZE: %d, USAGE: CURRENT %d (%d%%), PEAK %d (%d%%), ALLOC COUNT: %d\n", task_info_visual, next_heap_visual_start, heap_info->heap_stat.name, @@ -648,7 +653,7 @@ static void heap_caps_print_task_info(task_info_t *task_info, bool is_last_task_ alloc_stats_t *alloc_stats = NULL; STAILQ_FOREACH(alloc_stats, &heap_info->allocs_stats, next_alloc_stat) { - esp_rom_printf("%s %s ├ ALLOC %p, SIZE %d\n", task_info_visual, + fprintf(stream, "%s %s ├ ALLOC %p, SIZE %" PRIu32 "\n", task_info_visual, next_heap_visual, alloc_stats->alloc_stat.address, alloc_stats->alloc_stat.size); @@ -656,16 +661,20 @@ static void heap_caps_print_task_info(task_info_t *task_info, bool is_last_task_ } } -static void heap_caps_print_task_overview(task_info_t *task_info, bool is_first_task_info, bool is_last_task_info) +static void heap_caps_print_task_overview(FILE *stream, task_info_t *task_info, bool is_first_task_info, bool is_last_task_info) { + if (stream == NULL) { + stream = stdout; + } + if (is_first_task_info) { - esp_rom_printf("┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐\n"); - esp_rom_printf("│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │\n"); - esp_rom_printf("├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤\n"); + fprintf(stream, "┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐\n"); + fprintf(stream, "│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │\n"); + fprintf(stream, "├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤\n"); } task_stat_t task_stat = task_info->task_stat; - esp_rom_printf("│ %18s │ %7s │ %20d │ %17d │ %15d │\n", + fprintf(stream, "│ %18s │ %7s │ %20d │ %17d │ %15d │\n", task_stat.name, task_stat.is_alive ? "ALIVE " : "DELETED", task_stat.overall_current_usage, @@ -673,11 +682,11 @@ static void heap_caps_print_task_overview(task_info_t *task_info, bool is_first_ task_stat.heap_count); if (is_last_task_info) { - esp_rom_printf("└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘\n"); + fprintf(stream, "└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘\n"); } } -void heap_caps_print_single_task_stat(TaskHandle_t task_handle) +void heap_caps_print_single_task_stat(FILE *stream, TaskHandle_t task_handle) { if (task_handle == NULL) { task_handle = xTaskGetCurrentTaskHandle(); @@ -697,7 +706,7 @@ void heap_caps_print_single_task_stat(TaskHandle_t task_handle) xSemaphoreGive(s_task_tracking_mutex); } -void heap_caps_print_all_task_stat(void) +void heap_caps_print_all_task_stat(FILE *stream) { task_info_t *task_info = NULL; @@ -709,7 +718,7 @@ void heap_caps_print_all_task_stat(void) xSemaphoreGive(s_task_tracking_mutex); } -void heap_caps_print_single_task_stat_overview(TaskHandle_t task_handle) +void heap_caps_print_single_task_stat_overview(FILE *stream, TaskHandle_t task_handle) { if (task_handle == NULL) { task_handle = xTaskGetCurrentTaskHandle(); @@ -729,7 +738,7 @@ void heap_caps_print_single_task_stat_overview(TaskHandle_t task_handle) xSemaphoreGive(s_task_tracking_mutex); } -void heap_caps_print_all_task_stat_overview(void) +void heap_caps_print_all_task_stat_overview(FILE *stream) { task_info_t *task_info = NULL; bool is_first_task_info = true; diff --git a/components/heap/include/esp_heap_task_info.h b/components/heap/include/esp_heap_task_info.h index 1aee89b55d..e123afac55 100644 --- a/components/heap/include/esp_heap_task_info.h +++ b/components/heap/include/esp_heap_task_info.h @@ -10,6 +10,7 @@ #ifdef CONFIG_HEAP_TASK_TRACKING #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -167,16 +168,20 @@ esp_err_t heap_caps_get_single_task_stat(heap_single_task_stat_t *task_stat, Tas * * @note This function is an alternative to heap_caps_get_all_task_stat if the goal is just to print information * and not manipulate them. + * + * @param steam The stream to dump to, if NULL then stdout is used */ -void heap_caps_print_all_task_stat(void); +void heap_caps_print_all_task_stat(FILE *stream); /** * @brief Print summary information of all tasks * * @note The information printed by this function is an array formatted log of task_stat_t content for each running * task (and deleted ones if HEAP_TRACK_DELETED_TASKS is enabled) + * + * @param steam The stream to dump to, if NULL then stdout is used */ -void heap_caps_print_all_task_stat_overview(void); +void heap_caps_print_all_task_stat_overview(FILE *stream); /** * @brief Print heap memory usage and associated allocation information on each heap for a given task. @@ -184,9 +189,10 @@ void heap_caps_print_all_task_stat_overview(void); * @note This function is an alternative to heap_caps_get_single_task_stat if the goal is just to print information * and not manipulate them. * + * @param steam The stream to dump to, if NULL then stdout is used * @param task_handle The task handle of the task to get memory usage and associated allocation information from. */ -void heap_caps_print_single_task_stat(TaskHandle_t task_handle); +void heap_caps_print_single_task_stat(FILE *stream, TaskHandle_t task_handle); /** * @brief Print summary information of a given task @@ -195,9 +201,10 @@ void heap_caps_print_single_task_stat(TaskHandle_t task_handle); * task. This function will not print the task summary information if the given task is deleted and * HEAP_TRACK_DELETED_TASKS is disabled. * + * @param steam The stream to dump to, if NULL then stdout is used * @param task_handle The task handle of the task to get memory usage and associated allocation information from. */ -void heap_caps_print_single_task_stat_overview(TaskHandle_t task_handle); +void heap_caps_print_single_task_stat_overview(FILE *stream, TaskHandle_t task_handle); /** * @brief Allocate the memory used to store the heap and alloc statistics and fill task_stat diff --git a/docs/en/api-reference/system/heap_debug.rst b/docs/en/api-reference/system/heap_debug.rst index 85dc888e5c..dd554511a1 100644 --- a/docs/en/api-reference/system/heap_debug.rst +++ b/docs/en/api-reference/system/heap_debug.rst @@ -202,7 +202,7 @@ Heap Task Tracking Heap Task Tracking can be used to get per-task info for heap memory allocation. The application has to specify the heap capabilities for which the heap allocation is to be tracked. -Example code is provided in :example:`system/heap_task_tracking`. +Example applications are provided in :example:`system/heap_task_tracking/basic` and :example:`system/heap_task_tracking/advanced`. .. _heap-tracing: @@ -629,7 +629,8 @@ One way to differentiate between "real" and "false positive" memory leaks is to Application Examples -------------------- -- :example:`system/heap_task_tracking` demonstrates the use of the heap task tracking feature to track heap memory allocated on a per-task basis. +- :example:`system/heap_task_tracking/basic` demonstrates the use of the overview feature of the heap task tracking, dumping per-task summary statistics on heap memory usage. +- :example:`system/heap_task_tracking/advanced` demonstrates the use of the statistics getter functions of the heap task tracking, accessing per-task complete statistic on the heap memory usage. API Reference - Heap Tracing ---------------------------- diff --git a/examples/system/heap_task_tracking/README.md b/examples/system/heap_task_tracking/README.md deleted file mode 100644 index 79718e4b0e..0000000000 --- a/examples/system/heap_task_tracking/README.md +++ /dev/null @@ -1,39 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | - -# Heap Task Tracking Example - -## Overview - -The example creates a task which allocates random amount of memory in each iteration and demonstrates use of internal API to get heap info on per task basis running in a system. - -Heap task tracking feature has dependency on some of the internal heap debugging features (e.g. heap poisoning) which allows to store task control block in metadata of each heap block. - -This adds small memory overhead on per heap block and hence this feature should be used for debugging purpose only. - -### Configure the project - -To change the `Heap Corruption Detection level`, open the project configuration menu (`idf.py menuconfig`). - -Navigate to `Component config -> Heap memory debugging` menu. In `Heap corruption detection` menu select either "Light Impact" or "Comprehensive". - -**Note:** Enabling “Comprehensive” detection has a substantial runtime performance impact. - -### Build and Flash - -Run `idf.py -p PORT flash monitor` to build and flash the project.. - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -Task: Pre-Scheduler allocs -> CAP_8BIT: 5360 CAP_32BIT: 0 -Task: esp_timer -> CAP_8BIT: 1724 CAP_32BIT: 0 -Task: ipc0 -> CAP_8BIT: 8316 CAP_32BIT: 0 -Task: main -> CAP_8BIT: 3480 CAP_32BIT: 0 -Task: ipc1 -> CAP_8BIT: 12 CAP_32BIT: 0 -Task: example_task -> CAP_8BIT: 696 CAP_32BIT: 0 -``` diff --git a/examples/system/heap_task_tracking/advanced/CMakeLists.txt b/examples/system/heap_task_tracking/advanced/CMakeLists.txt new file mode 100644 index 0000000000..e788c7d4be --- /dev/null +++ b/examples/system/heap_task_tracking/advanced/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(advanced) diff --git a/examples/system/heap_task_tracking/advanced/README.md b/examples/system/heap_task_tracking/advanced/README.md new file mode 100644 index 0000000000..b528ea7877 --- /dev/null +++ b/examples/system/heap_task_tracking/advanced/README.md @@ -0,0 +1,141 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | + +# Heap Task Tracking Basic Example + +## Overview + +The example creates a task which allocates random amount of memory and frees it and another task that allocates random amount of memory but never frees it. +The main then goes into a loop calling functions retrieving statistics for the "no leak" task, the "leaking" tasks and all tasks and printing them. +For each tasks, the following information is retrieved and printed: + - the task name + - the task status (running or deleted) + - the overall peak memory usage of the task + - the overall current memory usage of the task +For each heap used by a given task, the following information is printed: + - the heap name + - the heap caps + - the heap size + - the heap current memory usage by the task + - the heap peak memory usage by the task + - the number of blocks currently allocated in the heap by the task +For each block of memory allocated in a given heap by a given task, the following information is printed: + - the allocation address + - the allocation size + +Because the heap task tracking feature requires additional metadata to be allocated for each memory allocations, the overall heap usage of the application is +greater than when the feature is disabled. For this reason, it is highly recommended to use the task tracking for debugging purpose only. + +### Configure the project + +- Enable thee option `Enable heap task tracking` by opening the project configuration menu (`idf.py menuconfig`) and navigate to `Component config -> Heap memory debugging` menu. +- (optional) Enable the option `Keep information about the memory usage on deleted tasks` if you wish to keep track of the information of a task after it has been deleted. + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build and flash the project.. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +-------------------------------------------------------------------------------- +PRINTING SINGLE TASK INFO +-------------------------------------------------------------------------------- +no_leak_task: ALIVE : Peak Usage 10128, Current Usage 0 + RAM: Caps: 1071118. Size 22308, Current Usage 0, Peak Usage 10128, alloc count 0 + +-------------------------------------------------------------------------------- +PRINTING SINGLE TASK INFO +-------------------------------------------------------------------------------- +leaking_task: ALIVE : Peak Usage 7232, Current Usage 6656 + RAM: Caps: 1071118. Size 22308, Current Usage 6656, Peak Usage 7232, alloc count 1 + 0x3fceb878: Size: 6656 + +-------------------------------------------------------------------------------- +PRINTING SINGLE TASK INFO +-------------------------------------------------------------------------------- +no_leak_task: ALIVE : Peak Usage 10128, Current Usage 0 + RAM: Caps: 1071118. Size 22308, Current Usage 0, Peak Usage 10128, alloc count 0 + RAM: Caps: 1071118. Size 14832, Current Usage 0, Peak Usage 8960, alloc count 0 + +-------------------------------------------------------------------------------- +PRINTING SINGLE TASK INFO +-------------------------------------------------------------------------------- +leaking_task: ALIVE : Peak Usage 15040, Current Usage 9664 + RAM: Caps: 1071118. Size 22308, Current Usage 6656, Peak Usage 12032, alloc count 1 + 0x3fceb878: Size: 6656 + RAM: Caps: 1071118. Size 14832, Current Usage 3008, Peak Usage 3008, alloc count 1 + 0x3fc9a0e4: Size: 3008 + +[...] + +-------------------------------------------------------------------------------- +PRINTING ALL TASKS INFO +-------------------------------------------------------------------------------- +leaking_task: DELETED: Peak Usage 19248, Current Usage 13616 + RAM: Caps: 1071118. Size 22308, Current Usage 10608, Peak Usage 13296, alloc count 3 + 0x3fceb878: Size: 6656 + 0x3fceb634: Size: 368 + 0x3fcedd00: Size: 3584 + RAM: Caps: 1071118. Size 14832, Current Usage 3008, Peak Usage 12224, alloc count 1 + 0x3fc9a0e4: Size: 3008 +no_leak_task: DELETED: Peak Usage 10128, Current Usage 0 + RAM: Caps: 1071118. Size 22308, Current Usage 0, Peak Usage 10128, alloc count 0 + RAM: Caps: 1071118. Size 14832, Current Usage 0, Peak Usage 9728, alloc count 0 +main: ALIVE : Peak Usage 7456, Current Usage 352 + RAM: Caps: 1071118. Size 14832, Current Usage 264, Peak Usage 264, alloc count 3 + 0x3fc99cf4: Size: 88 + 0x3fc99e1c: Size: 88 + 0x3fc99e78: Size: 88 + RAM: Caps: 1071118. Size 22308, Current Usage 88, Peak Usage 7192, alloc count 5 + 0x3fce99f8: Size: 20 + 0x3fce9a10: Size: 12 + 0x3fce9a20: Size: 16 + 0x3fce9a34: Size: 20 + 0x3fce9a4c: Size: 20 +ipc1: ALIVE : Peak Usage 44, Current Usage 32 + RAM: Caps: 1071118. Size 14832, Current Usage 32, Peak Usage 44, alloc count 2 + 0x3fc99dcc: Size: 16 + 0x3fc99df4: Size: 16 +ipc0: ALIVE : Peak Usage 10092, Current Usage 10080 + RAM: Caps: 1071118. Size 14832, Current Usage 10080, Peak Usage 10092, alloc count 10 + 0x3fc973b0: Size: 1312 + 0x3fc97950: Size: 344 + 0x3fc97ae4: Size: 16 + 0x3fc97b0c: Size: 4224 + 0x3fc98b90: Size: 344 + 0x3fc98d00: Size: 1568 + 0x3fc99338: Size: 344 + 0x3fc994a8: Size: 1568 + 0x3fc99ae0: Size: 344 + 0x3fc99c64: Size: 16 +Pre-scheduler: ALIVE : Peak Usage 3364, Current Usage 3364 + RAM: Caps: 1071118. Size 14832, Current Usage 3364, Peak Usage 3364, alloc count 22 + 0x3fc96410: Size: 164 + 0x3fc96538: Size: 12 + 0x3fc9655c: Size: 12 + 0x3fc96580: Size: 16 + 0x3fc965a8: Size: 24 + 0x3fc965d8: Size: 36 + 0x3fc96614: Size: 40 + 0x3fc96654: Size: 36 + 0x3fc96690: Size: 40 + 0x3fc966d0: Size: 88 + 0x3fc96740: Size: 88 + 0x3fc967b0: Size: 88 + 0x3fc96820: Size: 432 + 0x3fc969e8: Size: 88 + 0x3fc96a58: Size: 88 + 0x3fc96ac8: Size: 88 + 0x3fc96b38: Size: 132 + 0x3fc96bd4: Size: 132 + 0x3fc96c70: Size: 88 + 0x3fc96ce0: Size: 16 + 0x3fc96d08: Size: 1312 + 0x3fc97240: Size: 344 +I (4504) main_task: Returned from app_main() +``` diff --git a/examples/system/heap_task_tracking/advanced/main/CMakeLists.txt b/examples/system/heap_task_tracking/advanced/main/CMakeLists.txt new file mode 100644 index 0000000000..00c9065c5e --- /dev/null +++ b/examples/system/heap_task_tracking/advanced/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "heap_task_tracking_advanced_main.c" + INCLUDE_DIRS "") diff --git a/examples/system/heap_task_tracking/advanced/main/heap_task_tracking_advanced_main.c b/examples/system/heap_task_tracking/advanced/main/heap_task_tracking_advanced_main.c new file mode 100644 index 0000000000..cd551dbd1d --- /dev/null +++ b/examples/system/heap_task_tracking/advanced/main/heap_task_tracking_advanced_main.c @@ -0,0 +1,180 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Heap Task Tracking Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_heap_task_info.h" +#include "esp_heap_caps.h" +#include "esp_random.h" +#include "esp_log.h" + +static void print_single_task_info(TaskHandle_t task_hdl) +{ + heap_single_task_stat_t task_stat; + /* call API to dynamically allocate the memory necessary to store the + * information collected while calling heap_caps_get_single_task_stat */ + const esp_err_t ret_val = heap_caps_alloc_single_task_stat_arrays(&task_stat, task_hdl); + assert(ret_val == ESP_OK); + + /* collect the information */ + heap_caps_get_single_task_stat(&task_stat, task_hdl); + + /* process the information retrieved */ + printf("\n--------------------------------------------------------------------------------\n"); + printf("PRINTING SINGLE TASK INFO\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("%s: %s: Peak Usage %"PRIu16", Current Usage %"PRIu16"\n", task_stat.stat.name, + task_stat.stat.is_alive ? "ALIVE " : "DELETED", + task_stat.stat.overall_peak_usage, + task_stat.stat.overall_current_usage); + + for (size_t heap_idx = 0; heap_idx < task_stat.heap_count; heap_idx++) { + heap_stat_t heap_stat = task_stat.heap_stat_start[heap_idx]; + printf(" %s: Caps: %"PRIu32". Size %"PRIu16", Current Usage %"PRIu16", Peak Usage %"PRIu16", alloc count %"PRIu16"\n", heap_stat.name, + heap_stat.caps, + heap_stat.size, + heap_stat.current_usage, + heap_stat.peak_usage, + heap_stat.alloc_count); + + for (size_t alloc_idx = 0; alloc_idx < heap_stat.alloc_count; alloc_idx++) { + heap_task_block_t alloc_stat = heap_stat.alloc_stat[alloc_idx]; + printf(" %p: Size: %"PRIu32"\n", alloc_stat.address, alloc_stat.size); + } + } + + /* delete the memory dynamically allocated while calling heap_caps_alloc_all_task_stat_arrays */ + heap_caps_free_single_task_stat_arrays(&task_stat); +} + +static void print_all_tasks_info(void) +{ + heap_all_tasks_stat_t tasks_stat; + /* call API to dynamically allocate the memory necessary to store the + * information collected while calling heap_caps_get_all_task_stat */ + const esp_err_t ret_val = heap_caps_alloc_all_task_stat_arrays(&tasks_stat); + assert(ret_val == ESP_OK); + + /* collect the information */ + heap_caps_get_all_task_stat(&tasks_stat); + + /* process the information retrieved */ + printf("\n--------------------------------------------------------------------------------\n"); + printf("PRINTING ALL TASKS INFO\n"); + printf("--------------------------------------------------------------------------------\n"); + for (size_t task_idx = 0; task_idx < tasks_stat.task_count; task_idx++) { + task_stat_t task_stat = tasks_stat.stat_arr[task_idx]; + printf("%s: %s: Peak Usage %"PRIu16", Current Usage %"PRIu16"\n", task_stat.name, + task_stat.is_alive ? "ALIVE " : "DELETED", + task_stat.overall_peak_usage, + task_stat.overall_current_usage); + + for (size_t heap_idx = 0; heap_idx < task_stat.heap_count; heap_idx++) { + heap_stat_t heap_stat = task_stat.heap_stat[heap_idx]; + printf(" %s: Caps: %"PRIu32". Size %"PRIu16", Current Usage %"PRIu16", Peak Usage %"PRIu16", alloc count %"PRIu16"\n", heap_stat.name, + heap_stat.caps, + heap_stat.size, + heap_stat.current_usage, + heap_stat.peak_usage, + heap_stat.alloc_count); + + for (size_t alloc_idx = 0; alloc_idx < heap_stat.alloc_count; alloc_idx++) { + heap_task_block_t alloc_stat = heap_stat.alloc_stat[alloc_idx]; + printf(" %p: Size: %"PRIu32"\n", alloc_stat.address, alloc_stat.size); + } + } + } + + /* delete the memory dynamically allocated while calling heap_caps_alloc_all_task_stat_arrays */ + heap_caps_free_all_task_stat_arrays(&tasks_stat); +} + +static void no_leak_task(void *args) +{ + size_t size_a = 0; + size_t size_b = 0; + char *task_name = pcTaskGetName(*((TaskHandle_t*)args)); + + while(1) { + /* Allocate random amount of memory for demonstration */ + size_a = (esp_random() % 10000) + 1; + size_b = (esp_random() % (10000 - size_a)) + 1; + + void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT); + void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT); + if (ptr_a == NULL || ptr_b == NULL) { + ESP_LOGE(task_name, "Could not allocate heap memory"); + abort(); + } + + heap_caps_free(ptr_a); + heap_caps_free(ptr_b); + + // print the task statistics (passing NULL will print info for + // the currently running task) + print_single_task_info(NULL); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +static void leaking_task(void *args) +{ + size_t size_a = 0; + size_t size_b = 0; + char *task_name = pcTaskGetName(*((TaskHandle_t*)args)); + + while(1) { + /* Allocate random amount of memory for demonstration */ + size_a = (esp_random() % 10000) + 1; + size_b = (esp_random() % (10000 - size_a)) + 1; + + void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT); + void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT); + if (ptr_a == NULL || ptr_b == NULL) { + ESP_LOGE(task_name, "Could not allocate heap memory"); + abort(); + } + + heap_caps_free(ptr_a); + + // don't free ptr_b on purpose to create unfreed memory for the task info to print + // heap_caps_free(ptr_b); + + // print the task statistics (passing NULL will print info for + // the currently running task) + print_single_task_info(NULL); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void app_main(void) +{ + TaskHandle_t no_leak_task_hdl, leaking_task_hdl; + + /* Create example task to demonstrate heap_task_tracking */ + xTaskCreate(&no_leak_task, "no_leak_task", 3072, &no_leak_task_hdl, 0, &no_leak_task_hdl); + xTaskCreate(&leaking_task, "leaking_task", 3072, &leaking_task_hdl, 0, &leaking_task_hdl); + + size_t counter = 4; + while(counter != 0) { + vTaskDelay(pdMS_TO_TICKS(1000)); + counter--; + } + + vTaskDelete(leaking_task_hdl); + vTaskDelete(no_leak_task_hdl); + + print_all_tasks_info(); +} diff --git a/examples/system/heap_task_tracking/advanced/sdkconfig.defaults b/examples/system/heap_task_tracking/advanced/sdkconfig.defaults new file mode 100644 index 0000000000..a6efa77473 --- /dev/null +++ b/examples/system/heap_task_tracking/advanced/sdkconfig.defaults @@ -0,0 +1,5 @@ +# enable the task tracking feature +CONFIG_HEAP_TASK_TRACKING=y + +# keep task tracking information after the task is deleted +CONFIG_HEAP_TRACK_DELETED_TASKS=y diff --git a/examples/system/heap_task_tracking/CMakeLists.txt b/examples/system/heap_task_tracking/basic/CMakeLists.txt similarity index 92% rename from examples/system/heap_task_tracking/CMakeLists.txt rename to examples/system/heap_task_tracking/basic/CMakeLists.txt index c68b33b49f..6a651d0736 100644 --- a/examples/system/heap_task_tracking/CMakeLists.txt +++ b/examples/system/heap_task_tracking/basic/CMakeLists.txt @@ -5,4 +5,4 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) -project(heap_task_tracking) +project(basic) diff --git a/examples/system/heap_task_tracking/basic/README.md b/examples/system/heap_task_tracking/basic/README.md new file mode 100644 index 0000000000..a1d13ab472 --- /dev/null +++ b/examples/system/heap_task_tracking/basic/README.md @@ -0,0 +1,156 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | + +# Heap Task Tracking Basic Example + +## Overview + +The example creates a task which allocates random amount of memory and frees it and another task that allocates random amount of memory but never frees it. +The main then goes into a loop printing the overview information of each task that allocated memory dynamically. +The information include: +- The task name +- The task status +- The current memory usage +- The peak memory usage +- The number of heaps currently used by the task + +Because the heap task tracking feature requires additional metadata to be allocated for each memory allocations, the overall heap usage of the application is +greater than when the feature is disabled. For this reason, it is highly recommended to use the task tracking for debugging purpose only. + +### Configure the project + +- Enable thee option `Enable heap task tracking` by opening the project configuration menu (`idf.py menuconfig`) and navigate to `Component config -> Heap memory debugging` menu. +- (optional) Enable the option `Keep information about the memory usage on deleted tasks` if you wish to keep track of the information of a task after it has been deleted. + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build and flash the project.. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +Starting task: no_leak_task +Starting task: leaking_task + + PRINTING OVERVIEW STATISTICS OF EACH TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ leaking_task │ ALIVE │ 6656 │ 8064 │ 1 │ +│ no_leak_task │ ALIVE │ 0 │ 7152 │ 1 │ +│ main │ ALIVE │ 7412 │ 7412 │ 2 │ +│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │ +│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │ +│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + + PRINTING OVERVIEW STATISTICS OF NO LEAK TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ no_leak_task │ ALIVE │ 0 │ 7152 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + + PRINTING OVERVIEW STATISTICS OF LEAKING TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ leaking_task │ ALIVE │ 6656 │ 8064 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + +[...] +Deleting task: leaking_task + + PRINTING OVERVIEW STATISTICS OF EACH TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │ +│ no_leak_task │ ALIVE │ 0 │ 9408 │ 2 │ +│ main │ ALIVE │ 3860 │ 7412 │ 2 │ +│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │ +│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │ +│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + + PRINTING OVERVIEW STATISTICS OF NO LEAK TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ no_leak_task │ ALIVE │ 0 │ 9408 │ 2 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + + PRINTING OVERVIEW STATISTICS OF LEAKING TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ +Deleting task: no_leak_task + + PRINTING OVERVIEW STATISTICS OF EACH TASK +┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐ +│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │ +├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤ +│ leaking_task │ DELETED │ 11392 │ 11616 │ 1 │ +│ no_leak_task │ DELETED │ 0 │ 9408 │ 2 │ +│ main │ ALIVE │ 308 │ 7412 │ 2 │ +│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │ +│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │ +│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │ +└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘ + + PRINTING DETAILED STATISTICS OF EACH TASK +├ DELETED: leaking_task, CURRENT MEMORY USAGE 11392, PEAK MEMORY USAGE 11616, TOTAL HEAP USED 1: +│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 11392 (51%), PEAK 11616 (52%), ALLOC COUNT: 3 +│ ├ ALLOC 0x3fcebbb8, SIZE 6656 +│ ├ ALLOC 0x3fced5bc, SIZE 3584 +│ ├ ALLOC 0x3fceb718, SIZE 1152 +├ DELETED: no_leak_task, CURRENT MEMORY USAGE 0, PEAK MEMORY USAGE 9408, TOTAL HEAP USED 2: +│ ├ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 0 (0%), PEAK 7152 (32%), ALLOC COUNT: 0 +│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 0 (0%), PEAK 9216 (2%), ALLOC COUNT: 0 +├ ALIVE: main, CURRENT MEMORY USAGE 308, PEAK MEMORY USAGE 7412, TOTAL HEAP USED 2: +│ ├ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 220 (0%), PEAK 220 (0%), ALLOC COUNT: 2 +│ │ ├ ALLOC 0x3fc99024, SIZE 88 +│ │ ├ ALLOC 0x3fc99124, SIZE 132 +│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 88 (0%), PEAK 7192 (32%), ALLOC COUNT: 5 +│ ├ ALLOC 0x3fce99f8, SIZE 20 +│ ├ ALLOC 0x3fce9a10, SIZE 12 +│ ├ ALLOC 0x3fce9a20, SIZE 16 +│ ├ ALLOC 0x3fce9a34, SIZE 20 +│ ├ ALLOC 0x3fce9a4c, SIZE 20 +├ ALIVE: ipc1, CURRENT MEMORY USAGE 32, PEAK MEMORY USAGE 44, TOTAL HEAP USED 1: +│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 32 (0%), PEAK 44 (0%), ALLOC COUNT: 2 +│ ├ ALLOC 0x3fc990fc, SIZE 16 +│ ├ ALLOC 0x3fc991c0, SIZE 16 +├ ALIVE: ipc0, CURRENT MEMORY USAGE 10080, PEAK MEMORY USAGE 10092, TOTAL HEAP USED 1: +│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 10080 (2%), PEAK 10092 (2%), ALLOC COUNT: 10 +│ ├ ALLOC 0x3fc966e0, SIZE 1312 +│ ├ ALLOC 0x3fc96c80, SIZE 344 +│ ├ ALLOC 0x3fc96e14, SIZE 16 +│ ├ ALLOC 0x3fc96e3c, SIZE 4224 +│ ├ ALLOC 0x3fc97ec0, SIZE 344 +│ ├ ALLOC 0x3fc98030, SIZE 1568 +│ ├ ALLOC 0x3fc98668, SIZE 344 +│ ├ ALLOC 0x3fc987d8, SIZE 1568 +│ ├ ALLOC 0x3fc98e10, SIZE 344 +│ ├ ALLOC 0x3fc98f94, SIZE 16 +└ ALIVE: Pre-scheduler, CURRENT MEMORY USAGE 2236, PEAK MEMORY USAGE 2236, TOTAL HEAP USED 1: + └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 2236 (0%), PEAK 2236 (0%), ALLOC COUNT: 11 + ├ ALLOC 0x3fc95cb0, SIZE 164 + ├ ALLOC 0x3fc95dd8, SIZE 12 + ├ ALLOC 0x3fc95dfc, SIZE 12 + ├ ALLOC 0x3fc95e20, SIZE 16 + ├ ALLOC 0x3fc95e48, SIZE 24 + ├ ALLOC 0x3fc95e78, SIZE 88 + ├ ALLOC 0x3fc95ee8, SIZE 88 + ├ ALLOC 0x3fc95f58, SIZE 88 + ├ ALLOC 0x3fc95fc8, SIZE 88 + ├ ALLOC 0x3fc96038, SIZE 1312 + ├ ALLOC 0x3fc96570, SIZE 344 +I (5949) main_task: Returned from app_main() +``` diff --git a/examples/system/heap_task_tracking/main/CMakeLists.txt b/examples/system/heap_task_tracking/basic/main/CMakeLists.txt similarity index 100% rename from examples/system/heap_task_tracking/main/CMakeLists.txt rename to examples/system/heap_task_tracking/basic/main/CMakeLists.txt diff --git a/examples/system/heap_task_tracking/basic/main/heap_task_tracking_main.c b/examples/system/heap_task_tracking/basic/main/heap_task_tracking_main.c new file mode 100644 index 0000000000..5d0731ba88 --- /dev/null +++ b/examples/system/heap_task_tracking/basic/main/heap_task_tracking_main.c @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Heap Task Tracking Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_heap_task_info.h" +#include "esp_heap_caps.h" +#include "esp_random.h" +#include "esp_log.h" + +static void no_leak_task(void *args) +{ + size_t size_a = 0; + size_t size_b = 0; + char *task_name = pcTaskGetName(*((TaskHandle_t*)args)); + printf("Starting task: %s\n", task_name); + + while(1) { + /* Allocate random amount of memory for demonstration */ + size_a = (esp_random() % 10000) + 1; + size_b = (esp_random() % (10000 - size_a)) + 1; + + void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT); + void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT); + if (ptr_a == NULL || ptr_b == NULL) { + ESP_LOGE(task_name, "Could not allocate heap memory"); + abort(); + } + + heap_caps_free(ptr_a); + heap_caps_free(ptr_b); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +static void leaking_task(void *args) +{ + size_t size_a = 0; + size_t size_b = 0; + char *task_name = pcTaskGetName(*((TaskHandle_t*)args)); + printf("Starting task: %s\n", task_name); + + while(1) { + /* Allocate random amount of memory for demonstration */ + size_a = (esp_random() % 10000) + 1; + size_b = (esp_random() % (10000 - size_a)) + 1; + + void *ptr_a = heap_caps_malloc(size_a, MALLOC_CAP_DEFAULT); + void *ptr_b = heap_caps_malloc(size_b, MALLOC_CAP_DEFAULT); + if (ptr_a == NULL || ptr_b == NULL) { + ESP_LOGE(task_name, "Could not allocate heap memory"); + abort(); + } + + heap_caps_free(ptr_a); + // heap_caps_free(ptr_b); + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void app_main(void) +{ + TaskHandle_t no_leak_task_hdl, leaking_task_hdl; + + /* Create example task to demonstrate heap_task_tracking */ + xTaskCreate(&no_leak_task, "no_leak_task", 3072, &no_leak_task_hdl, 5, &no_leak_task_hdl); + xTaskCreate(&leaking_task, "leaking_task", 3072, &leaking_task_hdl, 5, &leaking_task_hdl); + + /* print task statistic periodically */ + for(size_t counter = 0; counter < 4; counter++) { + /* print the overview stats of every task */ + printf("\n PRINTING OVERVIEW STATISTICS OF EACH TASK\n"); + heap_caps_print_all_task_stat_overview(stdout); + + /* print the overview statistics of the no leak task */ + printf("\n PRINTING OVERVIEW STATISTICS OF NO LEAK TASK\n"); + heap_caps_print_single_task_stat_overview(stdout, no_leak_task_hdl); + + /* print the overview statistics of the leaking task */ + printf("\n PRINTING OVERVIEW STATISTICS OF LEAKING TASK\n"); + heap_caps_print_single_task_stat_overview(stdout, leaking_task_hdl); + + if (counter == 2) { + /* delete the leaking task and let the no leak task run + * for some more time */ + printf("Deleting task: %s\n", pcTaskGetName(leaking_task_hdl)); + vTaskDelete(leaking_task_hdl); + } + + /* wait for a second before running the loop again*/ + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + /* Delete the no leak task */ + printf("Deleting task: %s\n", pcTaskGetName(no_leak_task_hdl)); + vTaskDelete(no_leak_task_hdl); + + /* print overview information of every task */ + printf("\n PRINTING OVERVIEW STATISTICS OF EACH TASK\n"); + heap_caps_print_all_task_stat_overview(stdout); + + /* print detailed statistics for every task */ + printf("\n PRINTING DETAILED STATISTICS OF EACH TASK\n"); + heap_caps_print_all_task_stat(stdout); +} diff --git a/examples/system/heap_task_tracking/basic/sdkconfig.defaults b/examples/system/heap_task_tracking/basic/sdkconfig.defaults new file mode 100644 index 0000000000..a6efa77473 --- /dev/null +++ b/examples/system/heap_task_tracking/basic/sdkconfig.defaults @@ -0,0 +1,5 @@ +# enable the task tracking feature +CONFIG_HEAP_TASK_TRACKING=y + +# keep task tracking information after the task is deleted +CONFIG_HEAP_TRACK_DELETED_TASKS=y diff --git a/examples/system/heap_task_tracking/main/heap_task_tracking_main.c b/examples/system/heap_task_tracking/main/heap_task_tracking_main.c deleted file mode 100644 index a01868c0fc..0000000000 --- a/examples/system/heap_task_tracking/main/heap_task_tracking_main.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Heap Task Tracking Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_heap_task_info.h" -#include "esp_log.h" -#include "esp_random.h" - - -#define MAX_TASK_NUM 20 // Max number of per tasks info that it can store -#define MAX_BLOCK_NUM 20 // Max number of per block info that it can store - -static size_t s_prepopulated_num = 0; -static heap_task_totals_t s_totals_arr[MAX_TASK_NUM]; -static heap_task_block_t s_block_arr[MAX_BLOCK_NUM]; - -static void esp_dump_per_task_heap_info(void) -{ - heap_task_info_params_t heap_info = {0}; - heap_info.caps[0] = MALLOC_CAP_8BIT; // Gets heap with CAP_8BIT capabilities - heap_info.mask[0] = MALLOC_CAP_8BIT; - heap_info.caps[1] = MALLOC_CAP_32BIT; // Gets heap info with CAP_32BIT capabilities - heap_info.mask[1] = MALLOC_CAP_32BIT; - heap_info.tasks = NULL; // Passing NULL captures heap info for all tasks - heap_info.num_tasks = 0; - heap_info.totals = s_totals_arr; // Gets task wise allocation details - heap_info.num_totals = &s_prepopulated_num; - heap_info.max_totals = MAX_TASK_NUM; // Maximum length of "s_totals_arr" - heap_info.blocks = s_block_arr; // Gets block wise allocation details. For each block, gets owner task, address and size - heap_info.max_blocks = MAX_BLOCK_NUM; // Maximum length of "s_block_arr" - - heap_caps_get_per_task_info(&heap_info); - - for (int i = 0 ; i < *heap_info.num_totals; i++) { - printf("Task: %s -> CAP_8BIT: %d CAP_32BIT: %d\n", - heap_info.totals[i].task ? pcTaskGetName(heap_info.totals[i].task) : "Pre-Scheduler allocs" , - heap_info.totals[i].size[0], // Heap size with CAP_8BIT capabilities - heap_info.totals[i].size[1]); // Heap size with CAP32_BIT capabilities - } - - printf("\n\n"); -} - -static void example_task(void *args) -{ - uint32_t size = 0; - const char *TAG = "example_task"; - while (1) { - /* - * Allocate random amount of memory for demonstration - */ - size = (esp_random() % 1000); - void *ptr = malloc(size); - if (ptr == NULL) { - ESP_LOGE(TAG, "Could not allocate heap memory"); - abort(); - } - esp_dump_per_task_heap_info(); - free(ptr); - vTaskDelay(pdMS_TO_TICKS(2000)); - } -} - - -void app_main(void) -{ - /* - * Create example task to demonstrate heap_task_tracking - */ - xTaskCreate(&example_task, "example_task", 3072, NULL, 5, NULL); -} diff --git a/examples/system/heap_task_tracking/sdkconfig.defaults b/examples/system/heap_task_tracking/sdkconfig.defaults deleted file mode 100644 index 9c49654ecd..0000000000 --- a/examples/system/heap_task_tracking/sdkconfig.defaults +++ /dev/null @@ -1 +0,0 @@ -CONFIG_HEAP_TASK_TRACKING=y