9 #include <cdsannotate.h>
10 #include <specannotation.h>
11 #include <model_memory.h>
16 typedef void* (*read_func_ptr_t)(void*);
20 Every read will read the up-to-date value, and only one thread can be
25 Fixed the write to be lock-free. Use a CAS in the write instead of using the
26 mutex. There are a couple options for the implementation according to Hans
27 Boehm's paper <<Can seqlocks get along with programming language memory
30 Interesting thing in the read() function is the memory ordering we should
31 impose there. In Hans Boehm's paper, he presents 3 ways to do it. We will
32 try to use the fences one here as a special case to check programs written
40 bool equal(int64_t p1, int64_t p2) {
43 Data *d1 = (Data*) p1;
44 Data *d2 = (Data*) p2;
45 if (d1->data1 == d2->data1 &&
46 d1->data2 == d2->data2) {
61 // Sequence for reader consistency check
64 // The shared data structure to be protected;
65 // It needs to be atomic to avoid data races
78 set = createIntegerList();
79 Data *d = (Data*) MODEL_MALLOC(sizeof(Data));
82 push_back(set, (int64_t) d);
85 destroyIntegerList(set);
88 // This is a trick to get unique id
89 // The testcase should have a unique sum
90 call_id_t getID(int64_t d1, int64_t d2) {
94 bool print(int64_t p) {
96 model_print("Elem-> d1 = %d, d2 = %d\n", d->data1, d->data2);
99 void _write(int64_t d1, int64_t d2) {
100 Data *d = (Data*) MODEL_MALLOC(sizeof(Data));
103 push_back(set, (int64_t) d);
106 bool _read(int d1, int d2) {
107 Data *d = (Data*) MODEL_MALLOC(sizeof(Data));
110 bool hasElem = has_elem_by_value(set, (int64_t) d, &equal);
116 @Commutativity: Write <-> Read: true
122 _data1.store(0, memory_order_relaxed);
123 _data2.store(0, memory_order_relaxed);
124 _seq.store(0, memory_order_relaxed);
138 @Commit_point_set: ReadPoint
141 //model_print("Read_ID = %d, d1 = %d, d2 = %d\n", getID(*d1, *d2),
143 //do_by_value(set, &print);
148 void read(int *d1, int *d2) {
150 /**** SPEC (sequential) ****/
151 int seq1 = _seq.load(memory_order_acquire);
152 printf("seq1=%d\n", seq1);
153 if (seq1 & 0x1 == 1) {
157 // Try to read the data
158 *d1 = _data1.load(memory_order_relaxed);
159 *d2 = _data2.load(memory_order_relaxed);
160 /**** SPEC (sequential) ****/
161 atomic_thread_fence(memory_order_acquire);
163 printf("d1=%d\n", *d1);
164 printf("d2=%d\n", *d2);
165 // Now doulbe check nothing got updated
166 int seq2 = _seq.load(memory_order_relaxed);
169 @Commit_point_define_check: seq1 == seq2
173 printf("seq2=%d\n", seq1);
174 if (seq1 == seq2) { // Good to go
175 printf("Result: d1=%d, d2=%d\n", *d1, *d2);
186 @Commit_point_set: WritePoint
189 //model_print("Write_ID = %d, d1=%d, d2=%d\n", getID(d1, d2), d1, d2);
191 //do_by_value(set, &print);
194 void write(int d1, int d2) {
197 /**** admissibility ****/
198 seq = _seq.load(memory_order_acquire);
203 bool succ = _seq.compare_exchange_strong(seq, seq + 1,
204 memory_order_relaxed, memory_order_relaxed);
211 /**** SPEC (sequential) ****/
212 atomic_thread_fence(memory_order_release);
213 _data1.store(d1, memory_order_relaxed);
214 _data2.store(d2, memory_order_relaxed);
215 // Should be a store release!!!
216 /**** admissibility ****/
217 _seq.fetch_add(1, memory_order_release);
220 @Commit_point_define_check: true