allocate from an arena with fallback to the OS
| 192 | |
| 193 | // allocate from an arena with fallback to the OS |
| 194 | static mi_decl_noinline void* mi_arena_allocate(int numa_node, size_t size, size_t alignment, bool* commit, bool* large, |
| 195 | bool* is_pinned, bool* is_zero, |
| 196 | mi_arena_id_t req_arena_id, size_t* memid, mi_os_tld_t* tld ) |
| 197 | { |
| 198 | MI_UNUSED_RELEASE(alignment); |
| 199 | mi_assert_internal(alignment <= MI_SEGMENT_ALIGN); |
| 200 | const size_t max_arena = mi_atomic_load_relaxed(&mi_arena_count); |
| 201 | const size_t bcount = mi_block_count_of_size(size); |
| 202 | if mi_likely(max_arena == 0) return NULL; |
| 203 | mi_assert_internal(size <= bcount * MI_ARENA_BLOCK_SIZE); |
| 204 | |
| 205 | size_t arena_index = mi_arena_id_index(req_arena_id); |
| 206 | if (arena_index < MI_MAX_ARENAS) { |
| 207 | // try a specific arena if requested |
| 208 | mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[arena_index]); |
| 209 | if ((arena != NULL) && |
| 210 | (arena->numa_node < 0 || arena->numa_node == numa_node) && // numa local? |
| 211 | (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages |
| 212 | { |
| 213 | void* p = mi_arena_alloc_from(arena, arena_index, bcount, commit, large, is_pinned, is_zero, req_arena_id, memid, tld); |
| 214 | mi_assert_internal((uintptr_t)p % alignment == 0); |
| 215 | if (p != NULL) return p; |
| 216 | } |
| 217 | } |
| 218 | else { |
| 219 | // try numa affine allocation |
| 220 | for (size_t i = 0; i < max_arena; i++) { |
| 221 | mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); |
| 222 | if (arena == NULL) break; // end reached |
| 223 | if ((arena->numa_node < 0 || arena->numa_node == numa_node) && // numa local? |
| 224 | (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages |
| 225 | { |
| 226 | void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_pinned, is_zero, req_arena_id, memid, tld); |
| 227 | mi_assert_internal((uintptr_t)p % alignment == 0); |
| 228 | if (p != NULL) return p; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | // try from another numa node instead.. |
| 233 | for (size_t i = 0; i < max_arena; i++) { |
| 234 | mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); |
| 235 | if (arena == NULL) break; // end reached |
| 236 | if ((arena->numa_node >= 0 && arena->numa_node != numa_node) && // not numa local! |
| 237 | (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages |
| 238 | { |
| 239 | void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_pinned, is_zero, req_arena_id, memid, tld); |
| 240 | mi_assert_internal((uintptr_t)p % alignment == 0); |
| 241 | if (p != NULL) return p; |
| 242 | } |
| 243 | } |
| 244 | } |
| 245 | return NULL; |
| 246 | } |
| 247 | |
| 248 | void* _mi_arena_alloc_aligned(size_t size, size_t alignment, size_t align_offset, bool* commit, bool* large, bool* is_pinned, bool* is_zero, |
| 249 | mi_arena_id_t req_arena_id, size_t* memid, mi_os_tld_t* tld) |
no test coverage detected