Merge branch 'feature/add_heap_info_per_task_example' into 'master'

Add Task Heap Tracking example

See merge request espressif/esp-idf!7750
This commit is contained in:
Angus Gratton 2020-03-23 14:07:00 +08:00
commit b4d97a8076
8 changed files with 147 additions and 0 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
```

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "heap_task_tracking_main.c"
INCLUDE_DIRS "")

View File

@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -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 <stdio.h>
#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);
}

View File

@ -0,0 +1,2 @@
CONFIG_HEAP_POISONING_LIGHT=y
CONFIG_HEAP_TASK_TRACKING=y