[compiler-rt] r274749 - [tsan] Avoid false positives with GCD data callbacks

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 7 05:38:38 PDT 2016


Author: kuba.brecka
Date: Thu Jul  7 07:38:37 2016
New Revision: 274749

URL: http://llvm.org/viewvc/llvm-project?rev=274749&view=rev
Log:
[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


Added:
    compiler-rt/trunk/test/tsan/Darwin/gcd-data.mm
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc

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=274749&r1=274748&r2=274749&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_libdispatch_mac.cc Thu Jul  7 07:38:37 2016
@@ -475,6 +475,32 @@ TSAN_INTERCEPTOR(void, dispatch_apply_f,
   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

Added: compiler-rt/trunk/test/tsan/Darwin/gcd-data.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/gcd-data.mm?rev=274749&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/gcd-data.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/gcd-data.mm Thu Jul  7 07:38:37 2016
@@ -0,0 +1,36 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+long global;
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
+  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+
+  global = 44;
+  dispatch_data_t data = dispatch_data_create("buffer", 6, q, ^{
+    fprintf(stderr, "Data destructor.\n");
+    global++;
+
+    dispatch_semaphore_signal(sem);
+  });
+  dispatch_release(data);
+  data = nil;
+
+  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+  data = dispatch_data_create("buffer", 6, q, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+  dispatch_release(data);
+  data = nil;
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Data destructor.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.




More information about the llvm-commits mailing list