| 181 | } |
| 182 | |
| 183 | void * |
| 184 | large_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t usize, |
| 185 | size_t alignment, bool zero, tcache_t *tcache, |
| 186 | hook_ralloc_args_t *hook_args) { |
| 187 | edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); |
| 188 | |
| 189 | size_t oldusize = edata_usize_get(edata); |
| 190 | /* The following should have been caught by callers. */ |
| 191 | assert(usize > 0 && usize <= SC_LARGE_MAXCLASS); |
| 192 | /* Both allocation sizes must be large to avoid a move. */ |
| 193 | assert(oldusize >= SC_LARGE_MINCLASS |
| 194 | && usize >= SC_LARGE_MINCLASS); |
| 195 | |
| 196 | /* Try to avoid moving the allocation. */ |
| 197 | if (!large_ralloc_no_move(tsdn, edata, usize, usize, zero)) { |
| 198 | hook_invoke_expand(hook_args->is_realloc |
| 199 | ? hook_expand_realloc : hook_expand_rallocx, ptr, oldusize, |
| 200 | usize, (uintptr_t)ptr, hook_args->args); |
| 201 | return edata_addr_get(edata); |
| 202 | } |
| 203 | |
| 204 | /* |
| 205 | * usize and old size are different enough that we need to use a |
| 206 | * different size class. In that case, fall back to allocating new |
| 207 | * space and copying. |
| 208 | */ |
| 209 | void *ret = large_ralloc_move_helper(tsdn, arena, usize, alignment, |
| 210 | zero); |
| 211 | if (ret == NULL) { |
| 212 | return NULL; |
| 213 | } |
| 214 | |
| 215 | hook_invoke_alloc(hook_args->is_realloc |
| 216 | ? hook_alloc_realloc : hook_alloc_rallocx, ret, (uintptr_t)ret, |
| 217 | hook_args->args); |
| 218 | hook_invoke_dalloc(hook_args->is_realloc |
| 219 | ? hook_dalloc_realloc : hook_dalloc_rallocx, ptr, hook_args->args); |
| 220 | |
| 221 | size_t copysize = (usize < oldusize) ? usize : oldusize; |
| 222 | memcpy(ret, edata_addr_get(edata), copysize); |
| 223 | isdalloct(tsdn, edata_addr_get(edata), oldusize, tcache, NULL, true); |
| 224 | return ret; |
| 225 | } |
| 226 | |
| 227 | /* |
| 228 | * locked indicates whether the arena's large_mtx is currently held. |
no test coverage detected