diff options
author | Kuba Mracek <mracek@apple.com> | 2017-04-21 17:49:19 +0000 |
---|---|---|
committer | Kuba Mracek <mracek@apple.com> | 2017-04-21 17:49:19 +0000 |
commit | f94bfbbbbb7189d9e50ddf589a7567770859d0c0 (patch) | |
tree | 9e35d76aabc0fbae0081ff0c3384d21583d453da /test/tsan | |
parent | 65382e6212a3432756b51b149421769dc29e261e (diff) |
[tsan] Add a test for "external" API that checks the dup suppression is based on the caller PC
We need to make sure that the "external" API isn't dup'ing all data races into a single one (because the stack might look the same) and suppressing all external races. This works now, so just adding a test for that.
Differential Revision: https://reviews.llvm.org/D31734
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@301011 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/tsan')
-rw-r--r-- | test/tsan/Darwin/external-dups.cc | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/test/tsan/Darwin/external-dups.cc b/test/tsan/Darwin/external-dups.cc new file mode 100644 index 000000000..b276977d4 --- /dev/null +++ b/test/tsan/Darwin/external-dups.cc @@ -0,0 +1,66 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#include <thread> + +#import "../test.h" + +extern "C" { +void *__tsan_external_register_tag(const char *object_type); +void *__tsan_external_assign_tag(void *addr, void *tag); +void __tsan_external_read(void *addr, void *caller_pc, void *tag); +void __tsan_external_write(void *addr, void *caller_pc, void *tag); +void __tsan_write8(void *addr); +} + +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 |