diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutexset.h b/compiler-rt/lib/tsan/rtl/tsan_mutexset.h --- a/compiler-rt/lib/tsan/rtl/tsan_mutexset.h +++ b/compiler-rt/lib/tsan/rtl/tsan_mutexset.h @@ -59,6 +59,24 @@ #endif }; +// MutexSet is too large to live on stack. +// DynamicMutexSet can be use used to create local MutexSet's. +class DynamicMutexSet { + public: + DynamicMutexSet(); + ~DynamicMutexSet(); + MutexSet* operator->() { return ptr_; } + operator MutexSet*() { return ptr_; } + DynamicMutexSet(const DynamicMutexSet&) = delete; + DynamicMutexSet& operator=(const DynamicMutexSet&) = delete; + + private: + MutexSet* ptr_; +#if SANITIZER_GO + MutexSet set_; +#endif +}; + // Go does not have mutexes, so do not spend memory and time. // (Go sync.Mutex is actually a semaphore -- can be unlocked // in different goroutine). @@ -71,6 +89,8 @@ void MutexSet::DelAddr(uptr addr, bool destroy) {} uptr MutexSet::Size() const { return 0; } MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); } +DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {} +DynamicMutexSet::~DynamicMutexSet() {} #endif } // namespace __tsan diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp b/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// #include "tsan_mutexset.h" + +#include "sanitizer_common/sanitizer_placement_new.h" #include "tsan_rtl.h" namespace __tsan { @@ -124,4 +126,7 @@ return descs_[i]; } +DynamicMutexSet::DynamicMutexSet() : ptr_(New()) {} +DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); } + } // namespace __tsan diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -560,9 +560,7 @@ if (tctx->thr) last_pos = (Event *)atomic_load_relaxed(&tctx->thr->trace_pos); } - // Too large for stack. - alignas(MutexSet) static char mset_storage[sizeof(MutexSet)]; - MutexSet &mset = *new (mset_storage) MutexSet(); + DynamicMutexSet mset; Vector stack; uptr prev_pc = 0; bool found = false; @@ -588,7 +586,7 @@ if (match && type == EventType::kAccessExt && IsWithinAccess(addr, size, ev_addr, ev_size) && is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free) - RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); + RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found); return; } if (evp->is_func) { @@ -615,7 +613,7 @@ IsWithinAccess(addr, size, ev_addr, ev_size) && is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free) - RestoreStackMatch(pstk, pmset, &stack, &mset, ev->pc, &found); + RestoreStackMatch(pstk, pmset, &stack, mset, ev->pc, &found); break; } case EventType::kAccessRange: { @@ -630,7 +628,7 @@ if (match && type == EventType::kAccessExt && IsWithinAccess(addr, size, ev_addr, ev_size) && is_read == ev->is_read && !is_atomic && is_free == ev->is_free) - RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); + RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found); break; } case EventType::kLock: @@ -644,18 +642,18 @@ (ev->stack_hi << EventLock::kStackIDLoBits) + ev->stack_lo; DPrintf2(" Lock: pc=0x%zx addr=0x%zx stack=%u write=%d\n", ev_pc, ev_addr, stack_id, is_write); - mset.AddAddr(ev_addr, stack_id, is_write); + mset->AddAddr(ev_addr, stack_id, is_write); // Events with ev_pc == 0 are written to the beginning of trace // part as initial mutex set (are not real). if (match && type == EventType::kLock && addr == ev_addr && ev_pc) - RestoreStackMatch(pstk, pmset, &stack, &mset, ev_pc, &found); + RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found); break; } case EventType::kUnlock: { auto *ev = reinterpret_cast(evp); uptr ev_addr = RestoreAddr(ev->addr); DPrintf2(" Unlock: addr=0x%zx\n", ev_addr); - mset.DelAddr(ev_addr); + mset->DelAddr(ev_addr); break; } case EventType::kTime: @@ -897,11 +895,7 @@ if (IsFiredSuppression(ctx, typ, traces[0])) return; - // MutexSet is too large to live on stack. - Vector mset_buffer; - mset_buffer.Resize(sizeof(MutexSet) / sizeof(u64) + 1); - MutexSet *mset2 = new(&mset_buffer[0]) MutexSet(); - + DynamicMutexSet mset2; Shadow s2(thr->racy_state[1]); RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2, &tags[1]); if (IsFiredSuppression(ctx, typ, traces[1]))