@@ -2814,13 +2814,16 @@ JL_EXTENSION NOINLINE void gc_mark_loop_serial(jl_ptls_t ptls)
28142814 gc_drain_own_chunkqueue (ptls , & ptls -> mark_queue );
28152815}
28162816
2817- void gc_mark_and_steal (jl_ptls_t ptls )
2817+ int gc_mark_and_steal (jl_ptls_t ptls )
28182818{
28192819 jl_gc_markqueue_t * mq = & ptls -> mark_queue ;
28202820 jl_gc_markqueue_t * mq_master = NULL ;
28212821 int master_tid = jl_atomic_load (& gc_master_tid );
2822- if (master_tid != -1 )
2823- mq_master = & gc_all_tls_states [master_tid ]-> mark_queue ;
2822+ if (master_tid == -1 ) {
2823+ return 0 ;
2824+ }
2825+ mq_master = & gc_all_tls_states [master_tid ]-> mark_queue ;
2826+ int marked = 0 ;
28242827 void * new_obj ;
28252828 jl_gc_chunk_t c ;
28262829 pop : {
@@ -2836,6 +2839,7 @@ void gc_mark_and_steal(jl_ptls_t ptls)
28362839 goto steal ;
28372840 }
28382841 mark : {
2842+ marked = 1 ;
28392843 gc_mark_outrefs (ptls , mq , new_obj , 0 );
28402844 goto pop ;
28412845 }
@@ -2864,12 +2868,10 @@ void gc_mark_and_steal(jl_ptls_t ptls)
28642868 }
28652869 }
28662870 // Try to steal chunk from master thread
2867- if (mq_master != NULL ) {
2868- c = gc_chunkqueue_steal_from (mq_master );
2869- if (c .cid != GC_empty_chunk ) {
2870- gc_mark_chunk (ptls , mq , & c );
2871- goto pop ;
2872- }
2871+ c = gc_chunkqueue_steal_from (mq_master );
2872+ if (c .cid != GC_empty_chunk ) {
2873+ gc_mark_chunk (ptls , mq , & c );
2874+ goto pop ;
28732875 }
28742876 // Try to steal pointer from random GC thread
28752877 for (int i = 0 ; i < 4 * jl_n_markthreads ; i ++ ) {
@@ -2886,37 +2888,113 @@ void gc_mark_and_steal(jl_ptls_t ptls)
28862888 if (new_obj != NULL )
28872889 goto mark ;
28882890 }
2889- // Try to steal pointer from master thread
2890- if (mq_master != NULL ) {
2891- new_obj = gc_ptr_queue_steal_from (mq_master );
2892- if (new_obj != NULL )
2893- goto mark ;
2891+ new_obj = gc_ptr_queue_steal_from (mq_master );
2892+ if (new_obj != NULL )
2893+ goto mark ;
2894+ }
2895+ return marked ;
2896+ }
2897+
2898+ int gc_some_work_left_in_queue (jl_ptls_t ptls ) JL_NOTSAFEPOINT
2899+ {
2900+ if (jl_atomic_load_relaxed (& ptls -> mark_queue .ptr_queue .bottom ) !=
2901+ jl_atomic_load_relaxed (& ptls -> mark_queue .ptr_queue .top )) {
2902+ return 1 ;
2903+ }
2904+ if (jl_atomic_load_relaxed (& ptls -> mark_queue .chunk_queue .bottom ) !=
2905+ jl_atomic_load_relaxed (& ptls -> mark_queue .chunk_queue .top )) {
2906+ return 1 ;
2907+ }
2908+ return 0 ;
2909+ }
2910+
2911+ int gc_some_work_left (void ) JL_NOTSAFEPOINT
2912+ {
2913+ for (int i = gc_first_tid ; i < gc_first_tid + jl_n_markthreads ; i ++ ) {
2914+ jl_ptls_t ptls2 = gc_all_tls_states [i ];
2915+ if (gc_some_work_left_in_queue (ptls2 )) {
2916+ return 1 ;
28942917 }
28952918 }
2919+ int master_tid = jl_atomic_load (& gc_master_tid );
2920+ if (master_tid != -1 ) {
2921+ jl_ptls_t ptls2 = gc_all_tls_states [master_tid ];
2922+ if (gc_some_work_left_in_queue (ptls2 )) {
2923+ return 1 ;
2924+ }
2925+ }
2926+ return 0 ;
2927+ }
2928+
2929+ void gc_mark_loop_master_init (jl_ptls_t ptls )
2930+ {
2931+ jl_atomic_store (& gc_master_tid , ptls -> tid );
2932+ // Wake threads up and try to do some work
2933+ uv_mutex_lock (& gc_threads_lock );
2934+ jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2935+ uv_cond_broadcast (& gc_threads_cond );
2936+ uv_mutex_unlock (& gc_threads_lock );
2937+ gc_mark_and_steal (ptls );
2938+ jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
28962939}
28972940
2898- void gc_mark_loop_parallel (jl_ptls_t ptls , int master )
2941+ #define GC_MIN_BACKOFF_LG2 (4)
2942+ #define GC_MAX_BACKOFF_LG2 (12)
2943+
2944+ void gc_mark_loop_parallel (jl_ptls_t ptls )
28992945{
2900- int backoff = GC_BACKOFF_MIN ;
2901- if (master ) {
2902- jl_atomic_store (& gc_master_tid , ptls -> tid );
2903- // Wake threads up and try to do some work
2946+ int b = GC_MIN_BACKOFF_LG2 ;
2947+ while (jl_atomic_load (& gc_n_threads_marking ) > 0 ) {
2948+ if (gc_some_work_left ()) {
2949+ // Try to become a thief while other threads are marking
2950+ jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2951+ int marked = gc_mark_and_steal (ptls );
2952+ jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2953+ if (marked ) {
2954+ b = GC_MIN_BACKOFF_LG2 ;
2955+ }
2956+ }
2957+ uint64_t c0 = cycleclock ();
2958+ do {
2959+ jl_cpu_pause ();
2960+ } while (cycleclock () - c0 < (1 << b ));
2961+ if (b < GC_MAX_BACKOFF_LG2 ) {
2962+ b ++ ;
2963+ }
2964+ }
2965+ }
2966+
2967+ void gc_mark_loop_master (jl_ptls_t ptls )
2968+ {
2969+ gc_mark_loop_master_init (ptls );
2970+ gc_mark_loop_parallel (ptls );
2971+ }
2972+
2973+ STATIC_INLINE int gc_may_mark (void ) JL_NOTSAFEPOINT
2974+ {
2975+ return jl_atomic_load (& gc_n_threads_marking ) > 0 ;
2976+ }
2977+
2978+ STATIC_INLINE int gc_may_sweep (jl_ptls_t ptls ) JL_NOTSAFEPOINT
2979+ {
2980+ return jl_atomic_load (& ptls -> gc_sweeps_requested ) > 0 ;
2981+ }
2982+
2983+ void gc_worker_loop (jl_ptls_t ptls )
2984+ {
2985+ while (1 ) {
29042986 uv_mutex_lock (& gc_threads_lock );
2905- jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2906- uv_cond_broadcast (& gc_threads_cond );
2987+ while (!gc_may_mark () && !gc_may_sweep (ptls )) {
2988+ uv_cond_wait (& gc_threads_cond , & gc_threads_lock );
2989+ }
29072990 uv_mutex_unlock (& gc_threads_lock );
2908- gc_mark_and_steal (ptls );
2909- jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2910- }
2911- while (jl_atomic_load (& gc_n_threads_marking ) > 0 ) {
2912- // Try to become a thief while other threads are marking
2913- jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2914- if (jl_atomic_load (& gc_master_tid ) != -1 ) {
2915- gc_mark_and_steal (ptls );
2991+ if (gc_may_mark ()) {
2992+ gc_mark_loop_parallel (ptls );
2993+ }
2994+ if (gc_may_sweep (ptls )) { // not an else!
2995+ gc_sweep_pool_parallel ();
2996+ jl_atomic_fetch_add (& ptls -> gc_sweeps_requested , -1 );
29162997 }
2917- jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2918- // Failed to steal
2919- gc_backoff (& backoff );
29202998 }
29212999}
29223000
@@ -2926,7 +3004,7 @@ void gc_mark_loop(jl_ptls_t ptls)
29263004 gc_mark_loop_serial (ptls );
29273005 }
29283006 else {
2929- gc_mark_loop_parallel (ptls , 1 );
3007+ gc_mark_loop_master (ptls );
29303008 }
29313009}
29323010
0 commit comments