1 // RUN: %clangxx_tsan %p/external-lib.cpp -shared \ 2 // RUN: -o %t-lib-instrumented.dylib \ 3 // RUN: -install_name @rpath/`basename %t-lib-instrumented.dylib` 4 5 // RUN: %clangxx_tsan %p/external-lib.cpp -shared -fno-sanitize=thread \ 6 // RUN: -o %t-lib-noninstrumented.dylib \ 7 // RUN: -install_name @rpath/`basename %t-lib-noninstrumented.dylib` 8 9 // RUN: %clangxx_tsan %p/external-lib.cpp -shared -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ 10 // RUN: -o %t-lib-noninstrumented-callbacks.dylib \ 11 // RUN: -install_name @rpath/`basename %t-lib-noninstrumented-callbacks.dylib` 12 13 // RUN: %clangxx_tsan %s %t-lib-instrumented.dylib -o %t-lib-instrumented 14 // RUN: %clangxx_tsan %s %t-lib-noninstrumented.dylib -o %t-lib-noninstrumented 15 // RUN: %clangxx_tsan %s %t-lib-noninstrumented-callbacks.dylib -o %t-lib-noninstrumented-callbacks 16 17 // RUN: %deflake %run %t-lib-instrumented 2>&1 \ 18 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST1 19 // RUN: %run %t-lib-noninstrumented 2>&1 \ 20 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST2 21 // RUN: %deflake %run %t-lib-noninstrumented-callbacks 2>&1 \ 22 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=TEST3 23 24 #include <thread> 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 29 struct MyObject; 30 typedef MyObject *MyObjectRef; 31 extern "C" { 32 void InitializeLibrary(); 33 MyObject *ObjectCreate(); 34 long ObjectRead(MyObject *); 35 void ObjectWrite(MyObject *, long); 36 void ObjectWriteAnother(MyObject *, long); 37 } 38 39 int main(int argc, char *argv[]) { 40 InitializeLibrary(); 41 42 { 43 MyObjectRef ref = ObjectCreate(); 44 std::thread t1([ref]{ ObjectRead(ref); }); 45 std::thread t2([ref]{ ObjectRead(ref); }); 46 t1.join(); 47 t2.join(); 48 } 49 50 // CHECK-NOT: WARNING: ThreadSanitizer 51 52 fprintf(stderr, "RR test done\n"); 53 // CHECK: RR test done 54 55 { 56 MyObjectRef ref = ObjectCreate(); 57 std::thread t1([ref]{ ObjectRead(ref); }); 58 std::thread t2([ref]{ ObjectWrite(ref, 66); }); 59 t1.join(); 60 t2.join(); 61 } 62 63 // TEST1: WARNING: ThreadSanitizer: data race 64 // TEST1: {{Write|Read}} of size 8 at 65 // TEST1: Previous {{write|read}} of size 8 at 66 // TEST1: Location is heap block of size 16 at 67 68 // TEST2-NOT: WARNING: ThreadSanitizer 69 70 // TEST3: WARNING: ThreadSanitizer: race on MyLibrary::MyObject 71 // TEST3: {{Modifying|read-only}} access of MyLibrary::MyObject at 72 // TEST3: {{ObjectWrite|ObjectRead}} 73 // TEST3: Previous {{modifying|read-only}} access of MyLibrary::MyObject at 74 // TEST3: {{ObjectWrite|ObjectRead}} 75 // TEST3: Location is MyLibrary::MyObject of size 16 at 76 // TEST3: {{ObjectCreate}} 77 // TEST3: SUMMARY: ThreadSanitizer: race on MyLibrary::MyObject {{.*}} in {{ObjectWrite|ObjectRead}} 78 79 fprintf(stderr, "RW test done\n"); 80 // CHECK: RW test done 81 82 { 83 MyObjectRef ref = ObjectCreate(); 84 std::thread t1([ref]{ ObjectWrite(ref, 76); }); 85 std::thread t2([ref]{ ObjectWriteAnother(ref, 77); }); 86 t1.join(); 87 t2.join(); 88 } 89 90 // TEST1-NOT: WARNING: ThreadSanitizer: data race 91 92 // TEST2-NOT: WARNING: ThreadSanitizer 93 94 // TEST3: WARNING: ThreadSanitizer: race on MyLibrary::MyObject 95 // TEST3: Modifying access of MyLibrary::MyObject at 96 // TEST3: {{ObjectWrite|ObjectWriteAnother}} 97 // TEST3: Previous modifying access of MyLibrary::MyObject at 98 // TEST3: {{ObjectWrite|ObjectWriteAnother}} 99 // TEST3: Location is MyLibrary::MyObject of size 16 at 100 // TEST3: {{ObjectCreate}} 101 // TEST3: SUMMARY: ThreadSanitizer: race on MyLibrary::MyObject {{.*}} in {{ObjectWrite|ObjectWriteAnother}} 102 103 fprintf(stderr, "WW test done\n"); 104 // CHECK: WW test done 105 } 106