Index: lib/tsan/rtl/tsan_interface.h =================================================================== --- lib/tsan/rtl/tsan_interface.h +++ lib/tsan/rtl/tsan_interface.h @@ -94,6 +94,11 @@ SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write_range(void *addr, unsigned long size); // NOLINT +SANITIZER_INTERFACE_ATTRIBUTE +void __tsan_read_range_pc(void *addr, unsigned long size, void *pc); // NOLINT +SANITIZER_INTERFACE_ATTRIBUTE +void __tsan_write_range_pc(void *addr, unsigned long size, void *pc); // NOLINT + // User may provide function that would be called right when TSan detects // an error. The argument 'report' is an opaque pointer that can be used to // gather additional information using other TSan report API functions. Index: lib/tsan/rtl/tsan_interface_inl.h =================================================================== --- lib/tsan/rtl/tsan_interface_inl.h +++ lib/tsan/rtl/tsan_interface_inl.h @@ -122,3 +122,11 @@ void __tsan_write_range(void *addr, uptr size) { MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true); } + +void __tsan_read_range_pc(void *addr, uptr size, void *pc) { + MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false); +} + +void __tsan_write_range_pc(void *addr, uptr size, void *pc) { + MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true); +} Index: test/tsan/race_range_pc.cc =================================================================== --- /dev/null +++ test/tsan/race_range_pc.cc @@ -0,0 +1,40 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 big endian. +// The Tsan report is returning wrong information about +// the location of the race. +// XFAIL: powerpc64-unknown-linux-gnu + +#include "test.h" + +typedef unsigned long uptr; +extern "C" void __tsan_read_range_pc(uptr addr, uptr size, uptr pc); +extern "C" void __tsan_write_range_pc(uptr addr, uptr size, uptr pc); + +void foobar() { +} + +void barbaz() { +} + +void *Thread(void *p) { + barrier_wait(&barrier); + __tsan_read_range_pc((uptr)p, 32, (uptr)foobar + kPCInc); + return 0; +} + +int main() { + barrier_init(&barrier, 2); + int a[128]; + pthread_t th; + pthread_create(&th, 0, Thread, (void*)a); + __tsan_write_range_pc((uptr)(a+2), 32, (uptr)barbaz + kPCInc); + barrier_wait(&barrier); + pthread_join(th, 0); + fprintf(stderr, "DONE\n"); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: #0 foobar +// CHECK: #0 barbaz +// CHECK: DONE