[compiler-rt] r340342 - [tsan] Avoid calling Block_copy in the "sync" GCD interceptors

Kuba Mracek via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 21 14:24:23 PDT 2018


Author: kuba.brecka
Date: Tue Aug 21 14:24:22 2018
New Revision: 340342

URL: http://llvm.org/viewvc/llvm-project?rev=340342&view=rev
Log:
[tsan] Avoid calling Block_copy in the "sync" GCD interceptors

The synchronous dispatch functions in GCD (dispatch_sync, dispatch_barrier_sync), don't make a copy of the passed block. To maintain binary compatibility, we should avoid doing that as well in TSan, as there's no reason to do that. The synchronous dispatch functions will not return before the block is actually executed.

rdar://problem/42242579

Differential Revision: https://reviews.llvm.org/D50920


Added:
    compiler-rt/trunk/test/tsan/Darwin/gcd-sync-block-copy.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=340342&r1=340341&r2=340342&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc Tue Aug 21 14:24:22 2018
@@ -185,11 +185,8 @@ static void invoke_and_release_block(voi
   TSAN_INTERCEPTOR(void, name, dispatch_queue_t q,                           \
                    DISPATCH_NOESCAPE dispatch_block_t block) {               \
     SCOPED_TSAN_INTERCEPTOR(name, q, block);                                 \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
-    dispatch_block_t heap_block = Block_copy(block);                         \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
     tsan_block_context_t new_context = {                                     \
-        q, heap_block, &invoke_and_release_block, false, true, barrier, 0};  \
+        q, block, &invoke_and_release_block, false, true, barrier, 0};       \
     Release(thr, pc, (uptr)&new_context);                                    \
     SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
     REAL(name##_f)(q, &new_context, dispatch_callback_wrap);                 \

Added: compiler-rt/trunk/test/tsan/Darwin/gcd-sync-block-copy.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/gcd-sync-block-copy.mm?rev=340342&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/gcd-sync-block-copy.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/gcd-sync-block-copy.mm Tue Aug 21 14:24:22 2018
@@ -0,0 +1,34 @@
+// This test verifies that dispatch_sync() doesn't actually copy the block under TSan (without TSan, it doesn't).
+
+// RUN: %clang_tsan -fno-sanitize=thread %s -o %t_no_tsan -framework Foundation
+// RUN: %run %t_no_tsan 2>&1 | FileCheck %s
+
+// RUN: %clang_tsan %s -o %t_with_tsan -framework Foundation
+// RUN: %run %t_with_tsan 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+ at interface MyClass : NSObject
+ at end
+
+ at implementation MyClass
+- (instancetype)retain {
+  // Copying the dispatch_sync'd block below will increment the retain count of
+  // this object. Abort if that happens.
+  abort();
+}
+ at end
+
+int main(int argc, const char* argv[]) {
+  dispatch_queue_t q = dispatch_queue_create("my.queue", NULL);
+  id object = [[MyClass alloc] init];
+  dispatch_sync(q, ^{
+    NSLog(@"%@", object);
+  });
+  [object release];
+  NSLog(@"Done.");
+  return 0;
+}
+
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer




More information about the llvm-commits mailing list