c55b93866c32706d9fdd0937bf17978b7d415f72
[c11tester.git] / cmodelint.cc
1 #include <stdio.h>
2 #include "model.h"
3 #include "action.h"
4 #include "cmodelint.h"
5 #include "snapshot-interface.h"
6 #include "threads-model.h"
7
8 memory_order orders[6] = {
9         memory_order_relaxed, memory_order_consume, memory_order_acquire,
10         memory_order_release, memory_order_acq_rel, memory_order_seq_cst
11 };
12
13 static void ensureModel() {
14         if (!model) {
15                 snapshot_system_init(10000, 1024, 1024, 40000);
16                 model = new ModelChecker();
17         }
18 }
19
20 /** Performs a read action.*/
21 uint64_t model_read_action(void * obj, memory_order ord) {
22         return model->switch_to_master(new ModelAction(ATOMIC_READ, ord, obj));
23 }
24
25 /** Performs a write action.*/
26 void model_write_action(void * obj, memory_order ord, uint64_t val) {
27         model->switch_to_master(new ModelAction(ATOMIC_WRITE, ord, obj, val));
28 }
29
30 /** Performs an init action. */
31 void model_init_action(void * obj, uint64_t val) {
32         model->switch_to_master(new ModelAction(ATOMIC_INIT, memory_order_relaxed, obj, val));
33 }
34
35 /**
36  * Performs the read part of a RMW action. The next action must either be the
37  * write part of the RMW action or an explicit close out of the RMW action w/o
38  * a write.
39  */
40 uint64_t model_rmwr_action(void *obj, memory_order ord) {
41         return model->switch_to_master(new ModelAction(ATOMIC_RMWR, ord, obj));
42 }
43
44 /**
45  * Performs the read part of a RMW CAS action. The next action must
46  * either be the write part of the RMW action or an explicit close out
47  * of the RMW action w/o a write.
48  */
49 uint64_t model_rmwrcas_action(void *obj, memory_order ord, uint64_t oldval, int size) {
50         return model->switch_to_master(new ModelAction(ATOMIC_RMWRCAS, ord, obj, oldval, size));
51 }
52
53
54 /** Performs the write part of a RMW action. */
55 void model_rmw_action(void *obj, memory_order ord, uint64_t val) {
56         model->switch_to_master(new ModelAction(ATOMIC_RMW, ord, obj, val));
57 }
58
59 /** Closes out a RMW action without doing a write. */
60 void model_rmwc_action(void *obj, memory_order ord) {
61         model->switch_to_master(new ModelAction(ATOMIC_RMWC, ord, obj));
62 }
63
64 /** Issues a fence operation. */
65 void model_fence_action(memory_order ord) {
66         model->switch_to_master(new ModelAction(ATOMIC_FENCE, ord, FENCE_LOCATION));
67 }
68
69 /* ---  helper functions --- */
70 uint64_t model_rmwrcas_action_helper(void *obj, int atomic_index, uint64_t oldval, int size, const char *position) {
71         return model->switch_to_master(
72                 new ModelAction(ATOMIC_RMWRCAS, position, orders[atomic_index], obj)
73                 );
74 }
75
76 uint64_t model_rmwr_action_helper(void *obj, int atomic_index, const char *position) {
77         return model->switch_to_master(
78                 new ModelAction(ATOMIC_RMWR, position, orders[atomic_index], obj)
79                 );
80 }
81
82 void model_rmw_action_helper(void *obj, uint64_t val, int atomic_index, const char * position) {
83         model->switch_to_master(
84                 new ModelAction(ATOMIC_RMW, position, orders[atomic_index], obj, val)
85                 );
86 }
87
88 void model_rmwc_action_helper(void *obj, int atomic_index, const char *position) {
89         model->switch_to_master(
90                 new ModelAction(ATOMIC_RMWC, position, orders[atomic_index], obj)
91                 );
92 }
93
94 // cds atomic inits
95 void cds_atomic_init8(void * obj, uint8_t val, const char * position) {
96         ensureModel();
97         model->switch_to_master(
98                 new ModelAction(ATOMIC_INIT, position, memory_order_relaxed, obj, (uint64_t) val)
99                 );
100 }
101 void cds_atomic_init16(void * obj, uint16_t val, const char * position) {
102         ensureModel();
103         model->switch_to_master(
104                 new ModelAction(ATOMIC_INIT, position, memory_order_relaxed, obj, (uint64_t) val)
105                 );
106 }
107 void cds_atomic_init32(void * obj, uint32_t val, const char * position) {
108         ensureModel();
109         model->switch_to_master(
110                 new ModelAction(ATOMIC_INIT, position, memory_order_relaxed, obj, (uint64_t) val)
111                 );
112 }
113 void cds_atomic_init64(void * obj, uint64_t val, const char * position) {
114         ensureModel();
115         model->switch_to_master(
116                 new ModelAction(ATOMIC_INIT, position, memory_order_relaxed, obj, val)
117                 );
118 }
119
120
121 // cds atomic loads
122 uint8_t cds_atomic_load8(void * obj, int atomic_index, const char * position) {
123         return (uint8_t) ( model->switch_to_master(
124                                                                                          new ModelAction(ATOMIC_READ, position, orders[atomic_index], obj))
125                                                                                  );
126 }
127 uint16_t cds_atomic_load16(void * obj, int atomic_index, const char * position) {
128         return (uint16_t) ( model->switch_to_master(
129                                                                                                 new ModelAction(ATOMIC_READ, position, orders[atomic_index], obj))
130                                                                                         );
131 }
132 uint32_t cds_atomic_load32(void * obj, int atomic_index, const char * position) {
133         return (uint32_t) ( model->switch_to_master(
134                                                                                                 new ModelAction(ATOMIC_READ, position, orders[atomic_index], obj))
135                                                                                         );
136 }
137 uint64_t cds_atomic_load64(void * obj, int atomic_index, const char * position) {
138         return model->switch_to_master(
139                 new ModelAction(ATOMIC_READ, position, orders[atomic_index], obj)
140                 );
141 }
142
143 // cds atomic stores
144 void cds_atomic_store8(void * obj, uint8_t val, int atomic_index, const char * position) {
145         ensureModel();
146         model->switch_to_master(
147                 new ModelAction(ATOMIC_WRITE, position, orders[atomic_index], obj, (uint64_t) val)
148                 );
149 }
150 void cds_atomic_store16(void * obj, uint16_t val, int atomic_index, const char * position) {
151         ensureModel();
152         model->switch_to_master(
153                 new ModelAction(ATOMIC_WRITE, position, orders[atomic_index], obj, (uint64_t) val)
154                 );
155 }
156 void cds_atomic_store32(void * obj, uint32_t val, int atomic_index, const char * position) {
157         ensureModel();
158         model->switch_to_master(
159                 new ModelAction(ATOMIC_WRITE, position, orders[atomic_index], obj, (uint64_t) val)
160                 );
161 }
162 void cds_atomic_store64(void * obj, uint64_t val, int atomic_index, const char * position) {
163         ensureModel();
164         model->switch_to_master(
165                 new ModelAction(ATOMIC_WRITE, position, orders[atomic_index], obj, val)
166                 );
167 }
168
169 #define _ATOMIC_RMW_(__op__, size, addr, val, atomic_index, position)            \
170         ({                                                                      \
171                 uint ## size ## _t _old = model_rmwr_action_helper(addr, atomic_index, position);   \
172                 uint ## size ## _t _copy = _old;                                          \
173                 uint ## size ## _t _val = val;                                            \
174                 _copy __op__ _val;                                                    \
175                 model_rmw_action_helper(addr, (uint64_t) _copy, atomic_index, position);        \
176                 return _old;                                                          \
177         })
178
179 // cds atomic exchange
180 uint8_t cds_atomic_exchange8(void* addr, uint8_t val, int atomic_index, const char * position) {
181         _ATOMIC_RMW_( =, 8, addr, val, atomic_index, position);
182 }
183 uint16_t cds_atomic_exchange16(void* addr, uint16_t val, int atomic_index, const char * position) {
184         _ATOMIC_RMW_( =, 16, addr, val, atomic_index, position);
185 }
186 uint32_t cds_atomic_exchange32(void* addr, uint32_t val, int atomic_index, const char * position) {
187         _ATOMIC_RMW_( =, 32, addr, val, atomic_index, position);
188 }
189 uint64_t cds_atomic_exchange64(void* addr, uint64_t val, int atomic_index, const char * position) {
190         _ATOMIC_RMW_( =, 64, addr, val, atomic_index, position);
191 }
192
193 // cds atomic fetch add
194 uint8_t cds_atomic_fetch_add8(void* addr, uint8_t val, int atomic_index, const char * position) {
195         _ATOMIC_RMW_( +=, 8, addr, val, atomic_index, position);
196 }
197 uint16_t cds_atomic_fetch_add16(void* addr, uint16_t val, int atomic_index, const char * position) {
198         _ATOMIC_RMW_( +=, 16, addr, val, atomic_index, position);
199 }
200 uint32_t cds_atomic_fetch_add32(void* addr, uint32_t val, int atomic_index, const char * position) {
201         _ATOMIC_RMW_( +=, 32, addr, val, atomic_index, position);
202 }
203 uint64_t cds_atomic_fetch_add64(void* addr, uint64_t val, int atomic_index, const char * position) {
204         _ATOMIC_RMW_( +=, 64, addr, val, atomic_index, position);
205 }
206
207 // cds atomic fetch sub
208 uint8_t cds_atomic_fetch_sub8(void* addr, uint8_t val, int atomic_index, const char * position) {
209         _ATOMIC_RMW_( -=, 8, addr, val, atomic_index, position);
210 }
211 uint16_t cds_atomic_fetch_sub16(void* addr, uint16_t val, int atomic_index, const char * position) {
212         _ATOMIC_RMW_( -=, 16, addr, val, atomic_index, position);
213 }
214 uint32_t cds_atomic_fetch_sub32(void* addr, uint32_t val, int atomic_index, const char * position) {
215         _ATOMIC_RMW_( -=, 32, addr, val, atomic_index, position);
216 }
217 uint64_t cds_atomic_fetch_sub64(void* addr, uint64_t val, int atomic_index, const char * position) {
218         _ATOMIC_RMW_( -=, 64, addr, val, atomic_index, position);
219 }
220
221 // cds atomic fetch and
222 uint8_t cds_atomic_fetch_and8(void* addr, uint8_t val, int atomic_index, const char * position) {
223         _ATOMIC_RMW_( &=, 8, addr, val, atomic_index, position);
224 }
225 uint16_t cds_atomic_fetch_and16(void* addr, uint16_t val, int atomic_index, const char * position) {
226         _ATOMIC_RMW_( &=, 16, addr, val, atomic_index, position);
227 }
228 uint32_t cds_atomic_fetch_and32(void* addr, uint32_t val, int atomic_index, const char * position) {
229         _ATOMIC_RMW_( &=, 32, addr, val, atomic_index, position);
230 }
231 uint64_t cds_atomic_fetch_and64(void* addr, uint64_t val, int atomic_index, const char * position) {
232         _ATOMIC_RMW_( &=, 64, addr, val, atomic_index, position);
233 }
234
235 // cds atomic fetch or
236 uint8_t cds_atomic_fetch_or8(void* addr, uint8_t val, int atomic_index, const char * position) {
237         _ATOMIC_RMW_( |=, 8, addr, val, atomic_index, position);
238 }
239 uint16_t cds_atomic_fetch_or16(void* addr, uint16_t val, int atomic_index, const char * position) {
240         _ATOMIC_RMW_( |=, 16, addr, val, atomic_index, position);
241 }
242 uint32_t cds_atomic_fetch_or32(void* addr, uint32_t val, int atomic_index, const char * position) {
243         _ATOMIC_RMW_( |=, 32, addr, val, atomic_index, position);
244 }
245 uint64_t cds_atomic_fetch_or64(void* addr, uint64_t val, int atomic_index, const char * position) {
246         _ATOMIC_RMW_( |=, 64, addr, val, atomic_index, position);
247 }
248
249 // cds atomic fetch xor
250 uint8_t cds_atomic_fetch_xor8(void* addr, uint8_t val, int atomic_index, const char * position) {
251         _ATOMIC_RMW_( ^=, 8, addr, val, atomic_index, position);
252 }
253 uint16_t cds_atomic_fetch_xor16(void* addr, uint16_t val, int atomic_index, const char * position) {
254         _ATOMIC_RMW_( ^=, 16, addr, val, atomic_index, position);
255 }
256 uint32_t cds_atomic_fetch_xor32(void* addr, uint32_t val, int atomic_index, const char * position) {
257         _ATOMIC_RMW_( ^=, 32, addr, val, atomic_index, position);
258 }
259 uint64_t cds_atomic_fetch_xor64(void* addr, uint64_t val, int atomic_index, const char * position) {
260         _ATOMIC_RMW_( ^=, 64, addr, val, atomic_index, position);
261 }
262
263 // cds atomic compare and exchange
264 // In order to accomodate the LLVM PASS, the return values are not true or false.
265
266 #define _ATOMIC_CMPSWP_WEAK_ _ATOMIC_CMPSWP_
267 #define _ATOMIC_CMPSWP_(size, addr, expected, desired, atomic_index, position)                            \
268         ({                                                                                              \
269                 uint ## size ## _t _desired = desired;                                                            \
270                 uint ## size ## _t _expected = expected;                                                          \
271                 uint ## size ## _t _old = model_rmwrcas_action_helper(addr, atomic_index, _expected, sizeof(_expected), position); \
272                 if (_old == _expected) {                                                                    \
273                         model_rmw_action_helper(addr, (uint64_t) _desired, atomic_index, position); return _expected; }      \
274                 else {                                                                                        \
275                         model_rmwc_action_helper(addr, atomic_index, position); _expected = _old; return _old; }              \
276         })
277
278 // atomic_compare_exchange version 1: the CmpOperand (corresponds to expected)
279 // extracted from LLVM IR is an integer type.
280
281 uint8_t cds_atomic_compare_exchange8_v1(void* addr, uint8_t expected, uint8_t desired,
282                                                                                                                                                                 int atomic_index_succ, int atomic_index_fail, const char *position )
283 {
284         _ATOMIC_CMPSWP_(8, addr, expected, desired,
285                                                                         atomic_index_succ, position);
286 }
287 uint16_t cds_atomic_compare_exchange16_v1(void* addr, uint16_t expected, uint16_t desired,
288                                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
289 {
290         _ATOMIC_CMPSWP_(16, addr, expected, desired,
291                                                                         atomic_index_succ, position);
292 }
293 uint32_t cds_atomic_compare_exchange32_v1(void* addr, uint32_t expected, uint32_t desired,
294                                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
295 {
296         _ATOMIC_CMPSWP_(32, addr, expected, desired,
297                                                                         atomic_index_succ, position);
298 }
299 uint64_t cds_atomic_compare_exchange64_v1(void* addr, uint64_t expected, uint64_t desired,
300                                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
301 {
302         _ATOMIC_CMPSWP_(64, addr, expected, desired,
303                                                                         atomic_index_succ, position);
304 }
305
306 // atomic_compare_exchange version 2
307 bool cds_atomic_compare_exchange8_v2(void* addr, uint8_t* expected, uint8_t desired,
308                                                                                                                                                  int atomic_index_succ, int atomic_index_fail, const char *position )
309 {
310         uint8_t ret = cds_atomic_compare_exchange8_v1(addr, *expected,
311                                                                                                                                                                                                 desired, atomic_index_succ, atomic_index_fail, position);
312         if (ret == *expected) return true;
313         else return false;
314 }
315 bool cds_atomic_compare_exchange16_v2(void* addr, uint16_t* expected, uint16_t desired,
316                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
317 {
318         uint16_t ret = cds_atomic_compare_exchange16_v1(addr, *expected,
319                                                                                                                                                                                                         desired, atomic_index_succ, atomic_index_fail, position);
320         if (ret == *expected) return true;
321         else return false;
322 }
323 bool cds_atomic_compare_exchange32_v2(void* addr, uint32_t* expected, uint32_t desired,
324                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
325 {
326         uint32_t ret = cds_atomic_compare_exchange32_v1(addr, *expected,
327                                                                                                                                                                                                         desired, atomic_index_succ, atomic_index_fail, position);
328         if (ret == *expected) return true;
329         else return false;
330 }
331 bool cds_atomic_compare_exchange64_v2(void* addr, uint64_t* expected, uint64_t desired,
332                                                                                                                                                         int atomic_index_succ, int atomic_index_fail, const char *position)
333 {
334         uint64_t ret = cds_atomic_compare_exchange64_v1(addr, *expected,
335                                                                                                                                                                                                         desired, atomic_index_succ, atomic_index_fail, position);
336         if (ret == *expected) return true;
337         else return false;
338 }
339
340
341 // cds atomic thread fence
342
343 void cds_atomic_thread_fence(int atomic_index, const char * position) {
344         model->switch_to_master(
345                 new ModelAction(ATOMIC_FENCE, position, orders[atomic_index], FENCE_LOCATION)
346                 );
347 }
348
349 /*
350  #define _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ )                         \
351         ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__);   \
352                 __typeof__(__e__) __q__ = (__e__);                            \
353                 __typeof__(__m__) __v__ = (__m__);                            \
354                 bool __r__;                                                   \
355                 __typeof__((__a__)->__f__) __t__=(__typeof__((__a__)->__f__)) model_rmwr_action((void *)__p__, __x__); \
356                 if (__t__ == * __q__ ) {                                      \
357                         model_rmw_action((void *)__p__, __x__, (uint64_t) __v__); __r__ = true; } \
358                 else {  model_rmwc_action((void *)__p__, __x__); *__q__ = __t__;  __r__ = false;} \
359                 __r__; })
360
361  #define _ATOMIC_FENCE_( __x__ ) \
362         ({ model_fence_action(__x__);})
363  */
364
365 /*
366
367  #define _ATOMIC_MODIFY_( __a__, __o__, __m__, __x__ )                         \
368         ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__);   \
369         __typeof__((__a__)->__f__) __old__=(__typeof__((__a__)->__f__)) model_rmwr_action((void *)__p__, __x__); \
370         __typeof__(__m__) __v__ = (__m__);                                    \
371         __typeof__((__a__)->__f__) __copy__= __old__;                         \
372         __copy__ __o__ __v__;                                                 \
373         model_rmw_action((void *)__p__, __x__, (uint64_t) __copy__);          \
374         __old__ = __old__;  Silence clang (-Wunused-value)                    \
375          })
376  */