| 204 | } |
| 205 | |
| 206 | mi_decl_noinline bool _mi_segment_cache_push(void* start, size_t size, size_t memid, const mi_commit_mask_t* commit_mask, const mi_commit_mask_t* decommit_mask, bool is_large, bool is_pinned, mi_os_tld_t* tld) |
| 207 | { |
| 208 | #ifdef MI_CACHE_DISABLE |
| 209 | return false; |
| 210 | #else |
| 211 | |
| 212 | // only for normal segment blocks |
| 213 | if (size != MI_SEGMENT_SIZE || ((uintptr_t)start % MI_SEGMENT_ALIGN) != 0) return false; |
| 214 | |
| 215 | // numa node determines start field |
| 216 | int numa_node = _mi_os_numa_node(NULL); |
| 217 | size_t start_field = 0; |
| 218 | if (numa_node > 0) { |
| 219 | start_field = (MI_CACHE_FIELDS / _mi_os_numa_node_count())*numa_node; |
| 220 | if (start_field >= MI_CACHE_FIELDS) start_field = 0; |
| 221 | } |
| 222 | |
| 223 | // purge expired entries |
| 224 | mi_segment_cache_purge(false /* limit purges to a constant N */, false /* don't force unexpired */, tld); |
| 225 | |
| 226 | // find an available slot |
| 227 | mi_bitmap_index_t bitidx; |
| 228 | bool claimed = _mi_bitmap_try_find_from_claim(cache_inuse, MI_CACHE_FIELDS, start_field, 1, &bitidx); |
| 229 | if (!claimed) return false; |
| 230 | |
| 231 | mi_assert_internal(_mi_bitmap_is_claimed(cache_available, MI_CACHE_FIELDS, 1, bitidx)); |
| 232 | mi_assert_internal(_mi_bitmap_is_claimed(cache_available_large, MI_CACHE_FIELDS, 1, bitidx)); |
| 233 | #if MI_DEBUG>1 |
| 234 | if (is_pinned || is_large) { |
| 235 | mi_assert_internal(mi_commit_mask_is_full(commit_mask)); |
| 236 | } |
| 237 | #endif |
| 238 | |
| 239 | // set the slot |
| 240 | mi_cache_slot_t* slot = &cache[mi_bitmap_index_bit(bitidx)]; |
| 241 | slot->p = start; |
| 242 | slot->memid = memid; |
| 243 | slot->is_pinned = is_pinned; |
| 244 | mi_atomic_storei64_relaxed(&slot->expire,(mi_msecs_t)0); |
| 245 | slot->commit_mask = *commit_mask; |
| 246 | slot->decommit_mask = *decommit_mask; |
| 247 | if (!mi_commit_mask_is_empty(commit_mask) && !is_large && !is_pinned && mi_option_is_enabled(mi_option_allow_decommit)) { |
| 248 | long delay = mi_option_get(mi_option_segment_decommit_delay); |
| 249 | if (delay == 0) { |
| 250 | _mi_abandoned_await_readers(); // wait until safe to decommit |
| 251 | mi_commit_mask_decommit(&slot->commit_mask, start, MI_SEGMENT_SIZE, tld->stats); |
| 252 | mi_commit_mask_create_empty(&slot->decommit_mask); |
| 253 | } |
| 254 | else { |
| 255 | mi_atomic_storei64_release(&slot->expire, _mi_clock_now() + delay); |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | // make it available |
| 260 | _mi_bitmap_unclaim((is_large ? cache_available_large : cache_available), MI_CACHE_FIELDS, 1, bitidx); |
| 261 | return true; |
| 262 | #endif |
| 263 | } |
no test coverage detected