[compiler-rt] r356467 - [TSan][libdispatch] Avoid infinite recursion in dispatch_apply[_f] interceptors

Julian Lettner via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 09:12:59 PDT 2019


Author: yln
Date: Tue Mar 19 09:12:59 2019
New Revision: 356467

URL: http://llvm.org/viewvc/llvm-project?rev=356467&view=rev
Log:
[TSan][libdispatch] Avoid infinite recursion in dispatch_apply[_f] interceptors

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.

Reviewed By: kubamracek

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

Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch.cc?rev=356467&r1=356466&r2=356467&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch.cc Tue Mar 19 09:12:59 2019
@@ -479,34 +479,54 @@ TSAN_INTERCEPTOR(void, dispatch_apply, s
                  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)




More information about the llvm-commits mailing list