[PATCH 2/3] malloc: Don't statically initialize av_ if using malloc_init

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Tue Aug 1 18:56:46 CEST 2023


On 01.08.23 18:27, Sean Anderson wrote:
> 
> 
> On 8/1/23 12:23, Heinrich Schuchardt wrote:
>> On 01.08.23 18:02, Sean Anderson wrote:
>>>
>>>
>>> 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))

GD_FLG_FULL_MALLOC_INIT is set in initr_reloc().

*Thereafter*

mem_malloc_init is called in initr_malloc().

See init_sequence_r[].

This explains why calling malloc_init() here helped me.

Best regards

Heinrich


More information about the U-Boot mailing list