diff --git a/components/heap/CMakeLists.txt b/components/heap/CMakeLists.txt index ab5f978eee..a05c1bc4db 100644 --- a/components/heap/CMakeLists.txt +++ b/components/heap/CMakeLists.txt @@ -42,7 +42,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${includes} PRIV_INCLUDE_DIRS ${priv_includes} LDFRAGMENTS linker.lf - PRIV_REQUIRES soc spi_flash) + PRIV_REQUIRES soc) if(CONFIG_HEAP_TRACING) set(WRAP_FUNCTIONS diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index 50fe13763d..e28653f69c 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -14,7 +14,6 @@ #include "esp_log.h" #include "heap_private.h" #include "esp_system.h" -#include "esp_private/cache_utils.h" /* Forward declaration for base function, put in IRAM. * These functions don't check for errors after trying to allocate memory. */ @@ -56,16 +55,10 @@ IRAM_ATTR static void *dram_alloc_to_iram_addr(void *addr, size_t len) } -IRAM_ATTR static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name) +IRAM_ATTR NOINLINE_ATTR static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name) { - static const DRAM_ATTR char *default_func_name = ""; if (alloc_failed_callback) { - if (!spi_flash_cache_enabled() && !esp_ptr_internal(function_name)) { - alloc_failed_callback(requested_size, caps, default_func_name); - } - else { - alloc_failed_callback(requested_size, caps, function_name); - } + alloc_failed_callback(requested_size, caps, function_name); } #ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS diff --git a/components/heap/linker.lf b/components/heap/linker.lf index 4f15783695..9f04259780 100644 --- a/components/heap/linker.lf +++ b/components/heap/linker.lf @@ -15,7 +15,6 @@ entries: tlsf:tlsf_free (noflash) tlsf:tlsf_realloc (noflash) - multi_heap:assert_valid_block (noflash) multi_heap:multi_heap_get_block_address_impl (noflash) multi_heap:multi_heap_get_allocated_size_impl (noflash) multi_heap:multi_heap_set_lock (noflash) @@ -27,6 +26,9 @@ entries: multi_heap:multi_heap_realloc_impl (noflash) multi_heap:multi_heap_aligned_alloc_impl_offs (noflash) multi_heap:multi_heap_aligned_alloc_impl (noflash) + multi_heap:multi_heap_internal_lock (noflash) + multi_heap:multi_heap_internal_unlock (noflash) + multi_heap:assert_valid_block (noflash) if HEAP_TLSF_USE_ROM_IMPL = y: multi_heap:_multi_heap_lock (noflash) @@ -47,6 +49,6 @@ entries: multi_heap_poisoning:multi_heap_internal_check_block_poisoning (noflash) multi_heap_poisoning:multi_heap_internal_poison_fill_region (noflash) - if HEAP_POISONING_COMPREHENSIVE = y: - multi_heap_poisoning:verify_fill_pattern (noflash) - multi_heap_poisoning:block_absorb_post_hook (noflash) + if HEAP_POISONING_COMPREHENSIVE = y: + multi_heap_poisoning:verify_fill_pattern (noflash) + multi_heap_poisoning:block_absorb_post_hook (noflash) diff --git a/components/heap/multi_heap.c b/components/heap/multi_heap.c index 9c7a040854..63cce03f08 100644 --- a/components/heap/multi_heap.c +++ b/components/heap/multi_heap.c @@ -106,7 +106,7 @@ void multi_heap_in_rom_init(void) #else // CONFIG_HEAP_TLSF_USE_ROM_IMPL /* Check a block is valid for this heap. Used to verify parameters. */ -static void assert_valid_block(const heap_t *heap, const block_header_t *block) +__attribute__((noinline)) NOCLONE_ATTR static void assert_valid_block(const heap_t *heap, const block_header_t *block) { pool_t pool = tlsf_get_pool(heap->heap_data); void *ptr = block_to_ptr(block); @@ -154,12 +154,12 @@ void multi_heap_set_lock(multi_heap_handle_t heap, void *lock) heap->lock = lock; } -void inline multi_heap_internal_lock(multi_heap_handle_t heap) +void multi_heap_internal_lock(multi_heap_handle_t heap) { MULTI_HEAP_LOCK(heap->lock); } -void inline multi_heap_internal_unlock(multi_heap_handle_t heap) +void multi_heap_internal_unlock(multi_heap_handle_t heap) { MULTI_HEAP_UNLOCK(heap->lock); } @@ -348,7 +348,7 @@ bool multi_heap_check(multi_heap_handle_t heap, bool print_errors) return valid; } -static void multi_heap_dump_tlsf(void* ptr, size_t size, int used, void* user) +__attribute__((noinline)) static void multi_heap_dump_tlsf(void* ptr, size_t size, int used, void* user) { (void)user; MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n", @@ -385,7 +385,7 @@ size_t multi_heap_minimum_free_size_impl(multi_heap_handle_t heap) return heap->minimum_free_bytes; } -static void multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* user) +__attribute__((noinline)) static void multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* user) { multi_heap_info_t *info = user; diff --git a/components/heap/multi_heap_internal.h b/components/heap/multi_heap_internal.h index 00c1f23e91..b34c3393c6 100644 --- a/components/heap/multi_heap_internal.h +++ b/components/heap/multi_heap_internal.h @@ -5,6 +5,14 @@ */ #pragma once +/* Define a noclone attribute when compiled with GCC as certain functions + * in the heap component should not be cloned by the compiler */ +#if defined __has_attribute && __has_attribute(noclone) +#define NOCLONE_ATTR __attribute((noclone)) +#else +#define NOCLONE_ATTR +#endif + /* Define a structure that contains some function pointers that point to OS-related functions. An instance of this structure will be provided to the heap in ROM for use if needed. */ diff --git a/components/heap/multi_heap_poisoning.c b/components/heap/multi_heap_poisoning.c index 9cb42b95d4..27dac0b77b 100644 --- a/components/heap/multi_heap_poisoning.c +++ b/components/heap/multi_heap_poisoning.c @@ -68,7 +68,7 @@ typedef struct { Returns the pointer to the actual usable data buffer (ie after 'head') */ -static uint8_t *poison_allocated_region(poison_head_t *head, size_t alloc_size) +__attribute__((noinline)) static uint8_t *poison_allocated_region(poison_head_t *head, size_t alloc_size) { uint8_t *data = (uint8_t *)(&head[1]); /* start of data ie 'real' allocated buffer */ poison_tail_t *tail = (poison_tail_t *)(data + alloc_size); @@ -92,7 +92,7 @@ static uint8_t *poison_allocated_region(poison_head_t *head, size_t alloc_size) Returns a pointer to the poison header structure, or NULL if the poison structures are corrupt. */ -static poison_head_t *verify_allocated_region(void *data, bool print_errors) +__attribute__((noinline)) static poison_head_t *verify_allocated_region(void *data, bool print_errors) { poison_head_t *head = (poison_head_t *)((intptr_t)data - sizeof(poison_head_t)); poison_tail_t *tail = (poison_tail_t *)((intptr_t)data + head->alloc_size); @@ -134,8 +134,12 @@ static poison_head_t *verify_allocated_region(void *data, bool print_errors) if swap_pattern is true, swap patterns in the buffer (ie replace MALLOC_FILL_PATTERN with FREE_FILL_PATTERN, and vice versa.) Returns true if verification checks out. + + This function has the attribute noclone to prevent the compiler to create a clone on flash where expect_free is removed (as this + function is called only with expect_free == true throughout the component). */ -static bool verify_fill_pattern(void *data, size_t size, bool print_errors, bool expect_free, bool swap_pattern) +__attribute__((noinline)) NOCLONE_ATTR +static bool verify_fill_pattern(void *data, size_t size, const bool print_errors, const bool expect_free, bool swap_pattern) { const uint32_t FREE_FILL_WORD = (FREE_FILL_PATTERN << 24) | (FREE_FILL_PATTERN << 16) | (FREE_FILL_PATTERN << 8) | FREE_FILL_PATTERN; const uint32_t MALLOC_FILL_WORD = (MALLOC_FILL_PATTERN << 24) | (MALLOC_FILL_PATTERN << 16) | (MALLOC_FILL_PATTERN << 8) | MALLOC_FILL_PATTERN; @@ -261,7 +265,9 @@ void *multi_heap_malloc(multi_heap_handle_t heap, size_t size) return data; } -void multi_heap_free(multi_heap_handle_t heap, void *p) +/* This function has the noclone attribute to prevent the compiler to optimize out the + * check for p == NULL and create a clone function placed in flash. */ +NOCLONE_ATTR void multi_heap_free(multi_heap_handle_t heap, void *p) { if (p == NULL) { return;