Index: lib/tsan/rtl/tsan_interface.h =================================================================== --- lib/tsan/rtl/tsan_interface.h +++ lib/tsan/rtl/tsan_interface.h @@ -73,6 +73,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit(); +SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_begin(); +SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_end(); + SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read_range(void *addr, unsigned long size); // NOLINT SANITIZER_INTERFACE_ATTRIBUTE Index: lib/tsan/rtl/tsan_interface_inl.h =================================================================== --- lib/tsan/rtl/tsan_interface_inl.h +++ lib/tsan/rtl/tsan_interface_inl.h @@ -108,6 +108,14 @@ FuncExit(cur_thread()); } +void __tsan_ignore_thread_begin() { + ThreadIgnoreBegin(cur_thread(), CALLERPC); +} + +void __tsan_ignore_thread_end() { + ThreadIgnoreEnd(cur_thread(), CALLERPC); +} + void __tsan_read_range(void *addr, uptr size) { MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false); } Index: test/tsan/Darwin/release-dealloc-norace-objcpp.mm =================================================================== --- /dev/null +++ test/tsan/Darwin/release-dealloc-norace-objcpp.mm @@ -0,0 +1,55 @@ +// Check that we do not report races betwen object release and dealloc. + +// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation +// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck +// %s + +#import +#include + +pthread_t ThreadId; + +@interface MyObject : NSObject { +@public + int v; +} +- (void)accessMember; +@end + +@implementation MyObject + +- (void)accessMember { + v = 0; +} + +- (void)dealloc { + uint64_t tid; + pthread_threadid_np(NULL, &tid); + [self accessMember]; + printf("Dealloc from thread with id : %p \n", (void *)tid); +} + +@end + +void *Thread1(void *x) { + uint64_t tid; + pthread_threadid_np(NULL, &tid); + printf("Access from thread with id : %p \n", (void *)tid); + int *v = (int *)x; + *v = 1; + sleep(1); + return 0; +} + +void objectLifetimeContainer() { + MyObject *o = [MyObject new]; + pthread_create(&ThreadId, NULL, Thread1, &(o->v)); +} + +int main(int argc, const char *argv[]) { + objectLifetimeContainer(); + pthread_join(ThreadId, NULL); + return 0; +} + +// CHECK-NOT: ThreadSanitizer: data race Index: test/tsan/Darwin/release-dealloc-norace.m =================================================================== --- /dev/null +++ test/tsan/Darwin/release-dealloc-norace.m @@ -0,0 +1,55 @@ +// Check that we do not report races betwen object release and dealloc. + +// RUN: %clang_tsan %s -fobjc-arc -lobjc -o %t -framework Foundation +// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck +// %s + +#import +#include + +pthread_t ThreadId; + +@interface MyObject : NSObject { +@public + int v; +} +- (void)accessMember; +@end + +@implementation MyObject + +- (void)accessMember { + v = 0; +} + +- (void)dealloc { + uint64_t tid; + pthread_threadid_np(NULL, &tid); + [self accessMember]; + printf("Dealloc from thread with id : %p \n", (void *)tid); +} + +@end + +void *Thread1(void *x) { + uint64_t tid; + pthread_threadid_np(NULL, &tid); + printf("Access from thread with id : %p \n", (void *)tid); + int *v = (int *)x; + *v = 1; + sleep(1); + return 0; +} + +void objectLifetimeContainer() { + MyObject *o = [MyObject new]; + pthread_create(&ThreadId, NULL, Thread1, &(o->v)); +} + +int main(int argc, const char *argv[]) { + objectLifetimeContainer(); + pthread_join(ThreadId, NULL); + return 0; +} + +// CHECK-NOT: ThreadSanitizer: data race