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 b78193700a
commit 43ba878870
6 changed files with 31 additions and 22 deletions

View File

@@ -27,7 +27,7 @@ list(APPEND srcs "port/${target}/memory_layout.c")
idf_component_register(SRCS "${srcs}" idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS include INCLUDE_DIRS include
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

@@ -22,7 +22,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. */
@@ -64,16 +63,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

@@ -14,7 +14,6 @@ entries:
heap_tlsf:tlsf_free (noflash) heap_tlsf:tlsf_free (noflash)
heap_tlsf:tlsf_realloc (noflash) heap_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)
@@ -26,6 +25,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_POISONING_DISABLED = n: if HEAP_POISONING_DISABLED = n:
multi_heap_poisoning:poison_allocated_region (noflash) multi_heap_poisoning:poison_allocated_region (noflash)
@@ -41,5 +43,5 @@ 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)

View File

@@ -86,7 +86,7 @@ typedef struct multi_heap_info {
} heap_t; } heap_t;
/* 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);
@@ -137,12 +137,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);
} }
@@ -333,7 +333,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",
@@ -370,7 +370,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

@@ -13,6 +13,14 @@
// limitations under the License. // limitations under the License.
#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
/* Opaque handle to a heap block */ /* Opaque handle to a heap block */
typedef const struct block_header_t *multi_heap_block_handle_t; typedef const struct block_header_t *multi_heap_block_handle_t;

View File

@@ -65,7 +65,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);
@@ -89,7 +89,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);
@@ -131,8 +131,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;
@@ -242,7 +246,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;