[PATCH] malloc: Improve malloc initialization

Florian Weimer fweimer@redhat.com
Mon Mar 31 14:21:15 GMT 2025


* Wilco Dijkstra:

> Move malloc initialization out of hot paths - it is only required after checking
> fastbins in _int_malloc or before tcache initialization. Bench-malloc-thread
> improves by 1.8% for 1 thread and 1.3% for 32 threads on Neoverse V2.
>
> Passes regress, OK for commit?
>
> ---
>
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index b73ddbf554461da34d99258fae87c6ece6d175ba..b8eb4180570d20223109b1f0084f4a01bb97b9d6 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -3313,6 +3313,10 @@ tcache_init(void)
>    if (tcache_shutting_down)
>      return;
>  
> +  /* Ensure malloc is initialized before tcache.  */
> +  if (!__malloc_initialized)
> +    ptmalloc_init ();
> +
>    arena_get (ar_ptr, bytes);
>    victim = _int_malloc (ar_ptr, bytes);
>    if (!victim && ar_ptr != NULL)
> @@ -3389,8 +3393,6 @@ __libc_malloc (size_t bytes)
>    _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
>                    "PTRDIFF_MAX is not more than half of SIZE_MAX");
>  
> -  if (!__malloc_initialized)
> -    ptmalloc_init ();

I think we should document the invariant that tache_init is called as
part of pthread_create, before the new thread starts running.  This way,
ptmalloc_init does not need to be thread-safe.  I think it's still the
case after this patch becaue MAYBE_INIT_TCACHE is called unconditionally
early and does not depend on the allocation size.  (Not sure why this is
a macro and not a function.)  I'd suggest comments on ptmalloc_init and
MAYBE_INIT_TCACHE that reference each other, and one of them should
describe the expected sequence of events.  Maybe also put a comment on
MAYBE_INIT_TCACHE in __libc_malloc2?

Regarding doing this initialization early and unconditionally: This
could well work today, especially if we do it early via
__libc_early_init for dynamically linked builds (so that malloc is
available in PREINIT and LD_PRELOAD objects).

For static builds, additional work will be required, or we could keep
the current scheme for that case.  (I think in general, malloc can be
called before ELF constructors have run in the static case.)

If we ever start allocating during initialization (I expect us to
reserve address space for all possible struct malloc_state objects, for
example) and we want to avoid that for interposed mallocs, then I think
a lazy scheme is the only feasible way.  We can't call into the
interposed malloc from __libc_early_init because its ELF constructor has
not run yet.

Thanks,
Florian



More information about the Libc-alpha mailing list