Skip to content

Commit 4cff734

Browse files
committed
Implement caml_try_get_caml_state
1 parent 3223f45 commit 4cff734

File tree

2 files changed

+48
-22
lines changed

2 files changed

+48
-22
lines changed

otherlibs/systhreads/st_stubs.c

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ typedef struct caml_thread_struct* caml_thread_t;
9191
/* overall table for threads across domains */
9292
struct 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

133137
static 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+
135154
static 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

299318
static 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. */
331350
static 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

438457
static 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

666685
CAMLprim 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

runtime/caml/signals.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ void caml_free_signal_stack(void);
8080
/* These hooks are not modified after other threads are spawned. */
8181
CAMLextern void (*caml_enter_blocking_section_hook)(void);
8282
CAMLextern void (*caml_leave_blocking_section_hook)(void);
83+
84+
caml_domain_state *caml_try_get_caml_state(void);
85+
/* This function returns NULL if the current thread does not hold any
86+
domain lock, otherwise it returns the pointer to the domain state
87+
of which it holds the lock. This function can be called from any
88+
thread including unregistered C threads. */
89+
8390
#endif /* CAML_INTERNALS */
8491

8592
#ifdef __cplusplus

0 commit comments

Comments
 (0)