diff options
Diffstat (limited to 'test/tsan')
98 files changed, 1010 insertions, 219 deletions
diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt index 2996c1d80fbdc..01e80388bb95a 100644 --- a/test/tsan/CMakeLists.txt +++ b/test/tsan/CMakeLists.txt @@ -1,12 +1,13 @@ set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT ${LLVM_NATIVE_ARCH} STREQUAL "Mips") +if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "x86_64") list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND TSAN_TEST_DEPS tsan) endif() if(COMPILER_RT_HAS_LIBCXX_SOURCES AND - COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang") + COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang" + AND NOT APPLE) list(APPEND TSAN_TEST_DEPS libcxx_tsan) set(TSAN_HAS_LIBCXX True) else() diff --git a/test/tsan/Darwin/gcd-async-norace.mm b/test/tsan/Darwin/gcd-async-norace.mm new file mode 100644 index 0000000000000..b987e00656fbd --- /dev/null +++ b/test/tsan/Darwin/gcd-async-norace.mm @@ -0,0 +1,26 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +long global; + +int main() { + NSLog(@"Hello world."); + + global = 42; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + global = 43; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-async-race.mm b/test/tsan/Darwin/gcd-async-race.mm new file mode 100644 index 0000000000000..31163f972896c --- /dev/null +++ b/test/tsan/Darwin/gcd-async-race.mm @@ -0,0 +1,38 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &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(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'global' at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Done. diff --git a/test/tsan/Darwin/gcd-groups-norace.mm b/test/tsan/Darwin/gcd-groups-norace.mm new file mode 100644 index 0000000000000..fb4d804ed8c74 --- /dev/null +++ b/test/tsan/Darwin/gcd-groups-norace.mm @@ -0,0 +1,53 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + + dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + global = 42; + + dispatch_group_t g = dispatch_group_create(); + dispatch_group_async(g, q, ^{ + global = 43; + }); + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + global = 44; + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global = 45; + dispatch_group_leave(g); + }); + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + global = 46; + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global = 47; + dispatch_group_leave(g); + }); + dispatch_group_notify(g, q, ^{ + global = 48; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-groups-stress.mm b/test/tsan/Darwin/gcd-groups-stress.mm new file mode 100644 index 0000000000000..62a80085ed8d7 --- /dev/null +++ b/test/tsan/Darwin/gcd-groups-stress.mm @@ -0,0 +1,43 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +void notify_callback(void *context) { + // Do nothing. +} + +int main() { + NSLog(@"Hello world."); + + dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + for (int i = 0; i < 300000; i++) { + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + dispatch_async(q, ^{ + dispatch_group_leave(g); + }); + dispatch_group_notify(g, q, ^{ + // Do nothing. + }); + dispatch_release(g); + } + + for (int i = 0; i < 300000; i++) { + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + dispatch_async(q, ^{ + dispatch_group_leave(g); + }); + dispatch_group_notify_f(g, q, nullptr, ¬ify_callback); + dispatch_release(g); + } + + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK-NOT: CHECK failed diff --git a/test/tsan/Darwin/gcd-once.mm b/test/tsan/Darwin/gcd-once.mm new file mode 100644 index 0000000000000..17757d203751e --- /dev/null +++ b/test/tsan/Darwin/gcd-once.mm @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +static const long kNumThreads = 4; + +long global; +long global2; + +static dispatch_once_t once_token; +static dispatch_once_t once_token2; + +void f(void *) { + global2 = 42; + usleep(100000); +} + +void *Thread(void *a) { + barrier_wait(&barrier); + + dispatch_once(&once_token, ^{ + global = 42; + usleep(100000); + }); + long x = global; + + dispatch_once_f(&once_token2, NULL, f); + long x2 = global2; + + fprintf(stderr, "global = %ld\n", x); + fprintf(stderr, "global2 = %ld\n", x2); + return 0; +} + +int main() { + fprintf(stderr, "Hello world.\n"); + barrier_init(&barrier, kNumThreads); + + pthread_t t[kNumThreads]; + for (int i = 0; i < kNumThreads; i++) { + pthread_create(&t[i], 0, Thread, 0); + } + for (int i = 0; i < kNumThreads; i++) { + pthread_join(t[i], 0); + } + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-semaphore-norace.mm b/test/tsan/Darwin/gcd-semaphore-norace.mm new file mode 100644 index 0000000000000..cd52a79ca65ad --- /dev/null +++ b/test/tsan/Darwin/gcd-semaphore-norace.mm @@ -0,0 +1,29 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +long global; + +int main() { + NSLog(@"Hello world."); + + global = 42; + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + global = 43; + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + global = 44; + + NSLog(@"Done."); + return 0; +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-serial-queue-norace.mm b/test/tsan/Darwin/gcd-serial-queue-norace.mm new file mode 100644 index 0000000000000..8f6de27695a59 --- /dev/null +++ b/test/tsan/Darwin/gcd-serial-queue-norace.mm @@ -0,0 +1,40 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + + dispatch_queue_t q1 = dispatch_queue_create("my.queue1", DISPATCH_QUEUE_CONCURRENT); + dispatch_queue_t q2 = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_SERIAL); + + global = 42; + for (int i = 0; i < 10; i++) { + dispatch_async(q1, ^{ + for (int i = 0; i < 100; i++) { + dispatch_sync(q2, ^{ + global++; + }); + } + }); + } + + dispatch_barrier_async(q1, ^{ + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-sync-norace.mm b/test/tsan/Darwin/gcd-sync-norace.mm new file mode 100644 index 0000000000000..f21cfdedbce1d --- /dev/null +++ b/test/tsan/Darwin/gcd-sync-norace.mm @@ -0,0 +1,32 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +long global; + +static const long nIter = 1000; + +int main() { + NSLog(@"Hello world."); + + global = 42; + for (int i = 0; i < nIter; i++) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(dispatch_get_main_queue(), ^{ + global = i; + + if (i == nIter - 1) { + CFRunLoopStop(CFRunLoopGetCurrent()); + } + }); + }); + } + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/gcd-sync-race.mm b/test/tsan/Darwin/gcd-sync-race.mm new file mode 100644 index 0000000000000..62901d9b26128 --- /dev/null +++ b/test/tsan/Darwin/gcd-sync-race.mm @@ -0,0 +1,44 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + barrier_init(&barrier, 2); + + dispatch_queue_t q1 = dispatch_queue_create("my.queue1", DISPATCH_QUEUE_CONCURRENT); + dispatch_queue_t q2 = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT); + + global = 42; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(q1, ^{ + global = 43; + barrier_wait(&barrier); + }); + }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(q2, ^{ + barrier_wait(&barrier); + global = 44; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'global' at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Done. diff --git a/test/tsan/Darwin/lit.local.cfg b/test/tsan/Darwin/lit.local.cfg new file mode 100644 index 0000000000000..a85dfcd24c08e --- /dev/null +++ b/test/tsan/Darwin/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Darwin']: + config.unsupported = True diff --git a/test/tsan/Darwin/objc-race.mm b/test/tsan/Darwin/objc-race.mm new file mode 100644 index 0000000000000..bd93d2f1c2ea2 --- /dev/null +++ b/test/tsan/Darwin/objc-race.mm @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import <Foundation/Foundation.h> + +#import "../test.h" + +@interface MyClass : NSObject { + long instance_variable; +} +- (void)method:(long)value; +@end + +@implementation MyClass + +- (void)method:(long)value { + self->instance_variable = value; +} + +@end + +int main() { + NSLog(@"Hello world."); + barrier_init(&barrier, 2); + + MyClass *my_object = [MyClass new]; + [my_object method:42]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [my_object method:43]; + barrier_wait(&barrier); + }); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + barrier_wait(&barrier); + [my_object method:44]; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); + return 0; +} + +// CHECK: Hello world. +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write of size 8 +// CHECK: #0 -[MyClass method:] +// CHECK: Write of size 8 +// CHECK: #0 -[MyClass method:] +// CHECK: Location is heap block +// CHECK: Done. diff --git a/test/tsan/Darwin/objc-simple.mm b/test/tsan/Darwin/objc-simple.mm new file mode 100644 index 0000000000000..a4bf1f1beaa00 --- /dev/null +++ b/test/tsan/Darwin/objc-simple.mm @@ -0,0 +1,13 @@ +// Test that a simple Obj-C program runs and exits without any warnings. + +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import <Foundation/Foundation.h> + +int main() { + NSLog(@"Hello world"); +} + +// CHECK: Hello world +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/osspinlock-norace.cc b/test/tsan/Darwin/osspinlock-norace.cc new file mode 100644 index 0000000000000..2ac3989c223e1 --- /dev/null +++ b/test/tsan/Darwin/osspinlock-norace.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +#include <libkern/OSAtomic.h> +#include <pthread.h> +#include <stdio.h> + +int Global; +OSSpinLock lock; + +void *Thread(void *x) { + OSSpinLockLock(&lock); + Global++; + OSSpinLockUnlock(&lock); + return NULL; +} + +int main() { + fprintf(stderr, "Hello world.\n"); + + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread, NULL); + pthread_create(&t[1], NULL, Thread, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/symbolizer-atos.cc b/test/tsan/Darwin/symbolizer-atos.cc new file mode 100644 index 0000000000000..960fecc986414 --- /dev/null +++ b/test/tsan/Darwin/symbolizer-atos.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %env_tsan_opts=verbosity=2:external_symbolizer_path=/usr/bin/atos %deflake %run %t | FileCheck %s +#include "../test.h" + +int GlobalData[10]; + +void *Thread(void *a) { + barrier_wait(&barrier); + GlobalData[2] = 42; + return 0; +} + +int main() { + barrier_init(&barrier, 2); + print_address("addr=", 1, GlobalData); + pthread_t t; + pthread_create(&t, 0, Thread, 0); + GlobalData[2] = 43; + barrier_wait(&barrier); + pthread_join(t, 0); +} + +// CHECK: Using atos at user-specified path: /usr/bin/atos +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'GlobalData' at [[ADDR]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/test/tsan/Darwin/symbolizer-dladdr.cc b/test/tsan/Darwin/symbolizer-dladdr.cc new file mode 100644 index 0000000000000..3b213dda85d41 --- /dev/null +++ b/test/tsan/Darwin/symbolizer-dladdr.cc @@ -0,0 +1,27 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %env_tsan_opts=verbosity=2:external_symbolizer_path= %deflake %run %t | FileCheck %s +#include "../test.h" + +int GlobalData[10]; + +void *Thread(void *a) { + barrier_wait(&barrier); + GlobalData[2] = 42; + return 0; +} + +int main() { + barrier_init(&barrier, 2); + print_address("addr=", 1, GlobalData); + pthread_t t; + pthread_create(&t, 0, Thread, 0); + GlobalData[2] = 43; + barrier_wait(&barrier); + pthread_join(t, 0); +} + +// CHECK: External symbolizer is explicitly disabled. +// CHECK: Using dladdr symbolizer. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'GlobalData' at [[ADDR]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/test/tsan/Linux/check_memcpy.cc b/test/tsan/Linux/check_memcpy.cc new file mode 100644 index 0000000000000..8ad04c07cf514 --- /dev/null +++ b/test/tsan/Linux/check_memcpy.cc @@ -0,0 +1,15 @@ +// Test that verifies TSan runtime doesn't contain compiler-emitted +// memcpy/memmove calls. It builds the binary with TSan and passes it to +// check_memcpy.sh script. + +// RUN: %clangxx_tsan -O1 %s -o %t +// RUN: llvm-objdump -d %t | FileCheck %s + +int main() { + return 0; +} + +// CHECK-NOT: callq {{.*<(__interceptor_)?mem(cpy|set)>}} +// tail calls: +// CHECK-NOT: jmpq {{.*<(__interceptor_)?mem(cpy|set)>}} + diff --git a/test/tsan/allocator_returns_null.cc b/test/tsan/allocator_returns_null.cc index cde706bc8a1d8..66930076ac3ac 100644 --- a/test/tsan/allocator_returns_null.cc +++ b/test/tsan/allocator_returns_null.cc @@ -4,11 +4,11 @@ // // RUN: %clangxx_tsan -O0 %s -o %t // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrCRASH #include <limits.h> #include <stdlib.h> diff --git a/test/tsan/atomic_free3.cc b/test/tsan/atomic_free3.cc new file mode 100644 index 0000000000000..f2875aeb656f4 --- /dev/null +++ b/test/tsan/atomic_free3.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "test.h" + +// Test for https://github.com/google/sanitizers/issues/602 + +void *Thread(void *a) { + __atomic_store_n((int*)a, 1, __ATOMIC_RELAXED); + return 0; +} + +int main() { + int *a = new int(0); + pthread_t t; + pthread_create(&t, 0, Thread, a); + while (__atomic_load_n(a, __ATOMIC_RELAXED) == 0) + sched_yield(); + delete a; + pthread_join(t, 0); +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write +// CHECK: #0 operator delete +// CHECK: #1 main + +// CHECK: Previous atomic write +// CHECK: #0 __tsan_atomic32_store +// CHECK: #1 Thread diff --git a/test/tsan/barrier.cc b/test/tsan/barrier.cc index d8c2b6ffe5144..de2756de2a12c 100644 --- a/test/tsan/barrier.cc +++ b/test/tsan/barrier.cc @@ -2,6 +2,9 @@ // CHECK-NOT: ThreadSanitizer: data race // CHECK: DONE +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include <stdio.h> #include <stdlib.h> #include <pthread.h> diff --git a/test/tsan/bench_acquire_only.cc b/test/tsan/bench_acquire_only.cc index 5cd6bd74ebee5..0ed21b4612ab2 100644 --- a/test/tsan/bench_acquire_only.cc +++ b/test/tsan/bench_acquire_only.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/test/tsan/bench_acquire_release.cc b/test/tsan/bench_acquire_release.cc index 9e53a7b26efab..3799452a1629a 100644 --- a/test/tsan/bench_acquire_release.cc +++ b/test/tsan/bench_acquire_release.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/test/tsan/bench_local_mutex.cc b/test/tsan/bench_local_mutex.cc index 0fa1db0c883c1..15f83bc8b282f 100644 --- a/test/tsan/bench_local_mutex.cc +++ b/test/tsan/bench_local_mutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_mutex_t *mtx; diff --git a/test/tsan/bench_mutex.cc b/test/tsan/bench_mutex.cc index 324d53fd7f28d..58aa86a787d32 100644 --- a/test/tsan/bench_mutex.cc +++ b/test/tsan/bench_mutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_mutex_t mtx; diff --git a/test/tsan/bench_release_only.cc b/test/tsan/bench_release_only.cc index 0a86f73f249e2..7f26041afc49f 100644 --- a/test/tsan/bench_release_only.cc +++ b/test/tsan/bench_release_only.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int *x; diff --git a/test/tsan/bench_rwmutex.cc b/test/tsan/bench_rwmutex.cc index 818ee8c82bc11..2b3dcb012e506 100644 --- a/test/tsan/bench_rwmutex.cc +++ b/test/tsan/bench_rwmutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_rwlock_t mtx; diff --git a/test/tsan/bench_single_writer.cc b/test/tsan/bench_single_writer.cc index 0d3810a03ad01..3d2ea150b5fbc 100644 --- a/test/tsan/bench_single_writer.cc +++ b/test/tsan/bench_single_writer.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/test/tsan/bench_ten_mutexes.cc b/test/tsan/bench_ten_mutexes.cc index 876f1365ee432..e7fa05ea82039 100644 --- a/test/tsan/bench_ten_mutexes.cc +++ b/test/tsan/bench_ten_mutexes.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" const int kMutex = 10; diff --git a/test/tsan/cond_cancel.c b/test/tsan/cond_cancel.c index ddfb745174f63..fb6a66136b8af 100644 --- a/test/tsan/cond_cancel.c +++ b/test/tsan/cond_cancel.c @@ -1,6 +1,14 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // CHECK-NOT: WARNING // CHECK: OK +// This test is failing on powerpc64 (VMA=44). After calling pthread_cancel, +// the Thread-specific data destructors are not called, so the destructor +// "thread_finalize" (defined in tsan_interceptors.cc) can not set the status +// of the thread to "ThreadStatusFinished" failing a check in "SetJoined" +// (defined in sanitizer_thread_registry.cc). It might seem a bug on glibc, +// however the same version GLIBC-2.17 will not make fail the test on +// powerpc64 BE (VMA=46) +// XFAIL: powerpc64-unknown-linux-gnu #include "test.h" diff --git a/test/tsan/cond_version.c b/test/tsan/cond_version.c index 2282c3ad738d5..6bae776e6a4e3 100644 --- a/test/tsan/cond_version.c +++ b/test/tsan/cond_version.c @@ -3,6 +3,9 @@ // previously there were issues with versioned symbols. // CHECK: OK +// OS X doesn't have pthread_condattr_setclock. +// UNSUPPORTED: darwin + #include <stdio.h> #include <stdlib.h> #include <pthread.h> diff --git a/test/tsan/deadlock_detector_stress_test.cc b/test/tsan/deadlock_detector_stress_test.cc index c77ffe555ce5c..bbaaabbb3c14d 100644 --- a/test/tsan/deadlock_detector_stress_test.cc +++ b/test/tsan/deadlock_detector_stress_test.cc @@ -1,12 +1,12 @@ // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND -// RUN: TSAN_OPTIONS="detect_deadlocks=1 second_deadlock_stack=1" %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND +// RUN: %env_tsan_opts=detect_deadlocks=1:second_deadlock_stack=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRecursiveMutex -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC #include "test.h" #undef NDEBUG #include <assert.h> @@ -56,6 +56,7 @@ class PthreadRecursiveMutex : public PthreadMutex { static bool supports_recursive_lock() { return true; } }; +#ifndef __APPLE__ class PthreadSpinLock { public: PthreadSpinLock() { assert(0 == pthread_spin_init(&mu_, 0)); } @@ -76,6 +77,9 @@ class PthreadSpinLock { pthread_spinlock_t mu_; char padding_[64 - sizeof(pthread_spinlock_t)]; }; +#else +class PthreadSpinLock : public PthreadMutex { }; +#endif class PthreadRWLock { public: @@ -95,7 +99,7 @@ class PthreadRWLock { private: pthread_rwlock_t mu_; - char padding_[64 - sizeof(pthread_rwlock_t)]; + char padding_[256 - sizeof(pthread_rwlock_t)]; }; class LockTest { @@ -148,7 +152,7 @@ class LockTest { fprintf(stderr, "Starting Test1\n"); // CHECK: Starting Test1 Init(5); - fprintf(stderr, "Expecting lock inversion: %p %p\n", A(0), A(1)); + print_address("Expecting lock inversion: ", 2, A(0), A(1)); // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] Lock_0_1(); Lock_1_0(); @@ -174,7 +178,7 @@ class LockTest { fprintf(stderr, "Starting Test2\n"); // CHECK: Starting Test2 Init(5); - fprintf(stderr, "Expecting lock inversion: %p %p %p\n", A(0), A(1), A(2)); + print_address("Expecting lock inversion: ", 3, A(0), A(1), A(2)); // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] [[A3:0x[a-f0-9]*]] Lock2(0, 1); Lock2(1, 2); @@ -498,6 +502,19 @@ class LockTest { delete [] l; } + void Test19() { + if (test_number > 0 && test_number != 19) return; + fprintf(stderr, "Starting Test19: lots of lock inversions\n"); + const int kNumLocks = 45; + Init(kNumLocks); + for (int i = 0; i < kNumLocks; i++) { + for (int j = 0; j < kNumLocks; j++) + L((i + j) % kNumLocks); + for (int j = 0; j < kNumLocks; j++) + U((i + j) % kNumLocks); + } + } + private: void Lock2(size_t l1, size_t l2) { L(l1); L(l2); U(l2); U(l1); } @@ -602,6 +619,7 @@ int main(int argc, char **argv) { LockTest().Test16(); LockTest().Test17(); LockTest().Test18(); + LockTest().Test19(); fprintf(stderr, "ALL-DONE\n"); // CHECK: ALL-DONE } diff --git a/test/tsan/dl_iterate_phdr.cc b/test/tsan/dl_iterate_phdr.cc index b230a920ac4fb..b9ce615f82fe5 100644 --- a/test/tsan/dl_iterate_phdr.cc +++ b/test/tsan/dl_iterate_phdr.cc @@ -1,7 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// If we mention TSAN_OPTIONS, the test won't run from test_output.sh script. +// dl_iterate_phdr doesn't exist on OS X. +// UNSUPPORTED: darwin #ifdef BUILD_SO diff --git a/test/tsan/dlclose.cc b/test/tsan/dlclose.cc index 1a93fe6617e18..d497fd704e4f1 100644 --- a/test/tsan/dlclose.cc +++ b/test/tsan/dlclose.cc @@ -1,10 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// If we mention TSAN_OPTIONS, the test won't run from test_output.sh script. - // Test case for -// https://code.google.com/p/thread-sanitizer/issues/detail?id=80 +// https://github.com/google/sanitizers/issues/487 #ifdef BUILD_SO diff --git a/test/tsan/fd_tid_recycled.cc b/test/tsan/fd_tid_recycled.cc new file mode 100644 index 0000000000000..d31478728bc05 --- /dev/null +++ b/test/tsan/fd_tid_recycled.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "test.h" + +int fds[2]; + +void *ThreadCreatePipe(void *x) { + pipe(fds); + return NULL; +} + +void *ThreadDummy(void *x) { + return NULL; +} + +void *ThreadWrite(void *x) { + write(fds[1], "a", 1); + barrier_wait(&barrier); + return NULL; +} + +void *ThreadClose(void *x) { + barrier_wait(&barrier); + close(fds[0]); + close(fds[1]); + return NULL; +} + +int main() { + barrier_init(&barrier, 2); + pthread_t t_create; + pthread_create(&t_create, NULL, ThreadCreatePipe, NULL); + pthread_join(t_create, NULL); + + for (int i = 0; i < 100; i++) { + pthread_t t_dummy; + pthread_create(&t_dummy, NULL, ThreadDummy, NULL); + pthread_join(t_dummy, NULL); + } + + pthread_t t[2]; + pthread_create(&t[0], NULL, ThreadWrite, NULL); + pthread_create(&t[1], NULL, ThreadClose, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +// CHECK-NOT: CHECK failed +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write of size 8 +// CHECK: #0 close +// CHECK: #1 ThreadClose +// CHECK: Previous read of size 8 +// CHECK: #0 write +// CHECK: #1 ThreadWrite diff --git a/test/tsan/fork_atexit.cc b/test/tsan/fork_atexit.cc index 6801d3ffff7e4..51a64fc264d17 100644 --- a/test/tsan/fork_atexit.cc +++ b/test/tsan/fork_atexit.cc @@ -1,4 +1,5 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="atexit_sleep_ms=50" %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include <pthread.h> #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/fork_deadlock.cc b/test/tsan/fork_deadlock.cc index 9418800bd336a..22bed086f7d08 100644 --- a/test/tsan/fork_deadlock.cc +++ b/test/tsan/fork_deadlock.cc @@ -1,4 +1,5 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="atexit_sleep_ms=50" %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include "test.h" #include <errno.h> #include <sys/types.h> diff --git a/test/tsan/fork_multithreaded.cc b/test/tsan/fork_multithreaded.cc index 3ddb417c7cb5f..b345f58ad0c3d 100644 --- a/test/tsan/fork_multithreaded.cc +++ b/test/tsan/fork_multithreaded.cc @@ -1,5 +1,6 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-DIE -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="die_after_fork=0" %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-NODIE +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=die_after_fork=0 %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-NODIE +// UNSUPPORTED: darwin #include "test.h" #include <errno.h> #include <sys/types.h> diff --git a/test/tsan/fork_multithreaded3.cc b/test/tsan/fork_multithreaded3.cc index a651b3c18b4e7..5b8c13eb8b857 100644 --- a/test/tsan/fork_multithreaded3.cc +++ b/test/tsan/fork_multithreaded3.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include <stdlib.h> #include <stdio.h> #include <errno.h> diff --git a/test/tsan/free_race.c b/test/tsan/free_race.c index 63cee8c4adc57..d508552c98013 100644 --- a/test/tsan/free_race.c +++ b/test/tsan/free_race.c @@ -1,6 +1,6 @@ // RUN: %clang_tsan -O1 %s -o %t // RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOZUPP -// RUN: TSAN_OPTIONS="suppressions='%s.supp' print_suppressions=1" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUPP +// RUN: %env_tsan_opts=suppressions='%s.supp':print_suppressions=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUPP #include "test.h" diff --git a/test/tsan/getline_nohang.cc b/test/tsan/getline_nohang.cc index 89afbe1a66a8f..d103839b8bd02 100644 --- a/test/tsan/getline_nohang.cc +++ b/test/tsan/getline_nohang.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t // Make sure TSan doesn't deadlock on a file stream lock at program shutdown. -// See https://code.google.com/p/thread-sanitizer/issues/detail?id=47 +// See https://github.com/google/sanitizers/issues/454 #ifdef __FreeBSD__ #define _WITH_GETLINE // to declare getline() #endif diff --git a/test/tsan/global_race.cc b/test/tsan/global_race.cc index 3128ec411749e..a35299619e9d9 100644 --- a/test/tsan/global_race.cc +++ b/test/tsan/global_race.cc @@ -11,9 +11,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr="); - print_address(GlobalData); - fprintf(stderr, "\n"); + print_address("addr=", 1, GlobalData); pthread_t t; pthread_create(&t, 0, Thread, 0); GlobalData[2] = 43; @@ -23,5 +21,5 @@ int main() { // CHECK: addr=[[ADDR:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'GlobalData' of size 40 at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'GlobalData' {{(of size 40 )?}}at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) diff --git a/test/tsan/global_race2.cc b/test/tsan/global_race2.cc index 4ab2842e7eef4..95dff19978085 100644 --- a/test/tsan/global_race2.cc +++ b/test/tsan/global_race2.cc @@ -11,9 +11,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr2="); - print_address(&x); - fprintf(stderr, "\n"); + print_address("addr2=", 1, &x); pthread_t t; pthread_create(&t, 0, Thread, 0); x = 0; @@ -23,5 +21,5 @@ int main() { // CHECK: addr2=[[ADDR2:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'x' of size 4 at [[ADDR2]] ({{.*}}+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'x' {{(of size 4 )?}}at [[ADDR2]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/test/tsan/global_race3.cc b/test/tsan/global_race3.cc index 1531d7830f789..e0d59d284420b 100644 --- a/test/tsan/global_race3.cc +++ b/test/tsan/global_race3.cc @@ -16,9 +16,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr3="); - print_address(XXX::YYY::ZZZ); - fprintf(stderr, "\n"); + print_address("addr3=", 1, XXX::YYY::ZZZ); pthread_t t; pthread_create(&t, 0, Thread, 0); XXX::YYY::ZZZ[0] = 0; @@ -28,4 +26,4 @@ int main() { // CHECK: addr3=[[ADDR3:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'XXX::YYY::ZZZ' of size 40 at [[ADDR3]] ({{.*}}+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'XXX::YYY::ZZZ' {{(of size 40 )?}}at [[ADDR3]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/test/tsan/halt_on_error.cc b/test/tsan/halt_on_error.cc index e55454b57c1d7..5d481c3cbcd6a 100644 --- a/test/tsan/halt_on_error.cc +++ b/test/tsan/halt_on_error.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS halt_on_error=1" %deflake %run %t | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=halt_on_error=1 %deflake %run %t | FileCheck %s #include "test.h" int X; diff --git a/test/tsan/ignore_lib0.cc b/test/tsan/ignore_lib0.cc index 63c9340e99ac1..c72aa496a1cd7 100644 --- a/test/tsan/ignore_lib0.cc +++ b/test/tsan/ignore_lib0.cc @@ -3,11 +3,14 @@ // RUN: echo running w/o suppressions: // RUN: LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a library specified in called_from_lib // suppression are ignored. +// Some aarch64 kernels do not support non executable write pages +// REQUIRES: stable-runtime + #ifndef LIB extern "C" void libfunc(); diff --git a/test/tsan/ignore_lib1.cc b/test/tsan/ignore_lib1.cc index ef1f973795ed6..e6a13a3943955 100644 --- a/test/tsan/ignore_lib1.cc +++ b/test/tsan/ignore_lib1.cc @@ -3,11 +3,13 @@ // RUN: echo running w/o suppressions: // RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a dynamically loaded library specified // in called_from_lib suppression are ignored. +// REQUIRES: stable-runtime + #ifndef LIB #include <dlfcn.h> diff --git a/test/tsan/ignore_lib2.cc b/test/tsan/ignore_lib2.cc index ad3107cf53a2f..4f584b14664ac 100644 --- a/test/tsan/ignore_lib2.cc +++ b/test/tsan/ignore_lib2.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_0.so // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_1.so // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s // Tests that called_from_lib suppression matched against 2 libraries // causes program crash (this is not supported). diff --git a/test/tsan/ignore_lib3.cc b/test/tsan/ignore_lib3.cc index 96bf313f43a12..3f7be5cf82331 100644 --- a/test/tsan/ignore_lib3.cc +++ b/test/tsan/ignore_lib3.cc @@ -1,10 +1,13 @@ // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib3.so // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s // Tests that unloading of a library matched against called_from_lib suppression // causes program crash (this is not supported). +// Some aarch64 kernels do not support non executable write pages +// REQUIRES: stable-runtime + #ifndef LIB #include <dlfcn.h> diff --git a/test/tsan/inlined_memcpy_race.cc b/test/tsan/inlined_memcpy_race.cc index e3ed07abcf890..720f2bfcac8c0 100644 --- a/test/tsan/inlined_memcpy_race.cc +++ b/test/tsan/inlined_memcpy_race.cc @@ -32,6 +32,6 @@ int main() { // CHECK: #0 memset // CHECK: #1 MemSetThread // CHECK: Previous write -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 MemCpyThread diff --git a/test/tsan/java_race_pc.cc b/test/tsan/java_race_pc.cc index 015a0b1f43c63..0745ade6c4798 100644 --- a/test/tsan/java_race_pc.cc +++ b/test/tsan/java_race_pc.cc @@ -1,4 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 on both VMA (44 and 46). +// The Tsan report is returning wrong information about +// the location of the race. +// XFAIL: powerpc64 #include "java.h" void foobar() { diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg index d27500f8e3ea6..2be10dae1c851 100644 --- a/test/tsan/lit.cfg +++ b/test/tsan/lit.cfg @@ -18,9 +18,19 @@ config.name = 'ThreadSanitizer' config.test_source_root = os.path.dirname(__file__) # Setup environment variables for running ThreadSanitizer. -tsan_options = "atexit_sleep_ms=0" +default_tsan_opts = "atexit_sleep_ms=0" -config.environment['TSAN_OPTIONS'] = tsan_options +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' + +# Platform-specific default TSAN_OPTIONS for lit tests. +if default_tsan_opts: + config.environment['TSAN_OPTIONS'] = default_tsan_opts + default_tsan_opts += ':' +config.substitutions.append(('%env_tsan_opts=', + 'env TSAN_OPTIONS=' + default_tsan_opts)) # GCC driver doesn't add necessary compile/link flags with -fsanitize=thread. if config.compiler_id == 'GNU': @@ -34,7 +44,8 @@ clang_tsan_cflags = ["-fsanitize=thread", "-m64"] + config.debug_info_flags + extra_cflags clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags # Add additional flags if we're using instrumented libc++. -if config.has_libcxx: +# Instrumented libcxx currently not supported on Darwin. +if config.has_libcxx and config.host_os != 'Darwin': # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib", "tsan", "libcxx_tsan") @@ -58,8 +69,13 @@ config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os))) config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__), "deflake.bash")) ) # Default test suffixes. -config.suffixes = ['.c', '.cc', '.cpp'] +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm'] -# ThreadSanitizer tests are currently supported on FreeBSD and Linux only. -if config.host_os not in ['FreeBSD', 'Linux']: +# ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin. +if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']: config.unsupported = True + +# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL +# because the test hangs. +if config.target_arch != 'aarch64': + config.available_features.add('stable-runtime') diff --git a/test/tsan/load_shared_lib.cc b/test/tsan/load_shared_lib.cc index b7934b82df73a..f02280895f836 100644 --- a/test/tsan/load_shared_lib.cc +++ b/test/tsan/load_shared_lib.cc @@ -3,7 +3,7 @@ // symbolized correctly. // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t -rdynamic && %deflake %run %t | FileCheck %s #ifdef BUILD_SO diff --git a/test/tsan/malloc_overflow.cc b/test/tsan/malloc_overflow.cc index dadc94484f01e..b2f9b0f57798a 100644 --- a/test/tsan/malloc_overflow.cc +++ b/test/tsan/malloc_overflow.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/map32bit.cc b/test/tsan/map32bit.cc index d9a04655ddcac..0411f29a9504e 100644 --- a/test/tsan/map32bit.cc +++ b/test/tsan/map32bit.cc @@ -5,10 +5,15 @@ #include <sys/mman.h> // Test for issue: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=5 +// https://github.com/google/sanitizers/issues/412 // MAP_32BIT flag for mmap is supported only for x86_64. // XFAIL: mips64 +// XFAIL: aarch64 +// XFAIL: powerpc64 + +// MAP_32BIT doesn't exist on OS X. +// UNSUPPORTED: darwin void *Thread(void *ptr) { *(int*)ptr = 42; diff --git a/test/tsan/memcmp_race.cc b/test/tsan/memcmp_race.cc new file mode 100644 index 0000000000000..b76f427e121c1 --- /dev/null +++ b/test/tsan/memcmp_race.cc @@ -0,0 +1,42 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "test.h" +#include <string.h> + +char *data0 = new char[10]; +char *data1 = new char[10]; +char *data2 = new char[10]; + +void *Thread1(void *x) { + static volatile int size = 1; + static volatile int sink; + sink = memcmp(data0+5, data1, size); + barrier_wait(&barrier); + return NULL; +} + +void *Thread2(void *x) { + static volatile int size = 4; + barrier_wait(&barrier); + memcpy(data0+5, data2, size); + return NULL; +} + +int main() { + barrier_init(&barrier, 2); + print_address("addr=", 1, &data0[5]); + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + return 0; +} + +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write of size 1 at [[ADDR]] by thread T2: +// CHECK: #0 {{(memcpy|memmove)}} +// CHECK: #1 Thread2 +// CHECK: Previous read of size 1 at [[ADDR]] by thread T1: +// CHECK: #0 memcmp +// CHECK: #1 Thread1 diff --git a/test/tsan/memcpy_race.cc b/test/tsan/memcpy_race.cc index d49577306d6c3..4a098c0405fc0 100644 --- a/test/tsan/memcpy_race.cc +++ b/test/tsan/memcpy_race.cc @@ -22,7 +22,7 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr=%p\n", &data[5]); + print_address("addr=", 1, &data[5]); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); @@ -34,8 +34,8 @@ int main() { // CHECK: addr=[[ADDR:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race // CHECK: Write of size 1 at [[ADDR]] by thread T2: -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 Thread2 // CHECK: Previous write of size 1 at [[ADDR]] by thread T1: -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 Thread1 diff --git a/test/tsan/mmap_large.cc b/test/tsan/mmap_large.cc index 098530475df54..764e954f2b8ee 100644 --- a/test/tsan/mmap_large.cc +++ b/test/tsan/mmap_large.cc @@ -14,15 +14,17 @@ int main() { #ifdef __x86_64__ const size_t kLog2Size = 39; -#elif defined(__mips64) +#elif defined(__mips64) || defined(__aarch64__) const size_t kLog2Size = 32; +#elif defined(__powerpc64__) + const size_t kLog2Size = 39; #endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( reinterpret_cast<void*>(kLocation), 1ULL << kLog2Size, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, + MAP_PRIVATE|MAP_ANON|MAP_NORESERVE, -1, 0); fprintf(stderr, "DONE %p %d\n", p, errno); return p == MAP_FAILED; diff --git a/test/tsan/mop_with_offset.cc b/test/tsan/mop_with_offset.cc index c67e81e09cda9..e2496d099ef1e 100644 --- a/test/tsan/mop_with_offset.cc +++ b/test/tsan/mop_with_offset.cc @@ -18,8 +18,8 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); int *data = new int(42); - fprintf(stderr, "ptr1=%p\n", data); - fprintf(stderr, "ptr2=%p\n", (char*)data + 2); + print_address("ptr1=", 1, data); + print_address("ptr2=", 1, (char*)data + 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, data); pthread_create(&t[1], NULL, Thread2, data); diff --git a/test/tsan/mop_with_offset2.cc b/test/tsan/mop_with_offset2.cc index 460267359cec0..73c53f51233af 100644 --- a/test/tsan/mop_with_offset2.cc +++ b/test/tsan/mop_with_offset2.cc @@ -18,8 +18,8 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); int *data = new int(42); - fprintf(stderr, "ptr1=%p\n", data); - fprintf(stderr, "ptr2=%p\n", (char*)data + 2); + print_address("ptr1=", 1, data); + print_address("ptr2=", 1, (char*)data + 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, data); pthread_create(&t[1], NULL, Thread2, data); diff --git a/test/tsan/mutex_cycle2.c b/test/tsan/mutex_cycle2.c index 85d19a0d0c354..32659d4eec0db 100644 --- a/test/tsan/mutex_cycle2.c +++ b/test/tsan/mutex_cycle2.c @@ -1,11 +1,11 @@ // RUN: %clangxx_tsan %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s -// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s -// RUN: TSAN_OPTIONS=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED +// RUN: %env_tsan_opts=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: echo "deadlock:main" > %t.supp -// RUN: TSAN_OPTIONS="suppressions='%t.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED +// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: echo "deadlock:zzzz" > %t.supp -// RUN: TSAN_OPTIONS="suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' not %run %t 2>&1 | FileCheck %s #include <pthread.h> #include <stdio.h> diff --git a/test/tsan/mutexset1.cc b/test/tsan/mutexset1.cc index 407cfe5bd9f10..8403b3401743a 100644 --- a/test/tsan/mutexset1.cc +++ b/test/tsan/mutexset1.cc @@ -26,7 +26,7 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset1.cc:[[@LINE+1]] + // CHECK: #1 main {{.*}}mutexset1.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); diff --git a/test/tsan/mutexset2.cc b/test/tsan/mutexset2.cc index 2a3e5bb95e875..5f7c0c41bb06a 100644 --- a/test/tsan/mutexset2.cc +++ b/test/tsan/mutexset2.cc @@ -26,7 +26,7 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset2.cc:[[@LINE+1]] + // CHECK: #1 main {{.*}}mutexset2.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); diff --git a/test/tsan/mutexset3.cc b/test/tsan/mutexset3.cc index ce64cf86e37c8..24a9d9bf01ce2 100644 --- a/test/tsan/mutexset3.cc +++ b/test/tsan/mutexset3.cc @@ -29,10 +29,10 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset3.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+2]] + // CHECK: #1 main {{.*}}mutexset3.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/test/tsan/mutexset4.cc b/test/tsan/mutexset4.cc index b961efd2136c7..5d8ea9e400da0 100644 --- a/test/tsan/mutexset4.cc +++ b/test/tsan/mutexset4.cc @@ -29,10 +29,10 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]], write [[M2:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset4.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+2]] + // CHECK: #1 main {{.*}}mutexset4.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/test/tsan/mutexset5.cc b/test/tsan/mutexset5.cc index 8ef9af0ced524..b5f4e7794929d 100644 --- a/test/tsan/mutexset5.cc +++ b/test/tsan/mutexset5.cc @@ -30,10 +30,10 @@ int main() { // CHECK: (mutexes: write [[M2:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset5.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+5]] + // CHECK: #1 main {{.*}}mutexset5.cc:[[@LINE+5]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/test/tsan/mutexset6.cc b/test/tsan/mutexset6.cc index f4251db6970e8..ca349aaeee7a8 100644 --- a/test/tsan/mutexset6.cc +++ b/test/tsan/mutexset6.cc @@ -3,7 +3,7 @@ int Global; pthread_mutex_t mtx1; -pthread_spinlock_t mtx2; +pthread_mutex_t mtx2; pthread_rwlock_t mtx3; void *Thread1(void *x) { @@ -17,10 +17,10 @@ void *Thread1(void *x) { void *Thread2(void *x) { pthread_mutex_lock(&mtx1); pthread_mutex_unlock(&mtx1); - pthread_spin_lock(&mtx2); + pthread_mutex_lock(&mtx2); pthread_rwlock_rdlock(&mtx3); Global--; - pthread_spin_unlock(&mtx2); + pthread_mutex_unlock(&mtx2); pthread_rwlock_unlock(&mtx3); barrier_wait(&barrier); return NULL; @@ -34,13 +34,13 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2 // CHECK: (mutexes: write [[M2:M[0-9]+]], read [[M3:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+5]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+5]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+4]] // CHECK: Mutex [[M3]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+3]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+3]] pthread_mutex_init(&mtx1, 0); - pthread_spin_init(&mtx2, 0); + pthread_mutex_init(&mtx2, 0); pthread_rwlock_init(&mtx3, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); @@ -48,6 +48,6 @@ int main() { pthread_join(t[0], NULL); pthread_join(t[1], NULL); pthread_mutex_destroy(&mtx1); - pthread_spin_destroy(&mtx2); + pthread_mutex_destroy(&mtx2); pthread_rwlock_destroy(&mtx3); } diff --git a/test/tsan/mutexset8.cc b/test/tsan/mutexset8.cc index 40d5d043dedd3..69854e2ffa0a8 100644 --- a/test/tsan/mutexset8.cc +++ b/test/tsan/mutexset8.cc @@ -26,7 +26,7 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset8.cc + // CHECK: #1 main {{.*}}mutexset8.cc mtx = new pthread_mutex_t; pthread_mutex_init(mtx, 0); pthread_t t[2]; diff --git a/test/tsan/pie_test.cc b/test/tsan/pie_test.cc new file mode 100644 index 0000000000000..8635f9cd403fa --- /dev/null +++ b/test/tsan/pie_test.cc @@ -0,0 +1,12 @@ +// Check if tsan work with PIE binaries. +// RUN: %clang_tsan %s -pie -fpic -o %t && %run %t + +// Some kernels might map PIE segments outside the current segment +// mapping defined for x86 [1]. +// [1] https://git.kernel.org/linus/d1fd836dcf00d2028c700c7e44d2c23404062c90 + +// UNSUPPORTED: x86 + +int main(void) { + return 0; +} diff --git a/test/tsan/pthread_atfork_deadlock.c b/test/tsan/pthread_atfork_deadlock.c index 4aeec82b68508..01107ee6692c1 100644 --- a/test/tsan/pthread_atfork_deadlock.c +++ b/test/tsan/pthread_atfork_deadlock.c @@ -1,6 +1,6 @@ // RUN: %clang_tsan -O1 %s -lpthread -o %t && %deflake %run %t | FileCheck %s // Regression test for -// https://code.google.com/p/thread-sanitizer/issues/detail?id=61 +// https://github.com/google/sanitizers/issues/468 // When the data race was reported, pthread_atfork() handler used to be // executed which caused another race report in the same thread, which resulted // in a deadlock. diff --git a/test/tsan/race_on_barrier.c b/test/tsan/race_on_barrier.c index cf8a4cb992748..66fd339eb95bd 100644 --- a/test/tsan/race_on_barrier.c +++ b/test/tsan/race_on_barrier.c @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s + +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include "test.h" pthread_barrier_t B; diff --git a/test/tsan/race_on_barrier2.c b/test/tsan/race_on_barrier2.c index 98c028e19fdd2..49adb62312309 100644 --- a/test/tsan/race_on_barrier2.c +++ b/test/tsan/race_on_barrier2.c @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s + +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include <pthread.h> #include <stdio.h> #include <stddef.h> diff --git a/test/tsan/race_on_heap.cc b/test/tsan/race_on_heap.cc index a66e0c4f93f76..6c2defc835a63 100644 --- a/test/tsan/race_on_heap.cc +++ b/test/tsan/race_on_heap.cc @@ -2,6 +2,7 @@ #include <pthread.h> #include <stdlib.h> #include <stdio.h> +#include "test.h" void *Thread1(void *p) { *(int*)p = 42; @@ -26,7 +27,7 @@ int main() { pthread_t t[2]; pthread_create(&t[0], 0, AllocThread, 0); pthread_join(t[0], &p); - fprintf(stderr, "addr=%p\n", p); + print_address("addr=", 1, p); pthread_create(&t[0], 0, Thread1, (char*)p + 16); pthread_create(&t[1], 0, Thread2, (char*)p + 16); pthread_join(t[0], 0); diff --git a/test/tsan/race_on_mutex.c b/test/tsan/race_on_mutex.c index 7bd461bf37311..d998fdca2df31 100644 --- a/test/tsan/race_on_mutex.c +++ b/test/tsan/race_on_mutex.c @@ -1,4 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 (VMA=46). +// The size of the write reported by Tsan for T1 is 8 instead of 1. +// XFAIL: powerpc64-unknown-linux-gnu #include "test.h" pthread_mutex_t Mtx; @@ -35,7 +38,7 @@ int main() { // CHECK: WARNING: ThreadSanitizer: data race // CHECK-NEXT: Atomic read of size 1 at {{.*}} by thread T2: // CHECK-NEXT: #0 pthread_mutex_lock -// CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:18{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:21{{(:3)?}} ({{.*}}) // CHECK: Previous write of size 1 at {{.*}} by thread T1: // CHECK-NEXT: #0 pthread_mutex_init {{.*}} ({{.*}}) -// CHECK-NEXT: #1 Thread1{{.*}} {{.*}}race_on_mutex.c:8{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #1 Thread1{{.*}} {{.*}}race_on_mutex.c:11{{(:3)?}} ({{.*}}) diff --git a/test/tsan/race_on_speculative_load.cc b/test/tsan/race_on_speculative_load.cc index b50b69677d4b7..dd40daeb5c196 100644 --- a/test/tsan/race_on_speculative_load.cc +++ b/test/tsan/race_on_speculative_load.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t | FileCheck %s -// Regtest for https://code.google.com/p/thread-sanitizer/issues/detail?id=40 +// Regtest for https://github.com/google/sanitizers/issues/447 // This is a correct program and tsan should not report a race. #include "test.h" diff --git a/test/tsan/race_stress.cc b/test/tsan/race_stress.cc new file mode 100644 index 0000000000000..38acefce6e462 --- /dev/null +++ b/test/tsan/race_stress.cc @@ -0,0 +1,25 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +#include "test.h" + +const int kThreads = 16; +const int kIters = 1000; + +volatile int X = 0; + +void *thr(void *arg) { + for (int i = 0; i < kIters; i++) + X++; + return 0; +} + +int main() { + pthread_t th[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&th[i], 0, thr, 0); + for (int i = 0; i < kThreads; i++) + pthread_join(th[i], 0); + fprintf(stderr, "DONE\n"); +} + +// CHECK: ThreadSanitizer: data race +// CHECK: DONE diff --git a/test/tsan/race_top_suppression.cc b/test/tsan/race_top_suppression.cc index 7d42dbf3b4bf1..bd5c1bd5f4452 100644 --- a/test/tsan/race_top_suppression.cc +++ b/test/tsan/race_top_suppression.cc @@ -1,6 +1,6 @@ // RUN: echo "race_top:TopFunction" > %t.supp // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s // RUN: rm %t.supp #include "test.h" diff --git a/test/tsan/race_top_suppression1.cc b/test/tsan/race_top_suppression1.cc index 881e661ba789e..e34385a9b59c6 100644 --- a/test/tsan/race_top_suppression1.cc +++ b/test/tsan/race_top_suppression1.cc @@ -1,6 +1,6 @@ // RUN: echo "race_top:TopFunction" > %t.supp // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %deflake %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' %deflake %run %t 2>&1 | FileCheck %s // RUN: rm %t.supp #include "test.h" diff --git a/test/tsan/real_deadlock_detector_stress_test.cc b/test/tsan/real_deadlock_detector_stress_test.cc index 67c878f450847..feb1117e80abd 100644 --- a/test/tsan/real_deadlock_detector_stress_test.cc +++ b/test/tsan/real_deadlock_detector_stress_test.cc @@ -8,6 +8,7 @@ #include <errno.h> #include <vector> #include <algorithm> +#include <sys/time.h> const int kThreads = 4; const int kMutexes = 16 << 10; @@ -59,7 +60,7 @@ void *Thread(void *seed) { for (;;) { int old = __atomic_load_n(&m->state, __ATOMIC_RELAXED); if (old == kStateLocked) { - pthread_yield(); + sched_yield(); continue; } int newv = old + 1; @@ -165,9 +166,9 @@ void *Thread(void *seed) { } int main() { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned s = (unsigned)ts.tv_nsec; + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned s = tv.tv_sec + tv.tv_usec; fprintf(stderr, "seed %d\n", s); srand(s); for (int i = 0; i < kMutexes; i++) diff --git a/test/tsan/setuid2.c b/test/tsan/setuid2.c index 67a6fd14dbcb9..9dbb6577e1c60 100644 --- a/test/tsan/setuid2.c +++ b/test/tsan/setuid2.c @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=flush_memory_ms=1:memory_limit_mb=1 %run %t 2>&1 | FileCheck %s #include "test.h" #include <sys/types.h> #include <unistd.h> @@ -7,11 +7,11 @@ // Test that setuid call works in presence of stoptheworld. int main() { - struct timespec tp0, tp1; - clock_gettime(CLOCK_MONOTONIC, &tp0); - clock_gettime(CLOCK_MONOTONIC, &tp1); - while (tp1.tv_sec - tp0.tv_sec < 3) { - clock_gettime(CLOCK_MONOTONIC, &tp1); + unsigned long long tp0, tp1; + tp0 = monotonic_clock_ns(); + tp1 = monotonic_clock_ns(); + while (tp1 - tp0 < 3 * 1000000000ull) { + tp1 = monotonic_clock_ns(); setuid(0); } fprintf(stderr, "DONE\n"); diff --git a/test/tsan/signal_cond.cc b/test/tsan/signal_cond.cc index f5eae745d4072..beb2e0266e508 100644 --- a/test/tsan/signal_cond.cc +++ b/test/tsan/signal_cond.cc @@ -6,17 +6,16 @@ #include <semaphore.h> // Test that signals can be delivered to blocked pthread_cond_wait. -// https://code.google.com/p/thread-sanitizer/issues/detail?id=91 +// https://github.com/google/sanitizers/issues/498 int g_thread_run = 1; pthread_mutex_t mutex; pthread_cond_t cond; -sem_t sem; void sig_handler(int sig) { (void)sig; write(1, "SIGNAL\n", sizeof("SIGNAL\n") - 1); - sem_post(&sem); + barrier_wait(&barrier); } void* my_thread(void* arg) { @@ -28,7 +27,11 @@ void* my_thread(void* arg) { } int main() { - sem_init(&sem, 0, 0); + barrier_init(&barrier, 2); + + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + signal(SIGUSR1, &sig_handler); pthread_t thr; pthread_create(&thr, 0, &my_thread, 0); @@ -36,8 +39,7 @@ int main() { // (can't use barrier_wait for that) sleep(1); pthread_kill(thr, SIGUSR1); - while (sem_wait(&sem) == -1 && errno == EINTR) { - } + barrier_wait(&barrier); pthread_mutex_lock(&mutex); g_thread_run = 0; pthread_cond_signal(&cond); diff --git a/test/tsan/signal_errno.cc b/test/tsan/signal_errno.cc index 8305e84930f3f..e13e156fdf663 100644 --- a/test/tsan/signal_errno.cc +++ b/test/tsan/signal_errno.cc @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 BE (VMA=44), it does not appear to be +// a functional problem, but the Tsan report is missing some info. +// XFAIL: powerpc64-unknown-linux-gnu + #include "test.h" #include <signal.h> #include <sys/types.h> @@ -24,7 +28,7 @@ static __attribute__((noinline)) void loop() { volatile char *p = (char*)malloc(1); p[0] = 0; free((void*)p); - pthread_yield(); + sched_yield(); } } diff --git a/test/tsan/signal_longjmp.cc b/test/tsan/signal_longjmp.cc index 2525c898887b9..45e24626cbfab 100644 --- a/test/tsan/signal_longjmp.cc +++ b/test/tsan/signal_longjmp.cc @@ -1,10 +1,14 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // Test case for longjumping out of signal handler: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=75 +// https://github.com/google/sanitizers/issues/482 // Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 +// This test fails on powerpc64 BE (VMA=44), a segmentation fault +// error happens at the second assignment +// "((volatile int *volatile)mem)[1] = 1". +// XFAIL: powerpc64-unknown-linux-gnu #include <setjmp.h> #include <signal.h> @@ -12,6 +16,12 @@ #include <stdio.h> #include <sys/mman.h> +#ifdef __APPLE__ +#define SIGNAL_TO_HANDLE SIGBUS +#else +#define SIGNAL_TO_HANDLE SIGSEGV +#endif + sigjmp_buf fault_jmp; volatile int fault_expected; @@ -44,7 +54,7 @@ int main() { exit(1); } - if (sigaction(SIGSEGV, &act, NULL)) { + if (sigaction(SIGNAL_TO_HANDLE, &act, NULL)) { perror("sigaction"); exit(1); } diff --git a/test/tsan/signal_recursive.cc b/test/tsan/signal_recursive.cc index 67fc9c0ec9a32..40be2d01502b6 100644 --- a/test/tsan/signal_recursive.cc +++ b/test/tsan/signal_recursive.cc @@ -1,7 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // Test case for recursive signal handlers, adopted from: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=71 +// https://github.com/google/sanitizers/issues/478 // REQUIRES: disabled diff --git a/test/tsan/signal_reset.cc b/test/tsan/signal_reset.cc index aec98dc399e95..82758d882382f 100644 --- a/test/tsan/signal_reset.cc +++ b/test/tsan/signal_reset.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include <pthread.h> #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/signal_sync.cc b/test/tsan/signal_sync.cc index 6ff19d3bd1209..b529a1859f52a 100644 --- a/test/tsan/signal_sync.cc +++ b/test/tsan/signal_sync.cc @@ -1,4 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include "test.h" #include <signal.h> #include <sys/types.h> diff --git a/test/tsan/signal_thread.cc b/test/tsan/signal_thread.cc index 8eda80a522642..aa91d1ddeb101 100644 --- a/test/tsan/signal_thread.cc +++ b/test/tsan/signal_thread.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include <pthread.h> #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/stack_sync_reuse.cc b/test/tsan/stack_sync_reuse.cc index 5ea9e84b085a5..d2bc5cb1b2827 100644 --- a/test/tsan/stack_sync_reuse.cc +++ b/test/tsan/stack_sync_reuse.cc @@ -1,7 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s #include "test.h" -// Test case https://code.google.com/p/thread-sanitizer/issues/detail?id=87 +// Test case https://github.com/google/sanitizers/issues/494 // Tsan sees false HB edge on address pointed to by syncp variable. // It is false because when acquire is done syncp points to a var in one frame, // and during release it points to a var in a different frame. @@ -31,7 +31,8 @@ void *Thread(void *x) { } void __attribute__((noinline)) foobar() { - long s; + __attribute__((aligned(64))) long s; + addr = &s; __atomic_store_n(&s, 0, __ATOMIC_RELAXED); __atomic_store_n(&syncp, &s, __ATOMIC_RELEASE); @@ -40,7 +41,8 @@ void __attribute__((noinline)) foobar() { } void __attribute__((noinline)) barfoo() { - long s; + __attribute__((aligned(64))) long s; + if (addr != &s) { printf("address mismatch addr=%p &s=%p\n", addr, &s); exit(1); diff --git a/test/tsan/suppressions_global.cc b/test/tsan/suppressions_global.cc index c7b9bb99eb175..8928162cfb8a1 100644 --- a/test/tsan/suppressions_global.cc +++ b/test/tsan/suppressions_global.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include <pthread.h> #include <stdio.h> diff --git a/test/tsan/suppressions_race.cc b/test/tsan/suppressions_race.cc index 45c30481f0cd1..7a88434db8205 100644 --- a/test/tsan/suppressions_race.cc +++ b/test/tsan/suppressions_race.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include "test.h" int Global; diff --git a/test/tsan/suppressions_race2.cc b/test/tsan/suppressions_race2.cc index 24ecd8ef119fd..b6566a80178d1 100644 --- a/test/tsan/suppressions_race2.cc +++ b/test/tsan/suppressions_race2.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include "test.h" int Global; diff --git a/test/tsan/test.h b/test/tsan/test.h index 4e877f6d8dfd3..a681daa32906f 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -4,43 +4,66 @@ #include <unistd.h> #include <dlfcn.h> #include <stddef.h> +#include <sched.h> +#include <stdarg.h> + +#ifdef __APPLE__ +#include <mach/mach_time.h> +#endif // TSan-invisible barrier. // Tests use it to establish necessary execution order in a way that does not // interfere with tsan (does not establish synchronization between threads). -__typeof(pthread_barrier_wait) *barrier_wait; +typedef unsigned long long invisible_barrier_t; -void barrier_init(pthread_barrier_t *barrier, unsigned count) { -#if defined(__FreeBSD__) - static const char libpthread_name[] = "libpthread.so"; -#else - static const char libpthread_name[] = "libpthread.so.0"; +#ifdef __cplusplus +extern "C" { +#endif +void __tsan_testonly_barrier_init(invisible_barrier_t *barrier, + unsigned count); +void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier); +#ifdef __cplusplus +} #endif - if (barrier_wait == 0) { - void *h = dlopen(libpthread_name, RTLD_LAZY); - if (h == 0) { - fprintf(stderr, "failed to dlopen %s, exiting\n", libpthread_name); - exit(1); - } - barrier_wait = (__typeof(barrier_wait))dlsym(h, "pthread_barrier_wait"); - if (barrier_wait == 0) { - fprintf(stderr, "failed to resolve pthread_barrier_wait, exiting\n"); - exit(1); - } - } - pthread_barrier_init(barrier, 0, count); +static inline void barrier_init(invisible_barrier_t *barrier, unsigned count) { + __tsan_testonly_barrier_init(barrier, count); +} + +static inline void barrier_wait(invisible_barrier_t *barrier) { + __tsan_testonly_barrier_wait(barrier); } // Default instance of the barrier, but a test can declare more manually. -pthread_barrier_t barrier; +invisible_barrier_t barrier; -void print_address(void *address) { -// On FreeBSD, the %p conversion specifier works as 0x%x and thus does not match -// to the format used in the diagnotic message. -#ifdef __x86_64__ - fprintf(stderr, "0x%012lx", (unsigned long) address); +void print_address(const char *str, int n, ...) { + fprintf(stderr, "%s", str); + va_list ap; + va_start(ap, n); + while (n--) { + void *p = va_arg(ap, void *); +#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) + // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not + // match to the format used in the diagnotic message. + fprintf(stderr, "0x%012lx ", (unsigned long) p); #elif defined(__mips64) - fprintf(stderr, "0x%010lx", (unsigned long) address); + fprintf(stderr, "0x%010lx ", (unsigned long) p); #endif + } + fprintf(stderr, "\n"); +} + +#ifdef __APPLE__ +unsigned long long monotonic_clock_ns() { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) mach_timebase_info(&timebase_info); + return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom; } +#else +unsigned long long monotonic_clock_ns() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return (unsigned long long)t.tv_sec * 1000000000ull + t.tv_nsec; +} +#endif diff --git a/test/tsan/test_output.sh b/test/tsan/test_output.sh deleted file mode 100755 index bce0fe8b5511b..0000000000000 --- a/test/tsan/test_output.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -ulimit -s 8192 -set -e # fail on any error - -HERE=$(dirname $0) -TSAN_DIR=$(dirname $0)/../../lib/tsan - -# Assume clang and clang++ are in path. -: ${CC:=clang} -: ${CXX:=clang++} -: ${FILECHECK:=FileCheck} - -# TODO: add testing for all of -O0...-O3 -CFLAGS="-fsanitize=thread -O2 -g -Wall" -LDFLAGS="-pthread -ldl -lrt -lm -Wl,--whole-archive $TSAN_DIR/rtl/libtsan.a -Wl,--no-whole-archive" - -test_file() { - SRC=$1 - COMPILER=$2 - echo ----- TESTING $(basename $1) - OBJ=$SRC.o - EXE=$SRC.exe - $COMPILER $SRC $CFLAGS -c -o $OBJ - $COMPILER $OBJ $LDFLAGS -o $EXE - RES=$($EXE 2>&1 || true) - printf "%s\n" "$RES" | $FILECHECK $SRC - if [ "$3" == "" ]; then - rm -f $EXE $OBJ - fi -} - -if [ "$1" == "" ]; then - for c in $HERE/*.{c,cc}; do - if [[ $c == */failing_* ]]; then - echo SKIPPING FAILING TEST $c - continue - fi - if [[ $c == */load_shared_lib.cc ]]; then - echo TEST $c is not supported - continue - fi - if [[ $c == */*blacklist*.cc ]]; then - echo TEST $c is not supported - continue - fi - if [ "`grep "TSAN_OPTIONS" $c`" ]; then - echo SKIPPING $c -- requires TSAN_OPTIONS - continue - fi - if [ "`grep "XFAIL" $c`" ]; then - echo SKIPPING $c -- has XFAIL - continue - fi - COMPILER=$CXX - case $c in - *.c) COMPILER=$CC - esac - test_file $c $COMPILER & - done - for job in `jobs -p`; do - wait $job || exit 1 - done -else - test_file $HERE/$1 $CXX "DUMP" -fi diff --git a/test/tsan/thread_name2.cc b/test/tsan/thread_name2.cc index a44f4b9d32475..d7ed0f0d1952f 100644 --- a/test/tsan/thread_name2.cc +++ b/test/tsan/thread_name2.cc @@ -1,12 +1,15 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s #include "test.h" +// OS X doesn't have pthread_setname_np(tid, name). +// UNSUPPORTED: darwin + #if defined(__FreeBSD__) #include <pthread_np.h> #define pthread_setname_np pthread_set_name_np #endif -int Global; +long long Global; void *Thread1(void *x) { barrier_wait(&barrier); diff --git a/test/tsan/tls_race.cc b/test/tsan/tls_race.cc index 5e81722767089..b43a514cc8aa8 100644 --- a/test/tsan/tls_race.cc +++ b/test/tsan/tls_race.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK #include "test.h" void *Thread(void *a) { @@ -18,4 +18,6 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is TLS of main thread. +// CHECK-Linux: Location is TLS of main thread. +// CHECK-FreeBSD: Location is TLS of main thread. +// CHECK-Darwin: Location is heap block of size 4 diff --git a/test/tsan/tls_race2.cc b/test/tsan/tls_race2.cc index d0f7b03e09a1d..b04ff67881009 100644 --- a/test/tsan/tls_race2.cc +++ b/test/tsan/tls_race2.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK #include "test.h" void *Thread2(void *a) { @@ -25,5 +25,6 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is TLS of thread T1. - +// CHECK-Linux: Location is TLS of thread T1. +// CHECK-FreeBSD: Location is TLS of thread T1. +// CHECK-Darwin: Location is heap block of size 4 diff --git a/test/tsan/vfork.cc b/test/tsan/vfork.cc index 5ae1dd1ababd5..98a82623ee651 100644 --- a/test/tsan/vfork.cc +++ b/test/tsan/vfork.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include <pthread.h> #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/virtual_inheritance_compile_bug.cc b/test/tsan/virtual_inheritance_compile_bug.cc index 2a50c2e88d013..7da581d80601b 100644 --- a/test/tsan/virtual_inheritance_compile_bug.cc +++ b/test/tsan/virtual_inheritance_compile_bug.cc @@ -1,4 +1,4 @@ -// Regression test for http://code.google.com/p/thread-sanitizer/issues/detail?id=3. +// Regression test for https://github.com/google/sanitizers/issues/410. // The C++ variant is much more compact that the LLVM IR equivalent. // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s diff --git a/test/tsan/vptr_benign_race.cc b/test/tsan/vptr_benign_race.cc index 92a2b326e717c..c0068955129f9 100644 --- a/test/tsan/vptr_benign_race.cc +++ b/test/tsan/vptr_benign_race.cc @@ -1,28 +1,36 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s #include <pthread.h> -#include <semaphore.h> #include <stdio.h> struct A { A() { - sem_init(&sem_, 0, 0); + pthread_mutex_init(&m, 0); + pthread_cond_init(&c, 0); + signaled = false; } virtual void F() { } void Done() { - sem_post(&sem_); + pthread_mutex_lock(&m); + signaled = true; + pthread_cond_signal(&c); + pthread_mutex_unlock(&m); } virtual ~A() { } - sem_t sem_; + pthread_mutex_t m; + pthread_cond_t c; + bool signaled; }; struct B : A { virtual void F() { } virtual ~B() { - sem_wait(&sem_); - sem_destroy(&sem_); + pthread_mutex_lock(&m); + while (!signaled) + pthread_cond_wait(&c, &m); + pthread_mutex_unlock(&m); } }; |