@@ -2856,13 +2856,16 @@ JL_EXTENSION NOINLINE void gc_mark_loop_serial(jl_ptls_t ptls)
2856
2856
gc_drain_own_chunkqueue (ptls , & ptls -> mark_queue );
2857
2857
}
2858
2858
2859
- void gc_mark_and_steal (jl_ptls_t ptls )
2859
+ int gc_mark_and_steal (jl_ptls_t ptls )
2860
2860
{
2861
2861
jl_gc_markqueue_t * mq = & ptls -> mark_queue ;
2862
2862
jl_gc_markqueue_t * mq_master = NULL ;
2863
2863
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 ;
2866
2869
void * new_obj ;
2867
2870
jl_gc_chunk_t c ;
2868
2871
pop : {
@@ -2878,6 +2881,7 @@ void gc_mark_and_steal(jl_ptls_t ptls)
2878
2881
goto steal ;
2879
2882
}
2880
2883
mark : {
2884
+ marked = 1 ;
2881
2885
gc_mark_outrefs (ptls , mq , new_obj , 0 );
2882
2886
goto pop ;
2883
2887
}
@@ -2906,12 +2910,10 @@ void gc_mark_and_steal(jl_ptls_t ptls)
2906
2910
}
2907
2911
}
2908
2912
// 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 ;
2915
2917
}
2916
2918
// Try to steal pointer from random GC thread
2917
2919
for (int i = 0 ; i < 4 * jl_n_gcthreads ; i ++ ) {
@@ -2928,37 +2930,110 @@ void gc_mark_and_steal(jl_ptls_t ptls)
2928
2930
if (new_obj != NULL )
2929
2931
goto mark ;
2930
2932
}
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 ;
2959
+ }
2960
+ }
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 );
2981
+ }
2982
+
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 )
2987
+ {
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
+ }
2936
2998
}
2999
+ uint64_t c0 = cycleclock ();
3000
+ do {
3001
+ jl_cpu_pause ();
3002
+ } while (cycleclock () - c0 < (1 << b ));
2937
3003
}
2938
3004
}
2939
3005
2940
- void gc_mark_loop_parallel (jl_ptls_t ptls , int master )
3006
+ void gc_mark_loop_master (jl_ptls_t ptls )
2941
3007
{
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
3008
+ gc_mark_loop_master_init (ptls );
3009
+ gc_mark_loop_parallel (ptls );
3010
+ }
3011
+
3012
+ STATIC_INLINE int gc_may_mark (void ) JL_NOTSAFEPOINT
3013
+ {
3014
+ return jl_atomic_load (& gc_n_threads_marking ) > 0 ;
3015
+ }
3016
+
3017
+ STATIC_INLINE int gc_may_sweep (jl_ptls_t ptls ) JL_NOTSAFEPOINT
3018
+ {
3019
+ return jl_atomic_load (& ptls -> gc_sweeps_requested ) > 0 ;
3020
+ }
3021
+
3022
+ void gc_worker_loop (jl_ptls_t ptls )
3023
+ {
3024
+ while (1 ) {
2946
3025
uv_mutex_lock (& gc_threads_lock );
2947
- jl_atomic_fetch_add (& gc_n_threads_marking , 1 );
2948
- uv_cond_broadcast (& gc_threads_cond );
3026
+ while (!gc_may_mark () && !gc_may_sweep (ptls )) {
3027
+ uv_cond_wait (& gc_threads_cond , & gc_threads_lock );
3028
+ }
2949
3029
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 );
3030
+ if (gc_may_mark ()) {
3031
+ gc_mark_loop_parallel (ptls );
3032
+ }
3033
+ if (gc_may_sweep (ptls )) { // not an else!
3034
+ gc_sweep_pool_parallel ();
3035
+ jl_atomic_fetch_add (& ptls -> gc_sweeps_requested , -1 );
2958
3036
}
2959
- jl_atomic_fetch_add (& gc_n_threads_marking , -1 );
2960
- // Failed to steal
2961
- gc_backoff (& backoff );
2962
3037
}
2963
3038
}
2964
3039
@@ -2968,7 +3043,7 @@ void gc_mark_loop(jl_ptls_t ptls)
2968
3043
gc_mark_loop_serial (ptls );
2969
3044
}
2970
3045
else {
2971
- gc_mark_loop_parallel (ptls , 1 );
3046
+ gc_mark_loop_master (ptls );
2972
3047
}
2973
3048
}
2974
3049
0 commit comments