add experimental.arenas_create_ext mallctl
This mallctl accepts an arena_config_t structure which can be used to customize the behavior of the arena. Right now it contains extent_hooks and a new option, metadata_use_hooks, which controls whether the extent hooks are also used for metadata allocation. The medata_use_hooks option has two main use cases: 1. In heterogeneous memory systems, to avoid metadata being placed on potentially slower memory. 2. Avoiding virtual memory from being leaked as a result of metadata allocation failure originating in an extent hook.
This commit is contained in:
11
src/arena.c
11
src/arena.c
@@ -48,6 +48,11 @@ static unsigned nbins_total;
|
||||
|
||||
static unsigned huge_arena_ind;
|
||||
|
||||
const arena_config_t arena_config_default = {
|
||||
/* .extent_hooks = */ (extent_hooks_t *)&ehooks_default_extent_hooks,
|
||||
/* .metadata_use_hooks = */ true,
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Function prototypes for static functions that are referenced prior to
|
||||
@@ -1516,7 +1521,6 @@ arena_set_extent_hooks(tsd_t *tsd, arena_t *arena,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
dss_prec_t
|
||||
arena_dss_prec_get(arena_t *arena) {
|
||||
return (dss_prec_t)atomic_load_u(&arena->dss_prec, ATOMIC_ACQUIRE);
|
||||
@@ -1583,7 +1587,7 @@ arena_nthreads_dec(arena_t *arena, bool internal) {
|
||||
}
|
||||
|
||||
arena_t *
|
||||
arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) {
|
||||
arena_t *arena;
|
||||
base_t *base;
|
||||
unsigned i;
|
||||
@@ -1591,7 +1595,8 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
if (ind == 0) {
|
||||
base = b0get();
|
||||
} else {
|
||||
base = base_new(tsdn, ind, extent_hooks);
|
||||
base = base_new(tsdn, ind, config->extent_hooks,
|
||||
config->metadata_use_hooks);
|
||||
if (base == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
21
src/base.c
21
src/base.c
@@ -295,6 +295,12 @@ base_block_alloc(tsdn_t *tsdn, base_t *base, ehooks_t *ehooks, unsigned ind,
|
||||
return block;
|
||||
}
|
||||
|
||||
static ehooks_t *
|
||||
base_ehooks_get_for_metadata(base_t *base) {
|
||||
return base->metadata_use_hooks ? &base->ehooks :
|
||||
(struct ehooks_s *)&ehooks_default_extent_hooks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an extent that is at least as large as specified size, with
|
||||
* specified alignment.
|
||||
@@ -303,7 +309,7 @@ static edata_t *
|
||||
base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) {
|
||||
malloc_mutex_assert_owner(tsdn, &base->mtx);
|
||||
|
||||
ehooks_t *ehooks = base_ehooks_get(base);
|
||||
ehooks_t *ehooks = base_ehooks_get_for_metadata(base);
|
||||
/*
|
||||
* Drop mutex during base_block_alloc(), because an extent hook will be
|
||||
* called.
|
||||
@@ -342,7 +348,8 @@ b0get(void) {
|
||||
}
|
||||
|
||||
base_t *
|
||||
base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks) {
|
||||
base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks,
|
||||
bool metadata_use_hooks) {
|
||||
pszind_t pind_last = 0;
|
||||
size_t extent_sn_next = 0;
|
||||
|
||||
@@ -352,7 +359,9 @@ base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks) {
|
||||
* memory, and then initialize the ehooks within the base_t.
|
||||
*/
|
||||
ehooks_t fake_ehooks;
|
||||
ehooks_init(&fake_ehooks, (extent_hooks_t *)extent_hooks, ind);
|
||||
ehooks_init(&fake_ehooks, metadata_use_hooks ?
|
||||
(extent_hooks_t *)extent_hooks :
|
||||
(extent_hooks_t *)&ehooks_default_extent_hooks, ind);
|
||||
|
||||
base_block_t *block = base_block_alloc(tsdn, NULL, &fake_ehooks, ind,
|
||||
&pind_last, &extent_sn_next, sizeof(base_t), QUANTUM);
|
||||
@@ -375,6 +384,7 @@ base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks) {
|
||||
base->extent_sn_next = extent_sn_next;
|
||||
base->blocks = block;
|
||||
base->auto_thp_switched = false;
|
||||
base->metadata_use_hooks = metadata_use_hooks;
|
||||
for (szind_t i = 0; i < SC_NSIZES; i++) {
|
||||
edata_heap_new(&base->avail[i]);
|
||||
}
|
||||
@@ -397,7 +407,7 @@ base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks) {
|
||||
|
||||
void
|
||||
base_delete(tsdn_t *tsdn, base_t *base) {
|
||||
ehooks_t *ehooks = base_ehooks_get(base);
|
||||
ehooks_t *ehooks = base_ehooks_get_for_metadata(base);
|
||||
base_block_t *next = base->blocks;
|
||||
do {
|
||||
base_block_t *block = next;
|
||||
@@ -512,6 +522,7 @@ base_postfork_child(tsdn_t *tsdn, base_t *base) {
|
||||
|
||||
bool
|
||||
base_boot(tsdn_t *tsdn) {
|
||||
b0 = base_new(tsdn, 0, (extent_hooks_t *)&ehooks_default_extent_hooks);
|
||||
b0 = base_new(tsdn, 0,
|
||||
(extent_hooks_t *)&ehooks_default_extent_hooks, true);
|
||||
return (b0 == NULL);
|
||||
}
|
||||
|
42
src/ctl.c
42
src/ctl.c
@@ -315,6 +315,7 @@ INDEX_PROTO(experimental_arenas_i)
|
||||
CTL_PROTO(experimental_prof_recent_alloc_max)
|
||||
CTL_PROTO(experimental_prof_recent_alloc_dump)
|
||||
CTL_PROTO(experimental_batch_alloc)
|
||||
CTL_PROTO(experimental_arenas_create_ext)
|
||||
|
||||
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
||||
CTL_PROTO(stats_##n##_num_ops) \
|
||||
@@ -870,6 +871,7 @@ static const ctl_named_node_t experimental_node[] = {
|
||||
{NAME("hooks"), CHILD(named, experimental_hooks)},
|
||||
{NAME("utilization"), CHILD(named, experimental_utilization)},
|
||||
{NAME("arenas"), CHILD(indexed, experimental_arenas)},
|
||||
{NAME("arenas_create_ext"), CTL(experimental_arenas_create_ext)},
|
||||
{NAME("prof_recent"), CHILD(named, experimental_prof_recent)},
|
||||
{NAME("batch_alloc"), CTL(experimental_batch_alloc)},
|
||||
{NAME("thread"), CHILD(named, experimental_thread)}
|
||||
@@ -1242,7 +1244,7 @@ ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, ctl_arena_t *ctl_sdarena,
|
||||
}
|
||||
|
||||
static unsigned
|
||||
ctl_arena_init(tsd_t *tsd, extent_hooks_t *extent_hooks) {
|
||||
ctl_arena_init(tsd_t *tsd, const arena_config_t *config) {
|
||||
unsigned arena_ind;
|
||||
ctl_arena_t *ctl_arena;
|
||||
|
||||
@@ -1260,7 +1262,7 @@ ctl_arena_init(tsd_t *tsd, extent_hooks_t *extent_hooks) {
|
||||
}
|
||||
|
||||
/* Initialize new arena. */
|
||||
if (arena_init(tsd_tsdn(tsd), arena_ind, extent_hooks) == NULL) {
|
||||
if (arena_init(tsd_tsdn(tsd), arena_ind, config) == NULL) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
@@ -2881,8 +2883,11 @@ arena_i_extent_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
extent_hooks_t *new_extent_hooks
|
||||
JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
WRITE(new_extent_hooks, extent_hooks_t *);
|
||||
arena_config_t config = arena_config_default;
|
||||
config.extent_hooks = new_extent_hooks;
|
||||
|
||||
arena = arena_init(tsd_tsdn(tsd), arena_ind,
|
||||
new_extent_hooks);
|
||||
&config);
|
||||
if (arena == NULL) {
|
||||
ret = EFAULT;
|
||||
goto label_return;
|
||||
@@ -3069,15 +3074,14 @@ static int
|
||||
arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
extent_hooks_t *extent_hooks;
|
||||
unsigned arena_ind;
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
|
||||
VERIFY_READ(unsigned);
|
||||
extent_hooks = (extent_hooks_t *)&ehooks_default_extent_hooks;
|
||||
WRITE(extent_hooks, extent_hooks_t *);
|
||||
if ((arena_ind = ctl_arena_init(tsd, extent_hooks)) == UINT_MAX) {
|
||||
arena_config_t config = arena_config_default;
|
||||
WRITE(config.extent_hooks, extent_hooks_t *);
|
||||
if ((arena_ind = ctl_arena_init(tsd, &config)) == UINT_MAX) {
|
||||
ret = EAGAIN;
|
||||
goto label_return;
|
||||
}
|
||||
@@ -3089,6 +3093,30 @@ label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_arenas_create_ext_ctl(tsd_t *tsd,
|
||||
const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
unsigned arena_ind;
|
||||
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
|
||||
arena_config_t config = arena_config_default;
|
||||
VERIFY_READ(unsigned);
|
||||
WRITE(config, arena_config_t);
|
||||
|
||||
if ((arena_ind = ctl_arena_init(tsd, &config)) == UINT_MAX) {
|
||||
ret = EAGAIN;
|
||||
goto label_return;
|
||||
}
|
||||
READ(arena_ind, unsigned);
|
||||
ret = 0;
|
||||
label_return:
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
arenas_lookup_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp,
|
||||
|
@@ -384,7 +384,7 @@ narenas_total_get(void) {
|
||||
|
||||
/* Create a new arena and insert it into the arenas array at index ind. */
|
||||
static arena_t *
|
||||
arena_init_locked(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
arena_init_locked(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) {
|
||||
arena_t *arena;
|
||||
|
||||
assert(ind <= narenas_total_get());
|
||||
@@ -406,7 +406,7 @@ arena_init_locked(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
}
|
||||
|
||||
/* Actually initialize the arena. */
|
||||
arena = arena_new(tsdn, ind, extent_hooks);
|
||||
arena = arena_new(tsdn, ind, config);
|
||||
|
||||
return arena;
|
||||
}
|
||||
@@ -430,11 +430,11 @@ arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) {
|
||||
}
|
||||
|
||||
arena_t *
|
||||
arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
||||
arena_init(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) {
|
||||
arena_t *arena;
|
||||
|
||||
malloc_mutex_lock(tsdn, &arenas_lock);
|
||||
arena = arena_init_locked(tsdn, ind, extent_hooks);
|
||||
arena = arena_init_locked(tsdn, ind, config);
|
||||
malloc_mutex_unlock(tsdn, &arenas_lock);
|
||||
|
||||
arena_new_create_background_thread(tsdn, ind);
|
||||
@@ -570,8 +570,7 @@ arena_choose_hard(tsd_t *tsd, bool internal) {
|
||||
choose[j] = first_null;
|
||||
arena = arena_init_locked(tsd_tsdn(tsd),
|
||||
choose[j],
|
||||
(extent_hooks_t *)
|
||||
&ehooks_default_extent_hooks);
|
||||
&arena_config_default);
|
||||
if (arena == NULL) {
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd),
|
||||
&arenas_lock);
|
||||
@@ -1779,8 +1778,7 @@ malloc_init_hard_a0_locked() {
|
||||
* Initialize one arena here. The rest are lazily created in
|
||||
* arena_choose_hard().
|
||||
*/
|
||||
if (arena_init(TSDN_NULL, 0,
|
||||
(extent_hooks_t *)&ehooks_default_extent_hooks) == NULL) {
|
||||
if (arena_init(TSDN_NULL, 0, &arena_config_default) == NULL) {
|
||||
return true;
|
||||
}
|
||||
a0 = arena_get(TSDN_NULL, 0, false);
|
||||
|
Reference in New Issue
Block a user