note: can be called on abandoned segments
| 626 | |
| 627 | // note: can be called on abandoned segments |
| 628 | static mi_slice_t* mi_segment_span_free_coalesce(mi_slice_t* slice, mi_segments_tld_t* tld) { |
| 629 | mi_assert_internal(slice != NULL && slice->slice_count > 0 && slice->slice_offset == 0); |
| 630 | mi_segment_t* segment = _mi_ptr_segment(slice); |
| 631 | bool is_abandoned = mi_segment_is_abandoned(segment); |
| 632 | |
| 633 | // for huge pages, just mark as free but don't add to the queues |
| 634 | if (segment->kind == MI_SEGMENT_HUGE) { |
| 635 | mi_assert_internal(segment->used == 1); // decreased right after this call in `mi_segment_page_clear` |
| 636 | slice->xblock_size = 0; // mark as free anyways |
| 637 | // we should mark the last slice `xblock_size=0` now to maintain invariants but we skip it to |
| 638 | // avoid a possible cache miss (and the segment is about to be freed) |
| 639 | return slice; |
| 640 | } |
| 641 | |
| 642 | // otherwise coalesce the span and add to the free span queues |
| 643 | size_t slice_count = slice->slice_count; |
| 644 | mi_slice_t* next = slice + slice->slice_count; |
| 645 | mi_assert_internal(next <= mi_segment_slices_end(segment)); |
| 646 | if (next < mi_segment_slices_end(segment) && next->xblock_size==0) { |
| 647 | // free next block -- remove it from free and merge |
| 648 | mi_assert_internal(next->slice_count > 0 && next->slice_offset==0); |
| 649 | slice_count += next->slice_count; // extend |
| 650 | if (!is_abandoned) { mi_segment_span_remove_from_queue(next, tld); } |
| 651 | } |
| 652 | if (slice > segment->slices) { |
| 653 | mi_slice_t* prev = mi_slice_first(slice - 1); |
| 654 | mi_assert_internal(prev >= segment->slices); |
| 655 | if (prev->xblock_size==0) { |
| 656 | // free previous slice -- remove it from free and merge |
| 657 | mi_assert_internal(prev->slice_count > 0 && prev->slice_offset==0); |
| 658 | slice_count += prev->slice_count; |
| 659 | if (!is_abandoned) { mi_segment_span_remove_from_queue(prev, tld); } |
| 660 | slice = prev; |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | // and add the new free page |
| 665 | mi_segment_span_free(segment, mi_slice_index(slice), slice_count, true, tld); |
| 666 | return slice; |
| 667 | } |
| 668 | |
| 669 | |
| 670 |
no test coverage detected