[patch v2] malloc: avoid need for tcache == NULL checks

Florian Weimer fw@deneb.enyo.de
Thu Aug 28 21:14:35 GMT 2025


* DJ Delorie:

> Avoid needing to check for tcache == NULL by initializing it
> to a dummy read-only tcache structure.  This dummy is all zeros,
> so logically it is both full (when you want to put) and empty (when
> you want to get).  Also, there are two dummies, one used for
> "not yet initialized" and one for "tunables say we shouldn't have
> a tcache".
>
> The net result is twofold:
>
> 1. Checks for tcache == NULL may be removed from the fast path.
>     Whether this makes the fast path faster when tcache is
>     disabled is TBD, but the normal case is tcache enabled.
>
> 2. no memory for tcache is allocated if tunables disable caching.

> +/* TCACHE is never NULL; it's either "live" or points to one of the
> +   above dummy entries.  The dummy entries are all zero so act like an
> +   empty/unusable tcache.  */
> +static __thread tcache_perthread_struct *tcache = (tcache_perthread_struct *) &__tcache_dummy.inactive;
> +
> +/* This is the default, and means "check to see if a real tcache
> +   should be allocated."  */
> +#define TCACHE_INACTIVE() (tcache == &__tcache_dummy.inactive)
> +/* This means "the user has disabled the tcache but we have to point
> +   to something."  */
> +#define TCACHE_DISABLED() (tcache == &__tcache_dummy.disabled)
> +/* This means the tcache is active.  */
> +#define TCACHE_ENABLED() (!TCACHE_INACTIVE() && !TCACHE_DISABLED())
> +/* Sets the tcache to INACTIVE state.  */
> +#define TCACHE_SET_INACTIVE() tcache = (tcache_perthread_struct *) &__tcache_dummy.inactive;
> +/* Sets the tcache to DISABLED state.  */
> +#define TCACHE_SET_DISABLED() tcache = (tcache_perthread_struct *) &__tcache_dummy.disabled;

I suppose these could be inline functions instead of macros.  I've got
the impression

> @@ -3305,14 +3332,14 @@ tcache_thread_shutdown (void)
>  {
>    int i;
>    tcache_perthread_struct *tcache_tmp = tcache;
> +  int need_free = TCACHE_ENABLED ();
>  
>    tcache_shutting_down = true;

Isn't tcache_shutting_down now redundant?  Because we have
TCACHE_SET_DISABLED?

> @@ -3388,6 +3411,11 @@ __libc_malloc2 (size_t bytes)
>    mstate ar_ptr;
>    void *victim;
>  
> +#if USE_TCACHE
> +  if (__glibc_unlikely (TCACHE_INACTIVE ()))
> +    tcache_init ();
> +#endif

Could this be moved to the

>    if (SINGLE_THREAD_P)
>      {
>        victim = tag_new_usable (_int_malloc (&main_arena, bytes));
> @@ -3427,8 +3455,6 @@ __libc_malloc (size_t bytes)
>    if (nb < mp_.tcache_max_bytes)
>      {
>        size_t tc_idx = csize2tidx (nb);
> -      if(__glibc_unlikely (tcache == NULL))
> -	return tcache_malloc_init (bytes);

tcache path here?


More information about the Libc-alpha mailing list