[PATCH 2/3] malloc: Don't statically initialize av_ if using malloc_init
Sean Anderson
sean.anderson at seco.com
Tue Aug 1 18:02:25 CEST 2023
On 8/1/23 03:04, Heinrich Schuchardt wrote:
>
>
> On 8/1/23 00:33, Sean Anderson wrote:
>> When we enable malloc_init, there is no need to statically initialize
>> av_, since we are going to do it manually. This lets us move av_ to
>> .bss, saving around 1-2k of data (depending on the pointer size).
>>
>> cALLOc must be adjusted to not access top before malloc_init.
>>
>> While we're at it, rename/reword the Kconfig to better describe what
>> this option does.
>>
>> Signed-off-by: Sean Anderson <sean.anderson at seco.com>
>> ---
>>
>> Kconfig | 18 +++++++-----------
>> common/dlmalloc.c | 9 +++++++--
>> 2 files changed, 14 insertions(+), 13 deletions(-)
>>
>> diff --git a/Kconfig b/Kconfig
>> index 70efb41cc6..4b32286b69 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -372,18 +372,14 @@ if EXPERT
>> When disabling this, please check if malloc calls, maybe
>> should be replaced by calloc - if one expects zeroed memory.
>> -config SYS_MALLOC_DEFAULT_TO_INIT
>> - bool "Default malloc to init while reserving the memory for it"
>> +config SYS_MALLOC_RUNTIME_INIT
>> + bool "Initialize malloc's internal data at runtime"
>> help
>> - It may happen that one needs to move the dynamic allocation
>> - from one to another memory range, eg. when moving the malloc
>> - from the limited static to a potentially large dynamic (DDR)
>> - memory.
>> -
>> - If so then on top of setting the updated memory aside one
>> - needs to bring the malloc init.
>> -
>> - If such a scenario is sought choose yes.
>> + Initialize malloc's internal data structures at runtime,
>> rather than
>> + at compile-time. This is necessary if relocating the malloc
>> arena
>> + from a smaller static memory to a large DDR memory. It can also
>> + reduce the size of U-Boot by letting malloc's data reside in
>> .bss
>> + instead of .data.
>> config TOOLS_DEBUG
>> bool "Enable debug information for tools"
>> diff --git a/common/dlmalloc.c b/common/dlmalloc.c
>> index 30c78ae976..8a1daae5ec 100644
>> --- a/common/dlmalloc.c
>> +++ b/common/dlmalloc.c
>> @@ -556,6 +556,7 @@ typedef struct malloc_chunk* mbinptr;
>> #define IAV(i) bin_at(i), bin_at(i)
>> static mbinptr av_[NAV * 2 + 2] = {
>> +#if !CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT)
>> NULL, NULL,
>> IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5),
>> IAV(6), IAV(7),
>> IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13),
>> IAV(14), IAV(15),
>> @@ -573,6 +574,7 @@ static mbinptr av_[NAV * 2 + 2] = {
>> IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109),
>> IAV(110), IAV(111),
>> IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117),
>> IAV(118), IAV(119),
>> IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125),
>> IAV(126), IAV(127)
>> +#endif
>> };
>
> With this patch booting qemu-riscv64_spl_defconfig with
> SYS_MALLOC_RUNTIME_INIT=y fails without output from main U-Boot.
>
> After removing the #if above, main U-Boot output provides some output
> but driver binding fails.
>
> Without this patch and with SYS_MALLOC_DEFAULT_TO_INIT=y booting succeeds.
>
>> #ifdef CONFIG_NEEDS_MANUAL_RELOC
>> @@ -623,7 +625,7 @@ void mem_malloc_init(ulong start, ulong size)
>> mem_malloc_end = start + size;
>> mem_malloc_brk = start;
>> - if (CONFIG_IS_ENABLED(SYS_MALLOC_DEFAULT_TO_INIT))
>> + if (CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT))
>> malloc_init();
>> debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
>> @@ -2151,7 +2153,10 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t
>> elem_size;
>> #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
>> #if MORECORE_CLEARS
>> mchunkptr oldtop = top;
>> - INTERNAL_SIZE_T oldtopsize = chunksize(top);
>> + INTERNAL_SIZE_T oldtopsize;
>> + if (CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT) &&
>> + !(gd->flags & GD_FLG_FULL_MALLOC_INIT))
>> + oldtopsize = chunksize(top);
>
> malloc_simple needs a value for oldtopsize and this is before
> GD_FLG_FULL_MALLOC_INIT is set.
>
> This change worked for me:
>
> #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
> #if MORECORE_CLEARS
> mchunkptr oldtop = top;
> if (CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT) &&
> !(gd->flags & GD_FLG_FULL_MALLOC_INIT))
> malloc_init();
> INTERNAL_SIZE_T oldtopsize = chunksize(top);
> #endif
> #endif
>
> You don't want to call malloc_init() twice. So some flag should be added
> indicating if malloc_init() has been invoked.
Actually, I think the original condition was just backwards. It should
be
if (!CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT) &&
(gd->flags & GD_FLG_FULL_MALLOC_INIT))
although this still doesn't match the malloc_simple condition. So maybe
the condition to remove the initialization should be
#if !CONFIG_VAL(SYS_MALLOC_F_LEN) && \
!CONFIG_IS_ENABLED(SYS_MALLOC_RUNTIME_INIT)
or perhaps RUNTIME_INIT should depend on F_LEN? I don't see anyone using
for other purposes, so I think adding this dependency should be fine.
--Sean
More information about the U-Boot
mailing list