note: can be called on abandoned pages
| 983 | |
| 984 | // note: can be called on abandoned pages |
| 985 | static mi_slice_t* mi_segment_page_clear(mi_page_t* page, mi_segments_tld_t* tld) { |
| 986 | mi_assert_internal(page->xblock_size > 0); |
| 987 | mi_assert_internal(mi_page_all_free(page)); |
| 988 | mi_segment_t* segment = _mi_ptr_segment(page); |
| 989 | mi_assert_internal(segment->used > 0); |
| 990 | |
| 991 | size_t inuse = page->capacity * mi_page_block_size(page); |
| 992 | _mi_stat_decrease(&tld->stats->page_committed, inuse); |
| 993 | _mi_stat_decrease(&tld->stats->pages, 1); |
| 994 | |
| 995 | // reset the page memory to reduce memory pressure? |
| 996 | if (!segment->mem_is_pinned && !page->is_reset && mi_option_is_enabled(mi_option_page_reset)) { |
| 997 | size_t psize; |
| 998 | uint8_t* start = _mi_page_start(segment, page, &psize); |
| 999 | page->is_reset = true; |
| 1000 | _mi_os_reset(start, psize, tld->stats); |
| 1001 | } |
| 1002 | |
| 1003 | // zero the page data, but not the segment fields |
| 1004 | page->is_zero_init = false; |
| 1005 | ptrdiff_t ofs = offsetof(mi_page_t, capacity); |
| 1006 | memset((uint8_t*)page + ofs, 0, sizeof(*page) - ofs); |
| 1007 | page->xblock_size = 1; |
| 1008 | |
| 1009 | // and free it |
| 1010 | mi_slice_t* slice = mi_segment_span_free_coalesce(mi_page_to_slice(page), tld); |
| 1011 | segment->used--; |
| 1012 | // cannot assert segment valid as it is called during reclaim |
| 1013 | // mi_assert_expensive(mi_segment_is_valid(segment, tld)); |
| 1014 | return slice; |
| 1015 | } |
| 1016 | |
| 1017 | void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) |
| 1018 | { |
no test coverage detected