diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2021-07-20 10:44:37 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2021-07-20 14:21:51 -0700 |
commit | 90e46074e6b3561ae7d8ebd205127f286cc0c6b6 (patch) | |
tree | 6f21ee7eafae85d0aacc994e221c48d3bb172df0 /libsanitizer/tsan | |
parent | 8bf5b49ebd2176b8c535147377381dd07fbdd643 (diff) | |
download | gcc-90e46074e6b3561ae7d8ebd205127f286cc0c6b6.zip gcc-90e46074e6b3561ae7d8ebd205127f286cc0c6b6.tar.gz gcc-90e46074e6b3561ae7d8ebd205127f286cc0c6b6.tar.bz2 |
libsanitizer: Merge with upstream
Merged revision: 7704fedfff6ef5676adb6415f3be0ac927d1a746
Diffstat (limited to 'libsanitizer/tsan')
28 files changed, 219 insertions, 622 deletions
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am index fb20ff7..dcb247e 100644 --- a/libsanitizer/tsan/Makefile.am +++ b/libsanitizer/tsan/Makefile.am @@ -43,13 +43,12 @@ tsan_files = \ tsan_rtl_report.cpp \ tsan_rtl_thread.cpp \ tsan_stack_trace.cpp \ - tsan_stat.cpp \ tsan_suppressions.cpp \ tsan_symbolize.cpp \ tsan_sync.cpp libtsan_la_SOURCES = $(tsan_files) -EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S +EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S libtsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(TSAN_TARGET_DEPENDENT_OBJECTS) libtsan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(TSAN_TARGET_DEPENDENT_OBJECTS) if LIBBACKTRACE_SUPPORTED diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in index ce11d24..83617cf 100644 --- a/libsanitizer/tsan/Makefile.in +++ b/libsanitizer/tsan/Makefile.in @@ -155,8 +155,7 @@ am__objects_1 = tsan_clock.lo tsan_debugging.lo tsan_external.lo \ tsan_platform_posix.lo tsan_platform_windows.lo tsan_report.lo \ tsan_rtl.lo tsan_rtl_mutex.lo tsan_rtl_proc.lo \ tsan_rtl_report.lo tsan_rtl_thread.lo tsan_stack_trace.lo \ - tsan_stat.lo tsan_suppressions.lo tsan_symbolize.lo \ - tsan_sync.lo + tsan_suppressions.lo tsan_symbolize.lo tsan_sync.lo am_libtsan_la_OBJECTS = $(am__objects_1) libtsan_la_OBJECTS = $(am_libtsan_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -446,13 +445,12 @@ tsan_files = \ tsan_rtl_report.cpp \ tsan_rtl_thread.cpp \ tsan_stack_trace.cpp \ - tsan_stat.cpp \ tsan_suppressions.cpp \ tsan_symbolize.cpp \ tsan_sync.cpp libtsan_la_SOURCES = $(tsan_files) -EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S +EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S libtsan_la_LIBADD = \ $(top_builddir)/sanitizer_common/libsanitizer_common.la \ $(top_builddir)/interception/libinterception.la \ @@ -612,9 +610,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_ppc64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_proc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_report.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_s390x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_stack_trace.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_stat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_suppressions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_symbolize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_sync.Plo@am__quote@ diff --git a/libsanitizer/tsan/tsan_clock.cpp b/libsanitizer/tsan/tsan_clock.cpp index 8e51883..61848c2 100644 --- a/libsanitizer/tsan/tsan_clock.cpp +++ b/libsanitizer/tsan/tsan_clock.cpp @@ -80,14 +80,6 @@ // release-store operation by the thread with release_store_tid_ index. // release_store_reused_ - reuse count of release_store_tid_. -// We don't have ThreadState in these methods, so this is an ugly hack that -// works only in C++. -#if !SANITIZER_GO -# define CPP_STAT_INC(typ) StatInc(cur_thread(), typ) -#else -# define CPP_STAT_INC(typ) (void)0 -#endif - namespace __tsan { static atomic_uint32_t *ref_ptr(ClockBlock *cb) { @@ -138,14 +130,11 @@ void ThreadClock::ResetCached(ClockCache *c) { void ThreadClock::acquire(ClockCache *c, SyncClock *src) { DCHECK_LE(nclk_, kMaxTid); DCHECK_LE(src->size_, kMaxTid); - CPP_STAT_INC(StatClockAcquire); // Check if it's empty -> no need to do anything. const uptr nclk = src->size_; - if (nclk == 0) { - CPP_STAT_INC(StatClockAcquireEmpty); + if (nclk == 0) return; - } bool acquired = false; for (unsigned i = 0; i < kDirtyTids; i++) { @@ -162,7 +151,6 @@ void ThreadClock::acquire(ClockCache *c, SyncClock *src) { // Check if we've already acquired src after the last release operation on src if (tid_ >= nclk || src->elem(tid_).reused != reused_) { // O(N) acquire. - CPP_STAT_INC(StatClockAcquireFull); nclk_ = max(nclk_, nclk); u64 *dst_pos = &clk_[0]; for (ClockElem &src_elem : *src) { @@ -180,7 +168,6 @@ void ThreadClock::acquire(ClockCache *c, SyncClock *src) { } if (acquired) { - CPP_STAT_INC(StatClockAcquiredSomething); last_acquire_ = clk_[tid_]; ResetCached(c); } @@ -223,7 +210,6 @@ void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) { sc->release_store_reused_ = 0; if (acquired) { - CPP_STAT_INC(StatClockAcquiredSomething); last_acquire_ = clk_[tid_]; ResetCached(c); } @@ -240,7 +226,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { return; } - CPP_STAT_INC(StatClockRelease); // Check if we need to resize dst. if (dst->size_ < nclk_) dst->Resize(c, nclk_); @@ -257,12 +242,9 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { } // O(N) release. - CPP_STAT_INC(StatClockReleaseFull); dst->Unshare(c); // First, remember whether we've acquired dst. bool acquired = IsAlreadyAcquired(dst); - if (acquired) - CPP_STAT_INC(StatClockReleaseAcquired); // Update dst->clk_. dst->FlushDirty(); uptr i = 0; @@ -272,8 +254,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { i++; } // Clear 'acquired' flag in the remaining elements. - if (nclk_ < dst->size_) - CPP_STAT_INC(StatClockReleaseClearTail); dst->release_store_tid_ = kInvalidTid; dst->release_store_reused_ = 0; // If we've acquired dst, remember this fact, @@ -285,7 +265,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { DCHECK_LE(nclk_, kMaxTid); DCHECK_LE(dst->size_, kMaxTid); - CPP_STAT_INC(StatClockStore); if (dst->size_ == 0 && cached_idx_ != 0) { // Reuse the cached clock. @@ -320,13 +299,11 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { if (dst->release_store_tid_ == tid_ && dst->release_store_reused_ == reused_ && !HasAcquiredAfterRelease(dst)) { - CPP_STAT_INC(StatClockStoreFast); UpdateCurrentThread(c, dst); return; } // O(N) release-store. - CPP_STAT_INC(StatClockStoreFull); dst->Unshare(c); // Note: dst can be larger than this ThreadClock. // This is fine since clk_ beyond size is all zeros. @@ -358,7 +335,6 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { } void ThreadClock::acq_rel(ClockCache *c, SyncClock *dst) { - CPP_STAT_INC(StatClockAcquireRelease); acquire(c, dst); ReleaseStore(c, dst); } @@ -370,7 +346,6 @@ void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const { SyncClock::Dirty *dirty = &dst->dirty_[i]; const unsigned tid = dirty->tid(); if (tid == tid_ || tid == kInvalidTid) { - CPP_STAT_INC(StatClockReleaseFast); dirty->set_tid(tid_); dirty->epoch = clk_[tid_]; return; @@ -379,7 +354,6 @@ void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const { // Reset all 'acquired' flags, O(N). // We are going to touch dst elements, so we need to unshare it. dst->Unshare(c); - CPP_STAT_INC(StatClockReleaseSlow); dst->elem(tid_).epoch = clk_[tid_]; for (uptr i = 0; i < dst->size_; i++) dst->elem(i).reused = 0; @@ -456,7 +430,6 @@ void SyncClock::ResetImpl() { } void SyncClock::Resize(ClockCache *c, uptr nclk) { - CPP_STAT_INC(StatClockReleaseResize); Unshare(c); if (nclk <= capacity()) { // Memory is already allocated, just increase the size. diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h index f53787a..5c8f280 100644 --- a/libsanitizer/tsan/tsan_defs.h +++ b/libsanitizer/tsan/tsan_defs.h @@ -15,7 +15,6 @@ #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_libc.h" -#include "tsan_stat.h" #include "ubsan/ubsan_platform.h" // Setup defaults for compile definitions. @@ -23,10 +22,6 @@ # define TSAN_NO_HISTORY 0 #endif -#ifndef TSAN_COLLECT_STATS -# define TSAN_COLLECT_STATS 0 -#endif - #ifndef TSAN_CONTAINS_UBSAN # if CAN_SANITIZE_UB && !SANITIZER_GO # define TSAN_CONTAINS_UBSAN 1 @@ -107,23 +102,12 @@ void build_consistency_debug(); void build_consistency_release(); #endif -#if TSAN_COLLECT_STATS -void build_consistency_stats(); -#else -void build_consistency_nostats(); -#endif - static inline void USED build_consistency() { #if SANITIZER_DEBUG build_consistency_debug(); #else build_consistency_release(); #endif -#if TSAN_COLLECT_STATS - build_consistency_stats(); -#else - build_consistency_nostats(); -#endif } template<typename T> diff --git a/libsanitizer/tsan/tsan_interceptors.h b/libsanitizer/tsan/tsan_interceptors.h index 29576ea..c5716f5 100644 --- a/libsanitizer/tsan/tsan_interceptors.h +++ b/libsanitizer/tsan/tsan_interceptors.h @@ -30,14 +30,14 @@ inline bool in_symbolizer() { } // namespace __tsan -#define SCOPED_INTERCEPTOR_RAW(func, ...) \ - cur_thread_init(); \ - ThreadState *thr = cur_thread(); \ - const uptr caller_pc = GET_CALLER_PC(); \ - ScopedInterceptor si(thr, #func, caller_pc); \ - const uptr pc = StackTrace::GetCurrentPc(); \ - (void)pc; \ -/**/ +#define SCOPED_INTERCEPTOR_RAW(func, ...) \ + cur_thread_init(); \ + ThreadState *thr = cur_thread(); \ + const uptr caller_pc = GET_CALLER_PC(); \ + ScopedInterceptor si(thr, #func, caller_pc); \ + const uptr pc = GET_CURRENT_PC(); \ + (void)pc; \ + /**/ #define SCOPED_TSAN_INTERCEPTOR(func, ...) \ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ diff --git a/libsanitizer/tsan/tsan_interceptors_mac.cpp b/libsanitizer/tsan/tsan_interceptors_mac.cpp index ed10fcc..2d400c7 100644 --- a/libsanitizer/tsan/tsan_interceptors_mac.cpp +++ b/libsanitizer/tsan/tsan_interceptors_mac.cpp @@ -44,8 +44,9 @@ namespace __tsan { // actually aliases of each other, and we cannot have different interceptors for // them, because they're actually the same function. Thus, we have to stay // conservative and treat the non-barrier versions as mo_acq_rel. -static const morder kMacOrderBarrier = mo_acq_rel; -static const morder kMacOrderNonBarrier = mo_acq_rel; +static constexpr morder kMacOrderBarrier = mo_acq_rel; +static constexpr morder kMacOrderNonBarrier = mo_acq_rel; +static constexpr morder kMacFailureOrder = mo_relaxed; #define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ @@ -110,7 +111,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \ return tsan_atomic_f##_compare_exchange_strong( \ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderNonBarrier, kMacOrderNonBarrier); \ + kMacOrderNonBarrier, kMacFailureOrder); \ } \ \ TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \ @@ -118,7 +119,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \ return tsan_atomic_f##_compare_exchange_strong( \ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderBarrier, kMacOrderNonBarrier); \ + kMacOrderBarrier, kMacFailureOrder); \ } OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int) diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp index 2651e22..6808f2e 100644 --- a/libsanitizer/tsan/tsan_interceptors_posix.cpp +++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp @@ -71,7 +71,8 @@ struct ucontext_t { }; #endif -#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 +#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ + defined(__s390x__) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" #elif defined(__aarch64__) || SANITIZER_PPC64V2 #define PTHREAD_ABI_BASE "GLIBC_2.17" @@ -2270,6 +2271,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, #define NEED_TLS_GET_ADDR #endif #undef SANITIZER_INTERCEPT_TLS_GET_ADDR +#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1 #undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) @@ -2585,6 +2587,20 @@ static void syscall_post_fork(uptr pc, int pid) { #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" #ifdef NEED_TLS_GET_ADDR + +static void handle_tls_addr(void *arg, void *res) { + ThreadState *thr = cur_thread(); + if (!thr) + return; + DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, + thr->tls_addr + thr->tls_size); + if (!dtv) + return; + // New DTLS block has been allocated. + MemoryResetRange(thr, 0, dtv->beg, dtv->size); +} + +#if !SANITIZER_S390 // Define own interceptor instead of sanitizer_common's for three reasons: // 1. It must not process pending signals. // Signal handlers may contain MOVDQA instruction (see below). @@ -2597,18 +2613,18 @@ static void syscall_post_fork(uptr pc, int pid) { // execute MOVDQA with stack addresses. TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) { void *res = REAL(__tls_get_addr)(arg); - ThreadState *thr = cur_thread(); - if (!thr) - return res; - DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, - thr->tls_addr + thr->tls_size); - if (!dtv) - return res; - // New DTLS block has been allocated. - MemoryResetRange(thr, 0, dtv->beg, dtv->size); + handle_tls_addr(arg, res); + return res; +} +#else // SANITIZER_S390 +TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { + uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); + char *tp = static_cast<char *>(__builtin_thread_pointer()); + handle_tls_addr(arg, res + tp); return res; } #endif +#endif #if SANITIZER_NETBSD TSAN_INTERCEPTOR(void, _lwp_exit) { @@ -2830,7 +2846,12 @@ void InitializeInterceptors() { TSAN_INTERCEPT(_exit); #ifdef NEED_TLS_GET_ADDR +#if !SANITIZER_S390 TSAN_INTERCEPT(__tls_get_addr); +#else + TSAN_INTERCEPT(__tls_get_addr_internal); + TSAN_INTERCEPT(__tls_get_offset); +#endif #endif TSAN_MAYBE_INTERCEPT__LWP_EXIT; diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h index 6e022b5..124aa2f 100644 --- a/libsanitizer/tsan/tsan_interface.h +++ b/libsanitizer/tsan/tsan_interface.h @@ -196,7 +196,8 @@ typedef unsigned short a16; typedef unsigned int a32; typedef unsigned long long a64; #if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \ - || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64) + || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ + !defined(__mips64) && !defined(__s390x__) __extension__ typedef __int128 a128; # define __TSAN_HAS_INT128 1 #else diff --git a/libsanitizer/tsan/tsan_interface_ann.cpp b/libsanitizer/tsan/tsan_interface_ann.cpp index 99516d9..175855f 100644 --- a/libsanitizer/tsan/tsan_interface_ann.cpp +++ b/libsanitizer/tsan/tsan_interface_ann.cpp @@ -49,8 +49,6 @@ class ScopedAnnotation { return ret; \ ThreadState *thr = cur_thread(); \ const uptr caller_pc = (uptr)__builtin_return_address(0); \ - StatInc(thr, StatAnnotation); \ - StatInc(thr, Stat##typ); \ ScopedAnnotation sa(thr, __func__, caller_pc); \ const uptr pc = StackTrace::GetCurrentPc(); \ (void)pc; \ @@ -77,9 +75,7 @@ struct DynamicAnnContext { ExpectRace expect; ExpectRace benign; - DynamicAnnContext() - : mtx(MutexTypeAnnotations, StatMtxAnnotations) { - } + DynamicAnnContext() : mtx(MutexTypeAnnotations) {} }; static DynamicAnnContext *dyn_ann_ctx; diff --git a/libsanitizer/tsan/tsan_interface_atomic.cpp b/libsanitizer/tsan/tsan_interface_atomic.cpp index 3f459af..21fe4a1 100644 --- a/libsanitizer/tsan/tsan_interface_atomic.cpp +++ b/libsanitizer/tsan/tsan_interface_atomic.cpp @@ -402,34 +402,45 @@ static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) { template<typename T> static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v, morder mo, morder fmo) { - (void)fmo; // Unused because llvm does not pass it yet. + // 31.7.2.18: "The failure argument shall not be memory_order_release + // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic + // (mo_relaxed) when those are used. + CHECK(IsLoadOrder(fmo)); + MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>()); SyncVar *s = 0; - bool write_lock = mo != mo_acquire && mo != mo_consume; - if (mo != mo_relaxed) { + bool write_lock = IsReleaseOrder(mo); + + if (mo != mo_relaxed || fmo != mo_relaxed) s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock); + + T cc = *c; + T pr = func_cas(a, cc, v); + bool success = pr == cc; + if (!success) { + *c = pr; + mo = fmo; + } + + if (s) { thr->fast_state.IncrementEpoch(); // Can't increment epoch w/o writing to the trace as well. TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0); - if (IsAcqRelOrder(mo)) + + if (success && IsAcqRelOrder(mo)) AcquireReleaseImpl(thr, pc, &s->clock); - else if (IsReleaseOrder(mo)) + else if (success && IsReleaseOrder(mo)) ReleaseImpl(thr, pc, &s->clock); else if (IsAcquireOrder(mo)) AcquireImpl(thr, pc, &s->clock); - } - T cc = *c; - T pr = func_cas(a, cc, v); - if (s) { + if (write_lock) s->mtx.Unlock(); else s->mtx.ReadUnlock(); } - if (pr == cc) - return true; - *c = pr; - return false; + + return success; } template<typename T> @@ -481,7 +492,6 @@ static morder convert_morder(morder mo) { const uptr callpc = (uptr)__builtin_return_address(0); \ uptr pc = StackTrace::GetCurrentPc(); \ mo = convert_morder(mo); \ - AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \ ScopedAtomic sa(thr, callpc, a, mo, __func__); \ return Atomic##func(thr, pc, __VA_ARGS__); \ /**/ @@ -502,22 +512,6 @@ class ScopedAtomic { ThreadState *thr_; }; -static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) { - StatInc(thr, StatAtomic); - StatInc(thr, t); - StatInc(thr, size == 1 ? StatAtomic1 - : size == 2 ? StatAtomic2 - : size == 4 ? StatAtomic4 - : size == 8 ? StatAtomic8 - : StatAtomic16); - StatInc(thr, mo == mo_relaxed ? StatAtomicRelaxed - : mo == mo_consume ? StatAtomicConsume - : mo == mo_acquire ? StatAtomicAcquire - : mo == mo_release ? StatAtomicRelease - : mo == mo_acq_rel ? StatAtomicAcq_Rel - : StatAtomicSeq_Cst); -} - extern "C" { SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) { diff --git a/libsanitizer/tsan/tsan_mman.cpp b/libsanitizer/tsan/tsan_mman.cpp index 45a39f0..7765bc0 100644 --- a/libsanitizer/tsan/tsan_mman.cpp +++ b/libsanitizer/tsan/tsan_mman.cpp @@ -70,10 +70,7 @@ struct GlobalProc { Mutex mtx; Processor *proc; - GlobalProc() - : mtx(MutexTypeGlobalProc, StatMtxGlobalProc) - , proc(ProcCreate()) { - } + GlobalProc() : mtx(MutexTypeGlobalProc), proc(ProcCreate()) {} }; static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64); diff --git a/libsanitizer/tsan/tsan_mutex.cpp b/libsanitizer/tsan/tsan_mutex.cpp index 7a0918f..d8b1826 100644 --- a/libsanitizer/tsan/tsan_mutex.cpp +++ b/libsanitizer/tsan/tsan_mutex.cpp @@ -207,15 +207,12 @@ class Backoff { static const int kActiveSpinCnt = 20; }; -Mutex::Mutex(MutexType type, StatType stat_type) { +Mutex::Mutex(MutexType type) { CHECK_GT(type, MutexTypeInvalid); CHECK_LT(type, MutexTypeCount); #if SANITIZER_DEBUG type_ = type; #endif -#if TSAN_COLLECT_STATS - stat_type_ = stat_type; -#endif atomic_store(&state_, kUnlocked, memory_order_relaxed); } @@ -236,9 +233,6 @@ void Mutex::Lock() { cmp = kUnlocked; if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock, memory_order_acquire)) { -#if TSAN_COLLECT_STATS && !SANITIZER_GO - StatInc(cur_thread(), stat_type_, backoff.Contention()); -#endif return; } } @@ -264,9 +258,6 @@ void Mutex::ReadLock() { for (Backoff backoff; backoff.Do();) { prev = atomic_load(&state_, memory_order_acquire); if ((prev & kWriteLock) == 0) { -#if TSAN_COLLECT_STATS && !SANITIZER_GO - StatInc(cur_thread(), stat_type_, backoff.Contention()); -#endif return; } } diff --git a/libsanitizer/tsan/tsan_mutex.h b/libsanitizer/tsan/tsan_mutex.h index 80fdc6e..9a579ea 100644 --- a/libsanitizer/tsan/tsan_mutex.h +++ b/libsanitizer/tsan/tsan_mutex.h @@ -41,7 +41,7 @@ enum MutexType { class Mutex { public: - explicit Mutex(MutexType type, StatType stat_type); + explicit Mutex(MutexType type); ~Mutex(); void Lock(); @@ -57,9 +57,6 @@ class Mutex { #if SANITIZER_DEBUG MutexType type_; #endif -#if TSAN_COLLECT_STATS - StatType stat_type_; -#endif Mutex(const Mutex&); void operator = (const Mutex&); diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h index 101522d..8bd218e 100644 --- a/libsanitizer/tsan/tsan_platform.h +++ b/libsanitizer/tsan/tsan_platform.h @@ -365,6 +365,38 @@ struct Mapping47 { // Indicates the runtime will define the memory regions at runtime. #define TSAN_RUNTIME_VMA 1 +#elif defined(__s390x__) +/* +C/C++ on linux/s390x +While the kernel provides a 64-bit address space, we have to restrict ourselves +to 48 bits due to how e.g. SyncVar::GetId() works. +0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB +0e00 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) +8000 0000 0000 - 9000 0000 0000: - +9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) +9800 0000 0000 - a000 0000 0000: - +a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) +b000 0000 0000 - be00 0000 0000: - +be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator) +*/ +struct Mapping { + static const uptr kMetaShadowBeg = 0x900000000000ull; + static const uptr kMetaShadowEnd = 0x980000000000ull; + static const uptr kTraceMemBeg = 0xa00000000000ull; + static const uptr kTraceMemEnd = 0xb00000000000ull; + static const uptr kShadowBeg = 0x400000000000ull; + static const uptr kShadowEnd = 0x800000000000ull; + static const uptr kHeapMemBeg = 0xbe0000000000ull; + static const uptr kHeapMemEnd = 0xc00000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x0e0000000000ull; + static const uptr kHiAppMemBeg = 0xc00000004000ull; + static const uptr kHiAppMemEnd = 0xc00000004000ull; + static const uptr kAppMemMsk = 0xb00000000000ull; + static const uptr kAppMemXor = 0x100000000000ull; + static const uptr kVdsoBeg = 0xfffffffff000ull; +}; #endif #elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE @@ -528,6 +560,28 @@ struct Mapping47 { #define TSAN_RUNTIME_VMA 1 +#elif SANITIZER_GO && defined(__s390x__) +/* +Go on linux/s390x +0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB +1000 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) +8000 0000 0000 - 9000 0000 0000: - +9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) +9800 0000 0000 - a000 0000 0000: - +a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) +*/ +struct Mapping { + static const uptr kMetaShadowBeg = 0x900000000000ull; + static const uptr kMetaShadowEnd = 0x980000000000ull; + static const uptr kTraceMemBeg = 0xa00000000000ull; + static const uptr kTraceMemEnd = 0xb00000000000ull; + static const uptr kShadowBeg = 0x400000000000ull; + static const uptr kShadowEnd = 0x800000000000ull; + static const uptr kAppMemBeg = 0x000000001000ull; + static const uptr kAppMemEnd = 0x100000000000ull; +}; + #else # error "Unknown platform" #endif diff --git a/libsanitizer/tsan/tsan_platform_linux.cpp b/libsanitizer/tsan/tsan_platform_linux.cpp index e5b6690..cfe597e 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cpp +++ b/libsanitizer/tsan/tsan_platform_linux.cpp @@ -391,6 +391,10 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { return mangled_sp ^ xor_key; #elif defined(__mips__) return mangled_sp; +#elif defined(__s390x__) + // tcbhead_t.stack_guard + uptr xor_key = ((uptr *)__builtin_thread_pointer())[5]; + return mangled_sp ^ xor_key; #else #error "Unknown platform" #endif @@ -411,6 +415,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # define LONG_JMP_SP_ENV_SLOT 13 # elif defined(__mips64) # define LONG_JMP_SP_ENV_SLOT 1 +# elif defined(__s390x__) +# define LONG_JMP_SP_ENV_SLOT 9 # else # define LONG_JMP_SP_ENV_SLOT 6 # endif diff --git a/libsanitizer/tsan/tsan_platform_posix.cpp b/libsanitizer/tsan/tsan_platform_posix.cpp index 73e1d45..1c6198c 100644 --- a/libsanitizer/tsan/tsan_platform_posix.cpp +++ b/libsanitizer/tsan/tsan_platform_posix.cpp @@ -72,11 +72,15 @@ void InitializeShadowMemory() { InitializeShadowMemoryPlatform(); } -static void ProtectRange(uptr beg, uptr end) { +static bool TryProtectRange(uptr beg, uptr end) { CHECK_LE(beg, end); if (beg == end) - return; - if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) { + return true; + return beg == (uptr)MmapFixedNoAccess(beg, end - beg); +} + +static void ProtectRange(uptr beg, uptr end) { + if (!TryProtectRange(beg, end)) { Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); Printf("FATAL: Make sure you are not using unlimited stack\n"); Die(); @@ -118,6 +122,16 @@ void CheckAndProtect() { ProtectRange(TraceMemEnd(), HeapMemBeg()); ProtectRange(HeapEnd(), HiAppMemBeg()); #endif + +#if defined(__s390x__) + // Protect the rest of the address space. + const uptr user_addr_max_l4 = 0x0020000000000000ull; + const uptr user_addr_max_l5 = 0xfffffffffffff000ull; + // All the maintained s390x kernels support at least 4-level page tables. + ProtectRange(HiAppMemEnd(), user_addr_max_l4); + // Older s390x kernels may not support 5-level page tables. + TryProtectRange(user_addr_max_l4, user_addr_max_l5); +#endif } #endif diff --git a/libsanitizer/tsan/tsan_rtl.cpp b/libsanitizer/tsan/tsan_rtl.cpp index 0efa997..bcf489a 100644 --- a/libsanitizer/tsan/tsan_rtl.cpp +++ b/libsanitizer/tsan/tsan_rtl.cpp @@ -77,7 +77,7 @@ void OnInitialize() { } #endif -static char thread_registry_placeholder[sizeof(ThreadRegistry)]; +static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadContextBase *CreateThreadContext(u32 tid) { // Map thread trace when context is created. @@ -115,15 +115,15 @@ static const u32 kThreadQuarantineSize = 64; Context::Context() : initialized(), - report_mtx(MutexTypeReport, StatMtxReport), + report_mtx(MutexTypeReport), nreported(), nmissed_expected(), thread_registry(new (thread_registry_placeholder) ThreadRegistry( CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)), - racy_mtx(MutexTypeRacy, StatMtxRacy), + racy_mtx(MutexTypeRacy), racy_stacks(), racy_addresses(), - fired_suppressions_mtx(MutexTypeFired, StatMtxFired), + fired_suppressions_mtx(MutexTypeFired), clock_alloc(LINKER_INITIALIZED, "clock allocator") { fired_suppressions.reserve(8); } @@ -522,18 +522,14 @@ int Finalize(ThreadState *thr) { failed = OnFinalize(failed); -#if TSAN_COLLECT_STATS - StatAggregate(ctx->stat, thr->stat); - StatOutput(ctx->stat); -#endif - return failed ? common_flags()->exitcode : 0; } #if !SANITIZER_GO -void ForkBefore(ThreadState *thr, uptr pc) { +void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { ctx->thread_registry->Lock(); ctx->report_mtx.Lock(); + ScopedErrorReportLock::Lock(); // Suppress all reports in the pthread_atfork callbacks. // Reports will deadlock on the report_mtx. // We could ignore sync operations as well, @@ -545,16 +541,18 @@ void ForkBefore(ThreadState *thr, uptr pc) { thr->ignore_interceptors++; } -void ForkParentAfter(ThreadState *thr, uptr pc) { +void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry->Unlock(); } -void ForkChildAfter(ThreadState *thr, uptr pc) { +void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry->Unlock(); @@ -693,9 +691,6 @@ ALWAYS_INLINE void MemoryAccessImpl1(ThreadState *thr, uptr addr, int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic, u64 *shadow_mem, Shadow cur) { - StatInc(thr, StatMop); - StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); - StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); // This potentially can live in an MMX/SSE scratch register. // The required intrinsics are: @@ -752,7 +747,6 @@ void MemoryAccessImpl1(ThreadState *thr, uptr addr, return; // choose a random candidate slot and replace it StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); - StatInc(thr, StatShadowReplace); return; RACE: HandleRace(thr, shadow_mem, cur, old); @@ -891,19 +885,11 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, if (!SANITIZER_GO && !kAccessIsWrite && *shadow_mem == kShadowRodata) { // Access to .rodata section, no races here. // Measurements show that it can be 10-20% of all memory accesses. - StatInc(thr, StatMop); - StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); - StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); - StatInc(thr, StatMopRodata); return; } FastState fast_state = thr->fast_state; if (UNLIKELY(fast_state.GetIgnoreBit())) { - StatInc(thr, StatMop); - StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); - StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); - StatInc(thr, StatMopIgnored); return; } @@ -914,10 +900,6 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(), thr->fast_synch_epoch, kAccessIsWrite))) { - StatInc(thr, StatMop); - StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); - StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); - StatInc(thr, StatMopSame); return; } @@ -939,10 +921,6 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, u64 *shadow_mem, Shadow cur) { if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(), thr->fast_synch_epoch, kAccessIsWrite))) { - StatInc(thr, StatMop); - StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); - StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); - StatInc(thr, StatMopSame); return; } @@ -999,7 +977,6 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, // Reset middle part. u64 *p1 = p; p = RoundDown(end, kPageSize); - UnmapOrDie((void*)p1, (uptr)p - (uptr)p1); if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1)) Die(); // Set the ending. @@ -1059,7 +1036,6 @@ void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, ALWAYS_INLINE USED void FuncEntry(ThreadState *thr, uptr pc) { - StatInc(thr, StatFuncEnter); DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); if (kCollectHistory) { thr->fast_state.IncrementEpoch(); @@ -1081,7 +1057,6 @@ void FuncEntry(ThreadState *thr, uptr pc) { ALWAYS_INLINE USED void FuncExit(ThreadState *thr) { - StatInc(thr, StatFuncExit); DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); if (kCollectHistory) { thr->fast_state.IncrementEpoch(); @@ -1156,12 +1131,6 @@ void build_consistency_debug() {} void build_consistency_release() {} #endif -#if TSAN_COLLECT_STATS -void build_consistency_stats() {} -#else -void build_consistency_nostats() {} -#endif - } // namespace __tsan #if !SANITIZER_GO diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index 3ae519d..6576d40 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -400,9 +400,6 @@ struct ThreadState { Vector<JmpBuf> jmp_bufs; int ignore_interceptors; #endif -#if TSAN_COLLECT_STATS - u64 stat[StatCnt]; -#endif const u32 tid; const int unique_id; bool in_symbolizer; @@ -550,7 +547,6 @@ struct Context { Flags flags; - u64 stat[StatCnt]; u64 int_alloc_cnt[MBlockTypeCount]; u64 int_alloc_siz[MBlockTypeCount]; }; @@ -658,22 +654,6 @@ void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack, ObtainCurrentStack(thr, pc, &stack); \ stack.ReverseOrder(); -#if TSAN_COLLECT_STATS -void StatAggregate(u64 *dst, u64 *src); -void StatOutput(u64 *stat); -#endif - -void ALWAYS_INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) { -#if TSAN_COLLECT_STATS - thr->stat[typ] += n; -#endif -} -void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) { -#if TSAN_COLLECT_STATS - thr->stat[typ] = n; -#endif -} - void MapShadow(uptr addr, uptr size); void MapThreadTrace(uptr addr, uptr size, const char *name); void DontNeedShadowFor(uptr addr, uptr size); @@ -854,7 +834,6 @@ void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs, DCHECK_GE((int)typ, 0); DCHECK_LE((int)typ, 7); DCHECK_EQ(GetLsb(addr, kEventPCBits), addr); - StatInc(thr, StatEvents); u64 pos = fs.GetTracePos(); if (UNLIKELY((pos % kTracePartSize) == 0)) { #if !SANITIZER_GO diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cpp b/libsanitizer/tsan/tsan_rtl_mutex.cpp index 0a8f3aa..a214a33 100644 --- a/libsanitizer/tsan/tsan_rtl_mutex.cpp +++ b/libsanitizer/tsan/tsan_rtl_mutex.cpp @@ -65,7 +65,6 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ, void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { DPrintf("#%d: MutexCreate %zx flagz=0x%x\n", thr->tid, addr, flagz); - StatInc(thr, StatMutexCreate); if (!(flagz & MutexFlagLinkerInit) && IsAppMem(addr)) { CHECK(!thr->is_freeing); thr->is_freeing = true; @@ -81,7 +80,6 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr); - StatInc(thr, StatMutexDestroy); SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true); if (s == 0) return; @@ -183,11 +181,9 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) { const bool first = s->recursion == 0; s->recursion += rec; if (first) { - StatInc(thr, StatMutexLock); AcquireImpl(thr, pc, &s->clock); AcquireImpl(thr, pc, &s->read_clock); } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) { - StatInc(thr, StatMutexRecLock); } thr->mset.Add(s->GetId(), true, thr->fast_state.epoch()); bool pre_lock = false; @@ -229,11 +225,9 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1; s->recursion -= rec; if (s->recursion == 0) { - StatInc(thr, StatMutexUnlock); s->owner_tid = kInvalidTid; ReleaseStoreImpl(thr, pc, &s->clock); } else { - StatInc(thr, StatMutexRecUnlock); } } thr->mset.Del(s->GetId(), true); @@ -268,7 +262,6 @@ void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz); - StatInc(thr, StatMutexReadLock); if (IsAppMem(addr)) MemoryReadAtomic(thr, pc, addr, kSizeLog1); SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false); @@ -308,7 +301,6 @@ void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) { DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr); - StatInc(thr, StatMutexReadUnlock); if (IsAppMem(addr)) MemoryReadAtomic(thr, pc, addr, kSizeLog1); SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); @@ -348,7 +340,6 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) { if (s->owner_tid == kInvalidTid) { // Seems to be read unlock. write = false; - StatInc(thr, StatMutexReadUnlock); thr->fast_state.IncrementEpoch(); TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId()); ReleaseImpl(thr, pc, &s->read_clock); @@ -359,11 +350,9 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) { CHECK_GT(s->recursion, 0); s->recursion--; if (s->recursion == 0) { - StatInc(thr, StatMutexUnlock); s->owner_tid = kInvalidTid; ReleaseStoreImpl(thr, pc, &s->clock); } else { - StatInc(thr, StatMutexRecUnlock); } } else if (!s->IsFlagSet(MutexFlagBroken)) { s->SetFlags(MutexFlagBroken); @@ -494,7 +483,6 @@ void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { return; thr->clock.set(thr->fast_state.epoch()); thr->clock.acquire(&thr->proc()->clock_cache, c); - StatInc(thr, StatSyncAcquire); } void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { @@ -503,7 +491,6 @@ void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { thr->clock.set(thr->fast_state.epoch()); thr->fast_synch_epoch = thr->fast_state.epoch(); thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c); - StatInc(thr, StatSyncReleaseStoreAcquire); } void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { @@ -512,7 +499,6 @@ void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { thr->clock.set(thr->fast_state.epoch()); thr->fast_synch_epoch = thr->fast_state.epoch(); thr->clock.release(&thr->proc()->clock_cache, c); - StatInc(thr, StatSyncRelease); } void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) { @@ -521,7 +507,6 @@ void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) { thr->clock.set(thr->fast_state.epoch()); thr->fast_synch_epoch = thr->fast_state.epoch(); thr->clock.ReleaseStore(&thr->proc()->clock_cache, c); - StatInc(thr, StatSyncRelease); } void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { @@ -530,8 +515,6 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { thr->clock.set(thr->fast_state.epoch()); thr->fast_synch_epoch = thr->fast_state.epoch(); thr->clock.acq_rel(&thr->proc()->clock_cache, c); - StatInc(thr, StatSyncAcquire); - StatInc(thr, StatSyncRelease); } void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) { diff --git a/libsanitizer/tsan/tsan_rtl_ppc64.S b/libsanitizer/tsan/tsan_rtl_ppc64.S index 9e533a7..8285e21 100644 --- a/libsanitizer/tsan/tsan_rtl_ppc64.S +++ b/libsanitizer/tsan/tsan_rtl_ppc64.S @@ -1,6 +1,5 @@ #include "tsan_ppc_regs.h" - .machine altivec .section .text .hidden __tsan_setjmp .globl _setjmp diff --git a/libsanitizer/tsan/tsan_rtl_s390x.S b/libsanitizer/tsan/tsan_rtl_s390x.S new file mode 100644 index 0000000..fcff35f --- /dev/null +++ b/libsanitizer/tsan/tsan_rtl_s390x.S @@ -0,0 +1,47 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#define CFA_OFFSET 160 +#define R2_REL_OFFSET 16 +#define R3_REL_OFFSET 24 +#define R14_REL_OFFSET 112 +#define R15_REL_OFFSET 120 +#define FRAME_SIZE 160 + +.text + +ASM_HIDDEN(__tsan_setjmp) + +.macro intercept symbol, real +.comm \real, 8, 8 +.globl ASM_SYMBOL_INTERCEPTOR(\symbol) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol)) +ASM_SYMBOL_INTERCEPTOR(\symbol): + CFI_STARTPROC + stmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r2, R2_REL_OFFSET) + CFI_REL_OFFSET(%r3, R3_REL_OFFSET) + stmg %r14, %r15, R14_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r14, R14_REL_OFFSET) + CFI_REL_OFFSET(%r15, R15_REL_OFFSET) + aghi %r15, -FRAME_SIZE + CFI_ADJUST_CFA_OFFSET(FRAME_SIZE) + la %r2, FRAME_SIZE(%r15) + brasl %r14, ASM_SYMBOL(__tsan_setjmp) + lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15) + CFI_RESTORE(%r14) + CFI_RESTORE(%r15) + CFI_DEF_CFA_OFFSET(CFA_OFFSET) + lmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_RESTORE(%r2) + CFI_RESTORE(%r3) + larl %r1, \real + lg %r1, 0(%r1) + br %r1 + CFI_ENDPROC + ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol)) +.endm + +intercept setjmp, _ZN14__interception11real_setjmpE +intercept _setjmp, _ZN14__interception12real__setjmpE +intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE +intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE diff --git a/libsanitizer/tsan/tsan_rtl_thread.cpp b/libsanitizer/tsan/tsan_rtl_thread.cpp index 6d1ccd8..cdb6e60 100644 --- a/libsanitizer/tsan/tsan_rtl_thread.cpp +++ b/libsanitizer/tsan/tsan_rtl_thread.cpp @@ -61,8 +61,6 @@ void ThreadContext::OnCreated(void *arg) { TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0); ReleaseImpl(args->thr, 0, &sync); creation_stack_id = CurrentStackId(args->thr, args->pc); - if (reuse_count == 0) - StatInc(args->thr, StatThreadMaxTid); } void ThreadContext::OnReset() { @@ -115,7 +113,6 @@ void ThreadContext::OnStarted(void *arg) { thr->fast_synch_epoch = epoch0; AcquireImpl(thr, 0, &sync); - StatInc(thr, StatSyncAcquire); sync.Reset(&thr->proc()->clock_cache); thr->is_inited = true; DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx " @@ -149,9 +146,6 @@ void ThreadContext::OnFinished() { PlatformCleanUpThreadState(thr); #endif thr->~ThreadState(); -#if TSAN_COLLECT_STATS - StatAggregate(ctx->stat, thr->stat); -#endif thr = 0; } @@ -232,13 +226,11 @@ int ThreadCount(ThreadState *thr) { } int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { - StatInc(thr, StatThreadCreate); OnCreatedArgs args = { thr, pc }; u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers. int tid = ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args); DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid); - StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads()); return tid; } @@ -280,7 +272,6 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, void ThreadFinish(ThreadState *thr) { ThreadCheckIgnore(thr); - StatInc(thr, StatThreadFinish); if (thr->stk_addr && thr->stk_size) DontNeedShadowFor(thr->stk_addr, thr->stk_size); if (thr->tls_addr && thr->tls_size) @@ -372,13 +363,10 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, } #endif - StatInc(thr, StatMopRange); - if (*shadow_mem == kShadowRodata) { DCHECK(!is_write); // Access to .rodata section, no races here. // Measurements show that it can be 10-20% of all memory accesses. - StatInc(thr, StatMopRangeRodata); return; } diff --git a/libsanitizer/tsan/tsan_stack_trace.cpp b/libsanitizer/tsan/tsan_stack_trace.cpp index 403a21a..6c703d7 100644 --- a/libsanitizer/tsan/tsan_stack_trace.cpp +++ b/libsanitizer/tsan/tsan_stack_trace.cpp @@ -54,10 +54,8 @@ void __sanitizer::BufferedStackTrace::UnwindImpl( uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { uptr top = 0; uptr bottom = 0; - if (StackTrace::WillUseFastUnwind(request_fast)) { - GetThreadStackTopAndBottom(false, &top, &bottom); - Unwind(max_depth, pc, bp, nullptr, top, bottom, true); - } else - Unwind(max_depth, pc, 0, context, 0, 0, false); + GetThreadStackTopAndBottom(false, &top, &bottom); + bool fast = StackTrace::WillUseFastUnwind(request_fast); + Unwind(max_depth, pc, bp, context, top, bottom, fast); } #endif // SANITIZER_GO diff --git a/libsanitizer/tsan/tsan_stat.cpp b/libsanitizer/tsan/tsan_stat.cpp deleted file mode 100644 index 78f3cce..0000000 --- a/libsanitizer/tsan/tsan_stat.cpp +++ /dev/null @@ -1,186 +0,0 @@ -//===-- tsan_stat.cpp -----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_stat.h" -#include "tsan_rtl.h" - -namespace __tsan { - -#if TSAN_COLLECT_STATS - -void StatAggregate(u64 *dst, u64 *src) { - for (int i = 0; i < StatCnt; i++) - dst[i] += src[i]; -} - -void StatOutput(u64 *stat) { - stat[StatShadowNonZero] = stat[StatShadowProcessed] - stat[StatShadowZero]; - - static const char *name[StatCnt] = {}; - name[StatMop] = "Memory accesses "; - name[StatMopRead] = " Including reads "; - name[StatMopWrite] = " writes "; - name[StatMop1] = " Including size 1 "; - name[StatMop2] = " size 2 "; - name[StatMop4] = " size 4 "; - name[StatMop8] = " size 8 "; - name[StatMopSame] = " Including same "; - name[StatMopIgnored] = " Including ignored "; - name[StatMopRange] = " Including range "; - name[StatMopRodata] = " Including .rodata "; - name[StatMopRangeRodata] = " Including .rodata range "; - name[StatShadowProcessed] = "Shadow processed "; - name[StatShadowZero] = " Including empty "; - name[StatShadowNonZero] = " Including non empty "; - name[StatShadowSameSize] = " Including same size "; - name[StatShadowIntersect] = " intersect "; - name[StatShadowNotIntersect] = " not intersect "; - name[StatShadowSameThread] = " Including same thread "; - name[StatShadowAnotherThread] = " another thread "; - name[StatShadowReplace] = " Including evicted "; - - name[StatFuncEnter] = "Function entries "; - name[StatFuncExit] = "Function exits "; - name[StatEvents] = "Events collected "; - - name[StatThreadCreate] = "Total threads created "; - name[StatThreadFinish] = " threads finished "; - name[StatThreadReuse] = " threads reused "; - name[StatThreadMaxTid] = " max tid "; - name[StatThreadMaxAlive] = " max alive threads "; - - name[StatMutexCreate] = "Mutexes created "; - name[StatMutexDestroy] = " destroyed "; - name[StatMutexLock] = " lock "; - name[StatMutexUnlock] = " unlock "; - name[StatMutexRecLock] = " recursive lock "; - name[StatMutexRecUnlock] = " recursive unlock "; - name[StatMutexReadLock] = " read lock "; - name[StatMutexReadUnlock] = " read unlock "; - - name[StatSyncCreated] = "Sync objects created "; - name[StatSyncDestroyed] = " destroyed "; - name[StatSyncAcquire] = " acquired "; - name[StatSyncRelease] = " released "; - - name[StatClockAcquire] = "Clock acquire "; - name[StatClockAcquireEmpty] = " empty clock "; - name[StatClockAcquireFastRelease] = " fast from release-store "; - name[StatClockAcquireFull] = " full (slow) "; - name[StatClockAcquiredSomething] = " acquired something "; - name[StatClockRelease] = "Clock release "; - name[StatClockReleaseResize] = " resize "; - name[StatClockReleaseFast] = " fast "; - name[StatClockReleaseSlow] = " dirty overflow (slow) "; - name[StatClockReleaseFull] = " full (slow) "; - name[StatClockReleaseAcquired] = " was acquired "; - name[StatClockReleaseClearTail] = " clear tail "; - name[StatClockStore] = "Clock release store "; - name[StatClockStoreResize] = " resize "; - name[StatClockStoreFast] = " fast "; - name[StatClockStoreFull] = " slow "; - name[StatClockStoreTail] = " clear tail "; - name[StatClockAcquireRelease] = "Clock acquire-release "; - - name[StatAtomic] = "Atomic operations "; - name[StatAtomicLoad] = " Including load "; - name[StatAtomicStore] = " store "; - name[StatAtomicExchange] = " exchange "; - name[StatAtomicFetchAdd] = " fetch_add "; - name[StatAtomicFetchSub] = " fetch_sub "; - name[StatAtomicFetchAnd] = " fetch_and "; - name[StatAtomicFetchOr] = " fetch_or "; - name[StatAtomicFetchXor] = " fetch_xor "; - name[StatAtomicFetchNand] = " fetch_nand "; - name[StatAtomicCAS] = " compare_exchange "; - name[StatAtomicFence] = " fence "; - name[StatAtomicRelaxed] = " Including relaxed "; - name[StatAtomicConsume] = " consume "; - name[StatAtomicAcquire] = " acquire "; - name[StatAtomicRelease] = " release "; - name[StatAtomicAcq_Rel] = " acq_rel "; - name[StatAtomicSeq_Cst] = " seq_cst "; - name[StatAtomic1] = " Including size 1 "; - name[StatAtomic2] = " size 2 "; - name[StatAtomic4] = " size 4 "; - name[StatAtomic8] = " size 8 "; - name[StatAtomic16] = " size 16 "; - - name[StatAnnotation] = "Dynamic annotations "; - name[StatAnnotateHappensBefore] = " HappensBefore "; - name[StatAnnotateHappensAfter] = " HappensAfter "; - name[StatAnnotateCondVarSignal] = " CondVarSignal "; - name[StatAnnotateCondVarSignalAll] = " CondVarSignalAll "; - name[StatAnnotateMutexIsNotPHB] = " MutexIsNotPHB "; - name[StatAnnotateCondVarWait] = " CondVarWait "; - name[StatAnnotateRWLockCreate] = " RWLockCreate "; - name[StatAnnotateRWLockCreateStatic] = " StatAnnotateRWLockCreateStatic "; - name[StatAnnotateRWLockDestroy] = " RWLockDestroy "; - name[StatAnnotateRWLockAcquired] = " RWLockAcquired "; - name[StatAnnotateRWLockReleased] = " RWLockReleased "; - name[StatAnnotateTraceMemory] = " TraceMemory "; - name[StatAnnotateFlushState] = " FlushState "; - name[StatAnnotateNewMemory] = " NewMemory "; - name[StatAnnotateNoOp] = " NoOp "; - name[StatAnnotateFlushExpectedRaces] = " FlushExpectedRaces "; - name[StatAnnotateEnableRaceDetection] = " EnableRaceDetection "; - name[StatAnnotateMutexIsUsedAsCondVar] = " MutexIsUsedAsCondVar "; - name[StatAnnotatePCQGet] = " PCQGet "; - name[StatAnnotatePCQPut] = " PCQPut "; - name[StatAnnotatePCQDestroy] = " PCQDestroy "; - name[StatAnnotatePCQCreate] = " PCQCreate "; - name[StatAnnotateExpectRace] = " ExpectRace "; - name[StatAnnotateBenignRaceSized] = " BenignRaceSized "; - name[StatAnnotateBenignRace] = " BenignRace "; - name[StatAnnotateIgnoreReadsBegin] = " IgnoreReadsBegin "; - name[StatAnnotateIgnoreReadsEnd] = " IgnoreReadsEnd "; - name[StatAnnotateIgnoreWritesBegin] = " IgnoreWritesBegin "; - name[StatAnnotateIgnoreWritesEnd] = " IgnoreWritesEnd "; - name[StatAnnotateIgnoreSyncBegin] = " IgnoreSyncBegin "; - name[StatAnnotateIgnoreSyncEnd] = " IgnoreSyncEnd "; - name[StatAnnotatePublishMemoryRange] = " PublishMemoryRange "; - name[StatAnnotateUnpublishMemoryRange] = " UnpublishMemoryRange "; - name[StatAnnotateThreadName] = " ThreadName "; - name[Stat__tsan_mutex_create] = " __tsan_mutex_create "; - name[Stat__tsan_mutex_destroy] = " __tsan_mutex_destroy "; - name[Stat__tsan_mutex_pre_lock] = " __tsan_mutex_pre_lock "; - name[Stat__tsan_mutex_post_lock] = " __tsan_mutex_post_lock "; - name[Stat__tsan_mutex_pre_unlock] = " __tsan_mutex_pre_unlock "; - name[Stat__tsan_mutex_post_unlock] = " __tsan_mutex_post_unlock "; - name[Stat__tsan_mutex_pre_signal] = " __tsan_mutex_pre_signal "; - name[Stat__tsan_mutex_post_signal] = " __tsan_mutex_post_signal "; - name[Stat__tsan_mutex_pre_divert] = " __tsan_mutex_pre_divert "; - name[Stat__tsan_mutex_post_divert] = " __tsan_mutex_post_divert "; - - name[StatMtxTotal] = "Contentionz "; - name[StatMtxTrace] = " Trace "; - name[StatMtxThreads] = " Threads "; - name[StatMtxReport] = " Report "; - name[StatMtxSyncVar] = " SyncVar "; - name[StatMtxSyncTab] = " SyncTab "; - name[StatMtxSlab] = " Slab "; - name[StatMtxAtExit] = " Atexit "; - name[StatMtxAnnotations] = " Annotations "; - name[StatMtxMBlock] = " MBlock "; - name[StatMtxDeadlockDetector] = " DeadlockDetector "; - name[StatMtxFired] = " FiredSuppressions "; - name[StatMtxRacy] = " RacyStacks "; - name[StatMtxFD] = " FD "; - name[StatMtxGlobalProc] = " GlobalProc "; - - Printf("Statistics:\n"); - for (int i = 0; i < StatCnt; i++) - Printf("%s: %16zu\n", name[i], (uptr)stat[i]); -} - -#endif - -} // namespace __tsan diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h deleted file mode 100644 index 8b26a59..0000000 --- a/libsanitizer/tsan/tsan_stat.h +++ /dev/null @@ -1,191 +0,0 @@ -//===-- tsan_stat.h ---------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// - -#ifndef TSAN_STAT_H -#define TSAN_STAT_H - -namespace __tsan { - -enum StatType { - // Memory access processing related stuff. - StatMop, - StatMopRead, - StatMopWrite, - StatMop1, // These must be consequtive. - StatMop2, - StatMop4, - StatMop8, - StatMopSame, - StatMopIgnored, - StatMopRange, - StatMopRodata, - StatMopRangeRodata, - StatShadowProcessed, - StatShadowZero, - StatShadowNonZero, // Derived. - StatShadowSameSize, - StatShadowIntersect, - StatShadowNotIntersect, - StatShadowSameThread, - StatShadowAnotherThread, - StatShadowReplace, - - // Func processing. - StatFuncEnter, - StatFuncExit, - - // Trace processing. - StatEvents, - - // Threads. - StatThreadCreate, - StatThreadFinish, - StatThreadReuse, - StatThreadMaxTid, - StatThreadMaxAlive, - - // Mutexes. - StatMutexCreate, - StatMutexDestroy, - StatMutexLock, - StatMutexUnlock, - StatMutexRecLock, - StatMutexRecUnlock, - StatMutexReadLock, - StatMutexReadUnlock, - - // Synchronization. - StatSyncCreated, - StatSyncDestroyed, - StatSyncAcquire, - StatSyncRelease, - StatSyncReleaseStoreAcquire, - - // Clocks - acquire. - StatClockAcquire, - StatClockAcquireEmpty, - StatClockAcquireFastRelease, - StatClockAcquireFull, - StatClockAcquiredSomething, - // Clocks - release. - StatClockRelease, - StatClockReleaseResize, - StatClockReleaseFast, - StatClockReleaseSlow, - StatClockReleaseFull, - StatClockReleaseAcquired, - StatClockReleaseClearTail, - // Clocks - release store. - StatClockStore, - StatClockStoreResize, - StatClockStoreFast, - StatClockStoreFull, - StatClockStoreTail, - // Clocks - acquire-release. - StatClockAcquireRelease, - - // Atomics. - StatAtomic, - StatAtomicLoad, - StatAtomicStore, - StatAtomicExchange, - StatAtomicFetchAdd, - StatAtomicFetchSub, - StatAtomicFetchAnd, - StatAtomicFetchOr, - StatAtomicFetchXor, - StatAtomicFetchNand, - StatAtomicCAS, - StatAtomicFence, - StatAtomicRelaxed, - StatAtomicConsume, - StatAtomicAcquire, - StatAtomicRelease, - StatAtomicAcq_Rel, - StatAtomicSeq_Cst, - StatAtomic1, - StatAtomic2, - StatAtomic4, - StatAtomic8, - StatAtomic16, - - // Dynamic annotations. - StatAnnotation, - StatAnnotateHappensBefore, - StatAnnotateHappensAfter, - StatAnnotateCondVarSignal, - StatAnnotateCondVarSignalAll, - StatAnnotateMutexIsNotPHB, - StatAnnotateCondVarWait, - StatAnnotateRWLockCreate, - StatAnnotateRWLockCreateStatic, - StatAnnotateRWLockDestroy, - StatAnnotateRWLockAcquired, - StatAnnotateRWLockReleased, - StatAnnotateTraceMemory, - StatAnnotateFlushState, - StatAnnotateNewMemory, - StatAnnotateNoOp, - StatAnnotateFlushExpectedRaces, - StatAnnotateEnableRaceDetection, - StatAnnotateMutexIsUsedAsCondVar, - StatAnnotatePCQGet, - StatAnnotatePCQPut, - StatAnnotatePCQDestroy, - StatAnnotatePCQCreate, - StatAnnotateExpectRace, - StatAnnotateBenignRaceSized, - StatAnnotateBenignRace, - StatAnnotateIgnoreReadsBegin, - StatAnnotateIgnoreReadsEnd, - StatAnnotateIgnoreWritesBegin, - StatAnnotateIgnoreWritesEnd, - StatAnnotateIgnoreSyncBegin, - StatAnnotateIgnoreSyncEnd, - StatAnnotatePublishMemoryRange, - StatAnnotateUnpublishMemoryRange, - StatAnnotateThreadName, - Stat__tsan_mutex_create, - Stat__tsan_mutex_destroy, - Stat__tsan_mutex_pre_lock, - Stat__tsan_mutex_post_lock, - Stat__tsan_mutex_pre_unlock, - Stat__tsan_mutex_post_unlock, - Stat__tsan_mutex_pre_signal, - Stat__tsan_mutex_post_signal, - Stat__tsan_mutex_pre_divert, - Stat__tsan_mutex_post_divert, - - // Internal mutex contentionz. - StatMtxTotal, - StatMtxTrace, - StatMtxThreads, - StatMtxReport, - StatMtxSyncVar, - StatMtxSyncTab, - StatMtxSlab, - StatMtxAnnotations, - StatMtxAtExit, - StatMtxMBlock, - StatMtxDeadlockDetector, - StatMtxFired, - StatMtxRacy, - StatMtxFD, - StatMtxGlobalProc, - - // This must be the last. - StatCnt -}; - -} // namespace __tsan - -#endif // TSAN_STAT_H diff --git a/libsanitizer/tsan/tsan_sync.cpp b/libsanitizer/tsan/tsan_sync.cpp index ba24f98..d25434a 100644 --- a/libsanitizer/tsan/tsan_sync.cpp +++ b/libsanitizer/tsan/tsan_sync.cpp @@ -18,10 +18,7 @@ namespace __tsan { void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s); -SyncVar::SyncVar() - : mtx(MutexTypeSyncVar, StatMtxSyncVar) { - Reset(0); -} +SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(0); } void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) { this->addr = addr; diff --git a/libsanitizer/tsan/tsan_trace.h b/libsanitizer/tsan/tsan_trace.h index fbd0f72..9f2677b 100644 --- a/libsanitizer/tsan/tsan_trace.h +++ b/libsanitizer/tsan/tsan_trace.h @@ -65,9 +65,7 @@ struct Trace { // CreateThreadContext. TraceHeader headers[kTraceParts]; - Trace() - : mtx(MutexTypeTrace, StatMtxTrace) { - } + Trace() : mtx(MutexTypeTrace) {} }; } // namespace __tsan diff --git a/libsanitizer/tsan/tsan_update_shadow_word_inl.h b/libsanitizer/tsan/tsan_update_shadow_word_inl.h index 056c3aa..d23dfb0 100644 --- a/libsanitizer/tsan/tsan_update_shadow_word_inl.h +++ b/libsanitizer/tsan/tsan_update_shadow_word_inl.h @@ -13,12 +13,10 @@ // produce sligtly less efficient code. //===----------------------------------------------------------------------===// do { - StatInc(thr, StatShadowProcessed); const unsigned kAccessSize = 1 << kAccessSizeLog; u64 *sp = &shadow_mem[idx]; old = LoadShadow(sp); if (LIKELY(old.IsZero())) { - StatInc(thr, StatShadowZero); if (!stored) { StoreIfNotYetStored(sp, &store_word); stored = true; @@ -27,17 +25,14 @@ do { } // is the memory access equal to the previous? if (LIKELY(Shadow::Addr0AndSizeAreEqual(cur, old))) { - StatInc(thr, StatShadowSameSize); // same thread? if (LIKELY(Shadow::TidsAreEqual(old, cur))) { - StatInc(thr, StatShadowSameThread); if (LIKELY(old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))) { StoreIfNotYetStored(sp, &store_word); stored = true; } break; } - StatInc(thr, StatShadowAnotherThread); if (HappensBefore(old, thr)) { if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) { StoreIfNotYetStored(sp, &store_word); @@ -51,12 +46,8 @@ do { } // Do the memory access intersect? if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) { - StatInc(thr, StatShadowIntersect); - if (Shadow::TidsAreEqual(old, cur)) { - StatInc(thr, StatShadowSameThread); + if (Shadow::TidsAreEqual(old, cur)) break; - } - StatInc(thr, StatShadowAnotherThread); if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)) break; if (LIKELY(HappensBefore(old, thr))) @@ -64,6 +55,5 @@ do { goto RACE; } // The accesses do not intersect. - StatInc(thr, StatShadowNotIntersect); break; } while (0); |