560f53d35bbb162f13bbeb56aede565ce22d2208
[c11concurrency-benchmarks.git] / tsan11-missingbug / rwlock-test.cc
1 #include <stdio.h>
2 #include <atomic>
3 #include <pthread.h>
4 #include <assert.h>
5 // #include <stdatomic.h>
6
7 using namespace std;
8
9 #define RW_LOCK_BIAS        0x00100000
10 #define WRITE_LOCK_CMP    RW_LOCK_BIAS
11
12 /** Example implementation of linux rw lock along with 2 thread test
13  *  driver... */
14
15 typedef union {
16         atomic_int lock;
17 } rwlock_t;
18
19 static inline void read_lock(rwlock_t *rw)
20 {
21         int priorvalue = rw->lock.fetch_sub(1, memory_order_acquire);
22         while (priorvalue <= 0) {
23                 rw->lock.fetch_add(1, memory_order_relaxed);
24                 while (rw->lock.load(memory_order_relaxed) <= 0) {
25                         pthread_yield();
26                 }
27                 priorvalue = rw->lock.fetch_sub(1, memory_order_acquire);
28         }
29 }
30
31 // Injected bug for the two fetch_sub ***
32 static inline void write_lock(rwlock_t *rw)
33 {
34         int priorvalue = rw->lock.fetch_sub(RW_LOCK_BIAS, memory_order_relaxed);        // Should be acquire
35         while (priorvalue != RW_LOCK_BIAS) {
36                 rw->lock.fetch_add(RW_LOCK_BIAS, memory_order_relaxed);
37                 while (rw->lock.load(memory_order_relaxed) != RW_LOCK_BIAS) {
38                         pthread_yield();
39                 }
40                 priorvalue = rw->lock.fetch_sub(RW_LOCK_BIAS, memory_order_relaxed);    // Should be acquire
41         }
42 }
43
44 static inline void read_unlock(rwlock_t *rw)
45 {
46         rw->lock.fetch_add(1, memory_order_release);
47 }
48
49 static inline void write_unlock(rwlock_t *rw)
50 {
51         rw->lock.fetch_add(RW_LOCK_BIAS, memory_order_release);
52 }
53
54 rwlock_t mylock;
55 atomic_int data1, data2;
56
57 void * a(void *obj)
58 {
59         int i;
60         for(i = 0; i < 4; i++) {
61                 if ((i % 2) == 0) {
62                         read_lock(&mylock);
63                         int d1 = data1.load(memory_order_relaxed);
64                         int d2 = data2.load(memory_order_relaxed);
65                         assert(d1 == d2);
66                         read_unlock(&mylock);
67                 } else {
68                         write_lock(&mylock);
69                         data1.store(i, memory_order_relaxed);
70                         data2.store(i, memory_order_relaxed);
71                         write_unlock(&mylock);
72                 }
73         }
74
75         return NULL;
76 }
77
78 int main(int argc, char **argv)
79 {
80         pthread_t t1, t2, t3;
81         mylock.lock.store(RW_LOCK_BIAS);
82
83         pthread_create(&t1, NULL, &a, NULL);
84         pthread_create(&t2, NULL, &a, NULL);
85         pthread_create(&t3, NULL, &a, NULL);
86
87         pthread_join(t1, NULL);
88         pthread_join(t2, NULL);
89         pthread_join(t3, NULL);
90
91         return 0;
92 }