1*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_preamble.h" 2*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_internal_includes.h" 3*c43cad87SWarner Losh 4*c43cad87SWarner Losh #include "jemalloc/internal/emap.h" 5*c43cad87SWarner Losh 6*c43cad87SWarner Losh enum emap_lock_result_e { 7*c43cad87SWarner Losh emap_lock_result_success, 8*c43cad87SWarner Losh emap_lock_result_failure, 9*c43cad87SWarner Losh emap_lock_result_no_extent 10*c43cad87SWarner Losh }; 11*c43cad87SWarner Losh typedef enum emap_lock_result_e emap_lock_result_t; 12*c43cad87SWarner Losh 13*c43cad87SWarner Losh bool 14*c43cad87SWarner Losh emap_init(emap_t *emap, base_t *base, bool zeroed) { 15*c43cad87SWarner Losh return rtree_new(&emap->rtree, base, zeroed); 16*c43cad87SWarner Losh } 17*c43cad87SWarner Losh 18*c43cad87SWarner Losh void 19*c43cad87SWarner Losh emap_update_edata_state(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 20*c43cad87SWarner Losh extent_state_t state) { 21*c43cad87SWarner Losh witness_assert_positive_depth_to_rank(tsdn_witness_tsdp_get(tsdn), 22*c43cad87SWarner Losh WITNESS_RANK_CORE); 23*c43cad87SWarner Losh 24*c43cad87SWarner Losh edata_state_set(edata, state); 25*c43cad87SWarner Losh 26*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 27*c43cad87SWarner Losh rtree_leaf_elm_t *elm1 = rtree_leaf_elm_lookup(tsdn, &emap->rtree, 28*c43cad87SWarner Losh rtree_ctx, (uintptr_t)edata_base_get(edata), /* dependent */ true, 29*c43cad87SWarner Losh /* init_missing */ false); 30*c43cad87SWarner Losh assert(elm1 != NULL); 31*c43cad87SWarner Losh rtree_leaf_elm_t *elm2 = edata_size_get(edata) == PAGE ? NULL : 32*c43cad87SWarner Losh rtree_leaf_elm_lookup(tsdn, &emap->rtree, rtree_ctx, 33*c43cad87SWarner Losh (uintptr_t)edata_last_get(edata), /* dependent */ true, 34*c43cad87SWarner Losh /* init_missing */ false); 35*c43cad87SWarner Losh 36*c43cad87SWarner Losh rtree_leaf_elm_state_update(tsdn, &emap->rtree, elm1, elm2, state); 37*c43cad87SWarner Losh 38*c43cad87SWarner Losh emap_assert_mapped(tsdn, emap, edata); 39*c43cad87SWarner Losh } 40*c43cad87SWarner Losh 41*c43cad87SWarner Losh static inline edata_t * 42*c43cad87SWarner Losh emap_try_acquire_edata_neighbor_impl(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 43*c43cad87SWarner Losh extent_pai_t pai, extent_state_t expected_state, bool forward, 44*c43cad87SWarner Losh bool expanding) { 45*c43cad87SWarner Losh witness_assert_positive_depth_to_rank(tsdn_witness_tsdp_get(tsdn), 46*c43cad87SWarner Losh WITNESS_RANK_CORE); 47*c43cad87SWarner Losh assert(!edata_guarded_get(edata)); 48*c43cad87SWarner Losh assert(!expanding || forward); 49*c43cad87SWarner Losh assert(!edata_state_in_transition(expected_state)); 50*c43cad87SWarner Losh assert(expected_state == extent_state_dirty || 51*c43cad87SWarner Losh expected_state == extent_state_muzzy || 52*c43cad87SWarner Losh expected_state == extent_state_retained); 53*c43cad87SWarner Losh 54*c43cad87SWarner Losh void *neighbor_addr = forward ? edata_past_get(edata) : 55*c43cad87SWarner Losh edata_before_get(edata); 56*c43cad87SWarner Losh /* 57*c43cad87SWarner Losh * This is subtle; the rtree code asserts that its input pointer is 58*c43cad87SWarner Losh * non-NULL, and this is a useful thing to check. But it's possible 59*c43cad87SWarner Losh * that edata corresponds to an address of (void *)PAGE (in practice, 60*c43cad87SWarner Losh * this has only been observed on FreeBSD when address-space 61*c43cad87SWarner Losh * randomization is on, but it could in principle happen anywhere). In 62*c43cad87SWarner Losh * this case, edata_before_get(edata) is NULL, triggering the assert. 63*c43cad87SWarner Losh */ 64*c43cad87SWarner Losh if (neighbor_addr == NULL) { 65*c43cad87SWarner Losh return NULL; 66*c43cad87SWarner Losh } 67*c43cad87SWarner Losh 68*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 69*c43cad87SWarner Losh rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, &emap->rtree, 70*c43cad87SWarner Losh rtree_ctx, (uintptr_t)neighbor_addr, /* dependent*/ false, 71*c43cad87SWarner Losh /* init_missing */ false); 72*c43cad87SWarner Losh if (elm == NULL) { 73*c43cad87SWarner Losh return NULL; 74*c43cad87SWarner Losh } 75*c43cad87SWarner Losh 76*c43cad87SWarner Losh rtree_contents_t neighbor_contents = rtree_leaf_elm_read(tsdn, 77*c43cad87SWarner Losh &emap->rtree, elm, /* dependent */ true); 78*c43cad87SWarner Losh if (!extent_can_acquire_neighbor(edata, neighbor_contents, pai, 79*c43cad87SWarner Losh expected_state, forward, expanding)) { 80*c43cad87SWarner Losh return NULL; 81*c43cad87SWarner Losh } 82*c43cad87SWarner Losh 83*c43cad87SWarner Losh /* From this point, the neighbor edata can be safely acquired. */ 84*c43cad87SWarner Losh edata_t *neighbor = neighbor_contents.edata; 85*c43cad87SWarner Losh assert(edata_state_get(neighbor) == expected_state); 86*c43cad87SWarner Losh emap_update_edata_state(tsdn, emap, neighbor, extent_state_merging); 87*c43cad87SWarner Losh if (expanding) { 88*c43cad87SWarner Losh extent_assert_can_expand(edata, neighbor); 89*c43cad87SWarner Losh } else { 90*c43cad87SWarner Losh extent_assert_can_coalesce(edata, neighbor); 91*c43cad87SWarner Losh } 92*c43cad87SWarner Losh 93*c43cad87SWarner Losh return neighbor; 94*c43cad87SWarner Losh } 95*c43cad87SWarner Losh 96*c43cad87SWarner Losh edata_t * 97*c43cad87SWarner Losh emap_try_acquire_edata_neighbor(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 98*c43cad87SWarner Losh extent_pai_t pai, extent_state_t expected_state, bool forward) { 99*c43cad87SWarner Losh return emap_try_acquire_edata_neighbor_impl(tsdn, emap, edata, pai, 100*c43cad87SWarner Losh expected_state, forward, /* expand */ false); 101*c43cad87SWarner Losh } 102*c43cad87SWarner Losh 103*c43cad87SWarner Losh edata_t * 104*c43cad87SWarner Losh emap_try_acquire_edata_neighbor_expand(tsdn_t *tsdn, emap_t *emap, 105*c43cad87SWarner Losh edata_t *edata, extent_pai_t pai, extent_state_t expected_state) { 106*c43cad87SWarner Losh /* Try expanding forward. */ 107*c43cad87SWarner Losh return emap_try_acquire_edata_neighbor_impl(tsdn, emap, edata, pai, 108*c43cad87SWarner Losh expected_state, /* forward */ true, /* expand */ true); 109*c43cad87SWarner Losh } 110*c43cad87SWarner Losh 111*c43cad87SWarner Losh void 112*c43cad87SWarner Losh emap_release_edata(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 113*c43cad87SWarner Losh extent_state_t new_state) { 114*c43cad87SWarner Losh assert(emap_edata_in_transition(tsdn, emap, edata)); 115*c43cad87SWarner Losh assert(emap_edata_is_acquired(tsdn, emap, edata)); 116*c43cad87SWarner Losh 117*c43cad87SWarner Losh emap_update_edata_state(tsdn, emap, edata, new_state); 118*c43cad87SWarner Losh } 119*c43cad87SWarner Losh 120*c43cad87SWarner Losh static bool 121*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn_t *tsdn, emap_t *emap, rtree_ctx_t *rtree_ctx, 122*c43cad87SWarner Losh const edata_t *edata, bool dependent, bool init_missing, 123*c43cad87SWarner Losh rtree_leaf_elm_t **r_elm_a, rtree_leaf_elm_t **r_elm_b) { 124*c43cad87SWarner Losh *r_elm_a = rtree_leaf_elm_lookup(tsdn, &emap->rtree, rtree_ctx, 125*c43cad87SWarner Losh (uintptr_t)edata_base_get(edata), dependent, init_missing); 126*c43cad87SWarner Losh if (!dependent && *r_elm_a == NULL) { 127*c43cad87SWarner Losh return true; 128*c43cad87SWarner Losh } 129*c43cad87SWarner Losh assert(*r_elm_a != NULL); 130*c43cad87SWarner Losh 131*c43cad87SWarner Losh *r_elm_b = rtree_leaf_elm_lookup(tsdn, &emap->rtree, rtree_ctx, 132*c43cad87SWarner Losh (uintptr_t)edata_last_get(edata), dependent, init_missing); 133*c43cad87SWarner Losh if (!dependent && *r_elm_b == NULL) { 134*c43cad87SWarner Losh return true; 135*c43cad87SWarner Losh } 136*c43cad87SWarner Losh assert(*r_elm_b != NULL); 137*c43cad87SWarner Losh 138*c43cad87SWarner Losh return false; 139*c43cad87SWarner Losh } 140*c43cad87SWarner Losh 141*c43cad87SWarner Losh static void 142*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn_t *tsdn, emap_t *emap, rtree_leaf_elm_t *elm_a, 143*c43cad87SWarner Losh rtree_leaf_elm_t *elm_b, edata_t *edata, szind_t szind, bool slab) { 144*c43cad87SWarner Losh rtree_contents_t contents; 145*c43cad87SWarner Losh contents.edata = edata; 146*c43cad87SWarner Losh contents.metadata.szind = szind; 147*c43cad87SWarner Losh contents.metadata.slab = slab; 148*c43cad87SWarner Losh contents.metadata.is_head = (edata == NULL) ? false : 149*c43cad87SWarner Losh edata_is_head_get(edata); 150*c43cad87SWarner Losh contents.metadata.state = (edata == NULL) ? 0 : edata_state_get(edata); 151*c43cad87SWarner Losh rtree_leaf_elm_write(tsdn, &emap->rtree, elm_a, contents); 152*c43cad87SWarner Losh if (elm_b != NULL) { 153*c43cad87SWarner Losh rtree_leaf_elm_write(tsdn, &emap->rtree, elm_b, contents); 154*c43cad87SWarner Losh } 155*c43cad87SWarner Losh } 156*c43cad87SWarner Losh 157*c43cad87SWarner Losh bool 158*c43cad87SWarner Losh emap_register_boundary(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 159*c43cad87SWarner Losh szind_t szind, bool slab) { 160*c43cad87SWarner Losh assert(edata_state_get(edata) == extent_state_active); 161*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 162*c43cad87SWarner Losh 163*c43cad87SWarner Losh rtree_leaf_elm_t *elm_a, *elm_b; 164*c43cad87SWarner Losh bool err = emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, edata, 165*c43cad87SWarner Losh false, true, &elm_a, &elm_b); 166*c43cad87SWarner Losh if (err) { 167*c43cad87SWarner Losh return true; 168*c43cad87SWarner Losh } 169*c43cad87SWarner Losh assert(rtree_leaf_elm_read(tsdn, &emap->rtree, elm_a, 170*c43cad87SWarner Losh /* dependent */ false).edata == NULL); 171*c43cad87SWarner Losh assert(rtree_leaf_elm_read(tsdn, &emap->rtree, elm_b, 172*c43cad87SWarner Losh /* dependent */ false).edata == NULL); 173*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn, emap, elm_a, elm_b, edata, szind, slab); 174*c43cad87SWarner Losh return false; 175*c43cad87SWarner Losh } 176*c43cad87SWarner Losh 177*c43cad87SWarner Losh /* Invoked *after* emap_register_boundary. */ 178*c43cad87SWarner Losh void 179*c43cad87SWarner Losh emap_register_interior(tsdn_t *tsdn, emap_t *emap, edata_t *edata, 180*c43cad87SWarner Losh szind_t szind) { 181*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 182*c43cad87SWarner Losh 183*c43cad87SWarner Losh assert(edata_slab_get(edata)); 184*c43cad87SWarner Losh assert(edata_state_get(edata) == extent_state_active); 185*c43cad87SWarner Losh 186*c43cad87SWarner Losh if (config_debug) { 187*c43cad87SWarner Losh /* Making sure the boundary is registered already. */ 188*c43cad87SWarner Losh rtree_leaf_elm_t *elm_a, *elm_b; 189*c43cad87SWarner Losh bool err = emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, 190*c43cad87SWarner Losh edata, /* dependent */ true, /* init_missing */ false, 191*c43cad87SWarner Losh &elm_a, &elm_b); 192*c43cad87SWarner Losh assert(!err); 193*c43cad87SWarner Losh rtree_contents_t contents_a, contents_b; 194*c43cad87SWarner Losh contents_a = rtree_leaf_elm_read(tsdn, &emap->rtree, elm_a, 195*c43cad87SWarner Losh /* dependent */ true); 196*c43cad87SWarner Losh contents_b = rtree_leaf_elm_read(tsdn, &emap->rtree, elm_b, 197*c43cad87SWarner Losh /* dependent */ true); 198*c43cad87SWarner Losh assert(contents_a.edata == edata && contents_b.edata == edata); 199*c43cad87SWarner Losh assert(contents_a.metadata.slab && contents_b.metadata.slab); 200*c43cad87SWarner Losh } 201*c43cad87SWarner Losh 202*c43cad87SWarner Losh rtree_contents_t contents; 203*c43cad87SWarner Losh contents.edata = edata; 204*c43cad87SWarner Losh contents.metadata.szind = szind; 205*c43cad87SWarner Losh contents.metadata.slab = true; 206*c43cad87SWarner Losh contents.metadata.state = extent_state_active; 207*c43cad87SWarner Losh contents.metadata.is_head = false; /* Not allowed to access. */ 208*c43cad87SWarner Losh 209*c43cad87SWarner Losh assert(edata_size_get(edata) > (2 << LG_PAGE)); 210*c43cad87SWarner Losh rtree_write_range(tsdn, &emap->rtree, rtree_ctx, 211*c43cad87SWarner Losh (uintptr_t)edata_base_get(edata) + PAGE, 212*c43cad87SWarner Losh (uintptr_t)edata_last_get(edata) - PAGE, contents); 213*c43cad87SWarner Losh } 214*c43cad87SWarner Losh 215*c43cad87SWarner Losh void 216*c43cad87SWarner Losh emap_deregister_boundary(tsdn_t *tsdn, emap_t *emap, edata_t *edata) { 217*c43cad87SWarner Losh /* 218*c43cad87SWarner Losh * The edata must be either in an acquired state, or protected by state 219*c43cad87SWarner Losh * based locks. 220*c43cad87SWarner Losh */ 221*c43cad87SWarner Losh if (!emap_edata_is_acquired(tsdn, emap, edata)) { 222*c43cad87SWarner Losh witness_assert_positive_depth_to_rank( 223*c43cad87SWarner Losh tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE); 224*c43cad87SWarner Losh } 225*c43cad87SWarner Losh 226*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 227*c43cad87SWarner Losh rtree_leaf_elm_t *elm_a, *elm_b; 228*c43cad87SWarner Losh 229*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, edata, 230*c43cad87SWarner Losh true, false, &elm_a, &elm_b); 231*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn, emap, elm_a, elm_b, NULL, SC_NSIZES, 232*c43cad87SWarner Losh false); 233*c43cad87SWarner Losh } 234*c43cad87SWarner Losh 235*c43cad87SWarner Losh void 236*c43cad87SWarner Losh emap_deregister_interior(tsdn_t *tsdn, emap_t *emap, edata_t *edata) { 237*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 238*c43cad87SWarner Losh 239*c43cad87SWarner Losh assert(edata_slab_get(edata)); 240*c43cad87SWarner Losh if (edata_size_get(edata) > (2 << LG_PAGE)) { 241*c43cad87SWarner Losh rtree_clear_range(tsdn, &emap->rtree, rtree_ctx, 242*c43cad87SWarner Losh (uintptr_t)edata_base_get(edata) + PAGE, 243*c43cad87SWarner Losh (uintptr_t)edata_last_get(edata) - PAGE); 244*c43cad87SWarner Losh } 245*c43cad87SWarner Losh } 246*c43cad87SWarner Losh 247*c43cad87SWarner Losh void 248*c43cad87SWarner Losh emap_remap(tsdn_t *tsdn, emap_t *emap, edata_t *edata, szind_t szind, 249*c43cad87SWarner Losh bool slab) { 250*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 251*c43cad87SWarner Losh 252*c43cad87SWarner Losh if (szind != SC_NSIZES) { 253*c43cad87SWarner Losh rtree_contents_t contents; 254*c43cad87SWarner Losh contents.edata = edata; 255*c43cad87SWarner Losh contents.metadata.szind = szind; 256*c43cad87SWarner Losh contents.metadata.slab = slab; 257*c43cad87SWarner Losh contents.metadata.is_head = edata_is_head_get(edata); 258*c43cad87SWarner Losh contents.metadata.state = edata_state_get(edata); 259*c43cad87SWarner Losh 260*c43cad87SWarner Losh rtree_write(tsdn, &emap->rtree, rtree_ctx, 261*c43cad87SWarner Losh (uintptr_t)edata_addr_get(edata), contents); 262*c43cad87SWarner Losh /* 263*c43cad87SWarner Losh * Recall that this is called only for active->inactive and 264*c43cad87SWarner Losh * inactive->active transitions (since only active extents have 265*c43cad87SWarner Losh * meaningful values for szind and slab). Active, non-slab 266*c43cad87SWarner Losh * extents only need to handle lookups at their head (on 267*c43cad87SWarner Losh * deallocation), so we don't bother filling in the end 268*c43cad87SWarner Losh * boundary. 269*c43cad87SWarner Losh * 270*c43cad87SWarner Losh * For slab extents, we do the end-mapping change. This still 271*c43cad87SWarner Losh * leaves the interior unmodified; an emap_register_interior 272*c43cad87SWarner Losh * call is coming in those cases, though. 273*c43cad87SWarner Losh */ 274*c43cad87SWarner Losh if (slab && edata_size_get(edata) > PAGE) { 275*c43cad87SWarner Losh uintptr_t key = (uintptr_t)edata_past_get(edata) 276*c43cad87SWarner Losh - (uintptr_t)PAGE; 277*c43cad87SWarner Losh rtree_write(tsdn, &emap->rtree, rtree_ctx, key, 278*c43cad87SWarner Losh contents); 279*c43cad87SWarner Losh } 280*c43cad87SWarner Losh } 281*c43cad87SWarner Losh } 282*c43cad87SWarner Losh 283*c43cad87SWarner Losh bool 284*c43cad87SWarner Losh emap_split_prepare(tsdn_t *tsdn, emap_t *emap, emap_prepare_t *prepare, 285*c43cad87SWarner Losh edata_t *edata, size_t size_a, edata_t *trail, size_t size_b) { 286*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 287*c43cad87SWarner Losh 288*c43cad87SWarner Losh /* 289*c43cad87SWarner Losh * We use incorrect constants for things like arena ind, zero, ranged, 290*c43cad87SWarner Losh * and commit state, and head status. This is a fake edata_t, used to 291*c43cad87SWarner Losh * facilitate a lookup. 292*c43cad87SWarner Losh */ 293*c43cad87SWarner Losh edata_t lead = {0}; 294*c43cad87SWarner Losh edata_init(&lead, 0U, edata_addr_get(edata), size_a, false, 0, 0, 295*c43cad87SWarner Losh extent_state_active, false, false, EXTENT_PAI_PAC, EXTENT_NOT_HEAD); 296*c43cad87SWarner Losh 297*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, &lead, false, true, 298*c43cad87SWarner Losh &prepare->lead_elm_a, &prepare->lead_elm_b); 299*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, trail, false, true, 300*c43cad87SWarner Losh &prepare->trail_elm_a, &prepare->trail_elm_b); 301*c43cad87SWarner Losh 302*c43cad87SWarner Losh if (prepare->lead_elm_a == NULL || prepare->lead_elm_b == NULL 303*c43cad87SWarner Losh || prepare->trail_elm_a == NULL || prepare->trail_elm_b == NULL) { 304*c43cad87SWarner Losh return true; 305*c43cad87SWarner Losh } 306*c43cad87SWarner Losh return false; 307*c43cad87SWarner Losh } 308*c43cad87SWarner Losh 309*c43cad87SWarner Losh void 310*c43cad87SWarner Losh emap_split_commit(tsdn_t *tsdn, emap_t *emap, emap_prepare_t *prepare, 311*c43cad87SWarner Losh edata_t *lead, size_t size_a, edata_t *trail, size_t size_b) { 312*c43cad87SWarner Losh /* 313*c43cad87SWarner Losh * We should think about not writing to the lead leaf element. We can 314*c43cad87SWarner Losh * get into situations where a racing realloc-like call can disagree 315*c43cad87SWarner Losh * with a size lookup request. I think it's fine to declare that these 316*c43cad87SWarner Losh * situations are race bugs, but there's an argument to be made that for 317*c43cad87SWarner Losh * things like xallocx, a size lookup call should return either the old 318*c43cad87SWarner Losh * size or the new size, but not anything else. 319*c43cad87SWarner Losh */ 320*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn, emap, prepare->lead_elm_a, 321*c43cad87SWarner Losh prepare->lead_elm_b, lead, SC_NSIZES, /* slab */ false); 322*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn, emap, prepare->trail_elm_a, 323*c43cad87SWarner Losh prepare->trail_elm_b, trail, SC_NSIZES, /* slab */ false); 324*c43cad87SWarner Losh } 325*c43cad87SWarner Losh 326*c43cad87SWarner Losh void 327*c43cad87SWarner Losh emap_merge_prepare(tsdn_t *tsdn, emap_t *emap, emap_prepare_t *prepare, 328*c43cad87SWarner Losh edata_t *lead, edata_t *trail) { 329*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 330*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, lead, true, false, 331*c43cad87SWarner Losh &prepare->lead_elm_a, &prepare->lead_elm_b); 332*c43cad87SWarner Losh emap_rtree_leaf_elms_lookup(tsdn, emap, rtree_ctx, trail, true, false, 333*c43cad87SWarner Losh &prepare->trail_elm_a, &prepare->trail_elm_b); 334*c43cad87SWarner Losh } 335*c43cad87SWarner Losh 336*c43cad87SWarner Losh void 337*c43cad87SWarner Losh emap_merge_commit(tsdn_t *tsdn, emap_t *emap, emap_prepare_t *prepare, 338*c43cad87SWarner Losh edata_t *lead, edata_t *trail) { 339*c43cad87SWarner Losh rtree_contents_t clear_contents; 340*c43cad87SWarner Losh clear_contents.edata = NULL; 341*c43cad87SWarner Losh clear_contents.metadata.szind = SC_NSIZES; 342*c43cad87SWarner Losh clear_contents.metadata.slab = false; 343*c43cad87SWarner Losh clear_contents.metadata.is_head = false; 344*c43cad87SWarner Losh clear_contents.metadata.state = (extent_state_t)0; 345*c43cad87SWarner Losh 346*c43cad87SWarner Losh if (prepare->lead_elm_b != NULL) { 347*c43cad87SWarner Losh rtree_leaf_elm_write(tsdn, &emap->rtree, 348*c43cad87SWarner Losh prepare->lead_elm_b, clear_contents); 349*c43cad87SWarner Losh } 350*c43cad87SWarner Losh 351*c43cad87SWarner Losh rtree_leaf_elm_t *merged_b; 352*c43cad87SWarner Losh if (prepare->trail_elm_b != NULL) { 353*c43cad87SWarner Losh rtree_leaf_elm_write(tsdn, &emap->rtree, 354*c43cad87SWarner Losh prepare->trail_elm_a, clear_contents); 355*c43cad87SWarner Losh merged_b = prepare->trail_elm_b; 356*c43cad87SWarner Losh } else { 357*c43cad87SWarner Losh merged_b = prepare->trail_elm_a; 358*c43cad87SWarner Losh } 359*c43cad87SWarner Losh 360*c43cad87SWarner Losh emap_rtree_write_acquired(tsdn, emap, prepare->lead_elm_a, merged_b, 361*c43cad87SWarner Losh lead, SC_NSIZES, false); 362*c43cad87SWarner Losh } 363*c43cad87SWarner Losh 364*c43cad87SWarner Losh void 365*c43cad87SWarner Losh emap_do_assert_mapped(tsdn_t *tsdn, emap_t *emap, edata_t *edata) { 366*c43cad87SWarner Losh EMAP_DECLARE_RTREE_CTX; 367*c43cad87SWarner Losh 368*c43cad87SWarner Losh rtree_contents_t contents = rtree_read(tsdn, &emap->rtree, rtree_ctx, 369*c43cad87SWarner Losh (uintptr_t)edata_base_get(edata)); 370*c43cad87SWarner Losh assert(contents.edata == edata); 371*c43cad87SWarner Losh assert(contents.metadata.is_head == edata_is_head_get(edata)); 372*c43cad87SWarner Losh assert(contents.metadata.state == edata_state_get(edata)); 373*c43cad87SWarner Losh } 374*c43cad87SWarner Losh 375*c43cad87SWarner Losh void 376*c43cad87SWarner Losh emap_do_assert_not_mapped(tsdn_t *tsdn, emap_t *emap, edata_t *edata) { 377*c43cad87SWarner Losh emap_full_alloc_ctx_t context1 = {0}; 378*c43cad87SWarner Losh emap_full_alloc_ctx_try_lookup(tsdn, emap, edata_base_get(edata), 379*c43cad87SWarner Losh &context1); 380*c43cad87SWarner Losh assert(context1.edata == NULL); 381*c43cad87SWarner Losh 382*c43cad87SWarner Losh emap_full_alloc_ctx_t context2 = {0}; 383*c43cad87SWarner Losh emap_full_alloc_ctx_try_lookup(tsdn, emap, edata_last_get(edata), 384*c43cad87SWarner Losh &context2); 385*c43cad87SWarner Losh assert(context2.edata == NULL); 386*c43cad87SWarner Losh } 387