[PATCH] D15011: [tsan] Add release+acquire semantics for serial dispatch queues
Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 28 04:56:47 PST 2015
This revision was automatically updated to reflect the committed changes.
Closed by commit rL254229: [tsan] Add release+acquire semantics for serial dispatch queues (authored by kuba.brecka).
Changed prior to commit:
http://reviews.llvm.org/D15011?vs=41328&id=41331#toc
Repository:
rL LLVM
http://reviews.llvm.org/D15011
Files:
compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
compiler-rt/trunk/test/tsan/Darwin/gcd-serial-queue-norace.mm
Index: compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
===================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc
@@ -33,6 +33,35 @@
dispatch_function_t orig_work;
} tsan_block_context_t;
+// The offsets of different fields of the dispatch_queue_t structure, exported
+// by libdispatch.dylib.
+extern "C" struct dispatch_queue_offsets_s {
+ const uint16_t dqo_version;
+ const uint16_t dqo_label;
+ const uint16_t dqo_label_size;
+ const uint16_t dqo_flags;
+ const uint16_t dqo_flags_size;
+ const uint16_t dqo_serialnum;
+ const uint16_t dqo_serialnum_size;
+ const uint16_t dqo_width;
+ const uint16_t dqo_width_size;
+ const uint16_t dqo_running;
+ const uint16_t dqo_running_size;
+ const uint16_t dqo_suspend_cnt;
+ const uint16_t dqo_suspend_cnt_size;
+ const uint16_t dqo_target_queue;
+ const uint16_t dqo_target_queue_size;
+ const uint16_t dqo_priority;
+ const uint16_t dqo_priority_size;
+} dispatch_queue_offsets;
+
+static bool IsQueueSerial(dispatch_queue_t q) {
+ CHECK_EQ(dispatch_queue_offsets.dqo_width_size, 2);
+ uptr width = *(uint16_t *)(((uptr)q) + dispatch_queue_offsets.dqo_width);
+ CHECK_NE(width, 0);
+ return width == 1;
+}
+
static tsan_block_context_t *AllocContext(ThreadState *thr, uptr pc,
dispatch_queue_t queue,
void *orig_context,
@@ -49,7 +78,11 @@
SCOPED_INTERCEPTOR_RAW(dispatch_async_f_callback_wrap);
tsan_block_context_t *context = (tsan_block_context_t *)param;
Acquire(thr, pc, (uptr)context);
+ // In serial queues, work items can be executed on different threads, we need
+ // to explicitly synchronize on the queue itself.
+ if (IsQueueSerial(context->queue)) Acquire(thr, pc, (uptr)context->queue);
context->orig_work(context->orig_context);
+ if (IsQueueSerial(context->queue)) Release(thr, pc, (uptr)context->queue);
user_free(thr, pc, context);
}
Index: compiler-rt/trunk/test/tsan/Darwin/gcd-serial-queue-norace.mm
===================================================================
--- compiler-rt/trunk/test/tsan/Darwin/gcd-serial-queue-norace.mm
+++ compiler-rt/trunk/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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15011.41331.patch
Type: text/x-patch
Size: 3235 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151128/13453641/attachment.bin>
More information about the llvm-commits
mailing list