return true if successful
| 568 | |
| 569 | // return true if successful |
| 570 | bool _mi_free_delayed_block(mi_block_t* block) { |
| 571 | // get segment and page |
| 572 | const mi_segment_t* const segment = _mi_ptr_segment(block); |
| 573 | mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); |
| 574 | mi_assert_internal(_mi_thread_id() == segment->thread_id); |
| 575 | mi_page_t* const page = _mi_segment_page_of(segment, block); |
| 576 | |
| 577 | // Clear the no-delayed flag so delayed freeing is used again for this page. |
| 578 | // This must be done before collecting the free lists on this page -- otherwise |
| 579 | // some blocks may end up in the page `thread_free` list with no blocks in the |
| 580 | // heap `thread_delayed_free` list which may cause the page to be never freed! |
| 581 | // (it would only be freed if we happen to scan it in `mi_page_queue_find_free_ex`) |
| 582 | if (!_mi_page_try_use_delayed_free(page, MI_USE_DELAYED_FREE, false /* dont overwrite never delayed */)) { |
| 583 | return false; |
| 584 | } |
| 585 | |
| 586 | // collect all other non-local frees to ensure up-to-date `used` count |
| 587 | _mi_page_free_collect(page, false); |
| 588 | |
| 589 | // and free the block (possibly freeing the page as well since used is updated) |
| 590 | _mi_free_block(page, true, block); |
| 591 | return true; |
| 592 | } |
| 593 | |
| 594 | // Bytes available in a block |
| 595 | mi_decl_noinline static size_t mi_page_usable_aligned_size_of(const mi_segment_t* segment, const mi_page_t* page, const void* p) mi_attr_noexcept { |
no test coverage detected