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:
parent
a9031a0970
commit
7bb05e04be
@ -97,7 +97,7 @@ bool arena_retain_grow_limit_get_set(tsd_t *tsd, arena_t *arena,
|
|||||||
unsigned arena_nthreads_get(arena_t *arena, bool internal);
|
unsigned arena_nthreads_get(arena_t *arena, bool internal);
|
||||||
void arena_nthreads_inc(arena_t *arena, bool internal);
|
void arena_nthreads_inc(arena_t *arena, bool internal);
|
||||||
void arena_nthreads_dec(arena_t *arena, bool internal);
|
void arena_nthreads_dec(arena_t *arena, bool internal);
|
||||||
arena_t *arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks);
|
arena_t *arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config);
|
||||||
bool arena_init_huge(void);
|
bool arena_init_huge(void);
|
||||||
bool arena_is_huge(unsigned arena_ind);
|
bool arena_is_huge(unsigned arena_ind);
|
||||||
arena_t *arena_choose_huge(tsd_t *tsd);
|
arena_t *arena_choose_huge(tsd_t *tsd);
|
||||||
|
@ -41,4 +41,18 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
#define OVERSIZE_THRESHOLD_DEFAULT (8 << 20)
|
#define OVERSIZE_THRESHOLD_DEFAULT (8 << 20)
|
||||||
|
|
||||||
|
struct arena_config_s {
|
||||||
|
/* extent hooks to be used for the arena */
|
||||||
|
struct extent_hooks_s *extent_hooks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use extent hooks for metadata (base) allocations when true.
|
||||||
|
*/
|
||||||
|
bool metadata_use_hooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct arena_config_s arena_config_t;
|
||||||
|
|
||||||
|
extern const arena_config_t arena_config_default;
|
||||||
|
|
||||||
#endif /* JEMALLOC_INTERNAL_ARENA_TYPES_H */
|
#endif /* JEMALLOC_INTERNAL_ARENA_TYPES_H */
|
||||||
|
@ -46,6 +46,11 @@ struct base_s {
|
|||||||
*/
|
*/
|
||||||
ehooks_t ehooks;
|
ehooks_t ehooks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use user hooks for metadata when true.
|
||||||
|
*/
|
||||||
|
bool metadata_use_hooks;
|
||||||
|
|
||||||
/* Protects base_alloc() and base_stats_get() operations. */
|
/* Protects base_alloc() and base_stats_get() operations. */
|
||||||
malloc_mutex_t mtx;
|
malloc_mutex_t mtx;
|
||||||
|
|
||||||
@ -87,7 +92,7 @@ metadata_thp_enabled(void) {
|
|||||||
|
|
||||||
base_t *b0get(void);
|
base_t *b0get(void);
|
||||||
base_t *base_new(tsdn_t *tsdn, unsigned ind,
|
base_t *base_new(tsdn_t *tsdn, unsigned ind,
|
||||||
const extent_hooks_t *extent_hooks);
|
const extent_hooks_t *extent_hooks, bool metadata_use_hooks);
|
||||||
void base_delete(tsdn_t *tsdn, base_t *base);
|
void base_delete(tsdn_t *tsdn, base_t *base);
|
||||||
ehooks_t *base_ehooks_get(base_t *base);
|
ehooks_t *base_ehooks_get(base_t *base);
|
||||||
extent_hooks_t *base_extent_hooks_set(base_t *base,
|
extent_hooks_t *base_extent_hooks_set(base_t *base,
|
||||||
|
@ -25,6 +25,11 @@ struct base_s {
|
|||||||
*/
|
*/
|
||||||
ehooks_t ehooks;
|
ehooks_t ehooks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use user hooks for metadata when true.
|
||||||
|
*/
|
||||||
|
bool metadata_use_hooks;
|
||||||
|
|
||||||
/* Protects base_alloc() and base_stats_get() operations. */
|
/* Protects base_alloc() and base_stats_get() operations. */
|
||||||
malloc_mutex_t mtx;
|
malloc_mutex_t mtx;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ void *bootstrap_calloc(size_t num, size_t size);
|
|||||||
void bootstrap_free(void *ptr);
|
void bootstrap_free(void *ptr);
|
||||||
void arena_set(unsigned ind, arena_t *arena);
|
void arena_set(unsigned ind, arena_t *arena);
|
||||||
unsigned narenas_total_get(void);
|
unsigned narenas_total_get(void);
|
||||||
arena_t *arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks);
|
arena_t *arena_init(tsdn_t *tsdn, unsigned ind, const arena_config_t *config);
|
||||||
arena_t *arena_choose_hard(tsd_t *tsd, bool internal);
|
arena_t *arena_choose_hard(tsd_t *tsd, bool internal);
|
||||||
void arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind);
|
void arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind);
|
||||||
void iarena_cleanup(tsd_t *tsd);
|
void iarena_cleanup(tsd_t *tsd);
|
||||||
|
@ -66,7 +66,7 @@ arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing) {
|
|||||||
if (unlikely(ret == NULL)) {
|
if (unlikely(ret == NULL)) {
|
||||||
if (init_if_missing) {
|
if (init_if_missing) {
|
||||||
ret = arena_init(tsdn, ind,
|
ret = arena_init(tsdn, ind,
|
||||||
(extent_hooks_t *)&ehooks_default_extent_hooks);
|
&arena_config_default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
11
src/arena.c
11
src/arena.c
@ -48,6 +48,11 @@ static unsigned nbins_total;
|
|||||||
|
|
||||||
static unsigned huge_arena_ind;
|
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
|
* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dss_prec_t
|
dss_prec_t
|
||||||
arena_dss_prec_get(arena_t *arena) {
|
arena_dss_prec_get(arena_t *arena) {
|
||||||
return (dss_prec_t)atomic_load_u(&arena->dss_prec, ATOMIC_ACQUIRE);
|
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_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;
|
arena_t *arena;
|
||||||
base_t *base;
|
base_t *base;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -1591,7 +1595,8 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
|||||||
if (ind == 0) {
|
if (ind == 0) {
|
||||||
base = b0get();
|
base = b0get();
|
||||||
} else {
|
} else {
|
||||||
base = base_new(tsdn, ind, extent_hooks);
|
base = base_new(tsdn, ind, config->extent_hooks,
|
||||||
|
config->metadata_use_hooks);
|
||||||
if (base == NULL) {
|
if (base == NULL) {
|
||||||
return 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;
|
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
|
* Allocate an extent that is at least as large as specified size, with
|
||||||
* specified alignment.
|
* specified alignment.
|
||||||
@ -303,7 +309,7 @@ static edata_t *
|
|||||||
base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) {
|
base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) {
|
||||||
malloc_mutex_assert_owner(tsdn, &base->mtx);
|
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
|
* Drop mutex during base_block_alloc(), because an extent hook will be
|
||||||
* called.
|
* called.
|
||||||
@ -342,7 +348,8 @@ b0get(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
base_t *
|
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;
|
pszind_t pind_last = 0;
|
||||||
size_t extent_sn_next = 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.
|
* memory, and then initialize the ehooks within the base_t.
|
||||||
*/
|
*/
|
||||||
ehooks_t fake_ehooks;
|
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,
|
base_block_t *block = base_block_alloc(tsdn, NULL, &fake_ehooks, ind,
|
||||||
&pind_last, &extent_sn_next, sizeof(base_t), QUANTUM);
|
&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->extent_sn_next = extent_sn_next;
|
||||||
base->blocks = block;
|
base->blocks = block;
|
||||||
base->auto_thp_switched = false;
|
base->auto_thp_switched = false;
|
||||||
|
base->metadata_use_hooks = metadata_use_hooks;
|
||||||
for (szind_t i = 0; i < SC_NSIZES; i++) {
|
for (szind_t i = 0; i < SC_NSIZES; i++) {
|
||||||
edata_heap_new(&base->avail[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
|
void
|
||||||
base_delete(tsdn_t *tsdn, base_t *base) {
|
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;
|
base_block_t *next = base->blocks;
|
||||||
do {
|
do {
|
||||||
base_block_t *block = next;
|
base_block_t *block = next;
|
||||||
@ -512,6 +522,7 @@ base_postfork_child(tsdn_t *tsdn, base_t *base) {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
base_boot(tsdn_t *tsdn) {
|
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);
|
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_max)
|
||||||
CTL_PROTO(experimental_prof_recent_alloc_dump)
|
CTL_PROTO(experimental_prof_recent_alloc_dump)
|
||||||
CTL_PROTO(experimental_batch_alloc)
|
CTL_PROTO(experimental_batch_alloc)
|
||||||
|
CTL_PROTO(experimental_arenas_create_ext)
|
||||||
|
|
||||||
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
||||||
CTL_PROTO(stats_##n##_num_ops) \
|
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("hooks"), CHILD(named, experimental_hooks)},
|
||||||
{NAME("utilization"), CHILD(named, experimental_utilization)},
|
{NAME("utilization"), CHILD(named, experimental_utilization)},
|
||||||
{NAME("arenas"), CHILD(indexed, experimental_arenas)},
|
{NAME("arenas"), CHILD(indexed, experimental_arenas)},
|
||||||
|
{NAME("arenas_create_ext"), CTL(experimental_arenas_create_ext)},
|
||||||
{NAME("prof_recent"), CHILD(named, experimental_prof_recent)},
|
{NAME("prof_recent"), CHILD(named, experimental_prof_recent)},
|
||||||
{NAME("batch_alloc"), CTL(experimental_batch_alloc)},
|
{NAME("batch_alloc"), CTL(experimental_batch_alloc)},
|
||||||
{NAME("thread"), CHILD(named, experimental_thread)}
|
{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
|
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;
|
unsigned arena_ind;
|
||||||
ctl_arena_t *ctl_arena;
|
ctl_arena_t *ctl_arena;
|
||||||
|
|
||||||
@ -1260,7 +1262,7 @@ ctl_arena_init(tsd_t *tsd, extent_hooks_t *extent_hooks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize new arena. */
|
/* 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;
|
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
|
extent_hooks_t *new_extent_hooks
|
||||||
JEMALLOC_CC_SILENCE_INIT(NULL);
|
JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||||
WRITE(new_extent_hooks, extent_hooks_t *);
|
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,
|
arena = arena_init(tsd_tsdn(tsd), arena_ind,
|
||||||
new_extent_hooks);
|
&config);
|
||||||
if (arena == NULL) {
|
if (arena == NULL) {
|
||||||
ret = EFAULT;
|
ret = EFAULT;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
@ -3069,15 +3074,14 @@ static int
|
|||||||
arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||||
int ret;
|
int ret;
|
||||||
extent_hooks_t *extent_hooks;
|
|
||||||
unsigned arena_ind;
|
unsigned arena_ind;
|
||||||
|
|
||||||
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
|
||||||
|
|
||||||
VERIFY_READ(unsigned);
|
VERIFY_READ(unsigned);
|
||||||
extent_hooks = (extent_hooks_t *)&ehooks_default_extent_hooks;
|
arena_config_t config = arena_config_default;
|
||||||
WRITE(extent_hooks, extent_hooks_t *);
|
WRITE(config.extent_hooks, extent_hooks_t *);
|
||||||
if ((arena_ind = ctl_arena_init(tsd, extent_hooks)) == UINT_MAX) {
|
if ((arena_ind = ctl_arena_init(tsd, &config)) == UINT_MAX) {
|
||||||
ret = EAGAIN;
|
ret = EAGAIN;
|
||||||
goto label_return;
|
goto label_return;
|
||||||
}
|
}
|
||||||
@ -3089,6 +3093,30 @@ label_return:
|
|||||||
return ret;
|
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
|
static int
|
||||||
arenas_lookup_ctl(tsd_t *tsd, const size_t *mib,
|
arenas_lookup_ctl(tsd_t *tsd, const size_t *mib,
|
||||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp,
|
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. */
|
/* Create a new arena and insert it into the arenas array at index ind. */
|
||||||
static arena_t *
|
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;
|
arena_t *arena;
|
||||||
|
|
||||||
assert(ind <= narenas_total_get());
|
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. */
|
/* Actually initialize the arena. */
|
||||||
arena = arena_new(tsdn, ind, extent_hooks);
|
arena = arena_new(tsdn, ind, config);
|
||||||
|
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
@ -430,11 +430,11 @@ arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
arena_t *
|
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;
|
arena_t *arena;
|
||||||
|
|
||||||
malloc_mutex_lock(tsdn, &arenas_lock);
|
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);
|
malloc_mutex_unlock(tsdn, &arenas_lock);
|
||||||
|
|
||||||
arena_new_create_background_thread(tsdn, ind);
|
arena_new_create_background_thread(tsdn, ind);
|
||||||
@ -570,8 +570,7 @@ arena_choose_hard(tsd_t *tsd, bool internal) {
|
|||||||
choose[j] = first_null;
|
choose[j] = first_null;
|
||||||
arena = arena_init_locked(tsd_tsdn(tsd),
|
arena = arena_init_locked(tsd_tsdn(tsd),
|
||||||
choose[j],
|
choose[j],
|
||||||
(extent_hooks_t *)
|
&arena_config_default);
|
||||||
&ehooks_default_extent_hooks);
|
|
||||||
if (arena == NULL) {
|
if (arena == NULL) {
|
||||||
malloc_mutex_unlock(tsd_tsdn(tsd),
|
malloc_mutex_unlock(tsd_tsdn(tsd),
|
||||||
&arenas_lock);
|
&arenas_lock);
|
||||||
@ -1779,8 +1778,7 @@ malloc_init_hard_a0_locked() {
|
|||||||
* Initialize one arena here. The rest are lazily created in
|
* Initialize one arena here. The rest are lazily created in
|
||||||
* arena_choose_hard().
|
* arena_choose_hard().
|
||||||
*/
|
*/
|
||||||
if (arena_init(TSDN_NULL, 0,
|
if (arena_init(TSDN_NULL, 0, &arena_config_default) == NULL) {
|
||||||
(extent_hooks_t *)&ehooks_default_extent_hooks) == NULL) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
a0 = arena_get(TSDN_NULL, 0, false);
|
a0 = arena_get(TSDN_NULL, 0, false);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "test/extent_hooks.h"
|
#include "test/extent_hooks.h"
|
||||||
|
|
||||||
|
#include "jemalloc/internal/arena_types.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_extent_body(unsigned arena_ind) {
|
test_extent_body(unsigned arena_ind) {
|
||||||
void *p;
|
void *p;
|
||||||
@ -228,9 +230,58 @@ TEST_BEGIN(test_extent_auto_hook) {
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_arenas_create_ext_base(arena_config_t config,
|
||||||
|
bool expect_hook_data, bool expect_hook_metadata)
|
||||||
|
{
|
||||||
|
unsigned arena, arena1;
|
||||||
|
void *ptr;
|
||||||
|
size_t sz = sizeof(unsigned);
|
||||||
|
|
||||||
|
extent_hooks_prep();
|
||||||
|
|
||||||
|
called_alloc = false;
|
||||||
|
expect_d_eq(mallctl("experimental.arenas_create_ext",
|
||||||
|
(void *)&arena, &sz, &config, sizeof(arena_config_t)), 0,
|
||||||
|
"Unexpected mallctl() failure");
|
||||||
|
expect_b_eq(called_alloc, expect_hook_metadata,
|
||||||
|
"expected hook metadata alloc mismatch");
|
||||||
|
|
||||||
|
called_alloc = false;
|
||||||
|
ptr = mallocx(42, MALLOCX_ARENA(arena) | MALLOCX_TCACHE_NONE);
|
||||||
|
expect_b_eq(called_alloc, expect_hook_data,
|
||||||
|
"expected hook data alloc mismatch");
|
||||||
|
|
||||||
|
expect_ptr_not_null(ptr, "Unexpected mallocx() failure");
|
||||||
|
expect_d_eq(mallctl("arenas.lookup", &arena1, &sz, &ptr, sizeof(ptr)),
|
||||||
|
0, "Unexpected mallctl() failure");
|
||||||
|
expect_u_eq(arena, arena1, "Unexpected arena index");
|
||||||
|
dallocx(ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_BEGIN(test_arenas_create_ext_with_ehooks_no_metadata) {
|
||||||
|
arena_config_t config;
|
||||||
|
config.extent_hooks = &hooks;
|
||||||
|
config.metadata_use_hooks = false;
|
||||||
|
|
||||||
|
test_arenas_create_ext_base(config, true, false);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_arenas_create_ext_with_ehooks_with_metadata) {
|
||||||
|
arena_config_t config;
|
||||||
|
config.extent_hooks = &hooks;
|
||||||
|
config.metadata_use_hooks = true;
|
||||||
|
|
||||||
|
test_arenas_create_ext_base(config, true, true);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
return test(
|
return test(
|
||||||
test_extent_manual_hook,
|
test_extent_manual_hook,
|
||||||
test_extent_auto_hook);
|
test_extent_auto_hook,
|
||||||
|
test_arenas_create_ext_with_ehooks_no_metadata,
|
||||||
|
test_arenas_create_ext_with_ehooks_with_metadata);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,8 @@ TEST_BEGIN(test_base_hooks_default) {
|
|||||||
|
|
||||||
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
||||||
base = base_new(tsdn, 0,
|
base = base_new(tsdn, 0,
|
||||||
(extent_hooks_t *)&ehooks_default_extent_hooks);
|
(extent_hooks_t *)&ehooks_default_extent_hooks,
|
||||||
|
/* metadata_use_hooks */ true);
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
base_stats_get(tsdn, base, &allocated0, &resident, &mapped,
|
base_stats_get(tsdn, base, &allocated0, &resident, &mapped,
|
||||||
@ -74,7 +75,7 @@ TEST_BEGIN(test_base_hooks_null) {
|
|||||||
memcpy(&hooks, &hooks_null, sizeof(extent_hooks_t));
|
memcpy(&hooks, &hooks_null, sizeof(extent_hooks_t));
|
||||||
|
|
||||||
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
||||||
base = base_new(tsdn, 0, &hooks);
|
base = base_new(tsdn, 0, &hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new() failure");
|
expect_ptr_not_null(base, "Unexpected base_new() failure");
|
||||||
|
|
||||||
if (config_stats) {
|
if (config_stats) {
|
||||||
@ -120,7 +121,7 @@ TEST_BEGIN(test_base_hooks_not_null) {
|
|||||||
|
|
||||||
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
tsdn_t *tsdn = tsd_tsdn(tsd_fetch());
|
||||||
did_alloc = false;
|
did_alloc = false;
|
||||||
base = base_new(tsdn, 0, &hooks);
|
base = base_new(tsdn, 0, &hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new() failure");
|
expect_ptr_not_null(base, "Unexpected base_new() failure");
|
||||||
expect_true(did_alloc, "Expected alloc");
|
expect_true(did_alloc, "Expected alloc");
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
static void
|
static void
|
||||||
test_edata_cache_init(edata_cache_t *edata_cache) {
|
test_edata_cache_init(edata_cache_t *edata_cache) {
|
||||||
base_t *base = base_new(TSDN_NULL, /* ind */ 1,
|
base_t *base = base_new(TSDN_NULL, /* ind */ 1,
|
||||||
&ehooks_default_extent_hooks);
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
assert_ptr_not_null(base, "");
|
assert_ptr_not_null(base, "");
|
||||||
bool err = edata_cache_init(edata_cache, base);
|
bool err = edata_cache_init(edata_cache, base);
|
||||||
assert_false(err, "");
|
assert_false(err, "");
|
||||||
|
@ -37,7 +37,7 @@ static hpa_shard_t *
|
|||||||
create_test_data(hpa_hooks_t *hooks, hpa_shard_opts_t *opts) {
|
create_test_data(hpa_hooks_t *hooks, hpa_shard_opts_t *opts) {
|
||||||
bool err;
|
bool err;
|
||||||
base_t *base = base_new(TSDN_NULL, /* ind */ SHARD_IND,
|
base_t *base = base_new(TSDN_NULL, /* ind */ SHARD_IND,
|
||||||
&ehooks_default_extent_hooks);
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
assert_ptr_not_null(base, "");
|
assert_ptr_not_null(base, "");
|
||||||
|
|
||||||
test_data_t *test_data = malloc(sizeof(test_data_t));
|
test_data_t *test_data = malloc(sizeof(test_data_t));
|
||||||
|
@ -53,7 +53,8 @@ test_data_t *init_test_data(ssize_t dirty_decay_ms, ssize_t muzzy_decay_ms) {
|
|||||||
assert_ptr_not_null(test_data, "");
|
assert_ptr_not_null(test_data, "");
|
||||||
init_test_extent_hooks(&test_data->hooks);
|
init_test_extent_hooks(&test_data->hooks);
|
||||||
|
|
||||||
base_t *base = base_new(TSDN_NULL, /* ind */ 1, &test_data->hooks);
|
base_t *base = base_new(TSDN_NULL, /* ind */ 1,
|
||||||
|
&test_data->hooks, /* metadata_use_hooks */ true);
|
||||||
assert_ptr_not_null(base, "");
|
assert_ptr_not_null(base, "");
|
||||||
|
|
||||||
test_data->base = base;
|
test_data->base = base;
|
||||||
|
@ -12,7 +12,8 @@ TEST_BEGIN(test_rtree_read_empty) {
|
|||||||
|
|
||||||
tsdn = tsdn_fetch();
|
tsdn = tsdn_fetch();
|
||||||
|
|
||||||
base_t *base = base_new(tsdn, 0, &ehooks_default_extent_hooks);
|
base_t *base = base_new(tsdn, 0,
|
||||||
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new failure");
|
expect_ptr_not_null(base, "Unexpected base_new failure");
|
||||||
|
|
||||||
rtree_t *rtree = &test_rtree;
|
rtree_t *rtree = &test_rtree;
|
||||||
@ -52,7 +53,8 @@ TEST_BEGIN(test_rtree_extrema) {
|
|||||||
|
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
tsdn_t *tsdn = tsdn_fetch();
|
||||||
|
|
||||||
base_t *base = base_new(tsdn, 0, &ehooks_default_extent_hooks);
|
base_t *base = base_new(tsdn, 0,
|
||||||
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new failure");
|
expect_ptr_not_null(base, "Unexpected base_new failure");
|
||||||
|
|
||||||
rtree_t *rtree = &test_rtree;
|
rtree_t *rtree = &test_rtree;
|
||||||
@ -103,7 +105,8 @@ TEST_END
|
|||||||
|
|
||||||
TEST_BEGIN(test_rtree_bits) {
|
TEST_BEGIN(test_rtree_bits) {
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
tsdn_t *tsdn = tsdn_fetch();
|
||||||
base_t *base = base_new(tsdn, 0, &ehooks_default_extent_hooks);
|
base_t *base = base_new(tsdn, 0,
|
||||||
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new failure");
|
expect_ptr_not_null(base, "Unexpected base_new failure");
|
||||||
|
|
||||||
uintptr_t keys[] = {PAGE, PAGE + 1,
|
uintptr_t keys[] = {PAGE, PAGE + 1,
|
||||||
@ -152,7 +155,8 @@ TEST_BEGIN(test_rtree_random) {
|
|||||||
sfmt_t *sfmt = init_gen_rand(SEED);
|
sfmt_t *sfmt = init_gen_rand(SEED);
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
tsdn_t *tsdn = tsdn_fetch();
|
||||||
|
|
||||||
base_t *base = base_new(tsdn, 0, &ehooks_default_extent_hooks);
|
base_t *base = base_new(tsdn, 0,
|
||||||
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new failure");
|
expect_ptr_not_null(base, "Unexpected base_new failure");
|
||||||
|
|
||||||
uintptr_t keys[NSET];
|
uintptr_t keys[NSET];
|
||||||
@ -250,7 +254,8 @@ test_rtree_range_write(tsdn_t *tsdn, rtree_t *rtree, uintptr_t start,
|
|||||||
|
|
||||||
TEST_BEGIN(test_rtree_range) {
|
TEST_BEGIN(test_rtree_range) {
|
||||||
tsdn_t *tsdn = tsdn_fetch();
|
tsdn_t *tsdn = tsdn_fetch();
|
||||||
base_t *base = base_new(tsdn, 0, &ehooks_default_extent_hooks);
|
base_t *base = base_new(tsdn, 0,
|
||||||
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
expect_ptr_not_null(base, "Unexpected base_new failure");
|
expect_ptr_not_null(base, "Unexpected base_new failure");
|
||||||
|
|
||||||
rtree_t *rtree = &test_rtree;
|
rtree_t *rtree = &test_rtree;
|
||||||
|
@ -42,7 +42,7 @@ test_sec_init(sec_t *sec, pai_t *fallback, size_t nshards, size_t max_alloc,
|
|||||||
* short-running, and SECs are arena-scoped in reality.
|
* short-running, and SECs are arena-scoped in reality.
|
||||||
*/
|
*/
|
||||||
base_t *base = base_new(TSDN_NULL, /* ind */ 123,
|
base_t *base = base_new(TSDN_NULL, /* ind */ 123,
|
||||||
&ehooks_default_extent_hooks);
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
|
|
||||||
bool err = sec_init(TSDN_NULL, sec, base, fallback, &opts);
|
bool err = sec_init(TSDN_NULL, sec, base, fallback, &opts);
|
||||||
assert_false(err, "Unexpected initialization failure");
|
assert_false(err, "Unexpected initialization failure");
|
||||||
@ -442,7 +442,7 @@ TEST_BEGIN(test_nshards_0) {
|
|||||||
/* See the note above -- we can't use the real tsd. */
|
/* See the note above -- we can't use the real tsd. */
|
||||||
tsdn_t *tsdn = TSDN_NULL;
|
tsdn_t *tsdn = TSDN_NULL;
|
||||||
base_t *base = base_new(TSDN_NULL, /* ind */ 123,
|
base_t *base = base_new(TSDN_NULL, /* ind */ 123,
|
||||||
&ehooks_default_extent_hooks);
|
&ehooks_default_extent_hooks, /* metadata_use_hooks */ true);
|
||||||
|
|
||||||
sec_opts_t opts = SEC_OPTS_DEFAULT;
|
sec_opts_t opts = SEC_OPTS_DEFAULT;
|
||||||
opts.nshards = 0;
|
opts.nshards = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user