Fix arena 0 deferral_allowed flag init

Arena 0 have a dedicated initialization path, which differs from
initialization path of other arenas. The main difference for the purpose
of this change is that we initialize arena 0 before we initialize
background threads. HPA shard options have `deferral_allowed` flag which
should be equal to `background_thread_enabled()` return value, but it
wasn't the case before this change, because for arena 0
`background_thread_enabled()` was initialized correctly after arena 0
initialization phase already ended.

Below is initialization sequence for arena 0 after this commit to
illustrate everything still should be initialized correctly.

* `hpa_central_init` initializes HPA Central, before we initialize every
  HPA shard (including arena's 0).
* `background_thread_boot1` initializes `background_thread_enabled()`
  return value.
* `pa_shard_enable_hpa` initializes arena 0 HPA shard.

```
                       malloc_init_hard -------------
                      /           /                  \
                     /           /                    \
                    /           /                      \
malloc_init_hard_a0_locked  background_thread_boot1  pa_shard_enable_hpa
        /                     /                          \
       /                     /                            \
      /                     /                              \
arena_boot       background_thread_enabled_seta         hpa_shard_init
     |
     |
pa_central_init
     |
     |
hpa_central_init
```
This commit is contained in:
Dmitry Ilvokhin 2025-02-05 04:32:31 -08:00 committed by Qi Wang
parent 421b17a622
commit 499f306859
3 changed files with 47 additions and 9 deletions

View file

@ -1964,13 +1964,6 @@ malloc_init_hard_a0_locked(void) {
} else {
opt_hpa = false;
}
} else if (opt_hpa) {
hpa_shard_opts_t hpa_shard_opts = opt_hpa_opts;
hpa_shard_opts.deferral_allowed = background_thread_enabled();
if (pa_shard_enable_hpa(TSDN_NULL, &a0->pa_shard,
&hpa_shard_opts, &opt_hpa_sec_opts)) {
return true;
}
}
malloc_init_state = malloc_init_a0_initialized;
@ -2225,6 +2218,20 @@ malloc_init_hard(void) {
|| background_thread_boot1(tsd_tsdn(tsd), b0get())) {
UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
}
if (opt_hpa) {
/*
* We didn't initialize arena 0 hpa_shard in arena_new, because
* background_thread_enabled wasn't initialized yet, but we
* need it to set correct value for deferral_allowed.
*/
arena_t *a0 = arena_get(tsd_tsdn(tsd), 0, false);
hpa_shard_opts_t hpa_shard_opts = opt_hpa_opts;
hpa_shard_opts.deferral_allowed = background_thread_enabled();
if (pa_shard_enable_hpa(tsd_tsdn(tsd), &a0->pa_shard,
&hpa_shard_opts, &opt_hpa_sec_opts)) {
UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
}
}
if (config_prof && prof_boot2(tsd, b0get())) {
UNLOCK_RETURN(tsd_tsdn(tsd), true, true)
}