Changing comments that have references to code.google.com to point to GitHub instead, because the current links are not redirected properly (they instead redirect to different issues, mostly ASan). NFC. Differential Revision: http://reviews.llvm.org/D15053 llvm-svn: 254300
68 lines
1.9 KiB
C++
68 lines
1.9 KiB
C++
// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
|
|
#include "test.h"
|
|
|
|
// Test case https://github.com/google/sanitizers/issues/494
|
|
// 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() {
|
|
__attribute__((aligned(64))) 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() {
|
|
__attribute__((aligned(64))) 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;
|
|
}
|
|
|