[compiler-rt] r255030 - tsan: fix test invisible barrier

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 8 09:54:47 PST 2015


Author: dvyukov
Date: Tue Dec  8 11:54:47 2015
New Revision: 255030

URL: http://llvm.org/viewvc/llvm-project?rev=255030&view=rev
Log:
tsan: fix test invisible barrier

Another attempt at fixing tsan_invisible_barrier.
Current implementation causes:
https://llvm.org/bugs/show_bug.cgi?id=25643

There were several unsuccessful iterations for this functionality:

Initially it was implemented in user code using REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on MacOS. Futexes are linux-specific for this matter.
Then we switched to atomics+usleep(10). But usleep produced parasitic "as-if synchronized via sleep" messages in reports which failed some output tests.
Then we switched to atomics+sched_yield. But this produced tons of tsan- visible events, which lead to "failed to restore stack trace" failures.
Move implementation into runtime and use internal_sched_yield in the wait loop.
This way tsan should see no events from the barrier, so not trace overflows and
no "as-if synchronized via sleep" messages.



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

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=255030&r1=255029&r2=255030&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue Dec  8 11:54:47 2015
@@ -2683,3 +2683,39 @@ void InitializeInterceptors() {
 }
 
 }  // namespace __tsan
+
+// Invisible barrier for tests.
+// There were several unsuccessful iterations for this functionality:
+// 1. Initially it was implemented in user code using
+//    REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on
+//    MacOS. Futexes are linux-specific for this matter.
+// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic
+//    "as-if synchronized via sleep" messages in reports which failed some
+//    output tests.
+// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan-
+//    visible events, which lead to "failed to restore stack trace" failures.
+// Note that no_sanitize_thread attribute does not turn off atomic interception
+// so attaching it to the function defined in user code does not help.
+// That's why we now have what we have.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
+  if (count >= (1 << 8)) {
+      Printf("barrier_init: count is too large (%d)\n", count);
+      Die();
+  }
+  // 8 lsb is thread count, the remaining are count of entered threads.
+  *barrier = count;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_testonly_barrier_wait(u64 *barrier) {
+  unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
+  unsigned old_epoch = (old >> 8) / (old & 0xff);
+  for (;;) {
+    unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
+    unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
+    if (cur_epoch != old_epoch)
+      return;
+    internal_sched_yield();
+  }
+}

Modified: compiler-rt/trunk/test/tsan/load_shared_lib.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/load_shared_lib.cc?rev=255030&r1=255029&r2=255030&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/load_shared_lib.cc (original)
+++ compiler-rt/trunk/test/tsan/load_shared_lib.cc Tue Dec  8 11:54:47 2015
@@ -3,7 +3,7 @@
 // symbolized correctly.
 
 // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
-// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t -rdynamic && %deflake %run %t | FileCheck %s
 
 #ifdef BUILD_SO
 

Modified: compiler-rt/trunk/test/tsan/test.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/test.h?rev=255030&r1=255029&r2=255030&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/test.h (original)
+++ compiler-rt/trunk/test/tsan/test.h Tue Dec  8 11:54:47 2015
@@ -14,27 +14,24 @@
 // TSan-invisible barrier.
 // Tests use it to establish necessary execution order in a way that does not
 // interfere with tsan (does not establish synchronization between threads).
-// 8 lsb is thread count, the remaining are count of entered threads.
 typedef unsigned long long invisible_barrier_t;
 
-void barrier_init(invisible_barrier_t *barrier, unsigned count) {
-  if (count >= (1 << 8))
-      exit(fprintf(stderr, "barrier_init: count is too large (%d)\n", count));
-  *barrier = count;
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __tsan_testonly_barrier_init(invisible_barrier_t *barrier,
+    unsigned count);
+void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier);
+#ifdef __cplusplus
 }
+#endif
 
-void barrier_wait(invisible_barrier_t *barrier) {
-  unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
-  unsigned old_epoch = (old >> 8) / (old & 0xff);
-  for (;;) {
-    unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
-    unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
-    if (cur_epoch != old_epoch)
-      return;
-    // Can't use usleep, because it leads to spurious "As if synchronized via
-    // sleep" messages which fail some output tests.
-    sched_yield();
-  }
+static inline void barrier_init(invisible_barrier_t *barrier, unsigned count) {
+  __tsan_testonly_barrier_init(barrier, count);
+}
+
+static inline void barrier_wait(invisible_barrier_t *barrier) {
+  __tsan_testonly_barrier_wait(barrier);
 }
 
 // Default instance of the barrier, but a test can declare more manually.




More information about the llvm-commits mailing list