mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 13:14:32 +02:00
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:
committed by
Mahavir Jain
parent
5a1f0cd63c
commit
2f982107dc
@@ -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
|
||||||
|
@@ -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. */
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
1
components/heap/test_apps/sdkconfig.ci.func_hooks
Normal file
1
components/heap/test_apps/sdkconfig.ci.func_hooks
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_HEAP_USE_HOOKS=y
|
@@ -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
|
||||||
|
@@ -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.)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user