diff options
author | Kuba Brecka <kuba.brecka@gmail.com> | 2016-07-05 13:48:54 +0000 |
---|---|---|
committer | Kuba Brecka <kuba.brecka@gmail.com> | 2016-07-05 13:48:54 +0000 |
commit | eb3bc5d07a74e5dcc8c644a67ab96c3fe55dd253 (patch) | |
tree | 13103fa9279f37b27f739433387b706b3cce3464 /test/tsan/Darwin | |
parent | 81dbf028870b8d56567e0c601f946b344b330439 (diff) | |
download | compiler-rt-eb3bc5d07a74e5dcc8c644a67ab96c3fe55dd253.tar.gz |
[tsan] Synchronize leaving a GCD group with notifications
In the patch that introduced support for GCD barrier blocks, I removed releasing a group when leaving it (in dispatch_group_leave). However, this is necessary to synchronize leaving a group and a notification callback (dispatch_group_notify). Adding this back, simplifying dispatch_group_notify_f and adding a test case.
Differential Revision: http://reviews.llvm.org/D21927
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@274549 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/tsan/Darwin')
-rw-r--r-- | test/tsan/Darwin/gcd-groups-leave.mm | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/test/tsan/Darwin/gcd-groups-leave.mm b/test/tsan/Darwin/gcd-groups-leave.mm new file mode 100644 index 000000000..6ecf85f5f --- /dev/null +++ b/test/tsan/Darwin/gcd-groups-leave.mm @@ -0,0 +1,56 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +#import "../test.h" + +dispatch_semaphore_t sem; + +long global; +long global2; + +void callback(void *context) { + global2 = 48; + barrier_wait(&barrier); + + dispatch_semaphore_signal(sem); +} + +int main() { + fprintf(stderr, "Hello world.\n"); + barrier_init(&barrier, 2); + + dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT); + dispatch_group_t g = dispatch_group_create(); + sem = dispatch_semaphore_create(0); + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global = 47; + dispatch_group_leave(g); + barrier_wait(&barrier); + }); + dispatch_group_notify(g, q, ^{ + global = 48; + barrier_wait(&barrier); + + dispatch_semaphore_signal(sem); + }); + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global2 = 47; + dispatch_group_leave(g); + barrier_wait(&barrier); + }); + dispatch_group_notify_f(g, q, NULL, &callback); + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK: Done. |