Files
clang-p2996/compiler-rt/test/tsan/stack_sync_reuse.cc
Dmitry Vyukov 3ab6b2347e tsan: remove sleeps from tests
Even sleep(1) lead to episodical flakes on some machines.
Use an invisible by tsan barrier to enforce required execution order instead.
This makes the tests deterministic and faster.

llvm-svn: 226659
2015-01-21 13:50:02 +00:00

66 lines
1.8 KiB
C++

// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
#include "test.h"
// Test case https://code.google.com/p/thread-sanitizer/issues/detail?id=87
// Tsan sees false HB edge on address pointed to by syncp variable.
// It is false because when acquire is done syncp points to a var in one frame,
// and during release it points to a var in a different frame.
// The code is somewhat tricky because it prevents compiler from optimizing
// our accesses away, structured to not introduce other data races and
// not introduce other synchronization, and to arrange the vars in different
// frames to occupy the same address.
// The data race CHECK-NOT below actually must be CHECK, because the program
// does contain the data race on global.
// CHECK-NOT: WARNING: ThreadSanitizer: data race
// CHECK: DONE
long global;
long *syncp;
long *addr;
long sink;
void *Thread(void *x) {
while (__atomic_load_n(&syncp, __ATOMIC_ACQUIRE) == 0)
usleep(1000); // spin wait
global = 42;
__atomic_store_n(syncp, 1, __ATOMIC_RELEASE);
__atomic_store_n(&syncp, 0, __ATOMIC_RELAXED);
return NULL;
}
void __attribute__((noinline)) foobar() {
long s;
addr = &s;
__atomic_store_n(&s, 0, __ATOMIC_RELAXED);
__atomic_store_n(&syncp, &s, __ATOMIC_RELEASE);
while (__atomic_load_n(&syncp, __ATOMIC_RELAXED) != 0)
usleep(1000); // spin wait
}
void __attribute__((noinline)) barfoo() {
long s;
if (addr != &s) {
printf("address mismatch addr=%p &s=%p\n", addr, &s);
exit(1);
}
__atomic_store_n(&addr, &s, __ATOMIC_RELAXED);
__atomic_store_n(&s, 0, __ATOMIC_RELAXED);
sink = __atomic_load_n(&s, __ATOMIC_ACQUIRE);
global = 43;
}
int main() {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
foobar();
barfoo();
pthread_join(t, 0);
if (sink != 0)
exit(1);
fprintf(stderr, "DONE\n");
return 0;
}