Insert the given list of memory page spans in the global cache for small/medium blocks
| 445 | |
| 446 | //! Insert the given list of memory page spans in the global cache for small/medium blocks |
| 447 | static void |
| 448 | _memory_global_cache_insert(span_t* first_span, size_t list_size, size_t page_count) { |
| 449 | assert((list_size == 1) || (first_span->next_span != 0)); |
| 450 | #if MAX_SPAN_CACHE_DIVISOR > 0 |
| 451 | while (1) { |
| 452 | size_t span_class_idx = _span_class_from_page_count(page_count); |
| 453 | void* global_span_ptr = atomic_load_ptr(&_memory_span_cache[span_class_idx]); |
| 454 | if (global_span_ptr != SPAN_LIST_LOCK_TOKEN) { |
| 455 | uintptr_t global_list_size = (uintptr_t)global_span_ptr & ~SPAN_MASK; |
| 456 | span_t* global_span = (span_t*)((void*)((uintptr_t)global_span_ptr & SPAN_MASK)); |
| 457 | |
| 458 | #ifdef GLOBAL_SPAN_CACHE_MULTIPLIER |
| 459 | size_t cache_limit = GLOBAL_SPAN_CACHE_MULTIPLIER * (_memory_max_allocation[span_class_idx] / MAX_SPAN_CACHE_DIVISOR); |
| 460 | if ((global_list_size >= cache_limit) && (global_list_size > MIN_SPAN_CACHE_SIZE)) |
| 461 | break; |
| 462 | #endif |
| 463 | //We only have 16 bits for size of list, avoid overflow |
| 464 | if ((global_list_size + list_size) > 0xFFFF) |
| 465 | break; |
| 466 | |
| 467 | //Use prev_span as skip pointer over this sublist range of spans |
| 468 | first_span->data.list_size = (uint32_t)list_size; |
| 469 | first_span->prev_span = global_span; |
| 470 | |
| 471 | //Insert sublist into global cache |
| 472 | global_list_size += list_size; |
| 473 | void* first_span_ptr = (void*)((uintptr_t)first_span | global_list_size); |
| 474 | if (atomic_cas_ptr(&_memory_span_cache[span_class_idx], first_span_ptr, global_span_ptr)) |
| 475 | return; |
| 476 | } |
| 477 | else { |
| 478 | //Atomic operation failed, yield timeslice and retry |
| 479 | thread_yield(); |
| 480 | atomic_thread_fence_acquire(); |
| 481 | } |
| 482 | } |
| 483 | #endif |
| 484 | //Global cache full, release pages |
| 485 | for (size_t ispan = 0; ispan < list_size; ++ispan) { |
| 486 | assert(first_span); |
| 487 | span_t* next_span = first_span->next_span; |
| 488 | _memory_unmap(first_span, page_count); |
| 489 | first_span = next_span; |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | //! Extract a number of memory page spans from the global cache for small/medium blocks |
| 494 | static span_t* |
no test coverage detected