mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 18:57:19 +02:00
Merge branch 'bugfix/fix_heap_free_memory_v4.3' into 'release/v4.3'
Heap: fix free bytes calculation for TLSF heap (backport v4.3) See merge request espressif/esp-idf!17689
This commit is contained in:
@ -197,6 +197,7 @@ void *multi_heap_malloc_impl(multi_heap_handle_t heap, size_t size)
|
|||||||
void *result = tlsf_malloc(heap->heap_data, size);
|
void *result = tlsf_malloc(heap->heap_data, size);
|
||||||
if(result) {
|
if(result) {
|
||||||
heap->free_bytes -= tlsf_block_size(result);
|
heap->free_bytes -= tlsf_block_size(result);
|
||||||
|
heap->free_bytes -= tlsf_alloc_overhead();
|
||||||
if (heap->free_bytes < heap->minimum_free_bytes) {
|
if (heap->free_bytes < heap->minimum_free_bytes) {
|
||||||
heap->minimum_free_bytes = heap->free_bytes;
|
heap->minimum_free_bytes = heap->free_bytes;
|
||||||
}
|
}
|
||||||
@ -217,6 +218,7 @@ void multi_heap_free_impl(multi_heap_handle_t heap, void *p)
|
|||||||
|
|
||||||
multi_heap_internal_lock(heap);
|
multi_heap_internal_lock(heap);
|
||||||
heap->free_bytes += tlsf_block_size(p);
|
heap->free_bytes += tlsf_block_size(p);
|
||||||
|
heap->free_bytes += tlsf_alloc_overhead();
|
||||||
tlsf_free(heap->heap_data, p);
|
tlsf_free(heap->heap_data, p);
|
||||||
multi_heap_internal_unlock(heap);
|
multi_heap_internal_unlock(heap);
|
||||||
}
|
}
|
||||||
@ -239,6 +241,8 @@ void *multi_heap_realloc_impl(multi_heap_handle_t heap, void *p, size_t size)
|
|||||||
size_t previous_block_size = tlsf_block_size(p);
|
size_t previous_block_size = tlsf_block_size(p);
|
||||||
void *result = tlsf_realloc(heap->heap_data, p, size);
|
void *result = tlsf_realloc(heap->heap_data, p, size);
|
||||||
if(result) {
|
if(result) {
|
||||||
|
/* No need to subtract the tlsf_alloc_overhead() as it has already
|
||||||
|
* been subtracted when allocating the block at first with malloc */
|
||||||
heap->free_bytes += previous_block_size;
|
heap->free_bytes += previous_block_size;
|
||||||
heap->free_bytes -= tlsf_block_size(result);
|
heap->free_bytes -= tlsf_block_size(result);
|
||||||
if (heap->free_bytes < heap->minimum_free_bytes) {
|
if (heap->free_bytes < heap->minimum_free_bytes) {
|
||||||
@ -270,6 +274,7 @@ void *multi_heap_aligned_alloc_impl_offs(multi_heap_handle_t heap, size_t size,
|
|||||||
void *result = tlsf_memalign_offs(heap->heap_data, alignment, size, offset);
|
void *result = tlsf_memalign_offs(heap->heap_data, alignment, size, offset);
|
||||||
if(result) {
|
if(result) {
|
||||||
heap->free_bytes -= tlsf_block_size(result);
|
heap->free_bytes -= tlsf_block_size(result);
|
||||||
|
heap->free_bytes -= tlsf_alloc_overhead();
|
||||||
if(heap->free_bytes < heap->minimum_free_bytes) {
|
if(heap->free_bytes < heap->minimum_free_bytes) {
|
||||||
heap->minimum_free_bytes = heap->free_bytes;
|
heap->minimum_free_bytes = heap->free_bytes;
|
||||||
}
|
}
|
||||||
@ -361,6 +366,7 @@ static void multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* use
|
|||||||
void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
|
void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
|
||||||
{
|
{
|
||||||
uint32_t sl_interval;
|
uint32_t sl_interval;
|
||||||
|
uint32_t overhead;
|
||||||
|
|
||||||
memset(info, 0, sizeof(multi_heap_info_t));
|
memset(info, 0, sizeof(multi_heap_info_t));
|
||||||
|
|
||||||
@ -370,7 +376,10 @@ void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
|
|||||||
|
|
||||||
multi_heap_internal_lock(heap);
|
multi_heap_internal_lock(heap);
|
||||||
tlsf_walk_pool(tlsf_get_pool(heap->heap_data), multi_heap_get_info_tlsf, info);
|
tlsf_walk_pool(tlsf_get_pool(heap->heap_data), multi_heap_get_info_tlsf, info);
|
||||||
info->total_allocated_bytes = (heap->pool_size - tlsf_size()) - heap->free_bytes;
|
/* TLSF has an overhead per block. Calculate the total amount of overhead, it shall not be
|
||||||
|
* part of the allocated bytes */
|
||||||
|
overhead = info->allocated_blocks * tlsf_alloc_overhead();
|
||||||
|
info->total_allocated_bytes = (heap->pool_size - tlsf_size()) - heap->free_bytes - overhead;
|
||||||
info->minimum_free_bytes = heap->minimum_free_bytes;
|
info->minimum_free_bytes = heap->minimum_free_bytes;
|
||||||
info->total_free_bytes = heap->free_bytes;
|
info->total_free_bytes = heap->free_bytes;
|
||||||
if (info->largest_free_block) {
|
if (info->largest_free_block) {
|
||||||
|
@ -121,8 +121,10 @@ TEST_CASE("IRAM_8BIT capability test", "[heap]")
|
|||||||
|
|
||||||
TEST_ASSERT((((int)ptr)&0xFF000000)==0x40000000);
|
TEST_ASSERT((((int)ptr)&0xFF000000)==0x40000000);
|
||||||
|
|
||||||
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT) == (free_size - heap_caps_get_allocated_size(ptr)));
|
/* As the heap allocator may present an overhead for allocated blocks,
|
||||||
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_32BIT) == (free_size32 - heap_caps_get_allocated_size(ptr)));
|
* we need to check that the free heap size is now smaller or equal to the former free size. */
|
||||||
|
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT) <= (free_size - heap_caps_get_allocated_size(ptr)));
|
||||||
|
TEST_ASSERT(heap_caps_get_free_size(MALLOC_CAP_32BIT) <= (free_size32 - heap_caps_get_allocated_size(ptr)));
|
||||||
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
@ -503,3 +503,23 @@ TEST_CASE("multi_heap aligned allocations", "[multi_heap]")
|
|||||||
printf("[ALIGNED_ALLOC] heap_size after: %d \n", multi_heap_free_size(heap));
|
printf("[ALIGNED_ALLOC] heap_size after: %d \n", multi_heap_free_size(heap));
|
||||||
REQUIRE((old_size - multi_heap_free_size(heap)) <= leakage);
|
REQUIRE((old_size - multi_heap_free_size(heap)) <= leakage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TLSF has some overhead when allocating blocks, check that overhead
|
||||||
|
TEST_CASE("multi_heap allocation overhead", "[multi_heap]")
|
||||||
|
{
|
||||||
|
uint8_t heapdata[4 * 1024];
|
||||||
|
size_t alloc_size = 256;
|
||||||
|
multi_heap_handle_t heap = multi_heap_register(heapdata, sizeof(heapdata));
|
||||||
|
size_t free_bytes_1 = multi_heap_free_size(heap);
|
||||||
|
|
||||||
|
/* Allocate any amount of data, in any case there will be an overhead */
|
||||||
|
void *x = multi_heap_malloc(heap, alloc_size);
|
||||||
|
|
||||||
|
/* free_bytes_2 should be free_bytes_1 - alloc_size - overhead.
|
||||||
|
* We don't know the value of overhead, let's check that it is non-zero */
|
||||||
|
size_t free_bytes_2 = multi_heap_free_size(heap);
|
||||||
|
REQUIRE( free_bytes_1 > free_bytes_2 );
|
||||||
|
REQUIRE( free_bytes_1 - free_bytes_2 > alloc_size );
|
||||||
|
|
||||||
|
multi_heap_free(heap, x);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user