[PATCH] D27112: [tsan] Add support for GCD dispatch_suspend and dispatch_resume

Kuba (Brecka) Mracek via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 24 11:00:15 PST 2016


kubabrecka created this revision.
kubabrecka added a reviewer: dvyukov.
kubabrecka added subscribers: llvm-commits, zaks.anna.
kubabrecka set the repository for this revision to rL LLVM.
kubabrecka added a project: Sanitizers.

GCD queues can be suspended and resumed with dispatch_suspend and dispatch_resume.  Sometimes this is used as synchronization, e.g. in the following example, f1() is always fully executed before f2():

  dispatch_suspend(q);
  dispatch_async(q, ^{ f2(); });
  f1();
  dispatch_resume(q);

It seems to me that all we need to do is to add synchronization between the call to dispatch_resume and any subsequent executions of blocks in the queue that was resumed.  We already have an Acquire(q) before the block executes, so this patch just adds the Release(q) in an interceptor of dispatch_resume.


Repository:
  rL LLVM

https://reviews.llvm.org/D27112

Files:
  lib/tsan/rtl/tsan_libdispatch_mac.cc
  test/tsan/Darwin/gcd-suspend.mm


Index: test/tsan/Darwin/gcd-suspend.mm
===================================================================
--- test/tsan/Darwin/gcd-suspend.mm
+++ test/tsan/Darwin/gcd-suspend.mm
@@ -0,0 +1,45 @@
+// 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>
+
+long my_global = 0;
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q1 = dispatch_queue_create("queue1", NULL);
+  dispatch_queue_t q2 = dispatch_queue_create("queue2", NULL);
+  dispatch_group_t g = dispatch_group_create();
+
+  dispatch_sync(q1, ^{
+    dispatch_suspend(q1);
+    dispatch_async(q2, ^{
+      my_global++;
+      dispatch_resume(q1);
+    });
+  });
+
+  dispatch_sync(q1, ^{
+    my_global++;
+  });
+
+  dispatch_sync(q1, ^{
+    dispatch_suspend(q1);
+    dispatch_group_enter(g);
+    dispatch_async(q1,^{ my_global++; });
+    dispatch_async(q1,^{ my_global++; });
+    dispatch_async(q1,^{ my_global++; dispatch_group_leave(g); });
+    my_global++;
+    dispatch_resume(q1);
+  });
+
+  dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+
+  fprintf(stderr, "Done.\n");
+  return 0;
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
Index: lib/tsan/rtl/tsan_libdispatch_mac.cc
===================================================================
--- lib/tsan/rtl/tsan_libdispatch_mac.cc
+++ lib/tsan/rtl/tsan_libdispatch_mac.cc
@@ -706,6 +706,15 @@
   return REAL(dispatch_io_close)(channel, flags);
 }
 
+// Resuming a suspended queue needs to synchronize with all subsequent
+// executions of blocks in that queue.
+TSAN_INTERCEPTOR(void, dispatch_resume, dispatch_object_t o) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_resume, o);
+  Release(thr, pc, (uptr)o);  // Synchronizes with the Acquire() on serial_sync
+                              // in dispatch_sync_pre_execute
+  return REAL(dispatch_resume)(o);
+}
+
 }  // namespace __tsan
 
 #endif  // SANITIZER_MAC


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D27112.79249.patch
Type: text/x-patch
Size: 2051 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161124/6b4e56ed/attachment.bin>


More information about the llvm-commits mailing list