Add data structures with bugs that tsan11/tsan11rec cannot detect
[c11concurrency-benchmarks.git] / tsan11-missingbug / seqlock-test.cc
1 #include <pthread.h>
2 #include <atomic>
3 #include <assert.h>
4 //#include <threads.h>
5
6 using namespace std;
7
8 typedef struct seqlock {
9         // Sequence for reader consistency check
10         atomic_int _seq;
11         // It needs to be atomic to avoid data races
12         atomic_int _data1;
13         atomic_int _data2;
14
15         seqlock() {
16         _seq.store(0);
17         _data1.store(0);
18         _data2.store(0);
19         }
20
21         void read(int * d1, int *d2) {
22                 while (true) {
23                         int old_seq = _seq.load(memory_order_acquire);
24                         if (old_seq % 2 == 1) continue;
25
26                         *d1 = _data1.load(memory_order_acquire);
27                         *d2 = _data2.load(memory_order_acquire);
28                         if (_seq.load(memory_order_relaxed) == old_seq) {
29                                 return;
30                         }
31                 }
32         }
33
34         void write(int new_data, int new_data2) {
35                 while (true) {
36                         int old_seq = _seq.load(memory_order_relaxed); // Injected bug: should be acquire
37                         if (old_seq % 2 == 1)
38                                 continue; // Retry
39
40                         if (_seq.compare_exchange_strong(old_seq, old_seq + 1,
41                                 memory_order_relaxed, memory_order_relaxed))
42                                 break;
43                 }
44
45                 // Update the data
46                 _data1.store(new_data, memory_order_release);
47                 _data2.store(new_data, memory_order_release);
48
49                 _seq.fetch_add(1, memory_order_release);
50         }
51
52 } seqlock_t;
53
54
55 seqlock_t *lock;
56
57 void * a(void *obj) {
58         lock->write(3,3);
59         return NULL;
60 }
61
62 void * b(void *obj) {
63         lock->write(2,2);
64         return NULL;
65 }
66
67 void * c(void *obj) {
68         int r1, r2;
69         lock->read(&r1, &r2);
70         assert(r1 == r2);
71         return NULL;
72 }
73
74 int main(int argc, char **argv) {
75         lock = new seqlock_t();
76
77         pthread_t t1, t2, t3;
78         pthread_create(&t1, NULL, &a, NULL);
79         pthread_create(&t2, NULL, &b, NULL);
80         pthread_create(&t3, NULL, &c, NULL);
81
82         pthread_join(t1, NULL);
83         pthread_join(t2, NULL);
84         pthread_join(t3, NULL);
85
86         return 0;
87 }