summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2016-07-07 12:38:37 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2016-07-07 12:38:37 +0000
commit4446c216f5c3b78424ce1464134615c52a4399a5 (patch)
tree40139614cf5a0e3e88d4d2dd346a0c404f728854 /compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc
parent474c642172bb4265777caed68f4551a8223524bf (diff)
downloadbcm5719-llvm-4446c216f5c3b78424ce1464134615c52a4399a5.tar.gz
bcm5719-llvm-4446c216f5c3b78424ce1464134615c52a4399a5.zip
[tsan] Avoid false positives with GCD data callbacks
This patch adds synchronization between the creation of the GCD data object and destructor’s execution. It’s far from perfect, because ideally we’d want to synchronize the destruction of the last reference (via dispatch_release) and the destructor’s execution, but intercepting objc_release is problematic. Differential Revision: http://reviews.llvm.org/D21990 llvm-svn: 274749
Diffstat (limited to 'compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc26
1 files changed, 26 insertions, 0 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc b/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc
index cde5ed0a1e4..15805b98de6 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc
@@ -475,6 +475,32 @@ TSAN_INTERCEPTOR(void, dispatch_apply_f, size_t iterations,
WRAP(dispatch_apply)(iterations, queue, new_block);
}
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+DECLARE_REAL_AND_INTERCEPTOR(int, munmap, void *addr, long_t sz)
+
+TSAN_INTERCEPTOR(dispatch_data_t, dispatch_data_create, const void *buffer,
+ size_t size, dispatch_queue_t q, dispatch_block_t destructor) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_data_create, buffer, size, q, destructor);
+ if ((q == nullptr) || (destructor == DISPATCH_DATA_DESTRUCTOR_DEFAULT))
+ return REAL(dispatch_data_create)(buffer, size, q, destructor);
+
+ if (destructor == DISPATCH_DATA_DESTRUCTOR_FREE)
+ destructor = ^(void) { WRAP(free)((void *)buffer); };
+ else if (destructor == DISPATCH_DATA_DESTRUCTOR_MUNMAP)
+ destructor = ^(void) { WRAP(munmap)((void *)buffer, size); };
+
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ dispatch_block_t heap_block = Block_copy(destructor);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ tsan_block_context_t *new_context =
+ AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
+ uptr submit_sync = (uptr)new_context;
+ Release(thr, pc, submit_sync);
+ return REAL(dispatch_data_create)(buffer, size, q, ^(void) {
+ dispatch_callback_wrap(new_context);
+ });
+}
+
} // namespace __tsan
#endif // SANITIZER_MAC
OpenPOWER on IntegriCloud