From 9e9599ef782384847e734dfdb89d34a4bb8c6710 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 29 Jul 2021 13:50:29 +0200 Subject: [PATCH] tsan: introduce LazyInitialize We call non-inlinable Initialize from all interceptors/syscalls, but most of the time runtime is already initialized and this just introduces unnecessary overhead. Add LazyInitialize that (1) inlinable, (2) does nothing if .preinit_array is enabled (expected case on Linux). Depends on D107071. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D107072 --- .../lib/tsan/rtl/tsan_interceptors_posix.cpp | 7 ++----- compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 3 ++- compiler-rt/lib/tsan/rtl/tsan_rtl.h | 13 +++++++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 53f45ee120cb..2efc75b48f19 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -249,7 +249,7 @@ static ThreadSignalContext *SigCtx(ThreadState *thr) { ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc) : thr_(thr), in_ignored_lib_(false), ignoring_(false) { - Initialize(thr); + LazyInitialize(thr); if (!thr_->is_inited) return; if (!thr_->ignore_interceptors) FuncEntry(thr, pc); DPrintf("#%d: intercept %s()\n", thr_->tid, fname); @@ -2488,10 +2488,7 @@ static __sanitizer_sighandler_ptr signal_impl(int sig, struct ScopedSyscall { ThreadState *thr; - explicit ScopedSyscall(ThreadState *thr) - : thr(thr) { - Initialize(thr); - } + explicit ScopedSyscall(ThreadState *thr) : thr(thr) { LazyInitialize(thr); } ~ScopedSyscall() { ProcessPendingSignals(thr); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp index a8a508d4b175..0d09f3d279ff 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -384,9 +384,10 @@ void CheckUnwind() { PrintCurrentStackSlow(StackTrace::GetCurrentPc()); } +bool is_initialized; + void Initialize(ThreadState *thr) { // Thread safe because done before all threads exist. - static bool is_initialized = false; if (is_initialized) return; is_initialized = true; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index e45082d2230c..ddcac39e98b3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -859,6 +859,19 @@ enum FiberSwitchFlags { FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync }; +extern bool is_initialized; + +ALWAYS_INLINE +void LazyInitialize(ThreadState *thr) { + // If we can use .preinit_array, assume that __tsan_init + // called from .preinit_array initializes runtime before + // any instrumented code. +#if !SANITIZER_CAN_USE_PREINIT_ARRAY + if (UNLIKELY(!is_initialized)) + Initialize(thr); +#endif +} + } // namespace __tsan #endif // TSAN_RTL_H