| 2081 | #endif |
| 2082 | |
| 2083 | static bool |
| 2084 | extent_merge_impl(tsdn_t *tsdn, arena_t *arena, |
| 2085 | extent_hooks_t **r_extent_hooks, extent_t *a, extent_t *b, |
| 2086 | bool growing_retained) { |
| 2087 | witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), |
| 2088 | WITNESS_RANK_CORE, growing_retained ? 1 : 0); |
| 2089 | |
| 2090 | extent_hooks_assure_initialized(arena, r_extent_hooks); |
| 2091 | |
| 2092 | if ((*r_extent_hooks)->merge == NULL) { |
| 2093 | return true; |
| 2094 | } |
| 2095 | |
| 2096 | bool err; |
| 2097 | if (*r_extent_hooks == &extent_hooks_default) { |
| 2098 | /* Call directly to propagate tsdn. */ |
| 2099 | err = extent_merge_default_impl(extent_base_get(a), |
| 2100 | extent_base_get(b)); |
| 2101 | } else { |
| 2102 | extent_hook_pre_reentrancy(tsdn, arena); |
| 2103 | err = (*r_extent_hooks)->merge(*r_extent_hooks, |
| 2104 | extent_base_get(a), extent_size_get(a), extent_base_get(b), |
| 2105 | extent_size_get(b), extent_committed_get(a), |
| 2106 | arena_ind_get(arena)); |
| 2107 | extent_hook_post_reentrancy(tsdn); |
| 2108 | } |
| 2109 | |
| 2110 | if (err) { |
| 2111 | return true; |
| 2112 | } |
| 2113 | |
| 2114 | /* |
| 2115 | * The rtree writes must happen while all the relevant elements are |
| 2116 | * owned, so the following code uses decomposed helper functions rather |
| 2117 | * than extent_{,de}register() to do things in the right order. |
| 2118 | */ |
| 2119 | rtree_ctx_t rtree_ctx_fallback; |
| 2120 | rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); |
| 2121 | rtree_leaf_elm_t *a_elm_a, *a_elm_b, *b_elm_a, *b_elm_b; |
| 2122 | extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, a, true, false, &a_elm_a, |
| 2123 | &a_elm_b); |
| 2124 | extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, b, true, false, &b_elm_a, |
| 2125 | &b_elm_b); |
| 2126 | |
| 2127 | extent_lock2(tsdn, a, b); |
| 2128 | |
| 2129 | if (a_elm_b != NULL) { |
| 2130 | rtree_leaf_elm_write(tsdn, &extents_rtree, a_elm_b, NULL, |
| 2131 | NSIZES, false); |
| 2132 | } |
| 2133 | if (b_elm_b != NULL) { |
| 2134 | rtree_leaf_elm_write(tsdn, &extents_rtree, b_elm_a, NULL, |
| 2135 | NSIZES, false); |
| 2136 | } else { |
| 2137 | b_elm_b = b_elm_a; |
| 2138 | } |
| 2139 | |
| 2140 | extent_size_set(a, extent_size_get(a) + extent_size_get(b)); |
no test coverage detected