diff --git a/compiler-rt/lib/tsan/lit_tests/atomic_stack.cc b/compiler-rt/lib/tsan/lit_tests/atomic_stack.cc new file mode 100644 index 000000000000..50f6a8a889ca --- /dev/null +++ b/compiler-rt/lib/tsan/lit_tests/atomic_stack.cc @@ -0,0 +1,29 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include +#include + +int Global; + +void *Thread1(void *x) { + sleep(1); + __atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED); + return NULL; +} + +void *Thread2(void *x) { + Global++; + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Atomic write of size 4 +// CHECK: #0 __tsan_atomic32_fetch_add +// CHECK: #1 Thread1 diff --git a/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c b/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c index de1c2d4160a6..aff32f9bb1a2 100644 --- a/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c +++ b/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c @@ -34,7 +34,7 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK-NEXT: Read of size 1 at {{.*}} by thread T2: +// CHECK-NEXT: Atomic read of size 1 at {{.*}} by thread T2: // CHECK-NEXT: #0 pthread_mutex_lock // CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:20{{(:3)?}} ({{.*}}) // CHECK: Previous write of size 1 at {{.*}} by thread T1: diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc index b744011406c4..e39160b9bb33 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc @@ -29,7 +29,8 @@ using namespace __tsan; // NOLINT #define SCOPED_ATOMIC(func, ...) \ const uptr callpc = (uptr)__builtin_return_address(0); \ - const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \ + uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \ + pc = __sanitizer::StackTrace::GetPreviousInstructionPc(pc); \ mo = ConvertOrder(mo); \ mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \ ThreadState *const thr = cur_thread(); \ diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index 056dc97387b9..0d6fb2392271 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -89,11 +89,17 @@ static void PrintMutexSet(Vector const& mset) { } } +static const char *MopDesc(bool first, bool write, bool atomic) { + return atomic ? (first ? (write ? "Atomic write" : "Atomic read") + : (write ? "Previous atomic write" : "Previous atomic read")) + : (first ? (write ? "Write" : "Read") + : (write ? "Previous write" : "Previous read")); +} + static void PrintMop(const ReportMop *mop, bool first) { char thrbuf[kThreadBufSize]; Printf(" %s of size %d at %p by %s", - (first ? (mop->write ? "Write" : "Read") - : (mop->write ? "Previous write" : "Previous read")), + MopDesc(first, mop->write, mop->atomic), mop->size, (void*)mop->addr, thread_name(thrbuf, mop->tid)); PrintMutexSet(mop->mset); diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h index f6715d1aae9b..b2b7b53306d1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.h +++ b/compiler-rt/lib/tsan/rtl/tsan_report.h @@ -48,6 +48,7 @@ struct ReportMop { uptr addr; int size; bool write; + bool atomic; Vector mset; ReportStack *stack; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index 31eaac1579cf..ba9b0ad3add4 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -151,6 +151,7 @@ void ScopedReport::AddMemoryAccess(uptr addr, Shadow s, mop->addr = addr + s.addr0(); mop->size = s.size(); mop->write = s.IsWrite(); + mop->atomic = s.IsAtomic(); mop->stack = SymbolizeStack(*stack); for (uptr i = 0; i < mset->Size(); i++) { MutexSet::Desc d = mset->Get(i);