diff --git a/src/arena.c b/src/arena.c index 913a02a9..801475fd 100644 --- a/src/arena.c +++ b/src/arena.c @@ -946,7 +946,9 @@ static bool mi_arena_visit_abandoned_blocks(mi_subproc_t* subproc, int heap_tag, _mi_arena_field_cursor_init(NULL, subproc, ¤t); mi_segment_t* segment; while ((segment = _mi_arena_segment_clear_abandoned_next(¤t, true /* visit all */)) != NULL) { - if (!_mi_segment_visit_blocks(segment, heap_tag, visit_blocks, visitor, arg)) return false; + bool ok = _mi_segment_visit_blocks(segment, heap_tag, visit_blocks, visitor, arg); + _mi_arena_segment_mark_abandoned(segment); + if (!ok) return false; } return true; } diff --git a/test/test-stress.c b/test/test-stress.c index f82b9743..c3afde9b 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -39,6 +39,10 @@ static int ITER = 50; // N full iterations destructing and re-creating a #define STRESS // undefine for leak test +#ifndef NDEBUG +#define HEAP_WALK // walk the heap objects? +#endif + static bool allow_large_objects = true; // allow very large objects? (set to `true` if SCALE>100) static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`? @@ -129,7 +133,7 @@ static void free_items(void* p) { custom_free(p); } -/* +#ifdef HEAP_WALK static bool visit_blocks(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) { (void)(heap); (void)(area); size_t* total = (size_t*)arg; @@ -138,7 +142,7 @@ static bool visit_blocks(const mi_heap_t* heap, const mi_heap_area_t* area, void } return true; } -*/ +#endif static void stress(intptr_t tid) { //bench_start_thread(); @@ -183,9 +187,12 @@ static void stress(intptr_t tid) { data[data_idx] = q; } } + + #ifdef HEAP_WALK // walk the heap - // size_t total = 0; - // mi_heap_visit_blocks(mi_heap_get_default(), true, visit_blocks, &total); + size_t total = 0; + mi_heap_visit_blocks(mi_heap_get_default(), true, visit_blocks, &total); + #endif // free everything that is left for (size_t i = 0; i < retain_top; i++) { @@ -205,6 +212,10 @@ static void test_stress(void) { uintptr_t r = rand(); for (int n = 0; n < ITER; n++) { run_os_threads(THREADS, &stress); + #ifdef HEAP_WALK + size_t total = 0; + mi_abandoned_visit_blocks(mi_subproc_main(), -1, true, visit_blocks, &total); + #endif for (int i = 0; i < TRANSFERS; i++) { if (chance(50, &r) || n + 1 == ITER) { // free all on last run, otherwise free half of the transfers void* p = atomic_exchange_ptr(&transfer[i], NULL);