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