From: Simon Glass <simon.glass@canonical.com> Add a new NO_REALLOC_IN_PLACE option that disables in-place realloc optimization. When enabled via CONFIG_SYS_MALLOC_SMALL, realloc() always allocates new memory, copies data, and frees the old block instead of trying to extend the existing allocation. This saves about 500 bytes by eliminating try_realloc_chunk() and mmap_resize() functions. When unit tests are enabled, the extra realloc logic is included. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- common/dlmalloc.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 869473b2bd1..4439d278188 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -595,6 +595,10 @@ static inline void MALLOC_COPY(void *dest, const void *src, size_t sz) { memcpy( #define INSECURE 1 #endif +#if CONFIG_IS_ENABLED(SYS_MALLOC_SMALL) +#define NO_REALLOC_IN_PLACE 1 +#endif + /* Use simplified sys_alloc for non-sandbox builds */ #if !IS_ENABLED(CONFIG_SANDBOX) #define SIMPLE_SYSALLOC 1 @@ -807,6 +811,9 @@ ulong mem_malloc_brk; #ifndef NO_SEGMENT_TRAVERSAL #define NO_SEGMENT_TRAVERSAL 0 #endif /* NO_SEGMENT_TRAVERSAL */ +#ifndef NO_REALLOC_IN_PLACE +#define NO_REALLOC_IN_PLACE 0 +#endif /* NO_REALLOC_IN_PLACE */ /* mallopt tuning options. SVID/XPG defines four standard parameter @@ -3984,7 +3991,7 @@ static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { } return 0; } -#endif /* !NO_REALLOC_IN_PLACE */ +#endif /* !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE */ /* -------------------------- mspace management -------------------------- */ @@ -5002,6 +5009,7 @@ void* dlcalloc_impl(size_t n_elements, size_t elem_size) { /* ------------ Internal support for realloc, memalign, etc -------------- */ +#if !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE /* Try to realloc; only in-place unless can_move true */ static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, int can_move) { @@ -5081,6 +5089,7 @@ static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, } return newp; } +#endif /* !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE */ static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { void* mem = 0; @@ -5444,8 +5453,9 @@ void* dlrealloc_impl(void* oldmem, size_t bytes) { } #endif /* REALLOC_ZERO_BYTES_FREES */ else { - size_t nb = request2size(bytes); mchunkptr oldp = mem2chunk(oldmem); +#if !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE + size_t nb = request2size(bytes); #if ! FOOTERS mstate m = gm; #else /* FOOTERS */ @@ -5484,10 +5494,23 @@ void* dlrealloc_impl(void* oldmem, size_t bytes) { } } } +#else /* defined(__UBOOT__) && NO_REALLOC_IN_PLACE */ + mem = dlmalloc_impl(bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); +#ifdef __UBOOT__ + VALGRIND_MALLOCLIKE_BLOCK(mem, bytes, SIZE_SZ, false); + VALGRIND_FREELIKE_BLOCK(oldmem, SIZE_SZ); +#endif + dlfree_impl(oldmem); + } +#endif /* !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE */ } return mem; } +#if !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE void* dlrealloc_in_place(void* oldmem, size_t bytes) { void* mem = 0; if (oldmem != 0) { @@ -5522,6 +5545,7 @@ void* dlrealloc_in_place(void* oldmem, size_t bytes) { } return mem; } +#endif /* !defined(__UBOOT__) || !NO_REALLOC_IN_PLACE */ STATIC_IF_MCHECK void* dlmemalign_impl(size_t alignment, size_t bytes) { -- 2.43.0