note: can be called on abandoned segments
| 579 | |
| 580 | // note: can be called on abandoned segments |
| 581 | static void mi_segment_span_free(mi_segment_t* segment, size_t slice_index, size_t slice_count, bool allow_decommit, mi_segments_tld_t* tld) { |
| 582 | mi_assert_internal(slice_index < segment->slice_entries); |
| 583 | mi_span_queue_t* sq = (segment->kind == MI_SEGMENT_HUGE || mi_segment_is_abandoned(segment) |
| 584 | ? NULL : mi_span_queue_for(slice_count,tld)); |
| 585 | if (slice_count==0) slice_count = 1; |
| 586 | mi_assert_internal(slice_index + slice_count - 1 < segment->slice_entries); |
| 587 | |
| 588 | // set first and last slice (the intermediates can be undetermined) |
| 589 | mi_slice_t* slice = &segment->slices[slice_index]; |
| 590 | slice->slice_count = (uint32_t)slice_count; |
| 591 | mi_assert_internal(slice->slice_count == slice_count); // no overflow? |
| 592 | slice->slice_offset = 0; |
| 593 | if (slice_count > 1) { |
| 594 | mi_slice_t* last = &segment->slices[slice_index + slice_count - 1]; |
| 595 | last->slice_count = 0; |
| 596 | last->slice_offset = (uint32_t)(sizeof(mi_page_t)*(slice_count - 1)); |
| 597 | last->xblock_size = 0; |
| 598 | } |
| 599 | |
| 600 | // perhaps decommit |
| 601 | if (allow_decommit) { |
| 602 | mi_segment_perhaps_decommit(segment, mi_slice_start(slice), slice_count * MI_SEGMENT_SLICE_SIZE, tld->stats); |
| 603 | } |
| 604 | |
| 605 | // and push it on the free page queue (if it was not a huge page) |
| 606 | if (sq != NULL) mi_span_queue_push( sq, slice ); |
| 607 | else slice->xblock_size = 0; // mark huge page as free anyways |
| 608 | } |
| 609 | |
| 610 | /* |
| 611 | // called from reclaim to add existing free spans |
no test coverage detected