@@ -291,6 +291,18 @@ int exc_reg_is_write_fault(uintptr_t esr) {
291291#include "signals-mach.c"
292292#else
293293
294+ int jl_lock_stackwalk (void )
295+ {
296+ jl_lock_profile ();
297+ return 0 ;
298+ }
299+
300+ void jl_unlock_stackwalk (int lockret )
301+ {
302+ (void )lockret ;
303+ jl_unlock_profile ();
304+ }
305+
294306
295307#if defined(_OS_LINUX_ ) && (defined(_CPU_X86_64_ ) || defined(_CPU_X86_ ))
296308int is_write_fault (void * context ) {
@@ -384,12 +396,12 @@ JL_NO_ASAN static void segv_handler(int sig, siginfo_t *info, void *context)
384396}
385397
386398#if !defined(JL_DISABLE_LIBUNWIND )
387- static unw_context_t * signal_context ;
399+ static bt_context_t * signal_context ;
388400pthread_mutex_t in_signal_lock ;
389401static pthread_cond_t exit_signal_cond ;
390402static pthread_cond_t signal_caught_cond ;
391403
392- static void jl_thread_suspend_and_get_state (int tid , int timeout , unw_context_t * * ctx )
404+ int jl_thread_suspend_and_get_state (int tid , int timeout , bt_context_t * ctx )
393405{
394406 struct timespec ts ;
395407 clock_gettime (CLOCK_REALTIME , & ts );
@@ -399,9 +411,8 @@ static void jl_thread_suspend_and_get_state(int tid, int timeout, unw_context_t
399411 jl_task_t * ct2 = ptls2 ? jl_atomic_load_relaxed (& ptls2 -> current_task ) : NULL ;
400412 if (ct2 == NULL ) {
401413 // this thread is not alive or already dead
402- * ctx = NULL ;
403414 pthread_mutex_unlock (& in_signal_lock );
404- return ;
415+ return 0 ;
405416 }
406417 jl_atomic_store_release (& ptls2 -> signal_request , 1 );
407418 pthread_kill (ptls2 -> system_id , SIGUSR2 );
@@ -410,9 +421,8 @@ static void jl_thread_suspend_and_get_state(int tid, int timeout, unw_context_t
410421 if (err == ETIMEDOUT ) {
411422 sig_atomic_t request = 1 ;
412423 if (jl_atomic_cmpswap (& ptls2 -> signal_request , & request , 0 )) {
413- * ctx = NULL ;
414424 pthread_mutex_unlock (& in_signal_lock );
415- return ;
425+ return 0 ;
416426 }
417427 // Request is either now 0 (meaning the other thread is waiting for
418428 // exit_signal_cond already),
@@ -429,15 +439,16 @@ static void jl_thread_suspend_and_get_state(int tid, int timeout, unw_context_t
429439 // checking it is 0, and add an acquire barrier for good measure)
430440 int request = jl_atomic_load_acquire (& ptls2 -> signal_request );
431441 assert (request == 0 ); (void ) request ;
432- * ctx = signal_context ;
442+ jl_atomic_store_release (& ptls2 -> signal_request , 1 ); // prepare to resume normally
443+ * ctx = * signal_context ;
444+ return 1 ;
433445}
434446
435- static void jl_thread_resume (int tid , int sig )
447+ void jl_thread_resume (int tid )
436448{
437449 jl_ptls_t ptls2 = jl_atomic_load_relaxed (& jl_all_tls_states )[tid ];
438- jl_atomic_store_release (& ptls2 -> signal_request , sig == -1 ? 3 : 1 );
439450 pthread_cond_broadcast (& exit_signal_cond );
440- pthread_cond_wait (& signal_caught_cond , & in_signal_lock ); // wait for thread to acknowledge
451+ pthread_cond_wait (& signal_caught_cond , & in_signal_lock ); // wait for thread to acknowledge (so that signal_request doesn't get mixed up)
441452 // The other thread is waiting to leave exit_signal_cond (verify that here by
442453 // checking it is 0, and add an acquire barrier for good measure)
443454 int request = jl_atomic_load_acquire (& ptls2 -> signal_request );
@@ -472,14 +483,14 @@ CFI_NORETURN
472483static void jl_exit_thread0 (int signo , jl_bt_element_t * bt_data , size_t bt_size )
473484{
474485 jl_ptls_t ptls2 = jl_atomic_load_relaxed (& jl_all_tls_states )[0 ];
475- unw_context_t * signal_context ;
486+ bt_context_t signal_context ;
476487 // This also makes sure `sleep` is aborted.
477- jl_thread_suspend_and_get_state (0 , 30 , & signal_context );
478- if (signal_context != NULL ) {
488+ if (jl_thread_suspend_and_get_state (0 , 30 , & signal_context )) {
479489 thread0_exit_signo = signo ;
480490 ptls2 -> bt_size = bt_size ; // <= JL_MAX_BT_SIZE
481491 memcpy (ptls2 -> bt_data , bt_data , ptls2 -> bt_size * sizeof (bt_data [0 ]));
482- jl_thread_resume (0 , -1 ); // resume with message 3 (call jl_exit_thread0_cb)
492+ jl_atomic_store_release (& ptls2 -> signal_request , 3 );
493+ jl_thread_resume (0 ); // resume with message 3 (call jl_exit_thread0_cb)
483494 }
484495 else {
485496 // thread 0 is gone? just do the exit ourself
@@ -840,28 +851,27 @@ static void *signal_listener(void *arg)
840851 int nthreads = jl_atomic_load_acquire (& jl_n_threads );
841852 bt_size = 0 ;
842853#if !defined(JL_DISABLE_LIBUNWIND )
843- unw_context_t * signal_context ;
854+ bt_context_t signal_context ;
844855 // sample each thread, round-robin style in reverse order
845856 // (so that thread zero gets notified last)
846857 if (critical || profile ) {
847- jl_lock_profile ();
858+ int lockret = jl_lock_stackwalk ();
848859 int * randperm ;
849860 if (profile )
850861 randperm = profile_get_randperm (nthreads );
851862 for (int idx = nthreads ; idx -- > 0 ; ) {
852863 // Stop the threads in the random or reverse round-robin order.
853864 int i = profile ? randperm [idx ] : idx ;
854865 // notify thread to stop
855- jl_thread_suspend_and_get_state (i , 1 , & signal_context );
856- if (signal_context == NULL )
866+ if (!jl_thread_suspend_and_get_state (i , 1 , & signal_context ))
857867 continue ;
858868
859869 // do backtrace on thread contexts for critical signals
860870 // this part must be signal-handler safe
861871 if (critical ) {
862872 bt_size += rec_backtrace_ctx (bt_data + bt_size ,
863873 JL_MAX_BT_SIZE / nthreads - 1 ,
864- signal_context , NULL );
874+ & signal_context , NULL );
865875 bt_data [bt_size ++ ].uintptr = 0 ;
866876 }
867877
@@ -883,7 +893,7 @@ static void *signal_listener(void *arg)
883893 } else {
884894 // Get backtrace data
885895 bt_size_cur += rec_backtrace_ctx ((jl_bt_element_t * )bt_data_prof + bt_size_cur ,
886- bt_size_max - bt_size_cur - 1 , signal_context , NULL );
896+ bt_size_max - bt_size_cur - 1 , & signal_context , NULL );
887897 }
888898 jl_set_safe_restore (old_buf );
889899
@@ -908,9 +918,9 @@ static void *signal_listener(void *arg)
908918 }
909919
910920 // notify thread to resume
911- jl_thread_resume (i , sig );
921+ jl_thread_resume (i );
912922 }
913- jl_unlock_profile ( );
923+ jl_unlock_stackwalk ( lockret );
914924 }
915925#ifndef HAVE_MACH
916926 if (profile && running ) {
0 commit comments