From d30ba6ba62b66549ac60a9c8d678b039318f6a26 Mon Sep 17 00:00:00 2001 From: Rajkumar Kanagaraj Date: Mon, 24 Aug 2020 15:07:36 +0100 Subject: [PATCH 1/2] Fix malloc internal overhead size calculation for newlib and newlib-nano --- platform/source/mbed_alloc_wrappers.cpp | 44 +++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/platform/source/mbed_alloc_wrappers.cpp b/platform/source/mbed_alloc_wrappers.cpp index a3c2844c85..cf8d8e9c9e 100644 --- a/platform/source/mbed_alloc_wrappers.cpp +++ b/platform/source/mbed_alloc_wrappers.cpp @@ -52,6 +52,44 @@ typedef struct { static SingletonPtr malloc_stats_mutex; static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0, 0, 0}; +#if defined(TOOLCHAIN_GCC) + +typedef struct malloc_internal_overhead { + /* ------------------ + * malloc_internal_overhead_t->| size (4 bytes) | + * ------------------ + * | Padding for | + * | alignment | + * | holding neg | + * | offset to size | + * ------------------ + * mem_ptr->| point to next | + * | free when freed| + * | or data load | + * | when allocated | + * ------------------ + */ + /* size of the allocated payload area, including size before + OVERHEAD_OFFSET */ + int size; + + /* since here, the memory is either the next free block, or data load */ + struct malloc_internal_overhead *next; +} malloc_internal_overhead_t; + +#define OVERHEAD_OFFSET ((size_t)(&(((struct malloc_internal_overhead *)0)->next))) + +static int get_malloc_internal_overhead(void *ptr) +{ + malloc_internal_overhead_t *c = (malloc_internal_overhead_t *)((char *)ptr - OVERHEAD_OFFSET); + + /* Skip the padding area */ + if (c->size < 0) { + c = (malloc_internal_overhead_t *)((char *)c + c->size); + } + return (c->size & ~0x1); +} +#else typedef struct { size_t size; } mbed_heap_overhead_t; @@ -60,7 +98,7 @@ typedef struct { #define MALLOC_HEADER_PTR(p) (mbed_heap_overhead_t *)((char *)(p) - MALLOC_HEADER_SIZE) #define MALLOC_HEAP_TOTAL_SIZE(p) (((p)->size) & (~0x1)) #endif - +#endif void mbed_stats_heap_get(mbed_stats_heap_t *stats) { #if MBED_HEAP_STATS_ENABLED @@ -116,7 +154,7 @@ extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) if (heap_stats.current_size > heap_stats.max_size) { heap_stats.max_size = heap_stats.current_size; } - heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size; + heap_stats.overhead_size += get_malloc_internal_overhead((void *)alloc_info) - size; } else { heap_stats.alloc_fail_cnt += 1; } @@ -191,7 +229,7 @@ extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller) alloc_info = ((alloc_info_t *)ptr) - 1; if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) { size_t user_size = alloc_info->size; - size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)); + size_t alloc_size = get_malloc_internal_overhead((void *)alloc_info); alloc_info->signature = 0x0; heap_stats.current_size -= user_size; heap_stats.alloc_cnt -= 1; From f3c9132637710f6c2de8f8371031570b729dd6e2 Mon Sep 17 00:00:00 2001 From: Rajkumar Kanagaraj Date: Mon, 24 Aug 2020 23:54:19 +0100 Subject: [PATCH 2/2] Incorporated the review comments --- platform/source/mbed_alloc_wrappers.cpp | 67 +++++++------------------ 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/platform/source/mbed_alloc_wrappers.cpp b/platform/source/mbed_alloc_wrappers.cpp index cf8d8e9c9e..2442edc84d 100644 --- a/platform/source/mbed_alloc_wrappers.cpp +++ b/platform/source/mbed_alloc_wrappers.cpp @@ -52,53 +52,24 @@ typedef struct { static SingletonPtr malloc_stats_mutex; static mbed_stats_heap_t heap_stats = {0, 0, 0, 0, 0, 0, 0}; -#if defined(TOOLCHAIN_GCC) - -typedef struct malloc_internal_overhead { - /* ------------------ - * malloc_internal_overhead_t->| size (4 bytes) | - * ------------------ - * | Padding for | - * | alignment | - * | holding neg | - * | offset to size | - * ------------------ - * mem_ptr->| point to next | - * | free when freed| - * | or data load | - * | when allocated | - * ------------------ - */ - /* size of the allocated payload area, including size before - OVERHEAD_OFFSET */ - int size; - - /* since here, the memory is either the next free block, or data load */ - struct malloc_internal_overhead *next; -} malloc_internal_overhead_t; - -#define OVERHEAD_OFFSET ((size_t)(&(((struct malloc_internal_overhead *)0)->next))) - -static int get_malloc_internal_overhead(void *ptr) -{ - malloc_internal_overhead_t *c = (malloc_internal_overhead_t *)((char *)ptr - OVERHEAD_OFFSET); - - /* Skip the padding area */ - if (c->size < 0) { - c = (malloc_internal_overhead_t *)((char *)c + c->size); - } - return (c->size & ~0x1); -} -#else -typedef struct { - size_t size; +typedef struct mbed_heap_overhead { + int size; // Size of the allocated memory block, including internal overhead size + struct mbed_heap_overhead *next; // The memory is either the next free block, or allocated memory block } mbed_heap_overhead_t; -#define MALLOC_HEADER_SIZE (sizeof(mbed_heap_overhead_t)) -#define MALLOC_HEADER_PTR(p) (mbed_heap_overhead_t *)((char *)(p) - MALLOC_HEADER_SIZE) -#define MALLOC_HEAP_TOTAL_SIZE(p) (((p)->size) & (~0x1)) -#endif +static int get_malloc_block_total_size(void *ptr) +{ + mbed_heap_overhead_t *c = (mbed_heap_overhead_t *)((char *)ptr - offsetof(mbed_heap_overhead, next)); + + // Skip the padding area + if (c->size < 0) { + c = (mbed_heap_overhead_t *)((char *)c + c->size); + } + // Mask LSB as it is used for usage flags + return (c->size & ~0x1); +} #endif + void mbed_stats_heap_get(mbed_stats_heap_t *stats) { #if MBED_HEAP_STATS_ENABLED @@ -154,7 +125,7 @@ extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller) if (heap_stats.current_size > heap_stats.max_size) { heap_stats.max_size = heap_stats.current_size; } - heap_stats.overhead_size += get_malloc_internal_overhead((void *)alloc_info) - size; + heap_stats.overhead_size += get_malloc_block_total_size((void *)alloc_info) - size; } else { heap_stats.alloc_fail_cnt += 1; } @@ -229,7 +200,7 @@ extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller) alloc_info = ((alloc_info_t *)ptr) - 1; if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) { size_t user_size = alloc_info->size; - size_t alloc_size = get_malloc_internal_overhead((void *)alloc_info); + size_t alloc_size = get_malloc_block_total_size((void *)alloc_info); alloc_info->signature = 0x0; heap_stats.current_size -= user_size; heap_stats.alloc_cnt -= 1; @@ -341,7 +312,7 @@ extern "C" void *malloc_wrapper(size_t size, void *caller) if (heap_stats.current_size > heap_stats.max_size) { heap_stats.max_size = heap_stats.current_size; } - heap_stats.overhead_size += MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)) - size; + heap_stats.overhead_size += get_malloc_block_total_size((void *)alloc_info) - size; } else { heap_stats.alloc_fail_cnt += 1; } @@ -454,7 +425,7 @@ extern "C" void free_wrapper(void *ptr, void *caller) alloc_info = ((alloc_info_t *)ptr) - 1; if (MBED_HEAP_STATS_SIGNATURE == alloc_info->signature) { size_t user_size = alloc_info->size; - size_t alloc_size = MALLOC_HEAP_TOTAL_SIZE(MALLOC_HEADER_PTR(alloc_info)); + size_t alloc_size = get_malloc_block_total_size((void *)alloc_info); alloc_info->signature = 0x0; heap_stats.current_size -= user_size; heap_stats.alloc_cnt -= 1;