@@ -91,7 +91,7 @@ typedef struct caml_thread_struct* caml_thread_t;
9191/* overall table for threads across domains */
9292struct caml_thread_table {
9393 caml_thread_t all_threads ;
94- caml_thread_t current_thread ;
94+ _Atomic ( caml_thread_t ) current_thread ;
9595 st_tlskey thread_key ;
9696 st_masterlock thread_lock ;
9797 int tick_thread_running ;
@@ -105,7 +105,11 @@ static struct caml_thread_table thread_table[Max_domains];
105105#define All_threads thread_table[Caml_state->id].all_threads
106106
107107/* The descriptor for the currently executing thread for this domain */
108- #define Current_thread thread_table[Caml_state->id].current_thread
108+ #define Current_thread &thread_table[Caml_state->id].current_thread
109+ #define Get_current_thread () \
110+ (atomic_load_explicit(Current_thread, memory_order_relaxed))
111+ #define Set_current_thread (t ) \
112+ (atomic_store_explicit(Current_thread, t, memory_order_relaxed))
109113
110114/* The master lock protecting this domain's thread chaining */
111115#define Thread_main_lock thread_table[Caml_state->id].thread_lock
@@ -132,26 +136,41 @@ static st_retcode caml_threadstatus_wait (value);
132136
133137static scan_roots_hook prev_scan_roots_hook ;
134138
139+ caml_domain_state * caml_try_get_caml_state (void )
140+ {
141+ caml_domain_state * dom_st = Caml_state ;
142+ if (dom_st == NULL )
143+ // Not a registered thread
144+ return NULL ;
145+ if (Thread_key == NULL ) // FIXME
146+ // Systhreads not initialized
147+ return dom_st ;
148+ if (Get_current_thread () != st_tls_get (Thread_key ))
149+ // Not currently holding the lock
150+ return NULL ;
151+ return dom_st ;
152+ }
153+
135154static void caml_thread_scan_roots (scanning_action action ,
136155 void * fdata ,
137156 caml_domain_state * domain_state )
138157{
139158 caml_thread_t th ;
140159
141- th = Current_thread ;
160+ th = Get_current_thread () ;
142161
143162 /* GC could be triggered before [Current_thread] is initialized */
144163 if (th != NULL ) {
145164 do {
146165 (* action )(fdata , th -> descr , & th -> descr );
147166 (* action )(fdata , th -> backtrace_last_exn , & th -> backtrace_last_exn );
148- if (th != Current_thread ) {
167+ if (th != Get_current_thread () ) {
149168 if (th -> current_stack != NULL )
150169 caml_do_local_roots (action , fdata , th -> local_roots ,
151170 th -> current_stack , th -> gc_regs );
152171 }
153172 th = th -> next ;
154- } while (th != Current_thread );
173+ } while (th != Get_current_thread () );
155174
156175 };
157176
@@ -203,8 +222,8 @@ static void caml_thread_enter_blocking_section(void)
203222{
204223 /* Save the current runtime state in the thread descriptor
205224 of the current thread */
206- save_runtime_state (Current_thread );
207- /* Inform caml_try_get_caml_state() that we no longer hold the lock. */
225+ save_runtime_state (Get_current_thread () );
226+ /* Inform [ caml_try_get_caml_state()] that we no longer hold the lock. */
208227 Set_current_thread (NULL );
209228 /* Tell other threads that the runtime is free */
210229 st_masterlock_release (& Thread_main_lock );
@@ -217,7 +236,7 @@ static void caml_thread_leave_blocking_section(void)
217236 /* Update Current_thread to point to the thread descriptor corresponding to
218237 the thread currently executing */
219238 caml_thread_t th = st_tls_get (Thread_key );
220- Current_thread = th ;
239+ Set_current_thread ( th ) ;
221240 /* Restore the runtime state from the curr_thread descriptor */
222241 restore_runtime_state (th );
223242}
@@ -298,7 +317,7 @@ static void caml_thread_remove_info(caml_thread_t th)
298317
299318static void caml_thread_reinitialize (void )
300319{
301- caml_thread_t current_thread = Current_thread ;
320+ caml_thread_t current_thread = Get_current_thread () ;
302321 caml_thread_t th = current_thread -> next ;
303322 caml_thread_t next ;
304323 while (th != current_thread ) {
@@ -330,7 +349,7 @@ CAMLprim value caml_thread_join(value th);
330349 thread: the program will exit. */
331350static void caml_thread_domain_stop_hook (void )
332351{
333- caml_thread_t th = Current_thread ;
352+ caml_thread_t th = Get_current_thread () ;
334353 /* If the program runs multiple domains, we should not let systhreads to hang
335354 around when a domain exit. If the domain is not the last one (and the last
336355 one will always be domain 0) we force the domain to join on every thread
@@ -345,7 +364,7 @@ static void caml_thread_domain_stop_hook(void)
345364 caml_threadstatus_terminate (Terminated (th -> descr ));
346365
347366 caml_stat_free (th );
348- Current_thread = NULL ;
367+ Set_current_thread ( NULL ) ;
349368 All_threads = NULL ;
350369 };
351370}
@@ -373,7 +392,7 @@ CAMLprim value caml_thread_initialize_domain(value v)
373392 st_tls_set (Thread_key , (void * ) new_thread );
374393
375394 All_threads = new_thread ;
376- Current_thread = new_thread ;
395+ Set_current_thread ( new_thread ) ;
377396 Tick_thread_running = 0 ;
378397
379398 CAMLreturn (Val_unit );
@@ -437,7 +456,7 @@ CAMLprim value caml_thread_cleanup(value unit)
437456
438457static void caml_thread_stop (void )
439458{
440- caml_thread_t th = Current_thread ;
459+ caml_thread_t th = Get_current_thread () ;
441460 caml_thread_t next ;
442461
443462 /* PR#5188, PR#7220: some of the global runtime state may have
@@ -455,7 +474,7 @@ static void caml_thread_stop(void)
455474 caml_threadstatus_terminate (Terminated (th -> descr ));
456475 caml_thread_remove_info (th );
457476
458- Current_thread = NULL ;
477+ Set_current_thread ( NULL ) ;
459478
460479 /* Normally we expect another thread to kick in and resume operation by
461480 first setting Current_thread to the right TLS dec data. However it may
@@ -486,7 +505,7 @@ static void * caml_thread_start(void * v)
486505
487506 st_masterlock_acquire (& Thread_main_lock );
488507 caml_thread_t current_thread = st_tls_get (Thread_key );
489- Current_thread = current_thread ;
508+ Set_current_thread ( current_thread ) ;
490509 restore_runtime_state (current_thread );
491510
492511#ifdef POSIX_SIGNALS
@@ -551,7 +570,7 @@ CAMLprim value caml_thread_new(value clos)
551570 th -> init_mask = mask ;
552571#endif
553572
554- caml_thread_t current_thread = Current_thread ;
573+ caml_thread_t current_thread = Get_current_thread () ;
555574 th -> next = current_thread -> next ;
556575 th -> prev = current_thread ;
557576
@@ -647,7 +666,7 @@ CAMLexport int caml_c_thread_unregister(void)
647666 /* Remove thread info block from list of threads, and free it */
648667 caml_thread_remove_info (th );
649668
650- Current_thread = All_threads ;
669+ Set_current_thread ( All_threads ) ;
651670
652671 /* If no other OCaml thread remains, ask the tick thread to stop
653672 so that it does not prevent the whole process from exiting (#9971) */
@@ -665,7 +684,7 @@ CAMLexport int caml_c_thread_unregister(void)
665684
666685CAMLprim value caml_thread_self (value unit )
667686{
668- return Current_thread -> descr ;
687+ return Get_current_thread () -> descr ;
669688}
670689
671690/* Return the identifier of a thread */
@@ -681,7 +700,7 @@ CAMLprim value caml_thread_uncaught_exception(value exn)
681700{
682701 char * msg = caml_format_exception (exn );
683702 fprintf (stderr , "Thread %d killed on uncaught exception %s\n" ,
684- Int_val (Ident (Current_thread -> descr )), msg );
703+ Int_val (Ident (Get_current_thread () -> descr )), msg );
685704 caml_stat_free (msg );
686705 if (Caml_state -> backtrace_active ) caml_print_exception_backtrace ();
687706 fflush (stderr );
@@ -701,11 +720,11 @@ CAMLprim value caml_thread_yield(value unit)
701720 */
702721
703722 caml_raise_if_exception (caml_process_pending_signals_exn ());
704- save_runtime_state (Current_thread );
705- Current_thread = NULL ;
723+ save_runtime_state (Get_current_thread () );
724+ Set_current_thread ( NULL ) ;
706725 st_thread_yield (& Thread_main_lock );
707726 caml_thread_t th = st_tls_get (Thread_key );
708- Current_thread = th ;
727+ Set_current_thread ( th ) ;
709728 restore_runtime_state (th );
710729 caml_raise_if_exception (caml_process_pending_signals_exn ());
711730
0 commit comments