mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-28 03:13:09 +03:00
Refactor/fix arenas manipulation.
Abstract arenas access to use arena_get() (or a0get() where appropriate) rather than directly reading e.g. arenas[ind]. Prior to the addition of the arenas.extend mallctl, the worst possible outcome of directly accessing arenas was a stale read, but arenas.extend may allocate and assign a new array to arenas. Add a tsd-based arenas_cache, which amortizes arenas reads. This introduces some subtle bootstrapping issues, with tsd_boot() now being split into tsd_boot[01]() to support tsd wrapper allocation bootstrapping, as well as an arenas_cache_bypass tsd variable which dynamically terminates allocation of arenas_cache itself. Promote a0malloc(), a0calloc(), and a0free() to be generally useful for internal allocation, and use them in several places (more may be appropriate). Abstract arena->nthreads management and fix a missing decrement during thread destruction (recent tsd refactoring left arenas_cleanup() unused). Change arena_choose() to propagate OOM, and handle OOM in all callers. This is important for providing consistent allocation behavior when the MALLOCX_ARENA() flag is being used. Prior to this fix, it was possible for an OOM to result in allocation silently allocating from a different arena than the one specified.
This commit is contained in:
parent
bf40641c5c
commit
8bb3198f72
13 changed files with 745 additions and 352 deletions
30
src/arena.c
30
src/arena.c
|
|
@ -2192,27 +2192,37 @@ arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
arena_new(arena_t *arena, unsigned ind)
|
||||
arena_t *
|
||||
arena_new(unsigned ind)
|
||||
{
|
||||
arena_t *arena;
|
||||
unsigned i;
|
||||
arena_bin_t *bin;
|
||||
|
||||
/*
|
||||
* Allocate arena and arena->lstats contiguously, mainly because there
|
||||
* is no way to clean up if base_alloc() OOMs.
|
||||
*/
|
||||
if (config_stats) {
|
||||
arena = (arena_t *)base_alloc(CACHELINE_CEILING(sizeof(arena_t))
|
||||
+ nlclasses * sizeof(malloc_large_stats_t));
|
||||
} else
|
||||
arena = (arena_t *)base_alloc(sizeof(arena_t));
|
||||
if (arena == NULL)
|
||||
return (NULL);
|
||||
|
||||
arena->ind = ind;
|
||||
arena->nthreads = 0;
|
||||
arena->chunk_alloc = chunk_alloc_default;
|
||||
arena->chunk_dalloc = chunk_dalloc_default;
|
||||
|
||||
if (malloc_mutex_init(&arena->lock))
|
||||
return (true);
|
||||
return (NULL);
|
||||
|
||||
if (config_stats) {
|
||||
memset(&arena->stats, 0, sizeof(arena_stats_t));
|
||||
arena->stats.lstats =
|
||||
(malloc_large_stats_t *)base_alloc(nlclasses *
|
||||
sizeof(malloc_large_stats_t));
|
||||
if (arena->stats.lstats == NULL)
|
||||
return (true);
|
||||
arena->stats.lstats = (malloc_large_stats_t *)(((void *)arena) +
|
||||
CACHELINE_CEILING(sizeof(arena_t)));
|
||||
memset(arena->stats.lstats, 0, nlclasses *
|
||||
sizeof(malloc_large_stats_t));
|
||||
if (config_tcache)
|
||||
|
|
@ -2236,14 +2246,14 @@ arena_new(arena_t *arena, unsigned ind)
|
|||
for (i = 0; i < NBINS; i++) {
|
||||
bin = &arena->bins[i];
|
||||
if (malloc_mutex_init(&bin->lock))
|
||||
return (true);
|
||||
return (NULL);
|
||||
bin->runcur = NULL;
|
||||
arena_run_tree_new(&bin->runs);
|
||||
if (config_stats)
|
||||
memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
|
||||
}
|
||||
|
||||
return (false);
|
||||
return (arena);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue