diff --git a/src/gc-stacks.c b/src/gc-stacks.c index 7af1017cb55d9..eb627ec39d409 100644 --- a/src/gc-stacks.c +++ b/src/gc-stacks.c @@ -203,6 +203,8 @@ void sweep_stack_pools(void) assert(gc_n_threads); for (int i = 0; i < gc_n_threads; i++) { jl_ptls_t ptls2 = gc_all_tls_states[i]; + if (ptls2 == NULL) + continue; // free half of stacks that remain unused since last sweep for (int p = 0; p < JL_N_STACK_POOLS; p++) { @@ -227,6 +229,9 @@ void sweep_stack_pools(void) small_arraylist_free(al); } } + if (jl_atomic_load_relaxed(&ptls2->current_task) == NULL) { + small_arraylist_free(ptls2->heap.free_stacks); + } small_arraylist_t *live_tasks = &ptls2->heap.live_tasks; size_t n = 0; diff --git a/src/gc.c b/src/gc.c index 2b237ca95fe49..9edf863e28216 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1746,6 +1746,19 @@ void gc_free_pages(void) } } +void gc_move_to_global_page_pool(jl_gc_page_stack_t *pgstack) +{ + while (1) { + jl_gc_pagemeta_t *pg = pop_lf_back(pgstack); + if (pg == NULL) { + break; + } + jl_gc_free_page(pg); + jl_atomic_fetch_add_relaxed(&gc_heap_stats.heap_size, -GC_PAGE_SZ); + push_lf_back(&global_page_pool_freed, pg); + } +} + // setup the data-structures for a sweep over all memory pools static void gc_sweep_pool(void) { @@ -3776,7 +3789,8 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection) ptls2->heap.remset->len = 0; } // free empty GC state for threads that have exited - if (ptls2->current_task == NULL) { + if (jl_atomic_load_relaxed(&ptls2->current_task) == NULL && + (ptls->tid < gc_first_tid || ptls2->tid >= gc_first_tid + jl_n_gcthreads)) { jl_thread_heap_t *heap = &ptls2->heap; if (heap->weak_refs.len == 0) small_arraylist_free(&heap->weak_refs); @@ -3787,9 +3801,10 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection) if (heap->last_remset->len == 0) arraylist_free(heap->last_remset); if (ptls2->finalizers.len == 0) - arraylist_free(&ptls->finalizers); + arraylist_free(&ptls2->finalizers); if (ptls2->sweep_objs.len == 0) - arraylist_free(&ptls->sweep_objs); + arraylist_free(&ptls2->sweep_objs); + gc_move_to_global_page_pool(&ptls2->page_metadata_buffered); } } diff --git a/src/threading.c b/src/threading.c index 97b2a247cd202..2eecb59db1f17 100644 --- a/src/threading.c +++ b/src/threading.c @@ -435,6 +435,8 @@ JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void) void jl_task_frame_noreturn(jl_task_t *ct) JL_NOTSAFEPOINT; void scheduler_delete_thread(jl_ptls_t ptls) JL_NOTSAFEPOINT; +void jl_free_thread_gc_state(jl_ptls_t ptls); + static void jl_delete_thread(void *value) JL_NOTSAFEPOINT_ENTER { #ifndef _OS_WINDOWS_ @@ -509,9 +511,10 @@ static void jl_delete_thread(void *value) JL_NOTSAFEPOINT_ENTER pthread_mutex_unlock(&in_signal_lock); #endif free(ptls->bt_data); + small_arraylist_free(&ptls->locks); + ptls->previous_exception = NULL; // allow the page root_task is on to be freed ptls->root_task = NULL; - void jl_free_thread_gc_state(jl_ptls_t ptls); jl_free_thread_gc_state(ptls); // then park in safe-region (void)jl_gc_safe_enter(ptls);