diff --git a/include/jemalloc/internal/emap.h b/include/jemalloc/internal/emap.h index fcc9fe4c..7835da96 100644 --- a/include/jemalloc/internal/emap.h +++ b/include/jemalloc/internal/emap.h @@ -86,5 +86,9 @@ void emap_split_commit(tsdn_t *tsdn, emap_t *emap, emap_split_prepare_t *split_prepare, edata_t *lead, size_t size_a, szind_t szind_a, bool slab_a, edata_t *trail, size_t size_b, szind_t szind_b, bool slab_b); +void emap_merge_prepare(tsdn_t *tsdn, emap_t *emap, rtree_ctx_t *rtree_ctx, + emap_split_prepare_t *split_prepare, edata_t *lead, edata_t *trail); +void emap_merge_commit(tsdn_t *tsdn, emap_t *emap, + emap_split_prepare_t *split_prepare, edata_t *lead, edata_t *trail); #endif /* JEMALLOC_INTERNAL_EMAP_H */ diff --git a/src/emap.c b/src/emap.c index b79b66af..bde986f0 100644 --- a/src/emap.c +++ b/src/emap.c @@ -236,3 +236,40 @@ emap_split_commit(tsdn_t *tsdn, emap_t *emap, emap_rtree_write_acquired(tsdn, emap, split_prepare->trail_elm_a, split_prepare->trail_elm_b, trail, szind_b, slab_b); } + +void +emap_merge_prepare(tsdn_t *tsdn, emap_t *emap, rtree_ctx_t *rtree_ctx, + emap_split_prepare_t *split_prepare, edata_t *lead, edata_t *trail) { + emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, lead, true, false, + &split_prepare->lead_elm_a, &split_prepare->lead_elm_b); + emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, trail, true, false, + &split_prepare->trail_elm_a, &split_prepare->trail_elm_b); +} + +void +emap_merge_commit(tsdn_t *tsdn, emap_t *emap, + emap_split_prepare_t *split_prepare, edata_t *lead, edata_t *trail) { + if (split_prepare->lead_elm_b != NULL) { + rtree_leaf_elm_write(tsdn, &emap->rtree, + split_prepare->lead_elm_b, NULL, SC_NSIZES, false); + } + + rtree_leaf_elm_t *merged_b; + if (split_prepare->trail_elm_b != NULL) { + rtree_leaf_elm_write(tsdn, &emap->rtree, + split_prepare->trail_elm_a, NULL, SC_NSIZES, false); + merged_b = split_prepare->trail_elm_b; + } else { + merged_b = split_prepare->trail_elm_a; + } + + edata_size_set(lead, edata_size_get(lead) + edata_size_get(trail)); + edata_szind_set(lead, SC_NSIZES); + edata_sn_set(lead, (edata_sn_get(lead) < edata_sn_get(trail)) ? + edata_sn_get(lead) : edata_sn_get(trail)); + edata_zeroed_set(lead, edata_zeroed_get(lead) + && edata_zeroed_get(trail)); + + emap_rtree_write_acquired(tsdn, emap, split_prepare->lead_elm_a, + merged_b, lead, SC_NSIZES, false); +} diff --git a/src/extent.c b/src/extent.c index e8a12574..3db82a70 100644 --- a/src/extent.c +++ b/src/extent.c @@ -1342,33 +1342,11 @@ extent_merge_impl(tsdn_t *tsdn, ehooks_t *ehooks, edata_cache_t *edata_cache, */ rtree_ctx_t rtree_ctx_fallback; rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); - rtree_leaf_elm_t *a_elm_a, *a_elm_b, *b_elm_a, *b_elm_b; - emap_rtree_leaf_elms_lookup(tsdn, &emap_global, rtree_ctx, a, true, - false, &a_elm_a, &a_elm_b); - emap_rtree_leaf_elms_lookup(tsdn, &emap_global, rtree_ctx, b, true, - false, &b_elm_a, &b_elm_b); - + emap_split_prepare_t split_prepare; + emap_merge_prepare(tsdn, &emap_global, rtree_ctx, &split_prepare, a, b); emap_lock_edata2(tsdn, &emap_global, a, b); - if (a_elm_b != NULL) { - rtree_leaf_elm_write(tsdn, &emap_global.rtree, a_elm_b, NULL, - SC_NSIZES, false); - } - if (b_elm_b != NULL) { - rtree_leaf_elm_write(tsdn, &emap_global.rtree, b_elm_a, NULL, - SC_NSIZES, false); - } else { - b_elm_b = b_elm_a; - } - - edata_size_set(a, edata_size_get(a) + edata_size_get(b)); - edata_szind_set(a, SC_NSIZES); - edata_sn_set(a, (edata_sn_get(a) < edata_sn_get(b)) ? - edata_sn_get(a) : edata_sn_get(b)); - edata_zeroed_set(a, edata_zeroed_get(a) && edata_zeroed_get(b)); - - emap_rtree_write_acquired(tsdn, &emap_global, a_elm_a, b_elm_b, a, - SC_NSIZES, false); + emap_merge_commit(tsdn, &emap_global, &split_prepare, a, b); emap_unlock_edata2(tsdn, &emap_global, a, b);