Avoid the release & re-acquire of the ecache locks around the merge hook.
This commit is contained in:
parent
7dc77527ba
commit
ce68f326b0
72
src/extent.c
72
src/extent.c
@ -22,7 +22,7 @@ static bool extent_purge_forced_impl(tsdn_t *tsdn, ehooks_t *ehooks,
|
|||||||
static edata_t *extent_split_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
static edata_t *extent_split_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
edata_t *edata, size_t size_a, size_t size_b, bool growing_retained);
|
edata_t *edata, size_t size_a, size_t size_b, bool growing_retained);
|
||||||
static bool extent_merge_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
static bool extent_merge_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
edata_t *a, edata_t *b, bool growing_retained);
|
edata_t *a, edata_t *b, bool holding_core_locks);
|
||||||
|
|
||||||
/* Used exclusively for gdump triggering. */
|
/* Used exclusively for gdump triggering. */
|
||||||
static atomic_zu_t curpages;
|
static atomic_zu_t curpages;
|
||||||
@ -39,9 +39,9 @@ static edata_t *extent_recycle(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
ecache_t *ecache, edata_t *expand_edata, size_t usize, size_t alignment,
|
ecache_t *ecache, edata_t *expand_edata, size_t usize, size_t alignment,
|
||||||
bool zero, bool *commit, bool growing_retained);
|
bool zero, bool *commit, bool growing_retained);
|
||||||
static edata_t *extent_try_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
static edata_t *extent_try_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool *coalesced, bool growing_retained);
|
ecache_t *ecache, edata_t *edata, bool *coalesced);
|
||||||
static void extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
static void extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool growing_retained);
|
ecache_t *ecache, edata_t *edata);
|
||||||
static edata_t *extent_alloc_retained(tsdn_t *tsdn, pac_t *pac,
|
static edata_t *extent_alloc_retained(tsdn_t *tsdn, pac_t *pac,
|
||||||
ehooks_t *ehooks, edata_t *expand_edata, size_t size, size_t alignment,
|
ehooks_t *ehooks, edata_t *expand_edata, size_t size, size_t alignment,
|
||||||
bool zero, bool *commit);
|
bool zero, bool *commit);
|
||||||
@ -68,7 +68,7 @@ extent_try_delayed_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
|
|
||||||
bool coalesced;
|
bool coalesced;
|
||||||
edata = extent_try_coalesce(tsdn, pac, ehooks, ecache,
|
edata = extent_try_coalesce(tsdn, pac, ehooks, ecache,
|
||||||
edata, &coalesced, false);
|
edata, &coalesced);
|
||||||
emap_update_edata_state(tsdn, pac->emap, edata, ecache->state);
|
emap_update_edata_state(tsdn, pac->emap, edata, ecache->state);
|
||||||
|
|
||||||
if (!coalesced) {
|
if (!coalesced) {
|
||||||
@ -136,7 +136,7 @@ ecache_dalloc(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache,
|
|||||||
edata_addr_set(edata, edata_base_get(edata));
|
edata_addr_set(edata, edata_base_get(edata));
|
||||||
edata_zeroed_set(edata, false);
|
edata_zeroed_set(edata, false);
|
||||||
|
|
||||||
extent_record(tsdn, pac, ehooks, ecache, edata, false);
|
extent_record(tsdn, pac, ehooks, ecache, edata);
|
||||||
}
|
}
|
||||||
|
|
||||||
edata_t *
|
edata_t *
|
||||||
@ -574,8 +574,7 @@ extent_recycle(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache,
|
|||||||
if (*commit && !edata_committed_get(edata)) {
|
if (*commit && !edata_committed_get(edata)) {
|
||||||
if (extent_commit_impl(tsdn, ehooks, edata, 0,
|
if (extent_commit_impl(tsdn, ehooks, edata, 0,
|
||||||
edata_size_get(edata), growing_retained)) {
|
edata_size_get(edata), growing_retained)) {
|
||||||
extent_record(tsdn, pac, ehooks, ecache, edata,
|
extent_record(tsdn, pac, ehooks, ecache, edata);
|
||||||
growing_retained);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,11 +663,11 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
if (result == extent_split_interior_ok) {
|
if (result == extent_split_interior_ok) {
|
||||||
if (lead != NULL) {
|
if (lead != NULL) {
|
||||||
extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
|
extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
|
||||||
lead, true);
|
lead);
|
||||||
}
|
}
|
||||||
if (trail != NULL) {
|
if (trail != NULL) {
|
||||||
extent_record(tsdn, pac, ehooks,
|
extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
|
||||||
&pac->ecache_retained, trail, true);
|
trail);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@ -681,7 +680,7 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
extent_gdump_add(tsdn, to_salvage);
|
extent_gdump_add(tsdn, to_salvage);
|
||||||
}
|
}
|
||||||
extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
|
extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
|
||||||
to_salvage, true);
|
to_salvage);
|
||||||
}
|
}
|
||||||
if (to_leak != NULL) {
|
if (to_leak != NULL) {
|
||||||
extent_deregister_no_gdump_sub(tsdn, pac, to_leak);
|
extent_deregister_no_gdump_sub(tsdn, pac, to_leak);
|
||||||
@ -695,7 +694,7 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
if (extent_commit_impl(tsdn, ehooks, edata, 0,
|
if (extent_commit_impl(tsdn, ehooks, edata, 0,
|
||||||
edata_size_get(edata), true)) {
|
edata_size_get(edata), true)) {
|
||||||
extent_record(tsdn, pac, ehooks,
|
extent_record(tsdn, pac, ehooks,
|
||||||
&pac->ecache_retained, edata, true);
|
&pac->ecache_retained, edata);
|
||||||
goto label_err;
|
goto label_err;
|
||||||
}
|
}
|
||||||
/* A successful commit should return zeroed memory. */
|
/* A successful commit should return zeroed memory. */
|
||||||
@ -793,15 +792,13 @@ extent_alloc_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
extent_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache,
|
extent_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache,
|
||||||
edata_t *inner, edata_t *outer, bool forward, bool growing_retained) {
|
edata_t *inner, edata_t *outer, bool forward) {
|
||||||
extent_assert_can_coalesce(inner, outer);
|
extent_assert_can_coalesce(inner, outer);
|
||||||
eset_remove(&ecache->eset, outer);
|
eset_remove(&ecache->eset, outer);
|
||||||
|
|
||||||
malloc_mutex_unlock(tsdn, &ecache->mtx);
|
|
||||||
bool err = extent_merge_impl(tsdn, pac, ehooks,
|
bool err = extent_merge_impl(tsdn, pac, ehooks,
|
||||||
forward ? inner : outer, forward ? outer : inner, growing_retained);
|
forward ? inner : outer, forward ? outer : inner,
|
||||||
malloc_mutex_lock(tsdn, &ecache->mtx);
|
/* holding_core_locks */ true);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
extent_deactivate_locked(tsdn, pac, ecache, outer);
|
extent_deactivate_locked(tsdn, pac, ecache, outer);
|
||||||
}
|
}
|
||||||
@ -811,8 +808,7 @@ extent_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache,
|
|||||||
|
|
||||||
static edata_t *
|
static edata_t *
|
||||||
extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool *coalesced, bool growing_retained,
|
ecache_t *ecache, edata_t *edata, bool *coalesced) {
|
||||||
bool inactive_only) {
|
|
||||||
/*
|
/*
|
||||||
* We avoid checking / locking inactive neighbors for large size
|
* We avoid checking / locking inactive neighbors for large size
|
||||||
* classes, since they are eagerly coalesced on deallocation which can
|
* classes, since they are eagerly coalesced on deallocation which can
|
||||||
@ -831,7 +827,7 @@ extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
edata, EXTENT_PAI_PAC, ecache->state, /* forward */ true);
|
edata, EXTENT_PAI_PAC, ecache->state, /* forward */ true);
|
||||||
if (next != NULL) {
|
if (next != NULL) {
|
||||||
if (!extent_coalesce(tsdn, pac, ehooks, ecache, edata,
|
if (!extent_coalesce(tsdn, pac, ehooks, ecache, edata,
|
||||||
next, true, growing_retained)) {
|
next, true)) {
|
||||||
if (ecache->delay_coalesce) {
|
if (ecache->delay_coalesce) {
|
||||||
/* Do minimal coalescing. */
|
/* Do minimal coalescing. */
|
||||||
*coalesced = true;
|
*coalesced = true;
|
||||||
@ -846,7 +842,7 @@ extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
edata, EXTENT_PAI_PAC, ecache->state, /* forward */ false);
|
edata, EXTENT_PAI_PAC, ecache->state, /* forward */ false);
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
if (!extent_coalesce(tsdn, pac, ehooks, ecache, edata,
|
if (!extent_coalesce(tsdn, pac, ehooks, ecache, edata,
|
||||||
prev, false, growing_retained)) {
|
prev, false)) {
|
||||||
edata = prev;
|
edata = prev;
|
||||||
if (ecache->delay_coalesce) {
|
if (ecache->delay_coalesce) {
|
||||||
/* Do minimal coalescing. */
|
/* Do minimal coalescing. */
|
||||||
@ -866,16 +862,16 @@ extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
|
|
||||||
static edata_t *
|
static edata_t *
|
||||||
extent_try_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
extent_try_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool *coalesced, bool growing_retained) {
|
ecache_t *ecache, edata_t *edata, bool *coalesced) {
|
||||||
return extent_try_coalesce_impl(tsdn, pac, ehooks, ecache, edata,
|
return extent_try_coalesce_impl(tsdn, pac, ehooks, ecache, edata,
|
||||||
coalesced, growing_retained, false);
|
coalesced);
|
||||||
}
|
}
|
||||||
|
|
||||||
static edata_t *
|
static edata_t *
|
||||||
extent_try_coalesce_large(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
extent_try_coalesce_large(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool *coalesced, bool growing_retained) {
|
ecache_t *ecache, edata_t *edata, bool *coalesced) {
|
||||||
return extent_try_coalesce_impl(tsdn, pac, ehooks, ecache, edata,
|
return extent_try_coalesce_impl(tsdn, pac, ehooks, ecache, edata,
|
||||||
coalesced, growing_retained, true);
|
coalesced);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Purge a single extent to retained / unmapped directly. */
|
/* Purge a single extent to retained / unmapped directly. */
|
||||||
@ -906,7 +902,7 @@ extent_maximally_purge(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
ecache_t *ecache, edata_t *edata, bool growing_retained) {
|
ecache_t *ecache, edata_t *edata) {
|
||||||
assert((ecache->state != extent_state_dirty &&
|
assert((ecache->state != extent_state_dirty &&
|
||||||
ecache->state != extent_state_muzzy) ||
|
ecache->state != extent_state_muzzy) ||
|
||||||
!edata_zeroed_get(edata));
|
!edata_zeroed_get(edata));
|
||||||
@ -917,7 +913,7 @@ extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
|
|
||||||
if (!ecache->delay_coalesce) {
|
if (!ecache->delay_coalesce) {
|
||||||
edata = extent_try_coalesce(tsdn, pac, ehooks, ecache, edata,
|
edata = extent_try_coalesce(tsdn, pac, ehooks, ecache, edata,
|
||||||
NULL, growing_retained);
|
NULL);
|
||||||
} else if (edata_size_get(edata) >= SC_LARGE_MINCLASS) {
|
} else if (edata_size_get(edata) >= SC_LARGE_MINCLASS) {
|
||||||
assert(ecache == &pac->ecache_dirty);
|
assert(ecache == &pac->ecache_dirty);
|
||||||
/* Always coalesce large extents eagerly. */
|
/* Always coalesce large extents eagerly. */
|
||||||
@ -925,7 +921,7 @@ extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
do {
|
do {
|
||||||
assert(edata_state_get(edata) == extent_state_active);
|
assert(edata_state_get(edata) == extent_state_active);
|
||||||
edata = extent_try_coalesce_large(tsdn, pac, ehooks,
|
edata = extent_try_coalesce_large(tsdn, pac, ehooks,
|
||||||
ecache, edata, &coalesced, growing_retained);
|
ecache, edata, &coalesced);
|
||||||
} while (coalesced);
|
} while (coalesced);
|
||||||
if (edata_size_get(edata) >=
|
if (edata_size_get(edata) >=
|
||||||
atomic_load_zu(&pac->oversize_threshold, ATOMIC_RELAXED)
|
atomic_load_zu(&pac->oversize_threshold, ATOMIC_RELAXED)
|
||||||
@ -1020,8 +1016,7 @@ extent_dalloc_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
|||||||
extent_gdump_sub(tsdn, edata);
|
extent_gdump_sub(tsdn, edata);
|
||||||
}
|
}
|
||||||
|
|
||||||
extent_record(tsdn, pac, ehooks, &pac->ecache_retained, edata,
|
extent_record(tsdn, pac, ehooks, &pac->ecache_retained, edata);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1178,11 +1173,17 @@ extent_split_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *edata,
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
extent_merge_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *a,
|
extent_merge_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *a,
|
||||||
edata_t *b, bool growing_retained) {
|
edata_t *b, bool holding_core_locks) {
|
||||||
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
/* Only the expanding path may merge w/o holding ecache locks. */
|
||||||
WITNESS_RANK_CORE, growing_retained ? 1 : 0);
|
if (holding_core_locks) {
|
||||||
assert(edata_base_get(a) < edata_base_get(b));
|
witness_assert_positive_depth_to_rank(
|
||||||
|
tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE);
|
||||||
|
} else {
|
||||||
|
witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn),
|
||||||
|
WITNESS_RANK_CORE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(edata_base_get(a) < edata_base_get(b));
|
||||||
assert(edata_arena_ind_get(a) == edata_arena_ind_get(b));
|
assert(edata_arena_ind_get(a) == edata_arena_ind_get(b));
|
||||||
assert(edata_arena_ind_get(a) == ehooks_ind_get(ehooks));
|
assert(edata_arena_ind_get(a) == ehooks_ind_get(ehooks));
|
||||||
emap_assert_mapped(tsdn, pac->emap, a);
|
emap_assert_mapped(tsdn, pac->emap, a);
|
||||||
@ -1222,7 +1223,8 @@ extent_merge_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *a,
|
|||||||
bool
|
bool
|
||||||
extent_merge_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
extent_merge_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks,
|
||||||
edata_t *a, edata_t *b) {
|
edata_t *a, edata_t *b) {
|
||||||
return extent_merge_impl(tsdn, pac, ehooks, a, b, false);
|
return extent_merge_impl(tsdn, pac, ehooks, a, b,
|
||||||
|
/* holding_core_locks */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
Loading…
Reference in New Issue
Block a user