diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:20 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:20 +0000 |
commit | 2953104c9a262728031dc518429d15b969dd6028 (patch) | |
tree | d4fff23823637f2256cedf634a2be262862ea90f /test/tsan | |
parent | f351c8a560ddc5b5df9ee5ba4ccc1cfb9029146d (diff) | |
download | src-2953104c9a262728031dc518429d15b969dd6028.tar.gz src-2953104c9a262728031dc518429d15b969dd6028.zip |
Vendor import of compiler-rt trunk r301441:vendor/compiler-rt/compiler-rt-trunk-r301441
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=317449
svn path=/vendor/compiler-rt/compiler-rt-trunk-r301441/; revision=317450; tag=vendor/compiler-rt/compiler-rt-trunk-r301441
Diffstat (limited to 'test/tsan')
-rw-r--r-- | test/tsan/Darwin/deadlock.mm | 47 | ||||
-rw-r--r-- | test/tsan/Darwin/debug_external.cc | 2 | ||||
-rw-r--r-- | test/tsan/Darwin/external-dups.cc | 58 | ||||
-rw-r--r-- | test/tsan/Darwin/external-ignore-noninstrumented.cc | 19 | ||||
-rw-r--r-- | test/tsan/Darwin/external-lib.cc | 68 | ||||
-rw-r--r-- | test/tsan/Darwin/external-noninstrumented-module.cc | 27 | ||||
-rw-r--r-- | test/tsan/Darwin/external.cc | 78 | ||||
-rw-r--r-- | test/tsan/test.h | 2 | ||||
-rw-r--r-- | test/tsan/unaligned_race.cc | 23 |
9 files changed, 237 insertions, 87 deletions
diff --git a/test/tsan/Darwin/deadlock.mm b/test/tsan/Darwin/deadlock.mm new file mode 100644 index 000000000000..36ddfad54f7c --- /dev/null +++ b/test/tsan/Darwin/deadlock.mm @@ -0,0 +1,47 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +#import "../test.h" + +pthread_mutex_t m1; +pthread_mutex_t m2; + +int main(int argc, const char *argv[]) { + barrier_init(&barrier, 2); + fprintf(stderr, "Hello world.\n"); + + pthread_mutex_init(&m1, NULL); + pthread_mutex_init(&m2, NULL); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + pthread_mutex_lock(&m1); + pthread_mutex_lock(&m2); + pthread_mutex_unlock(&m2); + pthread_mutex_unlock(&m1); + + barrier_wait(&barrier); + }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + barrier_wait(&barrier); + + pthread_mutex_lock(&m2); + pthread_mutex_lock(&m1); + pthread_mutex_unlock(&m1); + pthread_mutex_unlock(&m2); + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + + fprintf(stderr, "Done.\n"); + return 0; +} + +// CHECK: Hello world. +// CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) +// CHECK: Done. diff --git a/test/tsan/Darwin/debug_external.cc b/test/tsan/Darwin/debug_external.cc index 217690fc5dd0..2418a271b23c 100644 --- a/test/tsan/Darwin/debug_external.cc +++ b/test/tsan/Darwin/debug_external.cc @@ -17,8 +17,6 @@ int __tsan_get_report_loc(void *report, unsigned long idx, const char **type, 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) { diff --git a/test/tsan/Darwin/external-dups.cc b/test/tsan/Darwin/external-dups.cc new file mode 100644 index 000000000000..79432bac4a02 --- /dev/null +++ b/test/tsan/Darwin/external-dups.cc @@ -0,0 +1,58 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#include <thread> + +#import "../test.h" + +void *tag; + +__attribute__((no_sanitize("thread"))) +void ExternalWrite(void *addr) { + __tsan_external_write(addr, __builtin_return_address(0), tag); +} + +int main(int argc, char *argv[]) { + barrier_init(&barrier, 2); + tag = __tsan_external_register_tag("HelloWorld"); + fprintf(stderr, "Start.\n"); + // CHECK: Start. + + for (int i = 0; i < 4; i++) { + void *opaque_object = malloc(16); + std::thread t1([opaque_object] { + ExternalWrite(opaque_object); + barrier_wait(&barrier); + }); + std::thread t2([opaque_object] { + barrier_wait(&barrier); + ExternalWrite(opaque_object); + }); + // CHECK: WARNING: ThreadSanitizer: race on a library object + t1.join(); + t2.join(); + } + + fprintf(stderr, "First phase done.\n"); + // CHECK: First phase done. + + for (int i = 0; i < 4; i++) { + void *opaque_object = malloc(16); + std::thread t1([opaque_object] { + ExternalWrite(opaque_object); + barrier_wait(&barrier); + }); + std::thread t2([opaque_object] { + barrier_wait(&barrier); + ExternalWrite(opaque_object); + }); + // CHECK: WARNING: ThreadSanitizer: race on a library object + t1.join(); + t2.join(); + } + + fprintf(stderr, "Second phase done.\n"); + // CHECK: Second phase done. +} + +// CHECK: ThreadSanitizer: reported 2 warnings diff --git a/test/tsan/Darwin/external-ignore-noninstrumented.cc b/test/tsan/Darwin/external-ignore-noninstrumented.cc new file mode 100644 index 000000000000..d2acaf54b263 --- /dev/null +++ b/test/tsan/Darwin/external-ignore-noninstrumented.cc @@ -0,0 +1,19 @@ +// RUN: %clangxx_tsan -shared %p/external-lib.cc -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ +// RUN: -o %t-lib.dylib -install_name @rpath/`basename %t-lib.dylib` + +// RUN: %clangxx_tsan -shared %p/external-noninstrumented-module.cc %t-lib.dylib -fno-sanitize=thread \ +// RUN: -o %t-module.dylib -install_name @rpath/`basename %t-module.dylib` + +// RUN: %clangxx_tsan %s %t-module.dylib -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include <stdio.h> + +extern "C" void NonInstrumentedModule(); +int main(int argc, char *argv[]) { + NonInstrumentedModule(); + fprintf(stderr, "Done.\n"); +} + +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK: Done. diff --git a/test/tsan/Darwin/external-lib.cc b/test/tsan/Darwin/external-lib.cc new file mode 100644 index 000000000000..f0afdf1dc060 --- /dev/null +++ b/test/tsan/Darwin/external-lib.cc @@ -0,0 +1,68 @@ +// This file is used from other tests. +// RUN: true + +#include <dlfcn.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); +} + +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; +} diff --git a/test/tsan/Darwin/external-noninstrumented-module.cc b/test/tsan/Darwin/external-noninstrumented-module.cc new file mode 100644 index 000000000000..ce65970834e5 --- /dev/null +++ b/test/tsan/Darwin/external-noninstrumented-module.cc @@ -0,0 +1,27 @@ +// This file is used from other tests. +// RUN: true + +#include <thread> + +#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); +} + +extern "C" void NonInstrumentedModule() { + InitializeLibrary(); + + MyObjectRef ref = ObjectCreate(); + std::thread t1([ref]{ ObjectWrite(ref, 42); }); + std::thread t2([ref]{ ObjectWrite(ref, 43); }); + t1.join(); + t2.join(); +} diff --git a/test/tsan/Darwin/external.cc b/test/tsan/Darwin/external.cc index 2605480d7b82..211694ab7db1 100644 --- a/test/tsan/Darwin/external.cc +++ b/test/tsan/Darwin/external.cc @@ -1,12 +1,12 @@ -// RUN: %clangxx_tsan %s -shared -DSHARED_LIB \ +// RUN: %clangxx_tsan %p/external-lib.cc -shared \ // 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: %clangxx_tsan %p/external-lib.cc -shared -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: %clangxx_tsan %p/external-lib.cc -shared -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ // RUN: -o %t-lib-noninstrumented-callbacks.dylib \ // RUN: -install_name @rpath/`basename %t-lib-noninstrumented-callbacks.dylib` @@ -23,8 +23,6 @@ #include <thread> -#include <dlfcn.h> -#include <pthread.h> #include <stdio.h> #include <stdlib.h> @@ -38,62 +36,6 @@ extern "C" { 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(); @@ -126,11 +68,11 @@ int main(int argc, char *argv[]) { // TEST2-NOT: WARNING: ThreadSanitizer // TEST3: WARNING: ThreadSanitizer: race on a library object - // TEST3: {{Mutating|read-only}} access of object MyLibrary::MyObject at + // TEST3: {{Mutating|read-only}} access of MyLibrary::MyObject at // TEST3: {{ObjectWrite|ObjectRead}} - // TEST3: Previous {{mutating|read-only}} access of object MyLibrary::MyObject at + // TEST3: Previous {{mutating|read-only}} access of MyLibrary::MyObject at // TEST3: {{ObjectWrite|ObjectRead}} - // TEST3: Location is MyLibrary::MyObject object of size 16 at + // TEST3: Location is MyLibrary::MyObject of size 16 at // TEST3: {{ObjectCreate}} fprintf(stderr, "RW test done\n"); @@ -149,15 +91,13 @@ int main(int argc, char *argv[]) { // TEST2-NOT: WARNING: ThreadSanitizer // TEST3: WARNING: ThreadSanitizer: race on a library object - // TEST3: Mutating access of object MyLibrary::MyObject at + // TEST3: Mutating access of MyLibrary::MyObject at // TEST3: {{ObjectWrite|ObjectWriteAnother}} - // TEST3: Previous mutating access of object MyLibrary::MyObject at + // TEST3: Previous mutating access of MyLibrary::MyObject at // TEST3: {{ObjectWrite|ObjectWriteAnother}} - // TEST3: Location is MyLibrary::MyObject object of size 16 at + // TEST3: Location is MyLibrary::MyObject 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/test.h b/test/tsan/test.h index 6b981c09f53d..bc4f7aad55fe 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -8,6 +8,8 @@ #include <stdarg.h> #include "sanitizer_common/print_address.h" +#include <sanitizer/tsan_interface.h> + #ifdef __APPLE__ #include <mach/mach_time.h> #endif diff --git a/test/tsan/unaligned_race.cc b/test/tsan/unaligned_race.cc index 030642a4ddfb..5850b21542d4 100644 --- a/test/tsan/unaligned_race.cc +++ b/test/tsan/unaligned_race.cc @@ -6,31 +6,22 @@ volatile uint64_t objs[8*2*(2 + 4 + 8)][2]; -extern "C" { -uint16_t __sanitizer_unaligned_load16(volatile void *addr); -uint32_t __sanitizer_unaligned_load32(volatile void *addr); -uint64_t __sanitizer_unaligned_load64(volatile void *addr); -void __sanitizer_unaligned_store16(volatile void *addr, uint16_t v); -void __sanitizer_unaligned_store32(volatile void *addr, uint32_t v); -void __sanitizer_unaligned_store64(volatile void *addr, uint64_t v); -} - // All this mess is to generate unique stack for each race, // otherwise tsan will suppress similar stacks. -static NOINLINE void access(volatile char *p, int sz, int rw) { +static NOINLINE void access(volatile void *p, int sz, int rw) { if (rw) { switch (sz) { - case 0: __sanitizer_unaligned_store16(p, 0); break; - case 1: __sanitizer_unaligned_store32(p, 0); break; - case 2: __sanitizer_unaligned_store64(p, 0); break; + case 0: __sanitizer_unaligned_store16((void *)p, 0); break; + case 1: __sanitizer_unaligned_store32((void *)p, 0); break; + case 2: __sanitizer_unaligned_store64((void *)p, 0); break; default: exit(1); } } else { switch (sz) { - case 0: __sanitizer_unaligned_load16(p); break; - case 1: __sanitizer_unaligned_load32(p); break; - case 2: __sanitizer_unaligned_load64(p); break; + case 0: __sanitizer_unaligned_load16((void *)p); break; + case 1: __sanitizer_unaligned_load32((void *)p); break; + case 2: __sanitizer_unaligned_load64((void *)p); break; default: exit(1); } } |