[compiler-rt] r274549 - [tsan] Synchronize leaving a GCD group with notifications
Kuba Brecka via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 5 06:48:54 PDT 2016
Author: kuba.brecka
Date: Tue Jul 5 08:48:54 2016
New Revision: 274549
URL: http://llvm.org/viewvc/llvm-project?rev=274549&view=rev
Log:
[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
Added:
compiler-rt/trunk/test/tsan/Darwin/gcd-groups-leave.mm
Modified:
compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc?rev=274549&r1=274548&r2=274549&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc Tue Jul 5 08:48:54 2016
@@ -274,6 +274,7 @@ TSAN_INTERCEPTOR(long_t, dispatch_group_
TSAN_INTERCEPTOR(void, dispatch_group_leave, dispatch_group_t group) {
SCOPED_TSAN_INTERCEPTOR(dispatch_group_leave, group);
+ // Acquired in the group noticifaction callback in dispatch_group_notify[_f].
Release(thr, pc, (uptr)group);
REAL(dispatch_group_leave)(group);
}
@@ -308,25 +309,32 @@ TSAN_INTERCEPTOR(void, dispatch_group_as
TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group,
dispatch_queue_t q, dispatch_block_t block) {
SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, q, block);
+
+ // To make sure the group is still available in the callback (otherwise
+ // it can be already destroyed). Will be released in the callback.
+ dispatch_retain(group);
+
SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
- dispatch_block_t heap_block = Block_copy(block);
+ dispatch_block_t heap_block = Block_copy(^(void) {
+ {
+ SCOPED_INTERCEPTOR_RAW(dispatch_read_callback);
+ // Released when leaving the group (dispatch_group_leave).
+ Acquire(thr, pc, (uptr)group);
+ }
+ dispatch_release(group);
+ block();
+ });
SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
tsan_block_context_t *new_context =
AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
new_context->is_barrier_block = true;
Release(thr, pc, (uptr)new_context);
- REAL(dispatch_group_notify_f)(group, q, new_context,
- dispatch_callback_wrap);
+ REAL(dispatch_group_notify_f)(group, q, new_context, dispatch_callback_wrap);
}
TSAN_INTERCEPTOR(void, dispatch_group_notify_f, dispatch_group_t group,
dispatch_queue_t q, void *context, dispatch_function_t work) {
- SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify_f, group, q, context, work);
- tsan_block_context_t *new_context = AllocContext(thr, pc, q, context, work);
- new_context->is_barrier_block = true;
- Release(thr, pc, (uptr)new_context);
- REAL(dispatch_group_notify_f)(group, q, new_context,
- dispatch_callback_wrap);
+ WRAP(dispatch_group_notify)(group, q, ^(void) { work(context); });
}
TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler,
Added: compiler-rt/trunk/test/tsan/Darwin/gcd-groups-leave.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/gcd-groups-leave.mm?rev=274549&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/gcd-groups-leave.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/gcd-groups-leave.mm Tue Jul 5 08:48:54 2016
@@ -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.
More information about the llvm-commits
mailing list