| 1215 | ----------------------------------------------------------- */ |
| 1216 | |
| 1217 | static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { |
| 1218 | mi_assert_internal(segment->used == segment->abandoned); |
| 1219 | mi_assert_internal(segment->used > 0); |
| 1220 | mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); |
| 1221 | mi_assert_internal(segment->abandoned_visits == 0); |
| 1222 | mi_assert_expensive(mi_segment_is_valid(segment,tld)); |
| 1223 | |
| 1224 | // remove the free pages from the free page queues |
| 1225 | mi_slice_t* slice = &segment->slices[0]; |
| 1226 | const mi_slice_t* end = mi_segment_slices_end(segment); |
| 1227 | while (slice < end) { |
| 1228 | mi_assert_internal(slice->slice_count > 0); |
| 1229 | mi_assert_internal(slice->slice_offset == 0); |
| 1230 | if (slice->xblock_size == 0) { // a free page |
| 1231 | mi_segment_span_remove_from_queue(slice,tld); |
| 1232 | slice->xblock_size = 0; // but keep it free |
| 1233 | } |
| 1234 | slice = slice + slice->slice_count; |
| 1235 | } |
| 1236 | |
| 1237 | // perform delayed decommits |
| 1238 | mi_segment_delayed_decommit(segment, mi_option_is_enabled(mi_option_abandoned_page_decommit) /* force? */, tld->stats); |
| 1239 | |
| 1240 | // all pages in the segment are abandoned; add it to the abandoned list |
| 1241 | _mi_stat_increase(&tld->stats->segments_abandoned, 1); |
| 1242 | mi_segments_track_size(-((long)mi_segment_size(segment)), tld); |
| 1243 | segment->thread_id = 0; |
| 1244 | mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); |
| 1245 | segment->abandoned_visits = 1; // from 0 to 1 to signify it is abandoned |
| 1246 | mi_abandoned_push(segment); |
| 1247 | } |
| 1248 | |
| 1249 | void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) { |
| 1250 | mi_assert(page != NULL); |
no test coverage detected