| 371 | } |
| 372 | |
| 373 | static void mi_segment_os_free(mi_segment_t* segment, mi_segments_tld_t* tld) { |
| 374 | segment->thread_id = 0; |
| 375 | _mi_segment_map_freed_at(segment); |
| 376 | mi_segments_track_size(-((long)mi_segment_size(segment)),tld); |
| 377 | if (MI_SECURE>0) { |
| 378 | // _mi_os_unprotect(segment, mi_segment_size(segment)); // ensure no more guard pages are set |
| 379 | // unprotect the guard pages; we cannot just unprotect the whole segment size as part may be decommitted |
| 380 | size_t os_pagesize = _mi_os_page_size(); |
| 381 | _mi_os_unprotect((uint8_t*)segment + mi_segment_info_size(segment) - os_pagesize, os_pagesize); |
| 382 | uint8_t* end = (uint8_t*)segment + mi_segment_size(segment) - os_pagesize; |
| 383 | _mi_os_unprotect(end, os_pagesize); |
| 384 | } |
| 385 | |
| 386 | // purge delayed decommits now? (no, leave it to the cache) |
| 387 | // mi_segment_delayed_decommit(segment,true,tld->stats); |
| 388 | |
| 389 | // _mi_os_free(segment, mi_segment_size(segment), /*segment->memid,*/ tld->stats); |
| 390 | const size_t size = mi_segment_size(segment); |
| 391 | if (size != MI_SEGMENT_SIZE || segment->mem_align_offset != 0 || segment->kind == MI_SEGMENT_HUGE || // only push regular segments on the cache |
| 392 | !_mi_segment_cache_push(segment, size, segment->memid, &segment->commit_mask, &segment->decommit_mask, segment->mem_is_large, segment->mem_is_pinned, tld->os)) |
| 393 | { |
| 394 | const size_t csize = _mi_commit_mask_committed_size(&segment->commit_mask, size); |
| 395 | if (csize > 0 && !segment->mem_is_pinned) _mi_stat_decrease(&_mi_stats_main.committed, csize); |
| 396 | _mi_abandoned_await_readers(); // wait until safe to free |
| 397 | _mi_arena_free(segment, mi_segment_size(segment), segment->mem_alignment, segment->mem_align_offset, segment->memid, segment->mem_is_pinned /* pretend not committed to not double count decommits */, tld->stats); |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | // called by threads that are terminating |
| 402 | void _mi_segment_thread_collect(mi_segments_tld_t* tld) { |
no test coverage detected