From 5f234f0fb5d047014b82232c744f0fd5c7ddcef9 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:00:06 -0300 Subject: [PATCH] create separate function to spawn GC threads (#55108) Third-party GCs (e.g. MMTk) will probably have their own function to spawn GC threads. --- src/gc.c | 20 ++++++++++++++++++++ src/gc.h | 1 + src/init.c | 2 ++ src/julia_internal.h | 2 ++ src/threading.c | 26 ++++++++------------------ src/threading.h | 2 ++ 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/gc.c b/src/gc.c index c70eee6905ee9..15d48f600ed80 100644 --- a/src/gc.c +++ b/src/gc.c @@ -3881,6 +3881,26 @@ void jl_init_thread_heap(jl_ptls_t ptls) jl_atomic_store_relaxed(&ptls->gc_tls.gc_num.allocd, -(int64_t)gc_num.interval); } +void jl_start_gc_threads(void) +{ + int nthreads = jl_atomic_load_relaxed(&jl_n_threads); + int ngcthreads = jl_n_gcthreads; + int nmutator_threads = nthreads - ngcthreads; + uv_thread_t uvtid; + for (int i = nmutator_threads; i < nthreads; ++i) { + jl_threadarg_t *t = (jl_threadarg_t *)malloc_s(sizeof(jl_threadarg_t)); // ownership will be passed to the thread + t->tid = i; + t->barrier = &thread_init_done; + if (i == nthreads - 1 && jl_n_sweepthreads == 1) { + uv_thread_create(&uvtid, jl_concurrent_gc_threadfun, t); + } + else { + uv_thread_create(&uvtid, jl_parallel_gc_threadfun, t); + } + uv_thread_detach(&uvtid); + } +} + // System-wide initializations void jl_gc_init(void) { diff --git a/src/gc.h b/src/gc.h index 2ec249d322d94..b4d421c708547 100644 --- a/src/gc.h +++ b/src/gc.h @@ -562,6 +562,7 @@ extern uv_cond_t gc_threads_cond; extern uv_sem_t gc_sweep_assists_needed; extern _Atomic(int) gc_n_threads_marking; extern _Atomic(int) gc_n_threads_sweeping; +extern uv_barrier_t thread_init_done; void gc_mark_queue_all_roots(jl_ptls_t ptls, jl_gc_markqueue_t *mq); void gc_mark_finlist_(jl_gc_markqueue_t *mq, jl_value_t *fl_parent, jl_value_t **fl_begin, jl_value_t **fl_end) JL_NOTSAFEPOINT; void gc_mark_finlist(jl_gc_markqueue_t *mq, arraylist_t *list, size_t start) JL_NOTSAFEPOINT; diff --git a/src/init.c b/src/init.c index 83f528b35ac11..0a0878a081e28 100644 --- a/src/init.c +++ b/src/init.c @@ -899,6 +899,8 @@ static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_ jl_n_threads_per_pool[1] = 0; } jl_start_threads(); + jl_start_gc_threads(); + uv_barrier_wait(&thread_init_done); jl_init_heartbeat(); diff --git a/src/julia_internal.h b/src/julia_internal.h index 75ebad73a4546..9ced95a8f027a 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -942,8 +942,10 @@ extern JL_DLLEXPORT ssize_t jl_tls_offset; extern JL_DLLEXPORT const int jl_tls_elf_support; void jl_init_threading(void); void jl_start_threads(void); +void jl_start_gc_threads(void); // Whether the GC is running +extern uv_mutex_t safepoint_lock; extern char *jl_safepoint_pages; STATIC_INLINE int jl_addr_is_safepoint(uintptr_t addr) { diff --git a/src/threading.c b/src/threading.c index 05607c12085f2..8f350d41f64b1 100644 --- a/src/threading.c +++ b/src/threading.c @@ -712,7 +712,7 @@ void jl_init_threading(void) gc_first_tid = nthreads + nthreadsi; } -static uv_barrier_t thread_init_done; +uv_barrier_t thread_init_done; void jl_start_threads(void) { @@ -751,30 +751,20 @@ void jl_start_threads(void) uv_barrier_init(&thread_init_done, nthreads); // GC/System threads need to be after the worker threads. - int nworker_threads = nthreads - ngcthreads; + int nmutator_threads = nthreads - ngcthreads; - for (i = 1; i < nthreads; ++i) { + for (i = 1; i < nmutator_threads; ++i) { jl_threadarg_t *t = (jl_threadarg_t *)malloc_s(sizeof(jl_threadarg_t)); // ownership will be passed to the thread t->tid = i; t->barrier = &thread_init_done; - if (i < nworker_threads) { - uv_thread_create(&uvtid, jl_threadfun, t); - if (exclusive) { - mask[i] = 1; - uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize); - mask[i] = 0; - } - } - else if (i == nthreads - 1 && jl_n_sweepthreads == 1) { - uv_thread_create(&uvtid, jl_concurrent_gc_threadfun, t); - } - else { - uv_thread_create(&uvtid, jl_parallel_gc_threadfun, t); + uv_thread_create(&uvtid, jl_threadfun, t); + if (exclusive) { + mask[i] = 1; + uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize); + mask[i] = 0; } uv_thread_detach(&uvtid); } - - uv_barrier_wait(&thread_init_done); } _Atomic(unsigned) _threadedregion; // HACK: keep track of whether to prioritize IO or threading diff --git a/src/threading.h b/src/threading.h index 260ecffa30dd5..cb26537699713 100644 --- a/src/threading.h +++ b/src/threading.h @@ -12,6 +12,8 @@ extern "C" { #define PROFILE_JL_THREADING 0 +extern uv_barrier_t thread_init_done; + extern _Atomic(jl_ptls_t*) jl_all_tls_states JL_GLOBALLY_ROOTED; /* thread local storage */ typedef struct _jl_threadarg_t {