mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-18 14:47:18 +03:00
Move background thread state operations into background thread modules.
Move operations touch background thread's lifecycle and states back into its own module.
This commit is contained in:
parent
6b7ab6166f
commit
97075555d5
5 changed files with 97 additions and 49 deletions
|
|
@ -76,6 +76,25 @@ bool background_thread_stats_read(
|
|||
tsdn_t *tsdn, background_thread_stats_t *stats);
|
||||
void background_thread_ctl_init(tsdn_t *tsdn);
|
||||
|
||||
/*
|
||||
* Arena-reset lifecycle bracket (owned by the bg-thread module so the
|
||||
* started<->paused state machine is mutated only inside the module). begin()
|
||||
* acquires the global background_thread_lock and RETURNS WITH IT HELD;
|
||||
* finish() releases it. The lock intentionally spans the whole arena-reset
|
||||
* body across the two calls. Pass arena_ind (not an arena_t *): the destroy
|
||||
* path frees the arena before calling finish().
|
||||
*/
|
||||
void background_thread_arena_reset_begin(tsd_t *tsd, unsigned arena_ind);
|
||||
void background_thread_arena_reset_finish(tsd_t *tsd, unsigned arena_ind);
|
||||
|
||||
/*
|
||||
* Serialize a rare admin operation against the background thread by holding the
|
||||
* per-arena info mutex (have_background_thread-gated). Used by
|
||||
* arena_set_extent_hooks to fence pa_shard_disable_hpa.
|
||||
*/
|
||||
void background_thread_serialize_lock(tsd_t *tsd, unsigned arena_ind);
|
||||
void background_thread_serialize_unlock(tsd_t *tsd, unsigned arena_ind);
|
||||
|
||||
#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
|
||||
extern int pthread_create_wrapper(pthread_t *__restrict, const pthread_attr_t *,
|
||||
void *(*)(void *), void *__restrict);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,6 @@ background_thread_enabled_set(tsdn_t *tsdn, bool state) {
|
|||
background_thread_enabled_set_impl(state);
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE background_thread_info_t *
|
||||
arena_background_thread_info_get(arena_t *arena) {
|
||||
unsigned arena_ind = arena_ind_get(arena);
|
||||
return &background_thread_info[arena_ind % max_background_threads];
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE background_thread_info_t *
|
||||
background_thread_info_get(size_t ind) {
|
||||
return &background_thread_info[ind % max_background_threads];
|
||||
|
|
|
|||
16
src/arena.c
16
src/arena.c
|
|
@ -1427,17 +1427,17 @@ arena_get_ehooks(const arena_t *arena) {
|
|||
extent_hooks_t *
|
||||
arena_set_extent_hooks(
|
||||
tsd_t *tsd, arena_t *arena, extent_hooks_t *extent_hooks) {
|
||||
background_thread_info_t *info;
|
||||
if (have_background_thread) {
|
||||
info = arena_background_thread_info_get(arena);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
/*
|
||||
* Serialize disabling the HPA against the background thread via the
|
||||
* module-owned bracket (have_background_thread-gated internally) rather
|
||||
* than reaching into info->mtx directly.
|
||||
*/
|
||||
unsigned arena_ind = arena_ind_get(arena);
|
||||
background_thread_serialize_lock(tsd, arena_ind);
|
||||
/* No using the HPA now that we have the custom hooks. */
|
||||
pa_shard_disable_hpa(tsd_tsdn(tsd), &arena->pa_shard);
|
||||
extent_hooks_t *ret = base_extent_hooks_set(arena->base, extent_hooks);
|
||||
if (have_background_thread) {
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
background_thread_serialize_unlock(tsd, arena_ind);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,72 @@ size_t max_background_threads;
|
|||
/* Thread info per-index. */
|
||||
background_thread_info_t *background_thread_info;
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Config-independent lifecycle/state-ownership helpers. Defined
|
||||
* unconditionally and gated at runtime on have_background_thread, so callers in
|
||||
* ctl.c / arena.c never touch background_thread_lock or info->state directly;
|
||||
* they compile to runtime no-ops when !have_background_thread.
|
||||
*/
|
||||
|
||||
void
|
||||
background_thread_arena_reset_begin(tsd_t *tsd, unsigned arena_ind) {
|
||||
/* Temporarily disable the background thread during arena reset. */
|
||||
if (have_background_thread) {
|
||||
/*
|
||||
* Hold background_thread_lock across the whole arena-reset
|
||||
* body (acquired here, released in _finish) so a concurrent
|
||||
* background_threads_enable() cannot start a background
|
||||
* thread mid-reset. This must happen whenever the feature
|
||||
* is compiled in (have_background_thread), even when the
|
||||
* thread is not currently enabled; the state transition
|
||||
* below is separately gated on background_thread_enabled().
|
||||
*/
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
if (background_thread_enabled()) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
assert(info->state == background_thread_started);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
info->state = background_thread_paused;
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
background_thread_arena_reset_finish(tsd_t *tsd, unsigned arena_ind) {
|
||||
if (have_background_thread) {
|
||||
if (background_thread_enabled()) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
assert(info->state == background_thread_paused);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
info->state = background_thread_started;
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
background_thread_serialize_lock(tsd_t *tsd, unsigned arena_ind) {
|
||||
if (have_background_thread) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
background_thread_serialize_unlock(tsd_t *tsd, unsigned arena_ind) {
|
||||
if (have_background_thread) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
|
||||
|
|
|
|||
39
src/ctl.c
39
src/ctl.c
|
|
@ -2790,37 +2790,6 @@ arena_i_reset_destroy_helper(tsd_t *tsd, const size_t *mib, size_t miblen,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
arena_reset_prepare_background_thread(tsd_t *tsd, unsigned arena_ind) {
|
||||
/* Temporarily disable the background thread during arena reset. */
|
||||
if (have_background_thread) {
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
if (background_thread_enabled()) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
assert(info->state == background_thread_started);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
info->state = background_thread_paused;
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arena_reset_finish_background_thread(tsd_t *tsd, unsigned arena_ind) {
|
||||
if (have_background_thread) {
|
||||
if (background_thread_enabled()) {
|
||||
background_thread_info_t *info =
|
||||
background_thread_info_get(arena_ind);
|
||||
assert(info->state == background_thread_paused);
|
||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||
info->state = background_thread_started;
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
|
||||
}
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
||||
size_t *oldlenp, void *newp, size_t newlen) {
|
||||
|
|
@ -2834,9 +2803,9 @@ arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
arena_reset_prepare_background_thread(tsd, arena_ind);
|
||||
background_thread_arena_reset_begin(tsd, arena_ind);
|
||||
arena_reset(tsd, arena);
|
||||
arena_reset_finish_background_thread(tsd, arena_ind);
|
||||
background_thread_arena_reset_finish(tsd, arena_ind);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2863,7 +2832,7 @@ arena_i_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||
goto label_return;
|
||||
}
|
||||
|
||||
arena_reset_prepare_background_thread(tsd, arena_ind);
|
||||
background_thread_arena_reset_begin(tsd, arena_ind);
|
||||
/* Merge stats after resetting and purging arena. */
|
||||
arena_reset(tsd, arena);
|
||||
arena_decay(tsd_tsdn(tsd), arena, false, true);
|
||||
|
|
@ -2877,7 +2846,7 @@ arena_i_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
|
|||
/* Record arena index for later recycling via arenas.create. */
|
||||
ql_elm_new(ctl_arena, destroyed_link);
|
||||
ql_tail_insert(&ctl_arenas->destroyed, ctl_arena, destroyed_link);
|
||||
arena_reset_finish_background_thread(tsd, arena_ind);
|
||||
background_thread_arena_reset_finish(tsd, arena_ind);
|
||||
|
||||
assert(ret == 0);
|
||||
label_return:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue