summaryrefslogtreecommitdiff
path: root/test/tsan/Darwin/gcd-sync-block-copy.mm
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2018-08-21 21:24:22 +0000
committerKuba Mracek <mracek@apple.com>2018-08-21 21:24:22 +0000
commit34f496d505e13f45be7b0bc2c6d9ae12022c42f7 (patch)
treed05d828ecda0482d03ca9353aa578d73c938d589 /test/tsan/Darwin/gcd-sync-block-copy.mm
parentbf533e0469db4e619af75476744f05ae7f5a090b (diff)
downloadcompiler-rt-34f496d505e13f45be7b0bc2c6d9ae12022c42f7.tar.gz
[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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@340342 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/tsan/Darwin/gcd-sync-block-copy.mm')
-rw-r--r--test/tsan/Darwin/gcd-sync-block-copy.mm34
1 files changed, 34 insertions, 0 deletions
diff --git a/test/tsan/Darwin/gcd-sync-block-copy.mm b/test/tsan/Darwin/gcd-sync-block-copy.mm
new file mode 100644
index 000000000..87658d7f3
--- /dev/null
+++ b/test/tsan/Darwin/gcd-sync-block-copy.mm
@@ -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>
+
+@interface MyClass : NSObject
+@end
+
+@implementation MyClass
+- (instancetype)retain {
+ // Copying the dispatch_sync'd block below will increment the retain count of
+ // this object. Abort if that happens.
+ abort();
+}
+@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