6a09bec7dd9f60050b358cf0e833ed6b222a72a0
[c11tester.git] / action.cc
1 #include <stdio.h>
2 #define __STDC_FORMAT_MACROS
3 #include <inttypes.h>
4 #include <stdlib.h>
5
6 #include "model.h"
7 #include "action.h"
8 #include "clockvector.h"
9 #include "common.h"
10 #include "threads-model.h"
11 #include "nodestack.h"
12 #include "wildcard.h"
13
14 #define ACTION_INITIAL_CLOCK 0
15
16 /** @brief A special value to represent a successful trylock */
17 #define VALUE_TRYSUCCESS 1
18
19 /** @brief A special value to represent a failed trylock */
20 #define VALUE_TRYFAILED 0
21
22 /**
23  * @brief Construct a new ModelAction
24  *
25  * @param type The type of action
26  * @param order The memory order of this action. A "don't care" for non-ATOMIC
27  * actions (e.g., THREAD_* or MODEL_* actions).
28  * @param loc The location that this action acts upon
29  * @param value (optional) A value associated with the action (e.g., the value
30  * read or written). Defaults to a given macro constant, for debugging purposes.
31  * @param thread (optional) The Thread in which this action occurred. If NULL
32  * (default), then a Thread is assigned according to the scheduler.
33  */
34 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, 
35                 uint64_t value, Thread *thread) :
36         location(loc),
37         position(NULL),
38         reads_from(NULL),
39         last_fence_release(NULL),
40         node(NULL),
41         cv(NULL),
42         value(value),
43         type(type),
44         order(order),
45         original_order(order),
46         seq_number(ACTION_INITIAL_CLOCK)
47 {
48         /* References to NULL atomic variables can end up here */
49         ASSERT(loc || type == ATOMIC_FENCE || type == NOOP);
50
51         Thread *t = thread ? thread : thread_current();
52         this->tid = t->get_id();
53 }
54
55
56 /**
57  * @brief Construct a new ModelAction
58  *
59  * @param type The type of action
60  * @param order The memory order of this action. A "don't care" for non-ATOMIC
61  * actions (e.g., THREAD_* or MODEL_* actions).
62  * @param loc The location that this action acts upon
63  * @param value (optional) A value associated with the action (e.g., the value
64  * read or written). Defaults to a given macro constant, for debugging purposes.
65  * @param size (optional) The Thread in which this action occurred. If NULL
66  * (default), then a Thread is assigned according to the scheduler.
67  */
68 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc,
69                 uint64_t value, int size) :
70         location(loc),
71         position(NULL),
72         reads_from(NULL),
73         last_fence_release(NULL),
74         node(NULL),
75         cv(NULL),
76         value(value),
77         type(type),
78         order(order),
79         original_order(order),
80         seq_number(ACTION_INITIAL_CLOCK)
81 {
82         /* References to NULL atomic variables can end up here */
83         ASSERT(loc);
84         this->size = size;
85         Thread *t = thread_current();
86         this->tid = t->get_id();
87 }
88
89
90 /**
91  * @brief Construct a new ModelAction with source line number (requires llvm support)
92  *
93  * @param type The type of action
94  * @param position The source line number of this atomic operation
95  * @param order The memory order of this action. A "don't care" for non-ATOMIC
96  * actions (e.g., THREAD_* or MODEL_* actions).
97  * @param loc The location that this action acts upon
98  * @param value (optional) A value associated with the action (e.g., the value
99  * read or written). Defaults to a given macro constant, for debugging purposes.
100  * @param thread (optional) The Thread in which this action occurred. If NULL
101  * (default), then a Thread is assigned according to the scheduler.
102  */
103 ModelAction::ModelAction(action_type_t type, const char * position, memory_order order, 
104                 void *loc, uint64_t value, Thread *thread) :
105         location(loc),
106         position(position),
107         reads_from(NULL),
108         last_fence_release(NULL),
109         node(NULL),
110         cv(NULL),
111         value(value),
112         type(type),
113         order(order),
114         original_order(order),
115         seq_number(ACTION_INITIAL_CLOCK)
116 {
117         /* References to NULL atomic variables can end up here */
118         ASSERT(loc || type == ATOMIC_FENCE);
119
120         Thread *t = thread ? thread : thread_current();
121         this->tid = t->get_id();
122         // model_print("position: %s\n", position);
123 }
124
125
126 /** @brief ModelAction destructor */
127 ModelAction::~ModelAction()
128 {
129         /**
130          * We can't free the clock vector:
131          * Clock vectors are snapshotting state. When we delete model actions,
132          * they are at the end of the node list and have invalid old clock
133          * vectors which have already been rolled back to an unallocated state.
134          */
135
136         /*
137            if (cv)
138                 delete cv; */
139 }
140
141 int ModelAction::getSize() const {
142         return size;
143 }
144
145 void ModelAction::copy_from_new(ModelAction *newaction)
146 {
147         seq_number = newaction->seq_number;
148 }
149
150 void ModelAction::set_seq_number(modelclock_t num)
151 {
152         /* ATOMIC_UNINIT actions should never have non-zero clock */
153         ASSERT(!is_uninitialized());
154         ASSERT(seq_number == ACTION_INITIAL_CLOCK);
155         seq_number = num;
156 }
157
158 bool ModelAction::is_thread_start() const
159 {
160         return type == THREAD_START;
161 }
162
163 bool ModelAction::is_thread_join() const
164 {
165         return type == THREAD_JOIN || type == PTHREAD_JOIN;
166 }
167
168 bool ModelAction::is_mutex_op() const
169 {
170         return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK || type == ATOMIC_WAIT || type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
171 }
172
173 bool ModelAction::is_lock() const
174 {
175         return type == ATOMIC_LOCK;
176 }
177
178 bool ModelAction::is_wait() const {
179         return type == ATOMIC_WAIT;
180 }
181
182 bool ModelAction::is_notify() const {
183         return type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
184 }
185
186 bool ModelAction::is_notify_one() const {
187         return type == ATOMIC_NOTIFY_ONE;
188 }
189
190 bool ModelAction::is_unlock() const
191 {
192         return type == ATOMIC_UNLOCK;
193 }
194
195 bool ModelAction::is_trylock() const
196 {
197         return type == ATOMIC_TRYLOCK;
198 }
199
200 bool ModelAction::is_success_lock() const
201 {
202         return type == ATOMIC_LOCK || (type == ATOMIC_TRYLOCK && value == VALUE_TRYSUCCESS);
203 }
204
205 bool ModelAction::is_failed_trylock() const
206 {
207         return (type == ATOMIC_TRYLOCK && value == VALUE_TRYFAILED);
208 }
209
210 /** @return True if this operation is performed on a C/C++ atomic variable */
211 bool ModelAction::is_atomic_var() const
212 {
213         return is_read() || could_be_write();
214 }
215
216 bool ModelAction::is_uninitialized() const
217 {
218         return type == ATOMIC_UNINIT;
219 }
220
221 bool ModelAction::is_read() const
222 {
223         return type == ATOMIC_READ || type == ATOMIC_RMWR || type == ATOMIC_RMWRCAS || type == ATOMIC_RMW;
224 }
225
226 bool ModelAction::is_write() const
227 {
228         return type == ATOMIC_WRITE || type == ATOMIC_RMW || type == ATOMIC_INIT || type == ATOMIC_UNINIT;
229 }
230
231 bool ModelAction::could_be_write() const
232 {
233         return is_write() || is_rmwr();
234 }
235
236 bool ModelAction::is_yield() const
237 {
238         return type == THREAD_YIELD;
239 }
240
241 bool ModelAction::is_rmwr() const
242 {
243         return type == ATOMIC_RMWR || type == ATOMIC_RMWRCAS;
244 }
245
246 bool ModelAction::is_rmwrcas() const
247 {
248         return type == ATOMIC_RMWRCAS;
249 }
250
251 bool ModelAction::is_rmw() const
252 {
253         return type == ATOMIC_RMW;
254 }
255
256 bool ModelAction::is_rmwc() const
257 {
258         return type == ATOMIC_RMWC;
259 }
260
261 bool ModelAction::is_fence() const
262 {
263         return type == ATOMIC_FENCE;
264 }
265
266 bool ModelAction::is_initialization() const
267 {
268         return type == ATOMIC_INIT;
269 }
270
271 bool ModelAction::is_annotation() const
272 {
273         return type == ATOMIC_ANNOTATION;
274 }
275
276 bool ModelAction::is_relaxed() const
277 {
278         return order == std::memory_order_relaxed;
279 }
280
281 bool ModelAction::is_acquire() const
282 {
283         switch (order) {
284         case std::memory_order_acquire:
285         case std::memory_order_acq_rel:
286         case std::memory_order_seq_cst:
287                 return true;
288         default:
289                 return false;
290         }
291 }
292
293 bool ModelAction::is_release() const
294 {
295         switch (order) {
296         case std::memory_order_release:
297         case std::memory_order_acq_rel:
298         case std::memory_order_seq_cst:
299                 return true;
300         default:
301                 return false;
302         }
303 }
304
305 bool ModelAction::is_seqcst() const
306 {
307         return order == std::memory_order_seq_cst;
308 }
309
310 bool ModelAction::same_var(const ModelAction *act) const
311 {
312         if (act->is_wait() || is_wait()) {
313                 if (act->is_wait() && is_wait()) {
314                         if (((void *)value) == ((void *)act->value))
315                                 return true;
316                 } else if (is_wait()) {
317                         if (((void *)value) == act->location)
318                                 return true;
319                 } else if (act->is_wait()) {
320                         if (location == ((void *)act->value))
321                                 return true;
322                 }
323         }
324
325         return location == act->location;
326 }
327
328 bool ModelAction::same_thread(const ModelAction *act) const
329 {
330         return tid == act->tid;
331 }
332
333 void ModelAction::copy_typeandorder(ModelAction * act)
334 {
335         this->type = act->type;
336         this->order = act->order;
337 }
338
339 /**
340  * Get the Thread which is the operand of this action. This is only valid for
341  * THREAD_* operations (currently only for THREAD_CREATE and THREAD_JOIN). Note
342  * that this provides a central place for determining the conventions of Thread
343  * storage in ModelAction, where we generally aren't very type-safe (e.g., we
344  * store object references in a (void *) address.
345  *
346  * For THREAD_CREATE, this yields the Thread which is created.
347  * For THREAD_JOIN, this yields the Thread we are joining with.
348  *
349  * @return The Thread which this action acts on, if exists; otherwise NULL
350  */
351 Thread * ModelAction::get_thread_operand() const
352 {
353         if (type == THREAD_CREATE) {
354                 /* thread_operand is set in execution.cc */
355                 return thread_operand;
356         } else if (type == PTHREAD_CREATE) {
357                 return thread_operand;
358         } else if (type == THREAD_JOIN) {
359                 /* THREAD_JOIN uses (Thread *) for location */
360                 return (Thread *)get_location();
361         } else if (type == PTHREAD_JOIN) {
362                 // return NULL;
363                 // thread_operand is stored in execution::pthread_map;
364                 return (Thread *)get_location();
365         } else
366                 return NULL;
367 }
368
369 /**
370  * @brief Convert the read portion of an RMW
371  *
372  * Changes an existing read part of an RMW action into either:
373  *  -# a full RMW action in case of the completed write or
374  *  -# a READ action in case a failed action.
375  *
376  * @todo  If the memory_order changes, we may potentially need to update our
377  * clock vector.
378  *
379  * @param act The second half of the RMW (either RMWC or RMW)
380  */
381 void ModelAction::process_rmw(ModelAction *act)
382 {
383         this->order = act->order;
384         if (act->is_rmwc())
385                 this->type = ATOMIC_READ;
386         else if (act->is_rmw()) {
387                 this->type = ATOMIC_RMW;
388                 this->value = act->value;
389         }
390 }
391
392 /**
393  * @brief Check if this action should be backtracked with another, due to
394  * potential synchronization
395  *
396  * The is_synchronizing method should only explore interleavings if:
397  *  -# the operations are seq_cst and don't commute or
398  *  -# the reordering may establish or break a synchronization relation.
399  *
400  * Other memory operations will be dealt with by using the reads_from relation.
401  *
402  * @param act The action to consider exploring a reordering
403  * @return True, if we have to explore a reordering; otherwise false
404  */
405 bool ModelAction::could_synchronize_with(const ModelAction *act) const
406 {
407         // Same thread can't be reordered
408         if (same_thread(act))
409                 return false;
410
411         // Different locations commute
412         if (!same_var(act) && !is_fence() && !act->is_fence())
413                 return false;
414
415         // Explore interleavings of seqcst writes/fences to guarantee total
416         // order of seq_cst operations that don't commute
417         if ((could_be_write() || act->could_be_write() || is_fence() || act->is_fence()) && is_seqcst() && act->is_seqcst())
418                 return true;
419
420         // Explore synchronizing read/write pairs
421         if (is_acquire() && act->is_release() && is_read() && act->could_be_write())
422                 return true;
423
424         // lock just released...we can grab lock
425         if ((is_lock() || is_trylock()) && (act->is_unlock() || act->is_wait()))
426                 return true;
427
428         // lock just acquired...we can fail to grab lock
429         if (is_trylock() && act->is_success_lock())
430                 return true;
431
432         // other thread stalling on lock...we can release lock
433         if (is_unlock() && (act->is_trylock() || act->is_lock()))
434                 return true;
435
436         if (is_trylock() && (act->is_unlock() || act->is_wait()))
437                 return true;
438
439         if (is_notify() && act->is_wait())
440                 return true;
441
442         if (is_wait() && act->is_notify())
443                 return true;
444
445         // Otherwise handle by reads_from relation
446         return false;
447 }
448
449 bool ModelAction::is_conflicting_lock(const ModelAction *act) const
450 {
451         // Must be different threads to reorder
452         if (same_thread(act))
453                 return false;
454
455         // Try to reorder a lock past a successful lock
456         if (act->is_success_lock())
457                 return true;
458
459         // Try to push a successful trylock past an unlock
460         if (act->is_unlock() && is_trylock() && value == VALUE_TRYSUCCESS)
461                 return true;
462
463         // Try to push a successful trylock past a wait
464         if (act->is_wait() && is_trylock() && value == VALUE_TRYSUCCESS)
465                 return true;
466
467         return false;
468 }
469
470 /**
471  * Create a new clock vector for this action. Note that this function allows a
472  * user to clobber (and leak) a ModelAction's existing clock vector. A user
473  * should ensure that the vector has already either been rolled back
474  * (effectively "freed") or freed.
475  *
476  * @param parent A ModelAction from which to inherit a ClockVector
477  */
478 void ModelAction::create_cv(const ModelAction *parent)
479 {
480         if (parent)
481                 cv = new ClockVector(parent->cv, this);
482         else
483                 cv = new ClockVector(NULL, this);
484 }
485
486 void ModelAction::set_try_lock(bool obtainedlock)
487 {
488         value = obtainedlock ? VALUE_TRYSUCCESS : VALUE_TRYFAILED;
489 }
490
491 /**
492  * @brief Get the value read by this load
493  *
494  * We differentiate this function from ModelAction::get_write_value and
495  * ModelAction::get_value for the purpose of RMW's, which may have both a
496  * 'read' and a 'write' value.
497  *
498  * Note: 'this' must be a load.
499  *
500  * @return The value read by this load
501  */
502 uint64_t ModelAction::get_reads_from_value() const
503 {
504         ASSERT(is_read());
505         if (reads_from)
506                 return reads_from->get_write_value();
507
508         return VALUE_NONE;      // Only for new actions with no reads-from
509 }
510
511 /**
512  * @brief Get the value written by this store
513  *
514  * We differentiate this function from ModelAction::get_reads_from_value and
515  * ModelAction::get_value for the purpose of RMW's, which may have both a
516  * 'read' and a 'write' value.
517  *
518  * Note: 'this' must be a store.
519  *
520  * @return The value written by this store
521  */
522 uint64_t ModelAction::get_write_value() const
523 {
524         ASSERT(is_write());
525         return value;
526 }
527
528 /**
529  * @brief Get the value returned by this action
530  *
531  * For atomic reads (including RMW), an operation returns the value it read.
532  * For atomic writes, an operation returns the value it wrote. For other
533  * operations, the return value varies (sometimes is a "don't care"), but the
534  * value is simply stored in the "value" field.
535  *
536  * @return This action's return value
537  */
538 uint64_t ModelAction::get_return_value() const
539 {
540         if (is_read())
541                 return get_reads_from_value();
542         else if (is_write())
543                 return get_write_value();
544         else
545                 return value;
546 }
547
548 /** @return The Node associated with this ModelAction */
549 Node * ModelAction::get_node() const
550 {
551         /* UNINIT actions do not have a Node */
552         ASSERT(!is_uninitialized());
553         return node;
554 }
555
556 /**
557  * Update the model action's read_from action
558  * @param act The action to read from; should be a write
559  */
560 void ModelAction::set_read_from(const ModelAction *act)
561 {
562         ASSERT(act);
563
564         reads_from = act;
565
566         if (act->is_uninitialized()) {  // WL
567                 uint64_t val = *((uint64_t *) location);
568                 ModelAction * act_initialized = (ModelAction *)act;
569                 act_initialized->set_value(val);
570                 reads_from = (const ModelAction *)act_initialized;
571
572 // disabled by WL, because LLVM IR is unable to detect atomic init
573 /*              model->assert_bug("May read from uninitialized atomic:\n"
574                                 "    action %d, thread %d, location %p (%s, %s)",
575                                 seq_number, id_to_int(tid), location,
576                                 get_type_str(), get_mo_str());
577  */
578         }
579 }
580
581 /**
582  * Synchronize the current thread with the thread corresponding to the
583  * ModelAction parameter.
584  * @param act The ModelAction to synchronize with
585  * @return True if this is a valid synchronization; false otherwise
586  */
587 bool ModelAction::synchronize_with(const ModelAction *act)
588 {
589         if (*this < *act)
590                 return false;
591         cv->merge(act->cv);
592         return true;
593 }
594
595 bool ModelAction::has_synchronized_with(const ModelAction *act) const
596 {
597         return cv->synchronized_since(act);
598 }
599
600 /**
601  * Check whether 'this' happens before act, according to the memory-model's
602  * happens before relation. This is checked via the ClockVector constructs.
603  * @return true if this action's thread has synchronized with act's thread
604  * since the execution of act, false otherwise.
605  */
606 bool ModelAction::happens_before(const ModelAction *act) const
607 {
608         return act->cv->synchronized_since(this);
609 }
610
611 const char * ModelAction::get_type_str() const
612 {
613         switch (this->type) {
614         case THREAD_CREATE: return "thread create";
615         case THREAD_START: return "thread start";
616         case THREAD_YIELD: return "thread yield";
617         case THREAD_JOIN: return "thread join";
618         case THREAD_FINISH: return "thread finish";
619
620         case PTHREAD_CREATE: return "pthread create";
621         case PTHREAD_JOIN: return "pthread join";
622
623         case ATOMIC_UNINIT: return "uninitialized";
624         case ATOMIC_READ: return "atomic read";
625         case ATOMIC_WRITE: return "atomic write";
626         case ATOMIC_RMW: return "atomic rmw";
627         case ATOMIC_FENCE: return "fence";
628         case ATOMIC_RMWR: return "atomic rmwr";
629         case ATOMIC_RMWRCAS: return "atomic rmwrcas";
630         case ATOMIC_RMWC: return "atomic rmwc";
631         case ATOMIC_INIT: return "init atomic";
632         case ATOMIC_LOCK: return "lock";
633         case ATOMIC_UNLOCK: return "unlock";
634         case ATOMIC_TRYLOCK: return "trylock";
635         case ATOMIC_WAIT: return "wait";
636         case ATOMIC_NOTIFY_ONE: return "notify one";
637         case ATOMIC_NOTIFY_ALL: return "notify all";
638         case ATOMIC_ANNOTATION: return "annotation";
639         default: return "unknown type";
640         };
641 }
642
643 const char * ModelAction::get_mo_str() const
644 {
645         switch (this->order) {
646         case std::memory_order_relaxed: return "relaxed";
647         case std::memory_order_acquire: return "acquire";
648         case std::memory_order_release: return "release";
649         case std::memory_order_acq_rel: return "acq_rel";
650         case std::memory_order_seq_cst: return "seq_cst";
651         default: return "unknown";
652         }
653 }
654
655 /** @brief Print nicely-formatted info about this ModelAction */
656 void ModelAction::print() const
657 {
658         const char *type_str = get_type_str(), *mo_str = get_mo_str();
659
660         model_print("%-4d %-2d   %-14s  %7s  %14p   %-#18" PRIx64,
661                                                         seq_number, id_to_int(tid), type_str, mo_str, location, get_return_value());
662         if (is_read()) {
663                 if (reads_from)
664                         model_print("  %-3d", reads_from->get_seq_number());
665                 else
666                         model_print("  ?  ");
667         }
668         if (cv) {
669                 if (is_read())
670                         model_print(" ");
671                 else
672                         model_print("      ");
673                 cv->print();
674         } else
675                 model_print("\n");
676 }
677
678 /** @brief Get a (likely) unique hash for this ModelAction */
679 unsigned int ModelAction::hash() const
680 {
681         unsigned int hash = (unsigned int)this->type;
682         hash ^= ((unsigned int)this->order) << 3;
683         hash ^= seq_number << 5;
684         hash ^= id_to_int(tid) << 6;
685
686         if (is_read()) {
687                 if (reads_from)
688                         hash ^= reads_from->get_seq_number();
689                 hash ^= get_reads_from_value();
690         }
691         return hash;
692 }
693
694 /**
695  * Only valid for LOCK, TRY_LOCK, UNLOCK, and WAIT operations.
696  * @return The mutex operated on by this action, if any; otherwise NULL
697  */
698 cdsc::mutex * ModelAction::get_mutex() const
699 {
700         if (is_trylock() || is_lock() || is_unlock())
701                 return (cdsc::mutex *)get_location();
702         else if (is_wait())
703                 return (cdsc::mutex *)get_value();
704         else
705                 return NULL;
706 }