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}
PRIV_INCLUDE_DIRS ${priv_includes}
LDFRAGMENTS linker.lf
PRIV_REQUIRES soc spi_flash)
PRIV_REQUIRES soc)
if(CONFIG_HEAP_TRACING)
set(WRAP_FUNCTIONS

View File

@ -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 = "<function_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

View File

@ -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)

View File

@ -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;

View File

@ -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.
*/

View File

@ -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;