heap: fix linker issues and remove spi flash dependencies

This commit is contained in:
Guillaume Souchere
2022-11-14 08:21:33 +01:00
parent 35260d4325
commit be74fd1e8c
6 changed files with 32 additions and 23 deletions

View File

@ -42,7 +42,7 @@ idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${includes} INCLUDE_DIRS ${includes}
PRIV_INCLUDE_DIRS ${priv_includes} PRIV_INCLUDE_DIRS ${priv_includes}
LDFRAGMENTS linker.lf LDFRAGMENTS linker.lf
PRIV_REQUIRES soc spi_flash) PRIV_REQUIRES soc)
if(CONFIG_HEAP_TRACING) if(CONFIG_HEAP_TRACING)
set(WRAP_FUNCTIONS set(WRAP_FUNCTIONS

View File

@ -14,7 +14,6 @@
#include "esp_log.h" #include "esp_log.h"
#include "heap_private.h" #include "heap_private.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_private/cache_utils.h"
/* 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. */
@ -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 = "<function_name>";
if (alloc_failed_callback) { if (alloc_failed_callback) {
if (!spi_flash_cache_enabled() && !esp_ptr_internal(function_name)) { alloc_failed_callback(requested_size, caps, function_name);
alloc_failed_callback(requested_size, caps, default_func_name);
}
else {
alloc_failed_callback(requested_size, caps, function_name);
}
} }
#ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS #ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS

View File

@ -15,7 +15,6 @@ entries:
tlsf:tlsf_free (noflash) tlsf:tlsf_free (noflash)
tlsf:tlsf_realloc (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_block_address_impl (noflash)
multi_heap:multi_heap_get_allocated_size_impl (noflash) multi_heap:multi_heap_get_allocated_size_impl (noflash)
multi_heap:multi_heap_set_lock (noflash) multi_heap:multi_heap_set_lock (noflash)
@ -27,6 +26,9 @@ entries:
multi_heap:multi_heap_realloc_impl (noflash) multi_heap:multi_heap_realloc_impl (noflash)
multi_heap:multi_heap_aligned_alloc_impl_offs (noflash) multi_heap:multi_heap_aligned_alloc_impl_offs (noflash)
multi_heap:multi_heap_aligned_alloc_impl (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: if HEAP_TLSF_USE_ROM_IMPL = y:
multi_heap:_multi_heap_lock (noflash) 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_check_block_poisoning (noflash)
multi_heap_poisoning:multi_heap_internal_poison_fill_region (noflash) multi_heap_poisoning:multi_heap_internal_poison_fill_region (noflash)
if HEAP_POISONING_COMPREHENSIVE = y: if HEAP_POISONING_COMPREHENSIVE = y:
multi_heap_poisoning:verify_fill_pattern (noflash) multi_heap_poisoning:verify_fill_pattern (noflash)
multi_heap_poisoning:block_absorb_post_hook (noflash) multi_heap_poisoning:block_absorb_post_hook (noflash)

View File

@ -106,7 +106,7 @@ void multi_heap_in_rom_init(void)
#else // CONFIG_HEAP_TLSF_USE_ROM_IMPL #else // CONFIG_HEAP_TLSF_USE_ROM_IMPL
/* Check a block is valid for this heap. Used to verify parameters. */ /* 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); pool_t pool = tlsf_get_pool(heap->heap_data);
void *ptr = block_to_ptr(block); 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; 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); 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); MULTI_HEAP_UNLOCK(heap->lock);
} }
@ -348,7 +348,7 @@ bool multi_heap_check(multi_heap_handle_t heap, bool print_errors)
return valid; 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; (void)user;
MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n", 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; 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; multi_heap_info_t *info = user;

View File

@ -5,6 +5,14 @@
*/ */
#pragma once #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. /* 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. An instance of this structure will be provided to the heap in ROM for use if needed.
*/ */

View File

@ -68,7 +68,7 @@ typedef struct {
Returns the pointer to the actual usable data buffer (ie after 'head') 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 */ uint8_t *data = (uint8_t *)(&head[1]); /* start of data ie 'real' allocated buffer */
poison_tail_t *tail = (poison_tail_t *)(data + alloc_size); 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. 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_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); 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.) 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. 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 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; 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; 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) { if (p == NULL) {
return; return;