* Tries to find and remove an extent from extents that can be used for the * given allocation request. */
| 889 | * given allocation request. |
| 890 | */ |
| 891 | static extent_t * |
| 892 | extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, |
| 893 | extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, |
| 894 | void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, |
| 895 | bool growing_retained) { |
| 896 | witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), |
| 897 | WITNESS_RANK_CORE, growing_retained ? 1 : 0); |
| 898 | assert(alignment > 0); |
| 899 | if (config_debug && new_addr != NULL) { |
| 900 | /* |
| 901 | * Non-NULL new_addr has two use cases: |
| 902 | * |
| 903 | * 1) Recycle a known-extant extent, e.g. during purging. |
| 904 | * 2) Perform in-place expanding reallocation. |
| 905 | * |
| 906 | * Regardless of use case, new_addr must either refer to a |
| 907 | * non-existing extent, or to the base of an extant extent, |
| 908 | * since only active slabs support interior lookups (which of |
| 909 | * course cannot be recycled). |
| 910 | */ |
| 911 | assert(PAGE_ADDR2BASE(new_addr) == new_addr); |
| 912 | assert(pad == 0); |
| 913 | assert(alignment <= PAGE); |
| 914 | } |
| 915 | |
| 916 | size_t esize = size + pad; |
| 917 | malloc_mutex_lock(tsdn, &extents->mtx); |
| 918 | extent_hooks_assure_initialized(arena, r_extent_hooks); |
| 919 | extent_t *extent; |
| 920 | if (new_addr != NULL) { |
| 921 | extent = extent_lock_from_addr(tsdn, rtree_ctx, new_addr, |
| 922 | false); |
| 923 | if (extent != NULL) { |
| 924 | /* |
| 925 | * We might null-out extent to report an error, but we |
| 926 | * still need to unlock the associated mutex after. |
| 927 | */ |
| 928 | extent_t *unlock_extent = extent; |
| 929 | assert(extent_base_get(extent) == new_addr); |
| 930 | if (extent_arena_get(extent) != arena || |
| 931 | extent_size_get(extent) < esize || |
| 932 | extent_state_get(extent) != |
| 933 | extents_state_get(extents)) { |
| 934 | extent = NULL; |
| 935 | } |
| 936 | extent_unlock(tsdn, unlock_extent); |
| 937 | } |
| 938 | } else { |
| 939 | extent = extents_fit_locked(tsdn, arena, extents, esize, |
| 940 | alignment); |
| 941 | } |
| 942 | if (extent == NULL) { |
| 943 | malloc_mutex_unlock(tsdn, &extents->mtx); |
| 944 | return NULL; |
| 945 | } |
| 946 | |
| 947 | extent_activate_locked(tsdn, arena, extents, extent); |
| 948 | malloc_mutex_unlock(tsdn, &extents->mtx); |
no test coverage detected