[PATCH] D59526: [TSan][libdispatch] Avoid infinite recursion in dispatch_apply[_f] interceptors

Julian Lettner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 18 17:55:06 PDT 2019


yln created this revision.
yln added reviewers: kubamracek, dcoughlin.
Herald added projects: Sanitizers, LLVM.
Herald added subscribers: llvm-commits, Sanitizers.

In libdispatch, dispatch_apply is implemented in terms of
dispatch_apply_f. Unfortunately, this means that we can't implement the
interceptor for dispatch_apply_f by forwarding to the dispatch_apply
interceptor.

In the interceptor dispatch_apply_f, we can't use WRAP(dispatch_apply).
WRAP(dispatch_apply) -> REAL(dispatch_apply_f). Requires duplication of
some setup code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D59526

Files:
  compiler-rt/lib/tsan/rtl/tsan_libdispatch.cc


Index: compiler-rt/lib/tsan/rtl/tsan_libdispatch.cc
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_libdispatch.cc
+++ compiler-rt/lib/tsan/rtl/tsan_libdispatch.cc
@@ -479,34 +479,54 @@
                  DISPATCH_NOESCAPE void (^block)(size_t)) {
   SCOPED_TSAN_INTERCEPTOR(dispatch_apply, iterations, queue, block);
 
-  void *parent_to_child_sync = nullptr;
-  uptr parent_to_child_sync_uptr = (uptr)&parent_to_child_sync;
-  void *child_to_parent_sync = nullptr;
-  uptr child_to_parent_sync_uptr = (uptr)&child_to_parent_sync;
+  u8 sync1, sync2;
+  uptr parent_to_child_sync = (uptr)&sync1;
+  uptr child_to_parent_sync = (uptr)&sync2;
 
-  Release(thr, pc, parent_to_child_sync_uptr);
+  Release(thr, pc, parent_to_child_sync);
   void (^new_block)(size_t) = ^(size_t iteration) {
     SCOPED_INTERCEPTOR_RAW(dispatch_apply);
-    Acquire(thr, pc, parent_to_child_sync_uptr);
+    Acquire(thr, pc, parent_to_child_sync);
     SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
     block(iteration);
     SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-    Release(thr, pc, child_to_parent_sync_uptr);
+    Release(thr, pc, child_to_parent_sync);
   };
   SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
   REAL(dispatch_apply)(iterations, queue, new_block);
   SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  Acquire(thr, pc, child_to_parent_sync_uptr);
+  Acquire(thr, pc, child_to_parent_sync);
+}
+
+static void invoke_block_iteration(void *param, size_t iteration) {
+  auto block = (void (^)(size_t)) param;
+  block(iteration);
 }
 
 TSAN_INTERCEPTOR(void, dispatch_apply_f, size_t iterations,
                  dispatch_queue_t queue, void *context,
                  void (*work)(void *, size_t)) {
   SCOPED_TSAN_INTERCEPTOR(dispatch_apply_f, iterations, queue, context, work);
+
+  // Unfortunately, we cannot delegate to dispatch_apply, since libdispatch
+  // implements dispatch_apply in terms of dispatch_apply_f.
+  u8 sync1, sync2;
+  uptr parent_to_child_sync = (uptr)&sync1;
+  uptr child_to_parent_sync = (uptr)&sync2;
+
+  Release(thr, pc, parent_to_child_sync);
   void (^new_block)(size_t) = ^(size_t iteration) {
+    SCOPED_INTERCEPTOR_RAW(dispatch_apply_f);
+    Acquire(thr, pc, parent_to_child_sync);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
     work(context, iteration);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+    Release(thr, pc, child_to_parent_sync);
   };
-  WRAP(dispatch_apply)(iterations, queue, new_block);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  REAL(dispatch_apply_f)(iterations, queue, new_block, invoke_block_iteration);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  Acquire(thr, pc, child_to_parent_sync);
 }
 
 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D59526.191220.patch
Type: text/x-patch
Size: 2801 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190319/41a99341/attachment.bin>


More information about the llvm-commits mailing list