[PATCH] D15288: tsan: fix test invisible barrier
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 7 05:45:02 PST 2015
dvyukov created this revision.
dvyukov added reviewers: kcc, eugenis.
dvyukov added subscribers: kubabrecka, llvm-commits, krasin.
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:
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.
Move implementation into runtime and use SleepForMillis 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.
http://reviews.llvm.org/D15288
Files:
lib/tsan/rtl/tsan_interceptors.cc
test/tsan/test.h
Index: test/tsan/test.h
===================================================================
--- test/tsan/test.h
+++ test/tsan/test.h
@@ -14,27 +14,20 @@
// 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;
+extern "C"
+void __tsan_invisible_barrier_init(invisible_barrier_t *barrier,
+ unsigned count);
+extern "C"
+void __tsan_invisible_barrier_wait(invisible_barrier_t *barrier);
+
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;
+ __tsan_invisible_barrier_init(barrier, count);
}
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();
- }
+ __tsan_invisible_barrier_wait(barrier);
}
// Default instance of the barrier, but a test can declare more manually.
Index: lib/tsan/rtl/tsan_interceptors.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors.cc
+++ lib/tsan/rtl/tsan_interceptors.cc
@@ -2683,3 +2683,37 @@
}
} // 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.
+// That's why we now have what we have.
+extern "C"
+void __tsan_invisible_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"
+void __tsan_invisible_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;
+ SleepForMillis(1);
+ }
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15288.42062.patch
Type: text/x-patch
Size: 3121 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151207/a3d4ab96/attachment.bin>
More information about the llvm-commits
mailing list