diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -168,7 +168,6 @@ struct ThreadSignalContext { int int_signal_send; atomic_uintptr_t in_blocking_func; - atomic_uintptr_t have_pending_signals; SignalDesc pending_signals[kSigCount]; // emptyset and oldset are too big for stack. __sanitizer_sigset_t emptyset; @@ -322,7 +321,7 @@ , ctx(SigCtx(thr)) { for (;;) { atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed); - if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0) + if (atomic_load(&thr->pending_signals, memory_order_relaxed) == 0) break; atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed); ProcessPendingSignals(thr); @@ -1992,12 +1991,11 @@ errno = saved_errno; } -void ProcessPendingSignals(ThreadState *thr) { +void ProcessPendingSignalsImpl(ThreadState *thr) { + atomic_store(&thr->pending_signals, 0, memory_order_relaxed); ThreadSignalContext *sctx = SigCtx(thr); - if (sctx == 0 || - atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0) + if (sctx == 0) return; - atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed); atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed); internal_sigfillset(&sctx->emptyset); int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset); @@ -2064,7 +2062,7 @@ signal->armed = true; internal_memcpy(&signal->siginfo, info, sizeof(*info)); internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx)); - atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed); + atomic_store(&thr->pending_signals, 1, memory_order_relaxed); } } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -380,6 +380,7 @@ // We do not distinguish beteween ignoring reads and writes // for better performance. int ignore_reads_and_writes; + atomic_sint32_t pending_signals; int ignore_sync; int suppress_reports; // Go does not support ignores. @@ -752,7 +753,7 @@ void ThreadFinalize(ThreadState *thr); void ThreadSetName(ThreadState *thr, const char *name); int ThreadCount(ThreadState *thr); -void ProcessPendingSignals(ThreadState *thr); +void ProcessPendingSignalsImpl(ThreadState *thr); void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid); Processor *ProcCreate(); @@ -858,6 +859,11 @@ FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync }; +ALWAYS_INLINE void ProcessPendingSignals(ThreadState *thr) { + if (UNLIKELY(atomic_load_relaxed(&thr->pending_signals))) + ProcessPendingSignalsImpl(thr); +} + extern bool is_initialized; ALWAYS_INLINE