forked from OSchip/llvm-project
Revert "tsan: add lock free stack pattern test"
This reverts commit 5deca650fd
.
This commit is contained in:
parent
f1d197f1a8
commit
d6a3c8ca18
|
@ -1,247 +0,0 @@
|
|||
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_tsan -O1 %s -DRACE -o %t && %deflake %run %t | FileCheck %s --check-prefix=CHECK-RACE
|
||||
#include "test.h"
|
||||
|
||||
const int kThreadCount = 4;
|
||||
#if RACE
|
||||
const int kTestCount = 16;
|
||||
#else
|
||||
const int kTestCount = 9;
|
||||
#endif
|
||||
|
||||
template <typename F> F for_each_mo(int mo, F f) {
|
||||
f(mo);
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
auto for_each_mo(int mo, Rest... rest) -> decltype(for_each_mo(rest...)) {
|
||||
auto f = for_each_mo(rest...);
|
||||
f(mo);
|
||||
return f;
|
||||
}
|
||||
|
||||
void LockFreeStackImpl(int test, bool main_thread, int mo2, int mo4) {
|
||||
struct Node {
|
||||
int data;
|
||||
Node *next;
|
||||
};
|
||||
static Node *heads[kTestCount]{};
|
||||
auto head = heads + test;
|
||||
|
||||
auto concurrent_push = [head](Node *new_head, int mo1, int mo2, int mo3) {
|
||||
auto expected = __atomic_load_n(head, mo1);
|
||||
do {
|
||||
new_head->next = expected;
|
||||
} while (!__atomic_compare_exchange_n(head, &expected, new_head,
|
||||
/*weak*/ true, mo2, mo3));
|
||||
};
|
||||
|
||||
auto concurrent_grab_all = [head](int mo4) {
|
||||
volatile int sink{};
|
||||
(void)sink;
|
||||
|
||||
auto h = __atomic_exchange_n(head, nullptr, mo4);
|
||||
while (h) {
|
||||
sink = ++h->data;
|
||||
auto next = h->next;
|
||||
delete h;
|
||||
h = next;
|
||||
}
|
||||
};
|
||||
|
||||
if (main_thread) {
|
||||
concurrent_grab_all(mo4);
|
||||
} else {
|
||||
int i = 0;
|
||||
// We have 15 combinations of mo1 and mo3. Since we have two race reports
|
||||
// for each combination (the first report is for 'data' and the second
|
||||
// report for 'next'), there are 30 race reports in total that should match
|
||||
// to "CHECK-RACE-COUNT{-number_of_reports}" below
|
||||
for_each_mo(
|
||||
__ATOMIC_RELAXED, __ATOMIC_ACQUIRE, __ATOMIC_SEQ_CST, [&](int mo1) {
|
||||
for_each_mo(__ATOMIC_RELAXED, __ATOMIC_ACQUIRE, __ATOMIC_RELEASE,
|
||||
__ATOMIC_ACQ_REL, __ATOMIC_SEQ_CST, [&](int mo3) {
|
||||
concurrent_push(new Node{i++}, mo1, mo2, mo3);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LockFreeStack(int test, bool main_thread, int mo2, int mo4) {
|
||||
barrier_wait(&barrier);
|
||||
if (main_thread) {
|
||||
// We need to call LockFreeStackImpl second time after the barrier
|
||||
// to guarantee at least one grab_all and cleanup.
|
||||
// However, it is better to have one instantiation of LockFreeStackImpl
|
||||
// on the main thread to merge the call stacks and prevent double race
|
||||
// reports. Therefore, we use two interation for loop and skip the barrier
|
||||
// on the second iteration.
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
LockFreeStackImpl(test, main_thread, mo2, mo4);
|
||||
if (i == 0) {
|
||||
barrier_wait(&barrier);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LockFreeStackImpl(test, main_thread, mo2, mo4);
|
||||
barrier_wait(&barrier);
|
||||
}
|
||||
}
|
||||
|
||||
void Test(bool main_thread) {
|
||||
for (int test = 0; test < kTestCount; test++) {
|
||||
if (main_thread) {
|
||||
fprintf(stderr, "Test %d\n", test);
|
||||
}
|
||||
switch (test) {
|
||||
#if RACE
|
||||
case 0:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
break;
|
||||
case 1:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELAXED, __ATOMIC_ACQUIRE);
|
||||
break;
|
||||
case 2:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELAXED, __ATOMIC_RELEASE);
|
||||
break;
|
||||
case 3:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELAXED, __ATOMIC_ACQ_REL);
|
||||
break;
|
||||
case 4:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST);
|
||||
break;
|
||||
case 5:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
|
||||
break;
|
||||
case 6:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
|
||||
break;
|
||||
case 7:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQUIRE, __ATOMIC_RELEASE);
|
||||
break;
|
||||
case 8:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQUIRE, __ATOMIC_ACQ_REL);
|
||||
break;
|
||||
case 9:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQUIRE, __ATOMIC_SEQ_CST);
|
||||
break;
|
||||
case 10:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
|
||||
break;
|
||||
case 11:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELEASE, __ATOMIC_RELEASE);
|
||||
break;
|
||||
case 12:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
|
||||
break;
|
||||
case 13:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQ_REL, __ATOMIC_RELEASE);
|
||||
break;
|
||||
case 14:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
|
||||
break;
|
||||
case 15:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
|
||||
break;
|
||||
#else
|
||||
case 0:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
|
||||
break;
|
||||
case 1:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELEASE, __ATOMIC_ACQ_REL);
|
||||
break;
|
||||
case 2:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_RELEASE, __ATOMIC_SEQ_CST);
|
||||
break;
|
||||
case 3:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
|
||||
break;
|
||||
case 4:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQ_REL, __ATOMIC_ACQ_REL);
|
||||
break;
|
||||
case 5:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_ACQ_REL, __ATOMIC_SEQ_CST);
|
||||
break;
|
||||
case 6:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
|
||||
break;
|
||||
case 7:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_SEQ_CST, __ATOMIC_ACQ_REL);
|
||||
break;
|
||||
case 8:
|
||||
LockFreeStack(test, main_thread, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *Thread(void *p) {
|
||||
Test(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
barrier_init(&barrier, kThreadCount);
|
||||
pthread_t t[kThreadCount - 1];
|
||||
for (int i = 0; i < kThreadCount - 1; ++i)
|
||||
pthread_create(t + i, 0, Thread, (void *)(uintptr_t)(i + 1));
|
||||
Test(true);
|
||||
for (int i = 0; i < kThreadCount - 1; ++i)
|
||||
pthread_join(t[i], 0);
|
||||
}
|
||||
|
||||
// No race tests
|
||||
// CHECK-NOT: ThreadSanitizer: data race
|
||||
|
||||
// Race tests
|
||||
// 30 is the number of race reports for 15 possible combinations of mo1 and mo3
|
||||
// CHECK-RACE: Test 0
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 1
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 2
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 3
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 4
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 5
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 6
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 7
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 8
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 9
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 10
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 11
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 12
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 13
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 14
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE: Test 15
|
||||
// CHECK-RACE-COUNT-30: SUMMARY: ThreadSanitizer: data race
|
||||
// CHECK-RACE-NOT: SUMMARY: ThreadSanitizer: data race
|
Loading…
Reference in New Issue