From 6e09056c25550331b535e0cd82005973611bd43f Mon Sep 17 00:00:00 2001 From: Shubham Kulkarni Date: Mon, 24 Feb 2020 10:25:16 +0530 Subject: [PATCH] example: Add Heap Task Tracking example --- docs/en/api-reference/system/heap_debug.rst | 10 +++ .../system/heap_task_tracking/CMakeLists.txt | 6 ++ examples/system/heap_task_tracking/Makefile | 9 +++ examples/system/heap_task_tracking/README.md | 36 +++++++++ .../heap_task_tracking/main/CMakeLists.txt | 2 + .../heap_task_tracking/main/component.mk | 5 ++ .../main/heap_task_tracking_main.c | 77 +++++++++++++++++++ .../heap_task_tracking/sdkconfig.defaults | 2 + 8 files changed, 147 insertions(+) create mode 100644 examples/system/heap_task_tracking/CMakeLists.txt create mode 100644 examples/system/heap_task_tracking/Makefile create mode 100644 examples/system/heap_task_tracking/README.md create mode 100644 examples/system/heap_task_tracking/main/CMakeLists.txt create mode 100644 examples/system/heap_task_tracking/main/component.mk create mode 100644 examples/system/heap_task_tracking/main/heap_task_tracking_main.c create mode 100644 examples/system/heap_task_tracking/sdkconfig.defaults diff --git a/docs/en/api-reference/system/heap_debug.rst b/docs/en/api-reference/system/heap_debug.rst index 92f74be404..1a9cb964b4 100644 --- a/docs/en/api-reference/system/heap_debug.rst +++ b/docs/en/api-reference/system/heap_debug.rst @@ -117,6 +117,16 @@ Calls to :cpp:func:`heap_caps_check_integrity` may print errors relating to 0xFE - For free heap blocks, the checker expects to find all bytes set to 0xFE. Any other values indicate a use-after-free bug where free memory has been incorrectly overwritten. - For allocated heap blocks, the behaviour is the same as for `Light Impact` mode. The canary bytes 0xABBA1234 and 0xBAAD5678 are checked at the head and tail of each allocated buffer, and any variation indicates a buffer overrun/underrun. +.. _heap-task-tracking: + +Heap Task Tracking +------------------ + +Heap Task Tracking can be used to get per task info for heap memory allocation. +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` + .. _heap-tracing: Heap Tracing diff --git a/examples/system/heap_task_tracking/CMakeLists.txt b/examples/system/heap_task_tracking/CMakeLists.txt new file mode 100644 index 0000000000..262a2e065d --- /dev/null +++ b/examples/system/heap_task_tracking/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.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(heap_task_tracking) diff --git a/examples/system/heap_task_tracking/Makefile b/examples/system/heap_task_tracking/Makefile new file mode 100644 index 0000000000..cb92798c55 --- /dev/null +++ b/examples/system/heap_task_tracking/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := heap_task_tracking + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/system/heap_task_tracking/README.md b/examples/system/heap_task_tracking/README.md new file mode 100644 index 0000000000..9284a519d5 --- /dev/null +++ b/examples/system/heap_task_tracking/README.md @@ -0,0 +1,36 @@ +# 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/main/CMakeLists.txt b/examples/system/heap_task_tracking/main/CMakeLists.txt new file mode 100644 index 0000000000..0a6f33d702 --- /dev/null +++ b/examples/system/heap_task_tracking/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "heap_task_tracking_main.c" + INCLUDE_DIRS "") diff --git a/examples/system/heap_task_tracking/main/component.mk b/examples/system/heap_task_tracking/main/component.mk new file mode 100644 index 0000000000..0b9d7585e7 --- /dev/null +++ b/examples/system/heap_task_tracking/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + 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 new file mode 100644 index 0000000000..bb82fd8122 --- /dev/null +++ b/examples/system/heap_task_tracking/main/heap_task_tracking_main.c @@ -0,0 +1,77 @@ +/* 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" + + +#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 ? pcTaskGetTaskName(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 new file mode 100644 index 0000000000..9f0f338bdf --- /dev/null +++ b/examples/system/heap_task_tracking/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_HEAP_POISONING_LIGHT=y +CONFIG_HEAP_TASK_TRACKING=y