* Accepts the extent to split, and the characteristics of each side of the * split. The 'a' parameters go with the 'lead' of the resulting pair of * extents (the lower addressed portion of the split), and the 'b' parameters go * with the trail (the higher addressed portion). This makes 'extent' the lead, * and returns the trail (except in case of error). */
| 1971 | * and returns the trail (except in case of error). |
| 1972 | */ |
| 1973 | static extent_t * |
| 1974 | extent_split_impl(tsdn_t *tsdn, arena_t *arena, |
| 1975 | extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, |
| 1976 | szind_t szind_a, bool slab_a, size_t size_b, szind_t szind_b, bool slab_b, |
| 1977 | bool growing_retained) { |
| 1978 | assert(extent_size_get(extent) == size_a + size_b); |
| 1979 | witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), |
| 1980 | WITNESS_RANK_CORE, growing_retained ? 1 : 0); |
| 1981 | |
| 1982 | extent_hooks_assure_initialized(arena, r_extent_hooks); |
| 1983 | |
| 1984 | if ((*r_extent_hooks)->split == NULL) { |
| 1985 | return NULL; |
| 1986 | } |
| 1987 | |
| 1988 | extent_t *trail = extent_alloc(tsdn, arena); |
| 1989 | if (trail == NULL) { |
| 1990 | goto label_error_a; |
| 1991 | } |
| 1992 | |
| 1993 | extent_init(trail, arena, (void *)((uintptr_t)extent_base_get(extent) + |
| 1994 | size_a), size_b, slab_b, szind_b, extent_sn_get(extent), |
| 1995 | extent_state_get(extent), extent_zeroed_get(extent), |
| 1996 | extent_committed_get(extent), extent_dumpable_get(extent)); |
| 1997 | |
| 1998 | rtree_ctx_t rtree_ctx_fallback; |
| 1999 | rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); |
| 2000 | rtree_leaf_elm_t *lead_elm_a, *lead_elm_b; |
| 2001 | { |
| 2002 | extent_t lead; |
| 2003 | |
| 2004 | extent_init(&lead, arena, extent_addr_get(extent), size_a, |
| 2005 | slab_a, szind_a, extent_sn_get(extent), |
| 2006 | extent_state_get(extent), extent_zeroed_get(extent), |
| 2007 | extent_committed_get(extent), extent_dumpable_get(extent)); |
| 2008 | |
| 2009 | extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, &lead, false, |
| 2010 | true, &lead_elm_a, &lead_elm_b); |
| 2011 | } |
| 2012 | rtree_leaf_elm_t *trail_elm_a, *trail_elm_b; |
| 2013 | extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, trail, false, true, |
| 2014 | &trail_elm_a, &trail_elm_b); |
| 2015 | |
| 2016 | if (lead_elm_a == NULL || lead_elm_b == NULL || trail_elm_a == NULL |
| 2017 | || trail_elm_b == NULL) { |
| 2018 | goto label_error_b; |
| 2019 | } |
| 2020 | |
| 2021 | extent_lock2(tsdn, extent, trail); |
| 2022 | |
| 2023 | if (*r_extent_hooks != &extent_hooks_default) { |
| 2024 | extent_hook_pre_reentrancy(tsdn, arena); |
| 2025 | } |
| 2026 | bool err = (*r_extent_hooks)->split(*r_extent_hooks, extent_base_get(extent), |
| 2027 | size_a + size_b, size_a, size_b, extent_committed_get(extent), |
| 2028 | arena_ind_get(arena)); |
| 2029 | if (*r_extent_hooks != &extent_hooks_default) { |
| 2030 | extent_hook_post_reentrancy(tsdn); |
no test coverage detected