diff --git a/src/heap.c b/src/heap.c index 9396871..b7f93b8 100644 --- a/src/heap.c +++ b/src/heap.c @@ -123,7 +123,7 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) if (collect == ABANDON) { for (mi_page_t* page = heap->pages[MI_BIN_FULL].first; page != NULL; page = page->next) { _mi_page_use_delayed_free(page, false); // set thread_free.delayed to MI_NO_DELAYED_FREE - } + } } // free thread delayed blocks. diff --git a/src/page-queue.c b/src/page-queue.c index 8817d99..ebe858b 100644 --- a/src/page-queue.c +++ b/src/page-queue.c @@ -293,7 +293,7 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro mi_assert_expensive(mi_page_queue_contains(from, page)); mi_assert_expensive(!mi_page_queue_contains(to, page)); mi_assert_internal(page->block_size == to->block_size || - (page->block_size > MI_LARGE_SIZE_MAX && mi_page_queue_is_huge(to)) || + (page->block_size > MI_LARGE_SIZE_MAX && (mi_page_queue_is_huge(to) || mi_page_queue_is_full(to))) || (page->block_size == from->block_size && mi_page_queue_is_full(to))); if (page->prev != NULL) page->prev->next = page->next; diff --git a/src/page.c b/src/page.c index 04464fc..1d5f77a 100644 --- a/src/page.c +++ b/src/page.c @@ -542,6 +542,7 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi mi_assert(mi_page_immediate_available(page)); } + /* ----------------------------------------------------------- Find pages with free blocks -------------------------------------------------------------*/ @@ -618,7 +619,6 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p // Find a page with free blocks of `size`. static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { - _mi_heap_delayed_free(heap); mi_page_queue_t* pq = mi_page_queue(heap,size); mi_page_t* page = pq->first; if (page != NULL) { @@ -674,7 +674,7 @@ static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) { mi_assert_internal(mi_page_immediate_available(page)); mi_assert_internal(page->block_size == block_size); mi_heap_stat_increase( heap, huge, block_size); - } + } return page; } @@ -694,6 +694,9 @@ void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept // call potential deferred free routines _mi_deferred_free(heap, false); + // free delayed frees from other threads + _mi_heap_delayed_free(heap); + // huge allocation? mi_page_t* page; if (mi_unlikely(size > MI_LARGE_SIZE_MAX)) { @@ -714,5 +717,10 @@ void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_assert_internal(page->block_size >= size); // and try again, this time succeeding! (i.e. this should never recurse) - return _mi_page_malloc(heap, page, size); + void* p = _mi_page_malloc(heap, page, size); + if (page->used == page->reserved) { + // needed for huge pages to free reliably from other threads. + mi_page_to_full(page,mi_page_queue_of(page)); + } + return p; }