diff --git a/include/mimalloc-types.h b/include/mimalloc-types.h index 9928f12d..5ce8513d 100644 --- a/include/mimalloc-types.h +++ b/include/mimalloc-types.h @@ -405,6 +405,7 @@ typedef struct mi_os_tld_s { // Thread local data struct mi_tld_s { unsigned long long heartbeat; // monotonic heartbeat count + bool recurse; // true if deferred was called; used to prevent infinite recursion. mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) mi_segments_tld_t segments; // segment tld mi_os_tld_t os; // os tld diff --git a/src/heap.c b/src/heap.c index 8465479e..15c5d02a 100644 --- a/src/heap.c +++ b/src/heap.c @@ -110,7 +110,7 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) { if (!mi_heap_is_initialized(heap)) return; _mi_deferred_free(heap, collect > NORMAL); - + // collect (some) abandoned pages if (collect >= NORMAL && !heap->no_reclaim) { if (collect == NORMAL) { diff --git a/src/init.c b/src/init.c index 480960b0..3d9b4842 100644 --- a/src/init.c +++ b/src/init.c @@ -96,7 +96,7 @@ mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty; #define tld_main_stats ((mi_stats_t*)((uint8_t*)&tld_main + offsetof(mi_tld_t,stats))) static mi_tld_t tld_main = { - 0, + 0, false, &_mi_heap_main, { { NULL, NULL }, {NULL ,NULL}, 0, 0, 0, 0, 0, 0, NULL, tld_main_stats }, // segments { 0, tld_main_stats }, // os diff --git a/src/page.c b/src/page.c index f1c96a71..59977f38 100644 --- a/src/page.c +++ b/src/page.c @@ -702,12 +702,14 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { a certain number of allocations. ----------------------------------------------------------- */ -static mi_deferred_free_fun* deferred_free = NULL; +static volatile mi_deferred_free_fun* deferred_free = NULL; void _mi_deferred_free(mi_heap_t* heap, bool force) { heap->tld->heartbeat++; - if (deferred_free != NULL) { + if (deferred_free != NULL && !heap->tld->recurse) { + heap->tld->recurse = true; deferred_free(force, heap->tld->heartbeat); + heap->tld->recurse = false; } }