@@ -2856,13 +2856,16 @@ JL_EXTENSION NOINLINE void gc_mark_loop_serial(jl_ptls_t ptls)
28562856 gc_drain_own_chunkqueue (ptls , & ptls -> mark_queue );
28572857}
28582858
2859- void gc_mark_and_steal (jl_ptls_t ptls )
2859+ int gc_mark_and_steal (jl_ptls_t ptls )
28602860{
28612861 jl_gc_markqueue_t * mq = & ptls -> mark_queue ;
28622862 jl_gc_markqueue_t * mq_master = NULL ;
28632863 int master_tid = jl_atomic_load (& gc_master_tid );
2864- if (master_tid != -1 )
2865- mq_master = & gc_all_tls_states [master_tid ]-> mark_queue ;
2864+ if (master_tid == -1 ) {
2865+ return 0 ;
2866+ }
2867+ mq_master = & gc_all_tls_states [master_tid ]-> mark_queue ;
2868+ int marked = 0 ;
28662869 void * new_obj ;
28672870 jl_gc_chunk_t c ;
28682871 pop : {
@@ -2878,6 +2881,7 @@ void gc_mark_and_steal(jl_ptls_t ptls)
28782881 goto steal ;
28792882 }
28802883 mark : {
2884+ marked = 1 ;
28812885 gc_mark_outrefs (ptls , mq , new_obj , 0 );
28822886 goto pop ;
28832887 }
@@ -2906,12 +2910,10 @@ void gc_mark_and_steal(jl_ptls_t ptls)
29062910 }
29072911 }
29082912 // Try to steal chunk from master thread
2909- if (mq_master != NULL ) {
2910- c = gc_chunkqueue_steal_from (mq_master );
2911- if (c .cid != GC_empty_chunk ) {
2912- gc_mark_chunk (ptls , mq , & c );
2913- goto pop ;
2914- }
2913+ c = gc_chunkqueue_steal_from (mq_master );
2914+ if (c .cid != GC_empty_chunk ) {
2915+ gc_mark_chunk (ptls , mq , & c );
2916+ goto pop ;
29152917 }
29162918 // Try to steal pointer from random GC thread
29172919 for (int i = 0 ; i < 4 * jl_n_gcthreads ; i ++ ) {
@@ -2928,37 +2930,113 @@ void gc_mark_and_steal(jl_ptls_t ptls)
29282930 if (new_obj != NULL )
29292931 goto mark ;
29302932 }
2931- // Try to steal pointer from master thread
2932- if (mq_master != NULL ) {
2933- new_obj = gc_ptr_queue_steal_from (mq_master );
2934- if (new_obj != NULL )
2935- goto mark ;
2933+ new_obj = gc_ptr_queue_steal_from (mq_master );
2934+ if (new_obj != NULL )
2935+ goto mark ;
2936+ }
2937+ return marked ;
2938+ }
2939+
2940+ int gc_some_work_left_in_queue (jl_ptls_t ptls ) JL_NOTSAFEPOINT
2941+ {
2942+ if (jl_atomic_load_relaxed (& ptls -> mark_queue .ptr_queue .bottom ) !=
2943+ jl_atomic_load_relaxed (& ptls -> mark_queue .ptr_queue .top )) {
2944+ return 1 ;
2945+ }
2946+ if (jl_atomic_load_relaxed (& ptls -> mark_queue .chunk_queue .bottom ) !=
2947+ jl_atomic_load_relaxed (& ptls -> mark_queue .chunk_queue .top )) {
2948+ return 1 ;
2949+ }
2950+ return 0 ;
2951+ }
2952+
2953+ int gc_some_work_left (void ) JL_NOTSAFEPOINT
2954+ {
2955+ for (int i = gc_first_tid ; i < gc_first_tid + jl_n_gcthreads ; i ++ ) {
2956+ jl_ptls_t ptls2 = gc_all_tls_states [i ];
2957+ if (gc_some_work_left_in_queue (ptls2 )) {
2958+ return 1 ;
29362959 }
29372960 }
2961+ int master_tid = jl_atomic_load (& gc_master_tid );
2962+ if (master_tid != -1 ) {
2963+ jl_ptls_t ptls2 = gc_all_tls_states [master_tid ];
2964+ if (gc_some_work_left_in_queue (ptls2 )) {
2965+ return 1 ;
2966+ }
2967+ }
2968+ return 0 ;
2969+ }
2970+
2971+ void gc_mark_loop_master_init (jl_ptls_t ptls )
2972+ {
2973+ jl_atomic_store (& gc_master_tid , ptls -> tid );
2974+ // Wake threads up and try to do some work
2975+ uv_mutex_lock (& gc_threads_lock );
2976+ jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2977+ uv_cond_broadcast (& gc_threads_cond );
2978+ uv_mutex_unlock (& gc_threads_lock );
2979+ gc_mark_and_steal (ptls );
2980+ jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
29382981}
29392982
2940- void gc_mark_loop_parallel (jl_ptls_t ptls , int master )
2983+ #define GC_MIN_BACKOFF_LG2 (4)
2984+ #define GC_MAX_BACKOFF_LG2 (12)
2985+
2986+ void gc_mark_loop_parallel (jl_ptls_t ptls )
29412987{
2942- int backoff = GC_BACKOFF_MIN ;
2943- if (master ) {
2944- jl_atomic_store (& gc_master_tid , ptls -> tid );
2945- // Wake threads up and try to do some work
2988+ int b = GC_MIN_BACKOFF_LG2 ;
2989+ while (jl_atomic_load (& gc_n_threads_marking ) > 0 ) {
2990+ if (gc_some_work_left ()) {
2991+ // Try to become a thief while other threads are marking
2992+ jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2993+ int marked = gc_mark_and_steal (ptls );
2994+ jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2995+ if (marked ) {
2996+ b = GC_MIN_BACKOFF_LG2 ;
2997+ }
2998+ }
2999+ uint64_t c0 = cycleclock ();
3000+ do {
3001+ jl_cpu_pause ();
3002+ } while (cycleclock () - c0 < (1 << b ));
3003+ if (b < GC_MAX_BACKOFF_LG2 ) {
3004+ b ++ ;
3005+ }
3006+ }
3007+ }
3008+
3009+ void gc_mark_loop_master (jl_ptls_t ptls )
3010+ {
3011+ gc_mark_loop_master_init (ptls );
3012+ gc_mark_loop_parallel (ptls );
3013+ }
3014+
3015+ STATIC_INLINE int gc_may_mark (void ) JL_NOTSAFEPOINT
3016+ {
3017+ return jl_atomic_load (& gc_n_threads_marking ) > 0 ;
3018+ }
3019+
3020+ STATIC_INLINE int gc_may_sweep (jl_ptls_t ptls ) JL_NOTSAFEPOINT
3021+ {
3022+ return jl_atomic_load (& ptls -> gc_sweeps_requested ) > 0 ;
3023+ }
3024+
3025+ void gc_worker_loop (jl_ptls_t ptls )
3026+ {
3027+ while (1 ) {
29463028 uv_mutex_lock (& gc_threads_lock );
2947- jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2948- uv_cond_broadcast (& gc_threads_cond );
3029+ while (!gc_may_mark () && !gc_may_sweep (ptls )) {
3030+ uv_cond_wait (& gc_threads_cond , & gc_threads_lock );
3031+ }
29493032 uv_mutex_unlock (& gc_threads_lock );
2950- gc_mark_and_steal (ptls );
2951- jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2952- }
2953- while (jl_atomic_load (& gc_n_threads_marking ) > 0 ) {
2954- // Try to become a thief while other threads are marking
2955- jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2956- if (jl_atomic_load (& gc_master_tid ) != -1 ) {
2957- gc_mark_and_steal (ptls );
3033+ if (gc_may_mark ()) {
3034+ gc_mark_loop_parallel (ptls );
3035+ }
3036+ if (gc_may_sweep (ptls )) { // not an else!
3037+ gc_sweep_pool_parallel ();
3038+ jl_atomic_fetch_add (& ptls -> gc_sweeps_requested , -1 );
29583039 }
2959- jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2960- // Failed to steal
2961- gc_backoff (& backoff );
29623040 }
29633041}
29643042
@@ -2968,7 +3046,7 @@ void gc_mark_loop(jl_ptls_t ptls)
29683046 gc_mark_loop_serial (ptls );
29693047 }
29703048 else {
2971- gc_mark_loop_parallel (ptls , 1 );
3049+ gc_mark_loop_master (ptls );
29723050 }
29733051}
29743052
0 commit comments