From 49ceb4d018f264bd4757df1ab3173d0760850af1 Mon Sep 17 00:00:00 2001 From: daan Date: Sun, 14 Jul 2019 16:48:53 -0700 Subject: [PATCH] refactor delayed_free code --- include/mimalloc-internal.h | 2 +- src/alloc.c | 14 +++++++++++++- src/page.c | 18 +++++------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index a7f2f66d..3a3f5c4d 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -90,7 +90,7 @@ void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_at void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero); void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero); mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p); -void _mi_free_delayed_block(mi_page_t* page, mi_block_t* block); +bool _mi_free_delayed_block(mi_block_t* block); #if MI_DEBUG>1 bool _mi_page_is_valid(mi_page_t* page); diff --git a/src/alloc.c b/src/alloc.c index 6a5395c7..1c391e64 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -249,8 +249,20 @@ void mi_free(void* p) mi_attr_noexcept } } -void _mi_free_delayed_block(mi_page_t* page, mi_block_t* block) { +bool _mi_free_delayed_block(mi_block_t* block) { + // get segment and page + const mi_segment_t* segment = _mi_ptr_segment(block); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(_mi_thread_id() == segment->thread_id); + mi_page_t* page = _mi_segment_page_of(segment, block); + if (mi_tf_delayed(page->thread_free) == MI_DELAYED_FREEING) { + // we might already start delayed freeing while another thread has not yet + // reset the delayed_freeing flag; in that case don't free it quite yet if + // this is the last block remaining. + if (page->used - page->thread_freed == 1) return false; + } _mi_free_block(page,true,block); + return true; } // Bytes available in a block diff --git a/src/page.c b/src/page.c index 9bc1ab87..fc7c4f01 100644 --- a/src/page.c +++ b/src/page.c @@ -139,8 +139,8 @@ void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay ) { static void mi_page_thread_free_collect(mi_page_t* page) { mi_block_t* head; - mi_thread_free_t tfree = 0; - mi_thread_free_t tfreex = 0; + mi_thread_free_t tfree; + mi_thread_free_t tfreex; do { tfreex = tfree = page->thread_free; head = mi_tf_block(tfree); @@ -258,18 +258,10 @@ void _mi_heap_delayed_free(mi_heap_t* heap) { // and free them all while(block != NULL) { mi_block_t* next = mi_block_nextx(heap->cookie,block); - // get segment and page - const mi_segment_t* segment = _mi_ptr_segment(block); - mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); - mi_assert_internal(_mi_thread_id() == segment->thread_id); - mi_page_t* page = _mi_segment_page_of(segment, block); - if (mi_tf_delayed(page->thread_free) != MI_DELAYED_FREEING) { - // use internal free instead of regular one to keep stats etc correct - _mi_free_delayed_block(page,block); - } - else { + // use internal free instead of regular one to keep stats etc correct + if (!_mi_free_delayed_block(block)) { // we might already start delayed freeing while another thread has not yet - // reset the flag; in that case delay it further :-( + // reset the delayed_freeing flag; in that case delay it further by reinserting. mi_block_t* dfree; do { dfree = (mi_block_t*)heap->thread_delayed_free;