n Wed, 1 Sept 2021 at 23:06, Alexey Katranov <
alexey....@gmail.com> wrote:
>
> I prototyped the idea of variation tests:
https://github.com/alexey-katranov/llvm-project/commit/fe373f14b8dc38e39c726b9605d3ec922f5fc0f1. Is the approach appropriate? Or does it make sense to reduce code duplication or rework it somehow?
>
> I am also thinking about adding lazy initialization and Peterson's algorithms if the approach is Ok.
Overall it looks fine. But it feels that it can be shortened somewhat.
I also found it somewhat hard to follow logic split over 3 files,
indirection, control inversions and test code intermixed with the
stack implementation.
Also if I am reading it correctly, it seems that only the main thread
prints "Test %d\n", but other threads can proceed to subsequent tests
and race. So that e.g. main thread only printed "Test 3", but other
threads already execute test 7 and produce a race on it. This will be
confusing to debug.
Also it seems that we don't check that all combinations of
mo1_arr/mo3_arr race, because there is only one "// CHECK:
ThreadSanitizer: data race" for all combinations. So if only 1 of them
races, the test will pass and we don't detect that other combinations
don't produce a race.
I am thinking about something along the following lines:
// 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"
struct Stack {
struct Node {
int data = 0;
Node *next;
};
Node* head = nullptr;
Stack(int mo1, int mo2, int mo3, int mo4) { ... }
void push(Node *n) { ... };
void grab_all() { ... }
};
void* Thread(Stack* s) {
s->push(new Stack::Node);
return 0;
}
int main() {
int test = 0;
#if RACE
for(auto& mo24 : {std::make_pair(__ATOMIC_RELAXED, __ATOMIC_RELAXED),
{__ATOMIC_RELAXED, __ATOMIC_ACQUIRE},
{__ATOMIC_RELAXED, __ATOMIC_RELEASE},
...
}) {
#else
for(auto& mo24 : {std::make_pair(__ATOMIC_RELEASE,__ATOMIC_ACQUIRE),
{__ATOMIC_RELEASE, __ATOMIC_ACQ_REL},
{__ATOMIC_RELEASE, __ATOMIC_SEQ_CST},
...
}) {
#endif
for (int mo1 : {__ATOMIC_RELAXED, __ATOMIC_ACQUIRE, __ATOMIC_SEQ_CST}) {
for (int mo3 : {__ATOMIC_RELAXED, __ATOMIC_ACQUIRE,
__ATOMIC_RELEASE, __ATOMIC_ACQ_REL, __ATOMIC_SEQ_CST}) {
printf(stderr, "TEST %d\n", test++);
Stack s(mo1, mo24.first, mo3, mo24.second);
pthread_t tt[3];
for (auto& t : tt)
pthread_create(&t, 0, Thread, &s);
s.grab_all();
for (auto t : tt)
pthread_join(t, 0);
s.grab_all();
}
}
}
}
}
// CHECK: TEST 0
// CHECK-NOT: ThreadSanitizer: data race
// CHECK: TEST 1
// CHECK-NOT: ThreadSanitizer: data race
...
// CHECK-RACE: TEST 0
// CHECK-RACE: ThreadSanitizer: data race
// CHECK-RACE: TEST 1
// CHECK-RACE: ThreadSanitizer: data race
...
> вт, 31 авг. 2021 г. в 14:22, Alexey Katranov <
alexey....@gmail.com>:
>>
>> Thank you for your answer and advice. I'll come back if I make any progress.
>>
>> пн, 30 авг. 2021 г. в 09:27, Dmitry Vyukov <
dvy...@google.com>: