heap: Wrap the function hook feature under a configuration

also update heap_debug.rst and mem_alloc.rst to provide information about the feature
This commit is contained in:
Guillaume Souchere
2023-03-08 10:48:17 +01:00
committed by Mahavir Jain
parent 5a1f0cd63c
commit 2f982107dc
8 changed files with 42 additions and 0 deletions

View File

@@ -56,6 +56,11 @@ menu "Heap memory debugging"
More stack frames uses more memory in the heap trace buffer (and slows down allocation), but More stack frames uses more memory in the heap trace buffer (and slows down allocation), but
can provide useful information. can provide useful information.
config HEAP_USE_HOOKS
bool "Use allocation and free hooks"
help
Enable the user to implement function hooks triggered for each successful allocation and free.
config HEAP_TASK_TRACKING config HEAP_TASK_TRACKING
bool "Enable heap task tracking" bool "Enable heap task tracking"
depends on !HEAP_POISONING_DISABLED depends on !HEAP_POISONING_DISABLED

View File

@@ -15,11 +15,15 @@
#include "heap_private.h" #include "heap_private.h"
#include "esp_system.h" #include "esp_system.h"
#ifdef CONFIG_HEAP_USE_HOOKS
#define CALL_HOOK(hook, ...) { \ #define CALL_HOOK(hook, ...) { \
if (hook != NULL) { \ if (hook != NULL) { \
hook(__VA_ARGS__); \ hook(__VA_ARGS__); \
} \ } \
} }
#else
#define CALL_HOOK(hook, ...) {}
#endif
/* Forward declaration for base function, put in IRAM. /* Forward declaration for base function, put in IRAM.
* These functions don't check for errors after trying to allocate memory. */ * These functions don't check for errors after trying to allocate memory. */

View File

@@ -54,6 +54,7 @@ typedef void (*esp_alloc_failed_hook_t) (size_t size, uint32_t caps, const char
*/ */
esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback); esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback);
#ifdef CONFIG_HEAP_USE_HOOKS
/** /**
* @brief callback called after every allocation * @brief callback called after every allocation
* @param ptr the allocated memory * @param ptr the allocated memory
@@ -71,6 +72,7 @@ __attribute__((weak)) IRAM_ATTR void esp_heap_trace_alloc_hook(void* ptr, size_t
* You should refrain from doing heavy work, logging, flash writes, or any locking. * You should refrain from doing heavy work, logging, flash writes, or any locking.
*/ */
__attribute__((weak)) IRAM_ATTR void esp_heap_trace_free_hook(void* ptr); __attribute__((weak)) IRAM_ATTR void esp_heap_trace_free_hook(void* ptr);
#endif
/** /**
* @brief Allocate a chunk of memory which has the given capabilities * @brief Allocate a chunk of memory which has the given capabilities

View File

@@ -182,6 +182,7 @@ TEST_CASE("test get allocated size", "[heap]")
} }
} }
#ifdef CONFIG_HEAP_USE_HOOKS
// provide the definition of alloc and free hooks // provide the definition of alloc and free hooks
static const size_t alloc_size = 1234; // make this size atypical to be able to rely on it in the hook static const size_t alloc_size = 1234; // make this size atypical to be able to rely on it in the hook
static const size_t expected_calls = 2; // one call for malloc/calloc and one call for realloc static const size_t expected_calls = 2; // one call for malloc/calloc and one call for realloc
@@ -247,3 +248,4 @@ TEST_CASE("test allocation and free function hooks", "[heap]")
TEST_ASSERT_TRUE(test_success); TEST_ASSERT_TRUE(test_success);
} }
#endif

View File

@@ -102,3 +102,17 @@ def test_memory_protection(dut: Dut) -> None:
dut.expect_exact('Press ENTER to see the list of tests') dut.expect_exact('Press ENTER to see the list of tests')
dut.write('[heap][mem_prot]') dut.write('[heap][mem_prot]')
dut.expect_unity_test_output(timeout=300) dut.expect_unity_test_output(timeout=300)
@pytest.mark.generic
@pytest.mark.esp32
@pytest.mark.parametrize(
'config',
[
'func_hooks'
]
)
def test_heap_func_hooks(dut: Dut) -> None:
dut.expect_exact('Press ENTER to see the list of tests')
dut.write('"test allocation and free function hooks"')
dut.expect_unity_test_output(timeout=300)

View File

@@ -0,0 +1 @@
CONFIG_HEAP_USE_HOOKS=y

View File

@@ -24,6 +24,19 @@ To obtain information about the state of the heap:
- :cpp:func:`heap_caps_dump` and :cpp:func:`heap_caps_dump_all` will output detailed information about the structure of each block in the heap. Note that this can be large amount of output. - :cpp:func:`heap_caps_dump` and :cpp:func:`heap_caps_dump_all` will output detailed information about the structure of each block in the heap. Note that this can be large amount of output.
.. _heap-allocation-free:
Heap allocation and free function hooks
---------------------------------------
Heap allocation and free detection hooks allows you to be notified of every successful allocation and free operations:
- Providing a definition of :cpp:func:`esp_heap_trace_alloc_hook` will allow you to be notified of every successful memory allocation operations
- Providing a definition of :cpp:func:`esp_heap_trace_free_hook` will allow you to be notified of every memory free operations
To activate the feature, navigate to ``Component config`` -> ``Heap Memory Debugging`` in the configuration menu and select ``Use allocation and free hooks`` option (see :ref:`CONFIG_HEAP_USE_HOOKS`).
:cpp:func:`esp_heap_trace_alloc_hook` and :cpp:func:`esp_heap_trace_free_hook` have weak declarations, it is not necessary to provide a declarations for both hooks.
Since allocating and freeing memory is allowed even though strongly recommended against, :cpp:func:`esp_heap_trace_alloc_hook` and :cpp:func:`esp_heap_trace_free_hook` can potentially be called from ISR.
.. _heap-corruption: .. _heap-corruption:
Heap Corruption Detection Heap Corruption Detection

View File

@@ -158,6 +158,7 @@ Heap Tracing & Debugging
The following features are documented on the :doc:`Heap Memory Debugging </api-reference/system/heap_debug>` page: The following features are documented on the :doc:`Heap Memory Debugging </api-reference/system/heap_debug>` page:
- :ref:`Heap Information <heap-information>` (free space, etc.) - :ref:`Heap Information <heap-information>` (free space, etc.)
- :ref:`Heap allocation and free function hooks <heap-allocation-free>`
- :ref:`Heap Corruption Detection <heap-corruption>` - :ref:`Heap Corruption Detection <heap-corruption>`
- :ref:`Heap Tracing <heap-tracing>` (memory leak detection, monitoring, etc.) - :ref:`Heap Tracing <heap-tracing>` (memory leak detection, monitoring, etc.)