[compiler-rt] r255995 - [tsan] Fix scoping of ScopedInteceptor in libdispatch support

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 18 03:16:25 PST 2015


Author: kuba.brecka
Date: Fri Dec 18 05:16:24 2015
New Revision: 255995

URL: http://llvm.org/viewvc/llvm-project?rev=255995&view=rev
Log:
[tsan] Fix scoping of ScopedInteceptor in libdispatch support

Some interceptors in tsan_libdispatch_mac.cc currently wrongly use TSAN_SCOPED_INTERCEPTOR/ScopedInterceptor. Its constructor can start ignoring memory accesses, and the destructor the stops this -- however, e.g. dispatch_sync can call user's code, so the ignoring will extend to user's code as well. This is not expected and we should only limit the scope of ScopedInterceptor to TSan code.  This patch introduces annotations that mark the beginning and ending of a callback into user's code.

Differential Revision: http://reviews.llvm.org/D15419


Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=255995&r1=255994&r2=255995&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri Dec 18 05:16:24 2015
@@ -295,6 +295,20 @@ ScopedInterceptor::~ScopedInterceptor()
   }
 }
 
+void ScopedInterceptor::UserCallbackStart() {
+  if (in_ignored_lib_) {
+    thr_->in_ignored_lib = false;
+    ThreadIgnoreEnd(thr_, pc_);
+  }
+}
+
+void ScopedInterceptor::UserCallbackEnd() {
+  if (in_ignored_lib_) {
+    thr_->in_ignored_lib = true;
+    ThreadIgnoreBegin(thr_, pc_);
+  }
+}
+
 #define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
 #if SANITIZER_FREEBSD
 # define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h?rev=255995&r1=255994&r2=255995&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h Fri Dec 18 05:16:24 2015
@@ -10,6 +10,8 @@ class ScopedInterceptor {
  public:
   ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
   ~ScopedInterceptor();
+  void UserCallbackStart();
+  void UserCallbackEnd();
  private:
   ThreadState *const thr_;
   const uptr pc_;
@@ -36,6 +38,12 @@ class ScopedInterceptor {
       return REAL(func)(__VA_ARGS__); \
 /**/
 
+#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
+    si.UserCallbackStart();
+
+#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
+    si.UserCallbackEnd();
+
 #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
 
 #if SANITIZER_FREEBSD

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=255995&r1=255994&r2=255995&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc Fri Dec 18 05:16:24 2015
@@ -94,7 +94,9 @@ static void dispatch_callback_wrap_acqui
   // In serial queues, work items can be executed on different threads, we need
   // to explicitly synchronize on the queue itself.
   if (IsQueueSerial(context->queue)) Acquire(thr, pc, (uptr)context->queue);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
   context->orig_work(context->orig_context);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
   if (IsQueueSerial(context->queue)) Release(thr, pc, (uptr)context->queue);
   user_free(thr, pc, context);
 }
@@ -108,11 +110,15 @@ static void invoke_and_release_block(voi
 #define DISPATCH_INTERCEPT_B(name)                                           \
   TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, 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 =                                      \
         AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);     \
     Release(thr, pc, (uptr)new_context);                                     \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
     REAL(name##_f)(q, new_context, dispatch_callback_wrap_acquire);          \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
   }
 
 #define DISPATCH_INTERCEPT_F(name)                                \
@@ -122,7 +128,9 @@ static void invoke_and_release_block(voi
     tsan_block_context_t *new_context =                           \
         AllocContext(thr, pc, q, context, work);                  \
     Release(thr, pc, (uptr)new_context);                          \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
     REAL(name)(q, new_context, dispatch_callback_wrap_acquire);   \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
   }
 
 // We wrap dispatch_async, dispatch_sync and friends where we allocate a new
@@ -158,7 +166,9 @@ TSAN_INTERCEPTOR(void, dispatch_once, di
   u32 v = atomic_load(a, memory_order_acquire);
   if (v == 0 &&
       atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) {
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
     block();
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
     Release(thr, pc, (uptr)a);
     atomic_store(a, 2, memory_order_release);
   } else {
@@ -174,9 +184,11 @@ TSAN_INTERCEPTOR(void, dispatch_once, di
 TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate,
                  void *context, dispatch_function_t function) {
   SCOPED_TSAN_INTERCEPTOR(dispatch_once_f, predicate, context, function);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
   WRAP(dispatch_once)(predicate, ^(void) {
     function(context);
   });
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
 }
 
 TSAN_INTERCEPTOR(long_t, dispatch_semaphore_signal,
@@ -236,7 +248,9 @@ TSAN_INTERCEPTOR(void, dispatch_group_as
 TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group,
                  dispatch_queue_t q, dispatch_block_t block) {
   SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, 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 =
       AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
   new_context->object_to_acquire = (uptr)group;




More information about the llvm-commits mailing list