aboutsummaryrefslogtreecommitdiff
path: root/test/tsan
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:53 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:53 +0000
commitab0bf875a5f328a6710f4e48258979ae1bc8da1c (patch)
tree66903cf9f73151825893dcc216b04c0930317a10 /test/tsan
parentabacad30a54c59ad437ccf54ec5236a8dd7f3ba9 (diff)
downloadsrc-ab0bf875a5f328a6710f4e48258979ae1bc8da1c.tar.gz
src-ab0bf875a5f328a6710f4e48258979ae1bc8da1c.zip
Vendor import of compiler-rt trunk r300422:vendor/compiler-rt/compiler-rt-trunk-r300422
Notes
Notes: svn path=/vendor/compiler-rt/dist/; revision=317021 svn path=/vendor/compiler-rt/compiler-rt-trunk-r300422/; revision=317022; tag=vendor/compiler-rt/compiler-rt-trunk-r300422
Diffstat (limited to 'test/tsan')
-rw-r--r--test/tsan/Darwin/debug_external.cc66
-rw-r--r--test/tsan/Darwin/dispatch_main.mm2
-rw-r--r--test/tsan/Darwin/dispatch_once_deadlock.mm2
-rw-r--r--test/tsan/Darwin/external.cc163
-rw-r--r--test/tsan/Darwin/gcd-after-null.mm23
-rw-r--r--test/tsan/Darwin/gcd-after.mm2
-rw-r--r--test/tsan/Darwin/gcd-apply-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-apply.mm2
-rw-r--r--test/tsan/Darwin/gcd-async-norace.mm2
-rw-r--r--test/tsan/Darwin/gcd-async-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-barrier-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-barrier.mm2
-rw-r--r--test/tsan/Darwin/gcd-blocks.mm2
-rw-r--r--test/tsan/Darwin/gcd-data.mm2
-rw-r--r--test/tsan/Darwin/gcd-fd.mm2
-rw-r--r--test/tsan/Darwin/gcd-groups-destructor.mm2
-rw-r--r--test/tsan/Darwin/gcd-groups-leave.mm2
-rw-r--r--test/tsan/Darwin/gcd-groups-norace.mm2
-rw-r--r--test/tsan/Darwin/gcd-groups-stress.mm2
-rw-r--r--test/tsan/Darwin/gcd-io-barrier-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-io-barrier.mm2
-rw-r--r--test/tsan/Darwin/gcd-io-cleanup.mm2
-rw-r--r--test/tsan/Darwin/gcd-io-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-io.mm2
-rw-r--r--test/tsan/Darwin/gcd-once.mm2
-rw-r--r--test/tsan/Darwin/gcd-semaphore-norace.mm2
-rw-r--r--test/tsan/Darwin/gcd-serial-queue-norace.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-cancel.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-cancel2.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-event.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-event2.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-registration.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-registration2.mm2
-rw-r--r--test/tsan/Darwin/gcd-source-serial.mm2
-rw-r--r--test/tsan/Darwin/gcd-suspend.mm2
-rw-r--r--test/tsan/Darwin/gcd-sync-norace.mm2
-rw-r--r--test/tsan/Darwin/gcd-sync-race.mm2
-rw-r--r--test/tsan/Darwin/gcd-target-queue-norace.mm2
-rw-r--r--test/tsan/Darwin/ignore-noninstrumented.mm2
-rw-r--r--test/tsan/Darwin/ignored-interceptors.mm6
-rw-r--r--test/tsan/Darwin/libcxx-call-once.mm2
-rw-r--r--test/tsan/Darwin/libcxx-future.mm2
-rw-r--r--test/tsan/Darwin/libcxx-shared-ptr-recursive.mm2
-rw-r--r--test/tsan/Darwin/libcxx-shared-ptr-stress.mm2
-rw-r--r--test/tsan/Darwin/libcxx-shared-ptr.mm2
-rw-r--r--test/tsan/Darwin/lit.local.cfg2
-rw-r--r--test/tsan/Darwin/main_tid.mm46
-rw-r--r--test/tsan/Darwin/norace-objcxx-run-time.mm2
-rw-r--r--test/tsan/Darwin/objc-double-property.mm8
-rw-r--r--test/tsan/Darwin/objc-simple.mm2
-rw-r--r--test/tsan/Darwin/workerthreads.mm43
-rw-r--r--test/tsan/Darwin/xpc-cancel.mm37
-rw-r--r--test/tsan/Darwin/xpc-race.mm2
-rw-r--r--test/tsan/Darwin/xpc.mm2
-rw-r--r--test/tsan/Linux/pie_no_aslr.cc6
-rw-r--r--test/tsan/Linux/user_malloc.cc1
-rw-r--r--test/tsan/Unit/lit.site.cfg.in10
-rw-r--r--test/tsan/atomic_hle.cc25
-rw-r--r--test/tsan/custom_mutex.h91
-rw-r--r--test/tsan/custom_mutex0.cc31
-rw-r--r--test/tsan/custom_mutex1.cc39
-rw-r--r--test/tsan/custom_mutex2.cc34
-rw-r--r--test/tsan/fd_socket_connect_norace.cc45
-rw-r--r--test/tsan/fd_socket_norace.cc45
-rw-r--r--test/tsan/lit.cfg7
65 files changed, 738 insertions, 80 deletions
diff --git a/test/tsan/Darwin/debug_external.cc b/test/tsan/Darwin/debug_external.cc
new file mode 100644
index 000000000000..217690fc5dd0
--- /dev/null
+++ b/test/tsan/Darwin/debug_external.cc
@@ -0,0 +1,66 @@
+// RUN: %clangxx_tsan -O1 %s -o %t
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test.h"
+
+extern "C" {
+void __tsan_on_report(void *report);
+int __tsan_get_report_loc(void *report, unsigned long idx, const char **type,
+ void **addr, void **start,
+ unsigned long *size, int *tid, int *fd,
+ int *suppressable, void **trace,
+ unsigned long trace_size);
+int __tsan_get_report_loc_object_type(void *report, unsigned long idx,
+ const char **object_type);
+void *__tsan_external_register_tag(const char *object_type);
+void __tsan_external_assign_tag(void *addr, void *tag);
+}
+
+void *Thread(void *arg) {
+ barrier_wait(&barrier);
+ *((long *)arg) = 42;
+ return NULL;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ void *tag = __tsan_external_register_tag("MyObject");
+ long *obj = (long *)malloc(sizeof(long));
+ fprintf(stderr, "obj = %p\n", obj);
+ // CHECK: obj = [[ADDR:0x[0-9a-f]+]]
+ __tsan_external_assign_tag(obj, tag);
+
+ pthread_t t;
+ pthread_create(&t, 0, Thread, obj);
+ *obj = 41;
+ barrier_wait(&barrier);
+ pthread_join(t, 0);
+ fprintf(stderr, "Done.\n");
+ return 0;
+}
+
+void __tsan_on_report(void *report) {
+ const char *type;
+ void *addr;
+ void *start;
+ unsigned long size;
+ int tid, fd, suppressable;
+ void *trace[16] = {0};
+ __tsan_get_report_loc(report, 0, &type, &addr, &start, &size, &tid, &fd,
+ &suppressable, trace, 16);
+ fprintf(stderr, "type = %s, start = %p, size = %ld\n", type, start, size);
+ // CHECK: type = heap, start = [[ADDR]], size = 8
+
+ const char *object_type;
+ __tsan_get_report_loc_object_type(report, 0, &object_type);
+ fprintf(stderr, "object_type = %s\n", object_type);
+ // CHECK: object_type = MyObject
+}
+
+// CHECK: Done.
+// CHECK: ThreadSanitizer: reported 1 warnings
diff --git a/test/tsan/Darwin/dispatch_main.mm b/test/tsan/Darwin/dispatch_main.mm
index 75887547c606..f4c1e44bc6b1 100644
--- a/test/tsan/Darwin/dispatch_main.mm
+++ b/test/tsan/Darwin/dispatch_main.mm
@@ -2,7 +2,7 @@
// quits the main thread.
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/dispatch_once_deadlock.mm b/test/tsan/Darwin/dispatch_once_deadlock.mm
index e88cdc0d0da5..e109f64a8dcb 100644
--- a/test/tsan/Darwin/dispatch_once_deadlock.mm
+++ b/test/tsan/Darwin/dispatch_once_deadlock.mm
@@ -1,7 +1,7 @@
// Check that calling dispatch_once from a report callback works.
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 not %run %t 2>&1 | FileCheck %s
+// RUN: not %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
#import <pthread.h>
diff --git a/test/tsan/Darwin/external.cc b/test/tsan/Darwin/external.cc
new file mode 100644
index 000000000000..2605480d7b82
--- /dev/null
+++ b/test/tsan/Darwin/external.cc
@@ -0,0 +1,163 @@
+// RUN: %clangxx_tsan %s -shared -DSHARED_LIB \
+// RUN: -o %t-lib-instrumented.dylib \
+// RUN: -install_name @rpath/`basename %t-lib-instrumented.dylib`
+
+// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread \
+// RUN: -o %t-lib-noninstrumented.dylib \
+// RUN: -install_name @rpath/`basename %t-lib-noninstrumented.dylib`
+
+// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \
+// RUN: -o %t-lib-noninstrumented-callbacks.dylib \
+// RUN: -install_name @rpath/`basename %t-lib-noninstrumented-callbacks.dylib`
+
+// RUN: %clangxx_tsan %s %t-lib-instrumented.dylib -o %t-lib-instrumented
+// RUN: %clangxx_tsan %s %t-lib-noninstrumented.dylib -o %t-lib-noninstrumented
+// RUN: %clangxx_tsan %s %t-lib-noninstrumented-callbacks.dylib -o %t-lib-noninstrumented-callbacks
+
+// RUN: %deflake %run %t-lib-instrumented 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST1
+// RUN: %run %t-lib-noninstrumented 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST2
+// RUN: %deflake %run %t-lib-noninstrumented-callbacks 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST3
+
+#include <thread>
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct MyObject;
+typedef MyObject *MyObjectRef;
+extern "C" {
+ void InitializeLibrary();
+ MyObject *ObjectCreate();
+ long ObjectRead(MyObject *);
+ void ObjectWrite(MyObject *, long);
+ void ObjectWriteAnother(MyObject *, long);
+}
+
+#if defined(SHARED_LIB)
+
+struct MyObject {
+ long _val;
+ long _another;
+};
+
+#if defined(USE_TSAN_CALLBACKS)
+static void *tag;
+void *(*callback_register_tag)(const char *object_type);
+void *(*callback_assign_tag)(void *addr, void *tag);
+void (*callback_read)(void *addr, void *caller_pc, void *tag);
+void (*callback_write)(void *addr, void *caller_pc, void *tag);
+#endif
+
+void InitializeLibrary() {
+#if defined(USE_TSAN_CALLBACKS)
+ callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag");
+ callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag");
+ callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read");
+ callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write");
+ tag = callback_register_tag("MyLibrary::MyObject");
+#endif
+}
+
+MyObject *ObjectCreate() {
+ MyObject *ref = (MyObject *)malloc(sizeof(MyObject));
+#if defined(USE_TSAN_CALLBACKS)
+ callback_assign_tag(ref, tag);
+#endif
+ return ref;
+}
+
+long ObjectRead(MyObject *ref) {
+#if defined(USE_TSAN_CALLBACKS)
+ callback_read(ref, __builtin_return_address(0), tag);
+#endif
+ return ref->_val;
+}
+
+void ObjectWrite(MyObject *ref, long val) {
+#if defined(USE_TSAN_CALLBACKS)
+ callback_write(ref, __builtin_return_address(0), tag);
+#endif
+ ref->_val = val;
+}
+
+void ObjectWriteAnother(MyObject *ref, long val) {
+#if defined(USE_TSAN_CALLBACKS)
+ callback_write(ref, __builtin_return_address(0), tag);
+#endif
+ ref->_another = val;
+}
+
+#else // defined(SHARED_LIB)
+
+int main(int argc, char *argv[]) {
+ InitializeLibrary();
+
+ {
+ MyObjectRef ref = ObjectCreate();
+ std::thread t1([ref]{ ObjectRead(ref); });
+ std::thread t2([ref]{ ObjectRead(ref); });
+ t1.join();
+ t2.join();
+ }
+
+ // CHECK-NOT: WARNING: ThreadSanitizer
+
+ fprintf(stderr, "RR test done\n");
+ // CHECK: RR test done
+
+ {
+ MyObjectRef ref = ObjectCreate();
+ std::thread t1([ref]{ ObjectRead(ref); });
+ std::thread t2([ref]{ ObjectWrite(ref, 66); });
+ t1.join();
+ t2.join();
+ }
+
+ // TEST1: WARNING: ThreadSanitizer: data race
+ // TEST1: {{Write|Read}} of size 8 at
+ // TEST1: Previous {{write|read}} of size 8 at
+ // TEST1: Location is heap block of size 16 at
+
+ // TEST2-NOT: WARNING: ThreadSanitizer
+
+ // TEST3: WARNING: ThreadSanitizer: race on a library object
+ // TEST3: {{Mutating|read-only}} access of object MyLibrary::MyObject at
+ // TEST3: {{ObjectWrite|ObjectRead}}
+ // TEST3: Previous {{mutating|read-only}} access of object MyLibrary::MyObject at
+ // TEST3: {{ObjectWrite|ObjectRead}}
+ // TEST3: Location is MyLibrary::MyObject object of size 16 at
+ // TEST3: {{ObjectCreate}}
+
+ fprintf(stderr, "RW test done\n");
+ // CHECK: RW test done
+
+ {
+ MyObjectRef ref = ObjectCreate();
+ std::thread t1([ref]{ ObjectWrite(ref, 76); });
+ std::thread t2([ref]{ ObjectWriteAnother(ref, 77); });
+ t1.join();
+ t2.join();
+ }
+
+ // TEST1-NOT: WARNING: ThreadSanitizer: data race
+
+ // TEST2-NOT: WARNING: ThreadSanitizer
+
+ // TEST3: WARNING: ThreadSanitizer: race on a library object
+ // TEST3: Mutating access of object MyLibrary::MyObject at
+ // TEST3: {{ObjectWrite|ObjectWriteAnother}}
+ // TEST3: Previous mutating access of object MyLibrary::MyObject at
+ // TEST3: {{ObjectWrite|ObjectWriteAnother}}
+ // TEST3: Location is MyLibrary::MyObject object of size 16 at
+ // TEST3: {{ObjectCreate}}
+
+ fprintf(stderr, "WW test done\n");
+ // CHECK: WW test done
+}
+
+#endif // defined(SHARED_LIB)
diff --git a/test/tsan/Darwin/gcd-after-null.mm b/test/tsan/Darwin/gcd-after-null.mm
new file mode 100644
index 000000000000..7c9913c0fb17
--- /dev/null
+++ b/test/tsan/Darwin/gcd-after-null.mm
@@ -0,0 +1,23 @@
+// Regression test to make sure we don't crash when dispatch_after is called with a NULL queue.
+
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "start\n");
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_MSEC)), NULL, ^{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ CFRunLoopStop(CFRunLoopGetMain());
+ });
+ });
+ CFRunLoopRun();
+
+ fprintf(stderr, "done\n");
+ return 0;
+}
+
+// CHECK: start
+// CHECK: done
diff --git a/test/tsan/Darwin/gcd-after.mm b/test/tsan/Darwin/gcd-after.mm
index 49b6bc6f71e9..4d66c508554a 100644
--- a/test/tsan/Darwin/gcd-after.mm
+++ b/test/tsan/Darwin/gcd-after.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-apply-race.mm b/test/tsan/Darwin/gcd-apply-race.mm
index 028be1ac5b1c..a7bf663a9fe2 100644
--- a/test/tsan/Darwin/gcd-apply-race.mm
+++ b/test/tsan/Darwin/gcd-apply-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-apply.mm b/test/tsan/Darwin/gcd-apply.mm
index a7dc3740dc7b..d9d256203aeb 100644
--- a/test/tsan/Darwin/gcd-apply.mm
+++ b/test/tsan/Darwin/gcd-apply.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-async-norace.mm b/test/tsan/Darwin/gcd-async-norace.mm
index c7e28b4ce791..83f8c0d6fb58 100644
--- a/test/tsan/Darwin/gcd-async-norace.mm
+++ b/test/tsan/Darwin/gcd-async-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-async-race.mm b/test/tsan/Darwin/gcd-async-race.mm
index 1002a56b0a16..cb8fb4bf5eca 100644
--- a/test/tsan/Darwin/gcd-async-race.mm
+++ b/test/tsan/Darwin/gcd-async-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-barrier-race.mm b/test/tsan/Darwin/gcd-barrier-race.mm
index c42eaebded2b..c11e147ff7cd 100644
--- a/test/tsan/Darwin/gcd-barrier-race.mm
+++ b/test/tsan/Darwin/gcd-barrier-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-barrier.mm b/test/tsan/Darwin/gcd-barrier.mm
index 6f58cae7d8f5..9d4dcb215027 100644
--- a/test/tsan/Darwin/gcd-barrier.mm
+++ b/test/tsan/Darwin/gcd-barrier.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-blocks.mm b/test/tsan/Darwin/gcd-blocks.mm
index e0082605f24e..1aac7e1f2ef6 100644
--- a/test/tsan/Darwin/gcd-blocks.mm
+++ b/test/tsan/Darwin/gcd-blocks.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-data.mm b/test/tsan/Darwin/gcd-data.mm
index a5154dc3598d..d451cf5e8efa 100644
--- a/test/tsan/Darwin/gcd-data.mm
+++ b/test/tsan/Darwin/gcd-data.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-fd.mm b/test/tsan/Darwin/gcd-fd.mm
index 75da9cd4252d..838cf20ca98b 100644
--- a/test/tsan/Darwin/gcd-fd.mm
+++ b/test/tsan/Darwin/gcd-fd.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-groups-destructor.mm b/test/tsan/Darwin/gcd-groups-destructor.mm
index 19c2c9bd147f..05c65c04b665 100644
--- a/test/tsan/Darwin/gcd-groups-destructor.mm
+++ b/test/tsan/Darwin/gcd-groups-destructor.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-groups-leave.mm b/test/tsan/Darwin/gcd-groups-leave.mm
index 6ecf85f5ff0d..49fd8e2101c8 100644
--- a/test/tsan/Darwin/gcd-groups-leave.mm
+++ b/test/tsan/Darwin/gcd-groups-leave.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-groups-norace.mm b/test/tsan/Darwin/gcd-groups-norace.mm
index 64ec386ca40f..e8501692fe80 100644
--- a/test/tsan/Darwin/gcd-groups-norace.mm
+++ b/test/tsan/Darwin/gcd-groups-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-groups-stress.mm b/test/tsan/Darwin/gcd-groups-stress.mm
index 457d9afd9c93..cfe4deb0a518 100644
--- a/test/tsan/Darwin/gcd-groups-stress.mm
+++ b/test/tsan/Darwin/gcd-groups-stress.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-io-barrier-race.mm b/test/tsan/Darwin/gcd-io-barrier-race.mm
index fffc19bd16de..137c3b26700c 100644
--- a/test/tsan/Darwin/gcd-io-barrier-race.mm
+++ b/test/tsan/Darwin/gcd-io-barrier-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-io-barrier.mm b/test/tsan/Darwin/gcd-io-barrier.mm
index fe30138f6036..af92b03c1c70 100644
--- a/test/tsan/Darwin/gcd-io-barrier.mm
+++ b/test/tsan/Darwin/gcd-io-barrier.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-io-cleanup.mm b/test/tsan/Darwin/gcd-io-cleanup.mm
index b15fa0dc2532..570e37dd04cd 100644
--- a/test/tsan/Darwin/gcd-io-cleanup.mm
+++ b/test/tsan/Darwin/gcd-io-cleanup.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-io-race.mm b/test/tsan/Darwin/gcd-io-race.mm
index 0bec28fdb758..99000fca1587 100644
--- a/test/tsan/Darwin/gcd-io-race.mm
+++ b/test/tsan/Darwin/gcd-io-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
// REQUIRES: disabled
diff --git a/test/tsan/Darwin/gcd-io.mm b/test/tsan/Darwin/gcd-io.mm
index 4a1726dac8c7..70ded40417d7 100644
--- a/test/tsan/Darwin/gcd-io.mm
+++ b/test/tsan/Darwin/gcd-io.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-once.mm b/test/tsan/Darwin/gcd-once.mm
index 3e4a5335607c..70e588aaf711 100644
--- a/test/tsan/Darwin/gcd-once.mm
+++ b/test/tsan/Darwin/gcd-once.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-semaphore-norace.mm b/test/tsan/Darwin/gcd-semaphore-norace.mm
index 20bc5724d165..fd5d14655182 100644
--- a/test/tsan/Darwin/gcd-semaphore-norace.mm
+++ b/test/tsan/Darwin/gcd-semaphore-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-serial-queue-norace.mm b/test/tsan/Darwin/gcd-serial-queue-norace.mm
index 95efbb764c53..8754b618df2a 100644
--- a/test/tsan/Darwin/gcd-serial-queue-norace.mm
+++ b/test/tsan/Darwin/gcd-serial-queue-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-cancel.mm b/test/tsan/Darwin/gcd-source-cancel.mm
index 86e1b28a61c4..8aa6f106932f 100644
--- a/test/tsan/Darwin/gcd-source-cancel.mm
+++ b/test/tsan/Darwin/gcd-source-cancel.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-cancel2.mm b/test/tsan/Darwin/gcd-source-cancel2.mm
index 956fe87298bb..92b31d7d0dab 100644
--- a/test/tsan/Darwin/gcd-source-cancel2.mm
+++ b/test/tsan/Darwin/gcd-source-cancel2.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-event.mm b/test/tsan/Darwin/gcd-source-event.mm
index e50cb568de1e..e707b6551000 100644
--- a/test/tsan/Darwin/gcd-source-event.mm
+++ b/test/tsan/Darwin/gcd-source-event.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-event2.mm b/test/tsan/Darwin/gcd-source-event2.mm
index c45d481a0028..b10e4741a3f6 100644
--- a/test/tsan/Darwin/gcd-source-event2.mm
+++ b/test/tsan/Darwin/gcd-source-event2.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-registration.mm b/test/tsan/Darwin/gcd-source-registration.mm
index db22613eddae..d6d339f94dbb 100644
--- a/test/tsan/Darwin/gcd-source-registration.mm
+++ b/test/tsan/Darwin/gcd-source-registration.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-registration2.mm b/test/tsan/Darwin/gcd-source-registration2.mm
index 4431bc9d6898..63657873cae3 100644
--- a/test/tsan/Darwin/gcd-source-registration2.mm
+++ b/test/tsan/Darwin/gcd-source-registration2.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-source-serial.mm b/test/tsan/Darwin/gcd-source-serial.mm
index c0989fcc732a..992203074c15 100644
--- a/test/tsan/Darwin/gcd-source-serial.mm
+++ b/test/tsan/Darwin/gcd-source-serial.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-suspend.mm b/test/tsan/Darwin/gcd-suspend.mm
index 3e8818a2d56e..561e7c0b79c8 100644
--- a/test/tsan/Darwin/gcd-suspend.mm
+++ b/test/tsan/Darwin/gcd-suspend.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-sync-norace.mm b/test/tsan/Darwin/gcd-sync-norace.mm
index c683524f73b6..18bf97320793 100644
--- a/test/tsan/Darwin/gcd-sync-norace.mm
+++ b/test/tsan/Darwin/gcd-sync-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-sync-race.mm b/test/tsan/Darwin/gcd-sync-race.mm
index 650faa4e082c..b7f3266dc09b 100644
--- a/test/tsan/Darwin/gcd-sync-race.mm
+++ b/test/tsan/Darwin/gcd-sync-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/gcd-target-queue-norace.mm b/test/tsan/Darwin/gcd-target-queue-norace.mm
index 36cb1b9298de..fbfa65806bdb 100644
--- a/test/tsan/Darwin/gcd-target-queue-norace.mm
+++ b/test/tsan/Darwin/gcd-target-queue-norace.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/ignore-noninstrumented.mm b/test/tsan/Darwin/ignore-noninstrumented.mm
index 5e4453102a9c..528e07b9a721 100644
--- a/test/tsan/Darwin/ignore-noninstrumented.mm
+++ b/test/tsan/Darwin/ignore-noninstrumented.mm
@@ -3,7 +3,7 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
// Check that without the flag, there are false positives.
-// RUN: %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE
+// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0 %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE
// With ignore_noninstrumented_modules=1, no races are reported.
// RUN: %env_tsan_opts=ignore_noninstrumented_modules=1 %run %t 2>&1 | FileCheck %s
diff --git a/test/tsan/Darwin/ignored-interceptors.mm b/test/tsan/Darwin/ignored-interceptors.mm
index d51314281844..1105132a3cb6 100644
--- a/test/tsan/Darwin/ignored-interceptors.mm
+++ b/test/tsan/Darwin/ignored-interceptors.mm
@@ -6,13 +6,13 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
// Check that without the flag, there are false positives.
-// RUN: %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE
+// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0 %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE
// With ignore_interceptors_accesses=1, no races are reported.
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0:ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
// With ignore_interceptors_accesses=1, races in user's code are still reported.
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t race 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RACE
+// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0:ignore_interceptors_accesses=1 %deflake %run %t race 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RACE
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/libcxx-call-once.mm b/test/tsan/Darwin/libcxx-call-once.mm
index 5388e495c9c2..ba4615fa3ab9 100644
--- a/test/tsan/Darwin/libcxx-call-once.mm
+++ b/test/tsan/Darwin/libcxx-call-once.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/libcxx-future.mm b/test/tsan/Darwin/libcxx-future.mm
index 902f267ecb89..720c2e089b47 100644
--- a/test/tsan/Darwin/libcxx-future.mm
+++ b/test/tsan/Darwin/libcxx-future.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#include <iostream>
#include <future>
diff --git a/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm b/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm
index eea02dc561e1..a9a3a96f2ada 100644
--- a/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm
+++ b/test/tsan/Darwin/libcxx-shared-ptr-recursive.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/libcxx-shared-ptr-stress.mm b/test/tsan/Darwin/libcxx-shared-ptr-stress.mm
index 7c36729f010f..e5cd7edc6bb7 100644
--- a/test/tsan/Darwin/libcxx-shared-ptr-stress.mm
+++ b/test/tsan/Darwin/libcxx-shared-ptr-stress.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/libcxx-shared-ptr.mm b/test/tsan/Darwin/libcxx-shared-ptr.mm
index 6187c438fec0..057ff22874c9 100644
--- a/test/tsan/Darwin/libcxx-shared-ptr.mm
+++ b/test/tsan/Darwin/libcxx-shared-ptr.mm
@@ -1,5 +1,5 @@
// RUN: %clangxx_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/lit.local.cfg b/test/tsan/Darwin/lit.local.cfg
index a85dfcd24c08..e74e82dbf474 100644
--- a/test/tsan/Darwin/lit.local.cfg
+++ b/test/tsan/Darwin/lit.local.cfg
@@ -7,3 +7,5 @@ root = getRoot(config)
if root.host_os not in ['Darwin']:
config.unsupported = True
+
+config.environment['TSAN_OPTIONS'] += ':ignore_noninstrumented_modules=1'
diff --git a/test/tsan/Darwin/main_tid.mm b/test/tsan/Darwin/main_tid.mm
new file mode 100644
index 000000000000..af658e4b96e5
--- /dev/null
+++ b/test/tsan/Darwin/main_tid.mm
@@ -0,0 +1,46 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
+
+#import <pthread.h>
+#import <stdio.h>
+#import <stdlib.h>
+
+extern "C" {
+void __tsan_on_report(void *report);
+int __tsan_get_report_thread(void *report, unsigned long idx, int *tid,
+ unsigned long *os_id, int *running,
+ const char **name, int *parent_tid, void **trace,
+ unsigned long trace_size);
+}
+
+void __tsan_on_report(void *report) {
+ fprintf(stderr, "__tsan_on_report(%p)\n", report);
+
+ int tid;
+ unsigned long os_id;
+ int running;
+ const char *name;
+ int parent_tid;
+ void *trace[16] = {0};
+ __tsan_get_report_thread(report, 0, &tid, &os_id, &running, &name, &parent_tid, trace, 16);
+ fprintf(stderr, "tid = %d, os_id = %lu\n", tid, os_id);
+}
+
+int main() {
+ fprintf(stderr, "Hello world.\n");
+
+ uint64_t threadid;
+ pthread_threadid_np(NULL, &threadid);
+ fprintf(stderr, "pthread_threadid_np = %llu\n", threadid);
+
+ pthread_mutex_t m;
+ pthread_mutex_init(&m, NULL);
+ pthread_mutex_unlock(&m);
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: pthread_threadid_np = [[ADDR:[0-9]+]]
+// CHECK: WARNING: ThreadSanitizer
+// CHECK: tid = 0, os_id = [[ADDR]]
+// CHECK: Done.
diff --git a/test/tsan/Darwin/norace-objcxx-run-time.mm b/test/tsan/Darwin/norace-objcxx-run-time.mm
index 0cf729e7f2d8..1de431a076c7 100644
--- a/test/tsan/Darwin/norace-objcxx-run-time.mm
+++ b/test/tsan/Darwin/norace-objcxx-run-time.mm
@@ -1,5 +1,5 @@
// 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
+// RUN: %run %t 2>&1 | FileCheck %s
// Check that we do not report races between:
// - Object retain and initialize
diff --git a/test/tsan/Darwin/objc-double-property.mm b/test/tsan/Darwin/objc-double-property.mm
index 51b10f21c9ca..c99151d28048 100644
--- a/test/tsan/Darwin/objc-double-property.mm
+++ b/test/tsan/Darwin/objc-double-property.mm
@@ -1,7 +1,7 @@
-// RUN: %clangxx_tsan -O0 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_tsan -O1 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_tsan -O2 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_tsan -O3 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O0 %s -o %t -framework Foundation && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t -framework Foundation && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O2 %s -o %t -framework Foundation && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O3 %s -o %t -framework Foundation && %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/objc-simple.mm b/test/tsan/Darwin/objc-simple.mm
index a8fc35592962..b62d0eb8702d 100644
--- a/test/tsan/Darwin/objc-simple.mm
+++ b/test/tsan/Darwin/objc-simple.mm
@@ -1,7 +1,7 @@
// Test that a simple Obj-C program runs and exits without any warnings.
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
diff --git a/test/tsan/Darwin/workerthreads.mm b/test/tsan/Darwin/workerthreads.mm
new file mode 100644
index 000000000000..18369fd62dd3
--- /dev/null
+++ b/test/tsan/Darwin/workerthreads.mm
@@ -0,0 +1,43 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+#import "../test.h"
+
+long global;
+
+int main() {
+ fprintf(stderr, "Hello world.\n");
+ print_address("addr=", 1, &global);
+ barrier_init(&barrier, 2);
+
+ global = 42;
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ global = 43;
+ barrier_wait(&barrier);
+ });
+
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ barrier_wait(&barrier);
+ global = 44;
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ });
+ });
+
+ CFRunLoopRun();
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 8
+// CHECK: Previous write of size 8
+// CHECK: Location is global
+// CHECK: Thread {{.*}} is a GCD worker thread
+// CHECK-NOT: failed to restore the stack
+// CHECK: Thread {{.*}} is a GCD worker thread
+// CHECK-NOT: failed to restore the stack
+// CHECK: Done.
diff --git a/test/tsan/Darwin/xpc-cancel.mm b/test/tsan/Darwin/xpc-cancel.mm
new file mode 100644
index 000000000000..5e326b7e4973
--- /dev/null
+++ b/test/tsan/Darwin/xpc-cancel.mm
@@ -0,0 +1,37 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+#import <xpc/xpc.h>
+
+long global;
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+
+ dispatch_queue_t server_q = dispatch_queue_create("server.queue", DISPATCH_QUEUE_CONCURRENT);
+ xpc_connection_t server_conn = xpc_connection_create(NULL, server_q);
+
+ xpc_connection_set_event_handler(server_conn, ^(xpc_object_t client) {
+ if (client == XPC_ERROR_CONNECTION_INTERRUPTED || client == XPC_ERROR_CONNECTION_INVALID) {
+ global = 43;
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ });
+ }
+ });
+ xpc_connection_resume(server_conn);
+
+ global = 42;
+
+ xpc_connection_cancel(server_conn);
+
+ CFRunLoopRun();
+
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/test/tsan/Darwin/xpc-race.mm b/test/tsan/Darwin/xpc-race.mm
index 9141da42e3a0..eaef4e06c1f6 100644
--- a/test/tsan/Darwin/xpc-race.mm
+++ b/test/tsan/Darwin/xpc-race.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %deflake %run %t 2>&1 | FileCheck %s
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
#import <xpc/xpc.h>
diff --git a/test/tsan/Darwin/xpc.mm b/test/tsan/Darwin/xpc.mm
index a939b02ef21a..2d6de269b59f 100644
--- a/test/tsan/Darwin/xpc.mm
+++ b/test/tsan/Darwin/xpc.mm
@@ -1,5 +1,5 @@
// RUN: %clang_tsan %s -o %t -framework Foundation
-// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
#import <Foundation/Foundation.h>
#import <xpc/xpc.h>
diff --git a/test/tsan/Linux/pie_no_aslr.cc b/test/tsan/Linux/pie_no_aslr.cc
new file mode 100644
index 000000000000..b99342da06bb
--- /dev/null
+++ b/test/tsan/Linux/pie_no_aslr.cc
@@ -0,0 +1,6 @@
+// RUN: %clang_tsan %s -pie -fPIE -o %t && %run setarch x86_64 -R %t
+// REQUIRES: x86_64-target-arch
+
+int main() {
+ return 0;
+}
diff --git a/test/tsan/Linux/user_malloc.cc b/test/tsan/Linux/user_malloc.cc
index 9c3ce681d748..6d51a9dd7d9b 100644
--- a/test/tsan/Linux/user_malloc.cc
+++ b/test/tsan/Linux/user_malloc.cc
@@ -1,4 +1,5 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: powerpc64le
#include <stdio.h>
// Defined by tsan.
diff --git a/test/tsan/Unit/lit.site.cfg.in b/test/tsan/Unit/lit.site.cfg.in
index 23894a839856..40cf096478f5 100644
--- a/test/tsan/Unit/lit.site.cfg.in
+++ b/test/tsan/Unit/lit.site.cfg.in
@@ -11,3 +11,13 @@ config.name = 'ThreadSanitizer-Unit'
# FIXME: De-hardcode this path.
config.test_exec_root = "@COMPILER_RT_BINARY_DIR@/lib/tsan/tests"
config.test_source_root = config.test_exec_root
+
+if config.host_os == 'Darwin':
+ config.parallelism_group = config.darwin_sanitizer_parallelism_group_func
+
+ # On Darwin, we default to ignore_noninstrumented_modules=1, which also
+ # suppresses some races the tests are supposed to find. See tsan/lit.cfg.
+ if 'TSAN_OPTIONS' in config.environment:
+ config.environment['TSAN_OPTIONS'] += ':ignore_noninstrumented_modules=0'
+ else:
+ config.environment['TSAN_OPTIONS'] = 'ignore_noninstrumented_modules=0'
diff --git a/test/tsan/atomic_hle.cc b/test/tsan/atomic_hle.cc
new file mode 100644
index 000000000000..345e363c2bc0
--- /dev/null
+++ b/test/tsan/atomic_hle.cc
@@ -0,0 +1,25 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <sanitizer/tsan_interface_atomic.h>
+
+#ifndef __ATOMIC_HLE_ACQUIRE
+#define __ATOMIC_HLE_ACQUIRE (1 << 16)
+#endif
+#ifndef __ATOMIC_HLE_RELEASE
+#define __ATOMIC_HLE_RELEASE (1 << 17)
+#endif
+
+int main() {
+ volatile int x = 0;
+ //__atomic_fetch_add(&x, 1, __ATOMIC_ACQUIRE | __ATOMIC_HLE_ACQUIRE);
+ //__atomic_store_n(&x, 0, __ATOMIC_RELEASE | __ATOMIC_HLE_RELEASE);
+ __tsan_atomic32_fetch_add(&x, 1,
+ (__tsan_memory_order)(__ATOMIC_ACQUIRE | __ATOMIC_HLE_ACQUIRE));
+ __tsan_atomic32_store(&x, 0,
+ (__tsan_memory_order)(__ATOMIC_RELEASE | __ATOMIC_HLE_RELEASE));
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: DONE
+
diff --git a/test/tsan/custom_mutex.h b/test/tsan/custom_mutex.h
new file mode 100644
index 000000000000..675ad59b322c
--- /dev/null
+++ b/test/tsan/custom_mutex.h
@@ -0,0 +1,91 @@
+#include "test.h"
+#include <atomic>
+#include <vector>
+#include <sanitizer/tsan_interface.h>
+
+// A very primitive mutex annotated with tsan annotations.
+class Mutex {
+ public:
+ Mutex(bool prof = true)
+ : prof_(prof)
+ , locked_(false)
+ , seq_(0) {
+ __tsan_mutex_create(this, 0);
+ }
+
+ ~Mutex() {
+ __tsan_mutex_destroy(this, 0);
+ }
+
+ void Lock() {
+ __tsan_mutex_pre_lock(this, 0);
+ LockImpl();
+ __tsan_mutex_post_lock(this, 0, 0);
+ }
+
+ bool TryLock() {
+ __tsan_mutex_pre_lock(this, __tsan_mutex_try_lock);
+ bool ok = TryLockImpl();
+ __tsan_mutex_post_lock(this, __tsan_mutex_try_lock |
+ (ok ? 0 : __tsan_mutex_try_lock_failed), 0);
+ return ok;
+ }
+
+ void Unlock() {
+ __tsan_mutex_pre_unlock(this, 0);
+ UnlockImpl();
+ __tsan_mutex_post_unlock(this, 0);
+ }
+
+ void Wait() {
+ for (int seq = seq_; seq == seq_;) {
+ Unlock();
+ usleep(100);
+ Lock();
+ }
+ }
+
+ void Broadcast() {
+ __tsan_mutex_pre_signal(this, 0);
+ LockImpl(false);
+ seq_++;
+ UnlockImpl();
+ __tsan_mutex_post_signal(this, 0);
+ }
+
+ private:
+ const bool prof_;
+ std::atomic<bool> locked_;
+ int seq_;
+
+ // This models mutex profiling subsystem.
+ static Mutex prof_mu_;
+ static int prof_data_;
+
+ void LockImpl(bool prof = true) {
+ while (!TryLockImpl())
+ usleep(100);
+ if (prof && prof_)
+ Prof();
+ }
+
+ bool TryLockImpl() {
+ return !locked_.exchange(true);
+ }
+
+ void UnlockImpl() {
+ locked_.store(false);
+ }
+
+ void Prof() {
+ // This happens inside of mutex lock annotations.
+ __tsan_mutex_pre_divert(this, 0);
+ prof_mu_.Lock();
+ prof_data_++;
+ prof_mu_.Unlock();
+ __tsan_mutex_post_divert(this, 0);
+ }
+};
+
+Mutex Mutex::prof_mu_(false);
+int Mutex::prof_data_;
diff --git a/test/tsan/custom_mutex0.cc b/test/tsan/custom_mutex0.cc
new file mode 100644
index 000000000000..998385ca1cf8
--- /dev/null
+++ b/test/tsan/custom_mutex0.cc
@@ -0,0 +1,31 @@
+// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "custom_mutex.h"
+
+// Test that custom annoations provide normal mutex synchronization
+// (no race reports for properly protected critical sections).
+
+Mutex mu;
+long data;
+
+void *thr(void *arg) {
+ barrier_wait(&barrier);
+ mu.Lock();
+ data++;
+ mu.Unlock();
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ barrier_wait(&barrier);
+ mu.Lock();
+ data++;
+ mu.Unlock();
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: DONE
diff --git a/test/tsan/custom_mutex1.cc b/test/tsan/custom_mutex1.cc
new file mode 100644
index 000000000000..06186515f697
--- /dev/null
+++ b/test/tsan/custom_mutex1.cc
@@ -0,0 +1,39 @@
+// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+#include "custom_mutex.h"
+
+// Test that failed TryLock does not induce parasitic synchronization.
+
+Mutex mu;
+long data;
+
+void *thr(void *arg) {
+ mu.Lock();
+ data++;
+ mu.Unlock();
+ mu.Lock();
+ barrier_wait(&barrier);
+ barrier_wait(&barrier);
+ mu.Unlock();
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ barrier_wait(&barrier);
+ if (mu.TryLock()) {
+ fprintf(stderr, "TryLock succeeded, should not\n");
+ exit(0);
+ }
+ data++;
+ barrier_wait(&barrier);
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK-NEXT: Write of size 8 at {{.*}} by main thread:
+// CHECK-NEXT: #0 main {{.*}}custom_mutex1.cc:29
+// CHECK: DONE
diff --git a/test/tsan/custom_mutex2.cc b/test/tsan/custom_mutex2.cc
new file mode 100644
index 000000000000..9329cbc3f432
--- /dev/null
+++ b/test/tsan/custom_mutex2.cc
@@ -0,0 +1,34 @@
+// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+#include "custom_mutex.h"
+
+// Test that Broadcast does not induce parasitic synchronization.
+
+Mutex mu;
+long data;
+
+void *thr(void *arg) {
+ barrier_wait(&barrier);
+ mu.Lock();
+ data++;
+ mu.Unlock();
+ data++;
+ mu.Broadcast();
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ mu.Lock();
+ barrier_wait(&barrier);
+ while (data == 0)
+ mu.Wait();
+ mu.Unlock();
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK: DONE
diff --git a/test/tsan/fd_socket_connect_norace.cc b/test/tsan/fd_socket_connect_norace.cc
index b9fb4340ad78..12375189a0f9 100644
--- a/test/tsan/fd_socket_connect_norace.cc
+++ b/test/tsan/fd_socket_connect_norace.cc
@@ -1,20 +1,24 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include <arpa/inet.h>
+#include <assert.h>
+#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <sys/types.h>
+#include <unistd.h>
-struct sockaddr_in addr;
+struct sockaddr_in addr4;
+struct sockaddr_in6 addr6;
+struct sockaddr *addr;
+socklen_t addrlen;
int X;
void *ClientThread(void *x) {
- int c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ int c = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
X = 42;
- if (connect(c, (struct sockaddr*)&addr, sizeof(addr))) {
+ if (connect(c, addr, addrlen)) {
perror("connect");
exit(1);
}
@@ -23,13 +27,26 @@ void *ClientThread(void *x) {
}
int main() {
- int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- addr.sin_family = AF_INET;
- inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
- addr.sin_port = INADDR_ANY;
- socklen_t len = sizeof(addr);
- bind(s, (sockaddr*)&addr, len);
- getsockname(s, (sockaddr*)&addr, &len);
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr4.sin_port = INADDR_ANY;
+ addr = (struct sockaddr *)&addr4;
+ addrlen = sizeof(addr4);
+
+ int s = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ if (s <= 0) {
+ // Try to fall-back to IPv6
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_addr = in6addr_loopback;
+ addr6.sin6_port = INADDR_ANY;
+ addr = (struct sockaddr *)&addr6;
+ addrlen = sizeof(addr6);
+ s = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ }
+ assert(s > 0);
+
+ bind(s, addr, addrlen);
+ getsockname(s, addr, &addrlen);
listen(s, 10);
pthread_t t;
pthread_create(&t, 0, ClientThread, 0);
diff --git a/test/tsan/fd_socket_norace.cc b/test/tsan/fd_socket_norace.cc
index 07b0cb356b8c..a1761cb27fd1 100644
--- a/test/tsan/fd_socket_norace.cc
+++ b/test/tsan/fd_socket_norace.cc
@@ -1,20 +1,24 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include <arpa/inet.h>
+#include <assert.h>
+#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <sys/types.h>
+#include <unistd.h>
-struct sockaddr_in addr;
+struct sockaddr_in addr4;
+struct sockaddr_in6 addr6;
+struct sockaddr *addr;
+socklen_t addrlen;
int X;
void *ClientThread(void *x) {
X = 42;
- int c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (connect(c, (struct sockaddr*)&addr, sizeof(addr))) {
+ int c = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ if (connect(c, addr, addrlen)) {
perror("connect");
exit(1);
}
@@ -27,13 +31,26 @@ void *ClientThread(void *x) {
}
int main() {
- int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- addr.sin_family = AF_INET;
- inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
- addr.sin_port = INADDR_ANY;
- socklen_t len = sizeof(addr);
- bind(s, (sockaddr*)&addr, len);
- getsockname(s, (sockaddr*)&addr, &len);
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr4.sin_port = INADDR_ANY;
+ addr = (struct sockaddr *)&addr4;
+ addrlen = sizeof(addr4);
+
+ int s = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ if (s <= 0) {
+ // Try to fall-back to IPv6
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_addr = in6addr_loopback;
+ addr6.sin6_port = INADDR_ANY;
+ addr = (struct sockaddr *)&addr6;
+ addrlen = sizeof(addr6);
+ s = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ }
+ assert(s > 0);
+
+ bind(s, addr, addrlen);
+ getsockname(s, addr, &addrlen);
listen(s, 10);
pthread_t t;
pthread_create(&t, 0, ClientThread, 0);
diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg
index 5d82cc9d4921..3c98d1fdca78 100644
--- a/test/tsan/lit.cfg
+++ b/test/tsan/lit.cfg
@@ -24,6 +24,10 @@ if config.host_os == 'Darwin':
# On Darwin, we default to `abort_on_error=1`, which would make tests run
# much slower. Let's override this and run lit tests with 'abort_on_error=0'.
default_tsan_opts += ':abort_on_error=0'
+ # On Darwin, we default to ignore_noninstrumented_modules=1, which also
+ # suppresses some races the tests are supposed to find. Let's run without this
+ # setting, but turn it back on for Darwin tests (see Darwin/lit.local.cfg).
+ default_tsan_opts += ':ignore_noninstrumented_modules=0'
# Platform-specific default TSAN_OPTIONS for lit tests.
if default_tsan_opts:
@@ -83,3 +87,6 @@ if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']:
# because the test hangs.
if config.target_arch != 'aarch64':
config.available_features.add('stable-runtime')
+
+if config.host_os == 'Darwin' and config.target_arch in ["x86_64", "x86_64h"]:
+ config.parallelism_group = "darwin-64bit-sanitizer"