Maintain list of writes
[c11tester.git] / execution.cc
1 #include <stdio.h>
2 #include <algorithm>
3 #include <new>
4 #include <stdarg.h>
5
6 #include "model.h"
7 #include "execution.h"
8 #include "action.h"
9 #include "schedule.h"
10 #include "common.h"
11 #include "clockvector.h"
12 #include "cyclegraph.h"
13 #include "datarace.h"
14 #include "threads-model.h"
15 #include "bugmessage.h"
16 #include "fuzzer.h"
17
18 #define INITIAL_THREAD_ID       0
19
20 /**
21  * Structure for holding small ModelChecker members that should be snapshotted
22  */
23 struct model_snapshot_members {
24         model_snapshot_members() :
25                 /* First thread created will have id INITIAL_THREAD_ID */
26                 next_thread_id(INITIAL_THREAD_ID),
27                 used_sequence_numbers(0),
28                 bugs(),
29                 bad_synchronization(false),
30                 asserted(false)
31         { }
32
33         ~model_snapshot_members() {
34                 for (unsigned int i = 0;i < bugs.size();i++)
35                         delete bugs[i];
36                 bugs.clear();
37         }
38
39         unsigned int next_thread_id;
40         modelclock_t used_sequence_numbers;
41         SnapVector<bug_message *> bugs;
42         /** @brief Incorrectly-ordered synchronization was made */
43         bool bad_synchronization;
44         bool asserted;
45
46         SNAPSHOTALLOC
47 };
48
49 /** @brief Constructor */
50 ModelExecution::ModelExecution(ModelChecker *m, Scheduler *scheduler) :
51         model(m),
52         params(NULL),
53         scheduler(scheduler),
54         action_trace(),
55         thread_map(2),  /* We'll always need at least 2 threads */
56         pthread_map(0),
57         pthread_counter(1),
58         obj_map(),
59         condvar_waiters_map(),
60         obj_thrd_map(),
61         mutex_map(),
62         thrd_last_action(1),
63         thrd_last_fence_release(),
64         priv(new struct model_snapshot_members ()),
65                          mo_graph(new CycleGraph()),
66         fuzzer(new Fuzzer())
67 {
68         /* Initialize a model-checker thread, for special ModelActions */
69         model_thread = new Thread(get_next_id());
70         add_thread(model_thread);
71         scheduler->register_engine(this);
72 }
73
74 /** @brief Destructor */
75 ModelExecution::~ModelExecution()
76 {
77         for (unsigned int i = 0;i < get_num_threads();i++)
78                 delete get_thread(int_to_id(i));
79
80         delete mo_graph;
81         delete priv;
82 }
83
84 int ModelExecution::get_execution_number() const
85 {
86         return model->get_execution_number();
87 }
88
89 static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 4> * hash, void * ptr)
90 {
91         action_list_t *tmp = hash->get(ptr);
92         if (tmp == NULL) {
93                 tmp = new action_list_t();
94                 hash->put(ptr, tmp);
95         }
96         return tmp;
97 }
98
99 static SnapVector<action_list_t> * get_safe_ptr_vect_action(HashTable<const void *, SnapVector<action_list_t> *, uintptr_t, 4> * hash, void * ptr)
100 {
101         SnapVector<action_list_t> *tmp = hash->get(ptr);
102         if (tmp == NULL) {
103                 tmp = new SnapVector<action_list_t>();
104                 hash->put(ptr, tmp);
105         }
106         return tmp;
107 }
108
109 /** @return a thread ID for a new Thread */
110 thread_id_t ModelExecution::get_next_id()
111 {
112         return priv->next_thread_id++;
113 }
114
115 /** @return the number of user threads created during this execution */
116 unsigned int ModelExecution::get_num_threads() const
117 {
118         return priv->next_thread_id;
119 }
120
121 /** @return a sequence number for a new ModelAction */
122 modelclock_t ModelExecution::get_next_seq_num()
123 {
124         return ++priv->used_sequence_numbers;
125 }
126
127 /**
128  * @brief Should the current action wake up a given thread?
129  *
130  * @param curr The current action
131  * @param thread The thread that we might wake up
132  * @return True, if we should wake up the sleeping thread; false otherwise
133  */
134 bool ModelExecution::should_wake_up(const ModelAction *curr, const Thread *thread) const
135 {
136         const ModelAction *asleep = thread->get_pending();
137         /* Don't allow partial RMW to wake anyone up */
138         if (curr->is_rmwr())
139                 return false;
140         /* Synchronizing actions may have been backtracked */
141         if (asleep->could_synchronize_with(curr))
142                 return true;
143         /* All acquire/release fences and fence-acquire/store-release */
144         if (asleep->is_fence() && asleep->is_acquire() && curr->is_release())
145                 return true;
146         /* Fence-release + store can awake load-acquire on the same location */
147         if (asleep->is_read() && asleep->is_acquire() && curr->same_var(asleep) && curr->is_write()) {
148                 ModelAction *fence_release = get_last_fence_release(curr->get_tid());
149                 if (fence_release && *(get_last_action(thread->get_id())) < *fence_release)
150                         return true;
151         }
152         return false;
153 }
154
155 void ModelExecution::wake_up_sleeping_actions(ModelAction *curr)
156 {
157         for (unsigned int i = 0;i < get_num_threads();i++) {
158                 Thread *thr = get_thread(int_to_id(i));
159                 if (scheduler->is_sleep_set(thr)) {
160                         if (should_wake_up(curr, thr))
161                                 /* Remove this thread from sleep set */
162                                 scheduler->remove_sleep(thr);
163                 }
164         }
165 }
166
167 /** @brief Alert the model-checker that an incorrectly-ordered
168  * synchronization was made */
169 void ModelExecution::set_bad_synchronization()
170 {
171         priv->bad_synchronization = true;
172 }
173
174 bool ModelExecution::assert_bug(const char *msg)
175 {
176         priv->bugs.push_back(new bug_message(msg));
177
178         if (isfeasibleprefix()) {
179                 set_assert();
180                 return true;
181         }
182         return false;
183 }
184
185 /** @return True, if any bugs have been reported for this execution */
186 bool ModelExecution::have_bug_reports() const
187 {
188         return priv->bugs.size() != 0;
189 }
190
191 SnapVector<bug_message *> * ModelExecution::get_bugs() const
192 {
193         return &priv->bugs;
194 }
195
196 /**
197  * Check whether the current trace has triggered an assertion which should halt
198  * its execution.
199  *
200  * @return True, if the execution should be aborted; false otherwise
201  */
202 bool ModelExecution::has_asserted() const
203 {
204         return priv->asserted;
205 }
206
207 /**
208  * Trigger a trace assertion which should cause this execution to be halted.
209  * This can be due to a detected bug or due to an infeasibility that should
210  * halt ASAP.
211  */
212 void ModelExecution::set_assert()
213 {
214         priv->asserted = true;
215 }
216
217 /**
218  * Check if we are in a deadlock. Should only be called at the end of an
219  * execution, although it should not give false positives in the middle of an
220  * execution (there should be some ENABLED thread).
221  *
222  * @return True if program is in a deadlock; false otherwise
223  */
224 bool ModelExecution::is_deadlocked() const
225 {
226         bool blocking_threads = false;
227         for (unsigned int i = 0;i < get_num_threads();i++) {
228                 thread_id_t tid = int_to_id(i);
229                 if (is_enabled(tid))
230                         return false;
231                 Thread *t = get_thread(tid);
232                 if (!t->is_model_thread() && t->get_pending())
233                         blocking_threads = true;
234         }
235         return blocking_threads;
236 }
237
238 /**
239  * Check if this is a complete execution. That is, have all thread completed
240  * execution (rather than exiting because sleep sets have forced a redundant
241  * execution).
242  *
243  * @return True if the execution is complete.
244  */
245 bool ModelExecution::is_complete_execution() const
246 {
247         for (unsigned int i = 0;i < get_num_threads();i++)
248                 if (is_enabled(int_to_id(i)))
249                         return false;
250         return true;
251 }
252
253
254 /**
255  * Processes a read model action.
256  * @param curr is the read model action to process.
257  * @param rf_set is the set of model actions we can possibly read from
258  * @return True if processing this read updates the mo_graph.
259  */
260 void ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> * rf_set)
261 {
262         SnapVector<const ModelAction *> * priorset = new SnapVector<const ModelAction *>();
263         while(true) {
264
265                 int index = fuzzer->selectWrite(curr, rf_set);
266                 ModelAction *rf = (*rf_set)[index];
267
268
269                 ASSERT(rf);
270                 bool canprune = false;
271                 if (r_modification_order(curr, rf, priorset, &canprune)) {
272                         for(unsigned int i=0;i<priorset->size();i++) {
273                                 mo_graph->addEdge((*priorset)[i], rf);
274                         }
275                         read_from(curr, rf);
276                         get_thread(curr)->set_return_value(curr->get_return_value());
277                         delete priorset;
278                         if (canprune && curr->get_type() == ATOMIC_READ) {
279                                 int tid = id_to_int(curr->get_tid());
280                                 (*obj_thrd_map.get(curr->get_location()))[tid].pop_back();
281                         }
282                         return;
283                 }
284                 priorset->clear();
285                 (*rf_set)[index] = rf_set->back();
286                 rf_set->pop_back();
287         }
288 }
289
290 /**
291  * Processes a lock, trylock, or unlock model action.  @param curr is
292  * the read model action to process.
293  *
294  * The try lock operation checks whether the lock is taken.  If not,
295  * it falls to the normal lock operation case.  If so, it returns
296  * fail.
297  *
298  * The lock operation has already been checked that it is enabled, so
299  * it just grabs the lock and synchronizes with the previous unlock.
300  *
301  * The unlock operation has to re-enable all of the threads that are
302  * waiting on the lock.
303  *
304  * @return True if synchronization was updated; false otherwise
305  */
306 bool ModelExecution::process_mutex(ModelAction *curr)
307 {
308         cdsc::mutex *mutex = curr->get_mutex();
309         struct cdsc::mutex_state *state = NULL;
310
311         if (mutex)
312                 state = mutex->get_state();
313
314         switch (curr->get_type()) {
315         case ATOMIC_TRYLOCK: {
316                 bool success = !state->locked;
317                 curr->set_try_lock(success);
318                 if (!success) {
319                         get_thread(curr)->set_return_value(0);
320                         break;
321                 }
322                 get_thread(curr)->set_return_value(1);
323         }
324         //otherwise fall into the lock case
325         case ATOMIC_LOCK: {
326                 if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock)
327                         assert_bug("Lock access before initialization");
328                 state->locked = get_thread(curr);
329                 ModelAction *unlock = get_last_unlock(curr);
330                 //synchronize with the previous unlock statement
331                 if (unlock != NULL) {
332                         synchronize(unlock, curr);
333                         return true;
334                 }
335                 break;
336         }
337         case ATOMIC_WAIT:
338         case ATOMIC_UNLOCK: {
339                 //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME AS NORMAL WAITS...THINK ABOUT PROBABILITIES THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS MUST EVENMTUALLY RELEASE...
340
341                 /* wake up the other threads */
342                 for (unsigned int i = 0;i < get_num_threads();i++) {
343                         Thread *t = get_thread(int_to_id(i));
344                         Thread *curr_thrd = get_thread(curr);
345                         if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
346                                 scheduler->wake(t);
347                 }
348
349                 /* unlock the lock - after checking who was waiting on it */
350                 state->locked = NULL;
351
352                 if (!curr->is_wait())
353                         break;/* The rest is only for ATOMIC_WAIT */
354
355                 break;
356         }
357         case ATOMIC_NOTIFY_ALL: {
358                 action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
359                 //activate all the waiting threads
360                 for (action_list_t::iterator rit = waiters->begin();rit != waiters->end();rit++) {
361                         scheduler->wake(get_thread(*rit));
362                 }
363                 waiters->clear();
364                 break;
365         }
366         case ATOMIC_NOTIFY_ONE: {
367                 action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
368                 if (waiters->size() != 0) {
369                         Thread * thread = fuzzer->selectNotify(waiters);
370                         scheduler->wake(thread);
371                 }
372                 break;
373         }
374
375         default:
376                 ASSERT(0);
377         }
378         return false;
379 }
380
381 /**
382  * Process a write ModelAction
383  * @param curr The ModelAction to process
384  * @return True if the mo_graph was updated or promises were resolved
385  */
386 void ModelExecution::process_write(ModelAction *curr)
387 {
388
389         w_modification_order(curr);
390
391
392         get_thread(curr)->set_return_value(VALUE_NONE);
393 }
394
395 /**
396  * Process a fence ModelAction
397  * @param curr The ModelAction to process
398  * @return True if synchronization was updated
399  */
400 bool ModelExecution::process_fence(ModelAction *curr)
401 {
402         /*
403          * fence-relaxed: no-op
404          * fence-release: only log the occurence (not in this function), for
405          *   use in later synchronization
406          * fence-acquire (this function): search for hypothetical release
407          *   sequences
408          * fence-seq-cst: MO constraints formed in {r,w}_modification_order
409          */
410         bool updated = false;
411         if (curr->is_acquire()) {
412                 action_list_t *list = &action_trace;
413                 action_list_t::reverse_iterator rit;
414                 /* Find X : is_read(X) && X --sb-> curr */
415                 for (rit = list->rbegin();rit != list->rend();rit++) {
416                         ModelAction *act = *rit;
417                         if (act == curr)
418                                 continue;
419                         if (act->get_tid() != curr->get_tid())
420                                 continue;
421                         /* Stop at the beginning of the thread */
422                         if (act->is_thread_start())
423                                 break;
424                         /* Stop once we reach a prior fence-acquire */
425                         if (act->is_fence() && act->is_acquire())
426                                 break;
427                         if (!act->is_read())
428                                 continue;
429                         /* read-acquire will find its own release sequences */
430                         if (act->is_acquire())
431                                 continue;
432
433                         /* Establish hypothetical release sequences */
434                         ClockVector *cv = get_hb_from_write(act);
435                         if (curr->get_cv()->merge(cv))
436                                 updated = true;
437                 }
438         }
439         return updated;
440 }
441
442 /**
443  * @brief Process the current action for thread-related activity
444  *
445  * Performs current-action processing for a THREAD_* ModelAction. Proccesses
446  * may include setting Thread status, completing THREAD_FINISH/THREAD_JOIN
447  * synchronization, etc.  This function is a no-op for non-THREAD actions
448  * (e.g., ATOMIC_{READ,WRITE,RMW,LOCK}, etc.)
449  *
450  * @param curr The current action
451  * @return True if synchronization was updated or a thread completed
452  */
453 bool ModelExecution::process_thread_action(ModelAction *curr)
454 {
455         bool updated = false;
456
457         switch (curr->get_type()) {
458         case THREAD_CREATE: {
459                 thrd_t *thrd = (thrd_t *)curr->get_location();
460                 struct thread_params *params = (struct thread_params *)curr->get_value();
461                 Thread *th = new Thread(get_next_id(), thrd, params->func, params->arg, get_thread(curr));
462                 curr->set_thread_operand(th);
463                 add_thread(th);
464                 th->set_creation(curr);
465                 break;
466         }
467         case PTHREAD_CREATE: {
468                 (*(uint32_t *)curr->get_location()) = pthread_counter++;
469
470                 struct pthread_params *params = (struct pthread_params *)curr->get_value();
471                 Thread *th = new Thread(get_next_id(), NULL, params->func, params->arg, get_thread(curr));
472                 curr->set_thread_operand(th);
473                 add_thread(th);
474                 th->set_creation(curr);
475
476                 if ( pthread_map.size() < pthread_counter )
477                         pthread_map.resize( pthread_counter );
478                 pthread_map[ pthread_counter-1 ] = th;
479
480                 break;
481         }
482         case THREAD_JOIN: {
483                 Thread *blocking = curr->get_thread_operand();
484                 ModelAction *act = get_last_action(blocking->get_id());
485                 synchronize(act, curr);
486                 updated = true; /* trigger rel-seq checks */
487                 break;
488         }
489         case PTHREAD_JOIN: {
490                 Thread *blocking = curr->get_thread_operand();
491                 ModelAction *act = get_last_action(blocking->get_id());
492                 synchronize(act, curr);
493                 updated = true; /* trigger rel-seq checks */
494                 break;  // WL: to be add (modified)
495         }
496
497         case THREAD_FINISH: {
498                 Thread *th = get_thread(curr);
499                 /* Wake up any joining threads */
500                 for (unsigned int i = 0;i < get_num_threads();i++) {
501                         Thread *waiting = get_thread(int_to_id(i));
502                         if (waiting->waiting_on() == th &&
503                                         waiting->get_pending()->is_thread_join())
504                                 scheduler->wake(waiting);
505                 }
506                 th->complete();
507                 updated = true; /* trigger rel-seq checks */
508                 break;
509         }
510         case THREAD_START: {
511                 break;
512         }
513         default:
514                 break;
515         }
516
517         return updated;
518 }
519
520 /**
521  * Initialize the current action by performing one or more of the following
522  * actions, as appropriate: merging RMWR and RMWC/RMW actions,
523  * manipulating backtracking sets, allocating and
524  * initializing clock vectors, and computing the promises to fulfill.
525  *
526  * @param curr The current action, as passed from the user context; may be
527  * freed/invalidated after the execution of this function, with a different
528  * action "returned" its place (pass-by-reference)
529  * @return True if curr is a newly-explored action; false otherwise
530  */
531 bool ModelExecution::initialize_curr_action(ModelAction **curr)
532 {
533         if ((*curr)->is_rmwc() || (*curr)->is_rmw()) {
534                 ModelAction *newcurr = process_rmw(*curr);
535                 delete *curr;
536
537                 *curr = newcurr;
538                 return false;
539         } else {
540                 ModelAction *newcurr = *curr;
541
542                 newcurr->set_seq_number(get_next_seq_num());
543                 /* Always compute new clock vector */
544                 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
545
546                 /* Assign most recent release fence */
547                 newcurr->set_last_fence_release(get_last_fence_release(newcurr->get_tid()));
548
549                 return true;    /* This was a new ModelAction */
550         }
551 }
552
553 /**
554  * @brief Establish reads-from relation between two actions
555  *
556  * Perform basic operations involved with establishing a concrete rf relation,
557  * including setting the ModelAction data and checking for release sequences.
558  *
559  * @param act The action that is reading (must be a read)
560  * @param rf The action from which we are reading (must be a write)
561  *
562  * @return True if this read established synchronization
563  */
564
565 void ModelExecution::read_from(ModelAction *act, ModelAction *rf)
566 {
567         ASSERT(rf);
568         ASSERT(rf->is_write());
569
570         act->set_read_from(rf);
571         if (act->is_acquire()) {
572                 ClockVector *cv = get_hb_from_write(rf);
573                 if (cv == NULL)
574                         return;
575                 act->get_cv()->merge(cv);
576         }
577 }
578
579 /**
580  * @brief Synchronizes two actions
581  *
582  * When A synchronizes with B (or A --sw-> B), B inherits A's clock vector.
583  * This function performs the synchronization as well as providing other hooks
584  * for other checks along with synchronization.
585  *
586  * @param first The left-hand side of the synchronizes-with relation
587  * @param second The right-hand side of the synchronizes-with relation
588  * @return True if the synchronization was successful (i.e., was consistent
589  * with the execution order); false otherwise
590  */
591 bool ModelExecution::synchronize(const ModelAction *first, ModelAction *second)
592 {
593         if (*second < *first) {
594                 set_bad_synchronization();
595                 return false;
596         }
597         return second->synchronize_with(first);
598 }
599
600 /**
601  * @brief Check whether a model action is enabled.
602  *
603  * Checks whether an operation would be successful (i.e., is a lock already
604  * locked, or is the joined thread already complete).
605  *
606  * For yield-blocking, yields are never enabled.
607  *
608  * @param curr is the ModelAction to check whether it is enabled.
609  * @return a bool that indicates whether the action is enabled.
610  */
611 bool ModelExecution::check_action_enabled(ModelAction *curr) {
612         if (curr->is_lock()) {
613                 cdsc::mutex *lock = curr->get_mutex();
614                 struct cdsc::mutex_state *state = lock->get_state();
615                 if (state->locked)
616                         return false;
617         } else if (curr->is_thread_join()) {
618                 Thread *blocking = curr->get_thread_operand();
619                 if (!blocking->is_complete()) {
620                         return false;
621                 }
622         }
623
624         return true;
625 }
626
627 /**
628  * This is the heart of the model checker routine. It performs model-checking
629  * actions corresponding to a given "current action." Among other processes, it
630  * calculates reads-from relationships, updates synchronization clock vectors,
631  * forms a memory_order constraints graph, and handles replay/backtrack
632  * execution when running permutations of previously-observed executions.
633  *
634  * @param curr The current action to process
635  * @return The ModelAction that is actually executed; may be different than
636  * curr
637  */
638 ModelAction * ModelExecution::check_current_action(ModelAction *curr)
639 {
640         ASSERT(curr);
641         bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
642         bool newly_explored = initialize_curr_action(&curr);
643
644         DBG();
645
646         wake_up_sleeping_actions(curr);
647
648         /* Add the action to lists before any other model-checking tasks */
649         if (!second_part_of_rmw && curr->get_type() != NOOP)
650                 add_action_to_lists(curr);
651
652         if (curr->is_write())
653                 add_write_to_lists(curr);
654
655         SnapVector<ModelAction *> * rf_set = NULL;
656         /* Build may_read_from set for newly-created actions */
657         if (newly_explored && curr->is_read())
658                 rf_set = build_may_read_from(curr);
659
660         process_thread_action(curr);
661
662         if (curr->is_read() && !second_part_of_rmw) {
663                 process_read(curr, rf_set);
664                 delete rf_set;
665         } else {
666                 ASSERT(rf_set == NULL);
667         }
668
669         if (curr->is_write())
670                 process_write(curr);
671
672         if (curr->is_fence())
673                 process_fence(curr);
674
675         if (curr->is_mutex_op())
676                 process_mutex(curr);
677
678         return curr;
679 }
680
681 /**
682  * This is the strongest feasibility check available.
683  * @return whether the current trace (partial or complete) must be a prefix of
684  * a feasible trace.
685  */
686 bool ModelExecution::isfeasibleprefix() const
687 {
688         return !is_infeasible();
689 }
690
691 /**
692  * Print disagnostic information about an infeasible execution
693  * @param prefix A string to prefix the output with; if NULL, then a default
694  * message prefix will be provided
695  */
696 void ModelExecution::print_infeasibility(const char *prefix) const
697 {
698         char buf[100];
699         char *ptr = buf;
700         if (priv->bad_synchronization)
701                 ptr += sprintf(ptr, "[bad sw ordering]");
702         if (ptr != buf)
703                 model_print("%s: %s", prefix ? prefix : "Infeasible", buf);
704 }
705
706 /**
707  * Check if the current partial trace is infeasible. Does not check any
708  * end-of-execution flags, which might rule out the execution. Thus, this is
709  * useful only for ruling an execution as infeasible.
710  * @return whether the current partial trace is infeasible.
711  */
712 bool ModelExecution::is_infeasible() const
713 {
714         return priv->bad_synchronization;
715 }
716
717 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
718 ModelAction * ModelExecution::process_rmw(ModelAction *act) {
719         ModelAction *lastread = get_last_action(act->get_tid());
720         lastread->process_rmw(act);
721         if (act->is_rmw()) {
722                 mo_graph->addRMWEdge(lastread->get_reads_from(), lastread);
723         }
724         return lastread;
725 }
726
727 /**
728  * @brief Updates the mo_graph with the constraints imposed from the current
729  * read.
730  *
731  * Basic idea is the following: Go through each other thread and find
732  * the last action that happened before our read.  Two cases:
733  *
734  * -# The action is a write: that write must either occur before
735  * the write we read from or be the write we read from.
736  * -# The action is a read: the write that that action read from
737  * must occur before the write we read from or be the same write.
738  *
739  * @param curr The current action. Must be a read.
740  * @param rf The ModelAction or Promise that curr reads from. Must be a write.
741  * @return True if modification order edges were added; false otherwise
742  */
743
744 bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf, SnapVector<const ModelAction *> * priorset, bool * canprune)
745 {
746         SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
747         unsigned int i;
748         ASSERT(curr->is_read());
749
750         /* Last SC fence in the current thread */
751         ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
752
753         int tid = curr->get_tid();
754         ModelAction *prev_same_thread = NULL;
755         /* Iterate over all threads */
756         for (i = 0;i < thrd_lists->size();i++, tid = (((unsigned int)(tid+1)) == thrd_lists->size()) ? 0 : tid + 1) {
757                 /* Last SC fence in thread tid */
758                 ModelAction *last_sc_fence_thread_local = NULL;
759                 if (i != 0)
760                         last_sc_fence_thread_local = get_last_seq_cst_fence(int_to_id(tid), NULL);
761
762                 /* Last SC fence in thread tid, before last SC fence in current thread */
763                 ModelAction *last_sc_fence_thread_before = NULL;
764                 if (last_sc_fence_local)
765                         last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(tid), last_sc_fence_local);
766
767                 //Only need to iterate if either hb has changed for thread in question or SC fence after last operation...
768                 if (prev_same_thread != NULL &&
769                                 (prev_same_thread->get_cv()->getClock(tid) == curr->get_cv()->getClock(tid)) &&
770                                 (last_sc_fence_thread_local == NULL || *last_sc_fence_thread_local < *prev_same_thread)) {
771                         continue;
772                 }
773
774                 /* Iterate over actions in thread, starting from most recent */
775                 action_list_t *list = &(*thrd_lists)[tid];
776                 action_list_t::reverse_iterator rit;
777                 for (rit = list->rbegin();rit != list->rend();rit++) {
778                         ModelAction *act = *rit;
779
780                         /* Skip curr */
781                         if (act == curr)
782                                 continue;
783                         /* Don't want to add reflexive edges on 'rf' */
784                         if (act->equals(rf)) {
785                                 if (act->happens_before(curr))
786                                         break;
787                                 else
788                                         continue;
789                         }
790
791                         if (act->is_write()) {
792                                 /* C++, Section 29.3 statement 5 */
793                                 if (curr->is_seqcst() && last_sc_fence_thread_local &&
794                                                 *act < *last_sc_fence_thread_local) {
795                                         if (mo_graph->checkReachable(rf, act))
796                                                 return false;
797                                         priorset->push_back(act);
798                                         break;
799                                 }
800                                 /* C++, Section 29.3 statement 4 */
801                                 else if (act->is_seqcst() && last_sc_fence_local &&
802                                                                  *act < *last_sc_fence_local) {
803                                         if (mo_graph->checkReachable(rf, act))
804                                                 return false;
805                                         priorset->push_back(act);
806                                         break;
807                                 }
808                                 /* C++, Section 29.3 statement 6 */
809                                 else if (last_sc_fence_thread_before &&
810                                                                  *act < *last_sc_fence_thread_before) {
811                                         if (mo_graph->checkReachable(rf, act))
812                                                 return false;
813                                         priorset->push_back(act);
814                                         break;
815                                 }
816                         }
817
818                         /*
819                          * Include at most one act per-thread that "happens
820                          * before" curr
821                          */
822                         if (act->happens_before(curr)) {
823                                 if (i==0) {
824                                         if (last_sc_fence_local == NULL ||
825                                                         (*last_sc_fence_local < *prev_same_thread)) {
826                                                 prev_same_thread = act;
827                                         }
828                                 }
829                                 if (act->is_write()) {
830                                         if (mo_graph->checkReachable(rf, act))
831                                                 return false;
832                                         priorset->push_back(act);
833                                 } else {
834                                         const ModelAction *prevrf = act->get_reads_from();
835                                         if (!prevrf->equals(rf)) {
836                                                 if (mo_graph->checkReachable(rf, prevrf))
837                                                         return false;
838                                                 priorset->push_back(prevrf);
839                                         } else {
840                                                 if (act->get_tid() == curr->get_tid()) {
841                                                         //Can prune curr from obj list
842                                                         *canprune = true;
843                                                 }
844                                         }
845                                 }
846                                 break;
847                         }
848                 }
849         }
850         return true;
851 }
852
853 /**
854  * Updates the mo_graph with the constraints imposed from the current write.
855  *
856  * Basic idea is the following: Go through each other thread and find
857  * the lastest action that happened before our write.  Two cases:
858  *
859  * (1) The action is a write => that write must occur before
860  * the current write
861  *
862  * (2) The action is a read => the write that that action read from
863  * must occur before the current write.
864  *
865  * This method also handles two other issues:
866  *
867  * (I) Sequential Consistency: Making sure that if the current write is
868  * seq_cst, that it occurs after the previous seq_cst write.
869  *
870  * (II) Sending the write back to non-synchronizing reads.
871  *
872  * @param curr The current action. Must be a write.
873  * @param send_fv A vector for stashing reads to which we may pass our future
874  * value. If NULL, then don't record any future values.
875  * @return True if modification order edges were added; false otherwise
876  */
877 void ModelExecution::w_modification_order(ModelAction *curr)
878 {
879         SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
880         unsigned int i;
881         ASSERT(curr->is_write());
882
883         if (curr->is_seqcst()) {
884                 /* We have to at least see the last sequentially consistent write,
885                          so we are initialized. */
886                 ModelAction *last_seq_cst = get_last_seq_cst_write(curr);
887                 if (last_seq_cst != NULL) {
888                         mo_graph->addEdge(last_seq_cst, curr);
889                 }
890         }
891
892         /* Last SC fence in the current thread */
893         ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
894
895         /* Iterate over all threads */
896         for (i = 0;i < thrd_lists->size();i++) {
897                 /* Last SC fence in thread i, before last SC fence in current thread */
898                 ModelAction *last_sc_fence_thread_before = NULL;
899                 if (last_sc_fence_local && int_to_id((int)i) != curr->get_tid())
900                         last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(i), last_sc_fence_local);
901
902                 /* Iterate over actions in thread, starting from most recent */
903                 action_list_t *list = &(*thrd_lists)[i];
904                 action_list_t::reverse_iterator rit;
905                 bool force_edge = false;
906                 for (rit = list->rbegin();rit != list->rend();rit++) {
907                         ModelAction *act = *rit;
908                         if (act == curr) {
909                                 /*
910                                  * 1) If RMW and it actually read from something, then we
911                                  * already have all relevant edges, so just skip to next
912                                  * thread.
913                                  *
914                                  * 2) If RMW and it didn't read from anything, we should
915                                  * whatever edge we can get to speed up convergence.
916                                  *
917                                  * 3) If normal write, we need to look at earlier actions, so
918                                  * continue processing list.
919                                  */
920                                 force_edge = true;
921                                 if (curr->is_rmw()) {
922                                         if (curr->get_reads_from() != NULL)
923                                                 break;
924                                         else
925                                                 continue;
926                                 } else
927                                         continue;
928                         }
929
930                         /* C++, Section 29.3 statement 7 */
931                         if (last_sc_fence_thread_before && act->is_write() &&
932                                         *act < *last_sc_fence_thread_before) {
933                                 mo_graph->addEdge(act, curr, force_edge);
934                                 break;
935                         }
936
937                         /*
938                          * Include at most one act per-thread that "happens
939                          * before" curr
940                          */
941                         if (act->happens_before(curr)) {
942                                 /*
943                                  * Note: if act is RMW, just add edge:
944                                  *   act --mo--> curr
945                                  * The following edge should be handled elsewhere:
946                                  *   readfrom(act) --mo--> act
947                                  */
948                                 if (act->is_write())
949                                         mo_graph->addEdge(act, curr, force_edge);
950                                 else if (act->is_read()) {
951                                         //if previous read accessed a null, just keep going
952                                         mo_graph->addEdge(act->get_reads_from(), curr, force_edge);
953                                 }
954                                 break;
955                         }
956                 }
957         }
958 }
959
960 /**
961  * Arbitrary reads from the future are not allowed. Section 29.3 part 9 places
962  * some constraints. This method checks one the following constraint (others
963  * require compiler support):
964  *
965  *   If X --hb-> Y --mo-> Z, then X should not read from Z.
966  *   If X --hb-> Y, A --rf-> Y, and A --mo-> Z, then X should not read from Z.
967  */
968 bool ModelExecution::mo_may_allow(const ModelAction *writer, const ModelAction *reader)
969 {
970         SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(reader->get_location());
971         unsigned int i;
972         /* Iterate over all threads */
973         for (i = 0;i < thrd_lists->size();i++) {
974                 const ModelAction *write_after_read = NULL;
975
976                 /* Iterate over actions in thread, starting from most recent */
977                 action_list_t *list = &(*thrd_lists)[i];
978                 action_list_t::reverse_iterator rit;
979                 for (rit = list->rbegin();rit != list->rend();rit++) {
980                         ModelAction *act = *rit;
981
982                         /* Don't disallow due to act == reader */
983                         if (!reader->happens_before(act) || reader == act)
984                                 break;
985                         else if (act->is_write())
986                                 write_after_read = act;
987                         else if (act->is_read() && act->get_reads_from() != NULL)
988                                 write_after_read = act->get_reads_from();
989                 }
990
991                 if (write_after_read && write_after_read != writer && mo_graph->checkReachable(write_after_read, writer))
992                         return false;
993         }
994         return true;
995 }
996
997 /**
998  * Computes the clock vector that happens before propagates from this write.
999  *
1000  * @param rf The action that might be part of a release sequence. Must be a
1001  * write.
1002  * @return ClockVector of happens before relation.
1003  */
1004
1005 ClockVector * ModelExecution::get_hb_from_write(ModelAction *rf) const {
1006         SnapVector<ModelAction *> * processset = NULL;
1007         for ( ;rf != NULL;rf = rf->get_reads_from()) {
1008                 ASSERT(rf->is_write());
1009                 if (!rf->is_rmw() || (rf->is_acquire() && rf->is_release()) || rf->get_rfcv() != NULL)
1010                         break;
1011                 if (processset == NULL)
1012                         processset = new SnapVector<ModelAction *>();
1013                 processset->push_back(rf);
1014         }
1015
1016         int i = (processset == NULL) ? 0 : processset->size();
1017
1018         ClockVector * vec = NULL;
1019         while(true) {
1020                 if (rf->get_rfcv() != NULL) {
1021                         vec = rf->get_rfcv();
1022                 } else if (rf->is_acquire() && rf->is_release()) {
1023                         vec = rf->get_cv();
1024                 } else if (rf->is_release() && !rf->is_rmw()) {
1025                         vec = rf->get_cv();
1026                 } else if (rf->is_release()) {
1027                         //have rmw that is release and doesn't have a rfcv
1028                         (vec = new ClockVector(vec, NULL))->merge(rf->get_cv());
1029                         rf->set_rfcv(vec);
1030                 } else {
1031                         //operation that isn't release
1032                         if (rf->get_last_fence_release()) {
1033                                 if (vec == NULL)
1034                                         vec = rf->get_last_fence_release()->get_cv();
1035                                 else
1036                                         (vec=new ClockVector(vec, NULL))->merge(rf->get_last_fence_release()->get_cv());
1037                         }
1038                         rf->set_rfcv(vec);
1039                 }
1040                 i--;
1041                 if (i >= 0) {
1042                         rf = (*processset)[i];
1043                 } else
1044                         break;
1045         }
1046         if (processset != NULL)
1047                 delete processset;
1048         return vec;
1049 }
1050
1051 /**
1052  * Performs various bookkeeping operations for the current ModelAction. For
1053  * instance, adds action to the per-object, per-thread action vector and to the
1054  * action trace list of all thread actions.
1055  *
1056  * @param act is the ModelAction to add.
1057  */
1058 void ModelExecution::add_action_to_lists(ModelAction *act)
1059 {
1060         int tid = id_to_int(act->get_tid());
1061         ModelAction *uninit = NULL;
1062         int uninit_id = -1;
1063         action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
1064         if (list->empty() && act->is_atomic_var()) {
1065                 uninit = get_uninitialized_action(act);
1066                 uninit_id = id_to_int(uninit->get_tid());
1067                 list->push_front(uninit);
1068                 SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, act->get_location());
1069                 if (uninit_id >= (int)vec->size())
1070                         vec->resize(uninit_id + 1);
1071                 (*vec)[uninit_id].push_front(uninit);
1072         }
1073         list->push_back(act);
1074
1075         // Update action trace, a total order of all actions
1076         action_trace.push_back(act);
1077         if (uninit)
1078                 action_trace.push_front(uninit);
1079
1080         // Update obj_thrd_map, a per location, per thread, order of actions
1081         SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
1082         if (tid >= (int)vec->size())
1083                 vec->resize(priv->next_thread_id);
1084         (*vec)[tid].push_back(act);
1085         if (uninit)
1086                 (*vec)[uninit_id].push_front(uninit);
1087
1088         // Update thrd_last_action, the last action taken by each thrad
1089         if ((int)thrd_last_action.size() <= tid)
1090                 thrd_last_action.resize(get_num_threads());
1091         thrd_last_action[tid] = act;
1092         if (uninit)
1093                 thrd_last_action[uninit_id] = uninit;
1094
1095         // Update thrd_last_fence_release, the last release fence taken by each thread
1096         if (act->is_fence() && act->is_release()) {
1097                 if ((int)thrd_last_fence_release.size() <= tid)
1098                         thrd_last_fence_release.resize(get_num_threads());
1099                 thrd_last_fence_release[tid] = act;
1100         }
1101
1102         if (act->is_wait()) {
1103                 void *mutex_loc = (void *) act->get_value();
1104                 get_safe_ptr_action(&obj_map, mutex_loc)->push_back(act);
1105
1106                 SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, mutex_loc);
1107                 if (tid >= (int)vec->size())
1108                         vec->resize(priv->next_thread_id);
1109                 (*vec)[tid].push_back(act);
1110         }
1111 }
1112
1113 void ModelExecution::add_write_to_lists(ModelAction *write) {
1114         // Update seq_cst map
1115         if (write->is_seqcst())
1116                 obj_last_sc_map.put(write->get_location(), write);
1117
1118         SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, write->get_location());
1119         int tid = id_to_int(write->get_tid());
1120         if (tid >= (int)vec->size())
1121                 vec->resize(priv->next_thread_id);
1122         (*vec)[tid].push_back(write);
1123 }
1124
1125 /**
1126  * @brief Get the last action performed by a particular Thread
1127  * @param tid The thread ID of the Thread in question
1128  * @return The last action in the thread
1129  */
1130 ModelAction * ModelExecution::get_last_action(thread_id_t tid) const
1131 {
1132         int threadid = id_to_int(tid);
1133         if (threadid < (int)thrd_last_action.size())
1134                 return thrd_last_action[id_to_int(tid)];
1135         else
1136                 return NULL;
1137 }
1138
1139 /**
1140  * @brief Get the last fence release performed by a particular Thread
1141  * @param tid The thread ID of the Thread in question
1142  * @return The last fence release in the thread, if one exists; NULL otherwise
1143  */
1144 ModelAction * ModelExecution::get_last_fence_release(thread_id_t tid) const
1145 {
1146         int threadid = id_to_int(tid);
1147         if (threadid < (int)thrd_last_fence_release.size())
1148                 return thrd_last_fence_release[id_to_int(tid)];
1149         else
1150                 return NULL;
1151 }
1152
1153 /**
1154  * Gets the last memory_order_seq_cst write (in the total global sequence)
1155  * performed on a particular object (i.e., memory location), not including the
1156  * current action.
1157  * @param curr The current ModelAction; also denotes the object location to
1158  * check
1159  * @return The last seq_cst write
1160  */
1161 ModelAction * ModelExecution::get_last_seq_cst_write(ModelAction *curr) const
1162 {
1163         void *location = curr->get_location();
1164         return obj_last_sc_map.get(location);
1165 }
1166
1167 /**
1168  * Gets the last memory_order_seq_cst fence (in the total global sequence)
1169  * performed in a particular thread, prior to a particular fence.
1170  * @param tid The ID of the thread to check
1171  * @param before_fence The fence from which to begin the search; if NULL, then
1172  * search for the most recent fence in the thread.
1173  * @return The last prior seq_cst fence in the thread, if exists; otherwise, NULL
1174  */
1175 ModelAction * ModelExecution::get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const
1176 {
1177         /* All fences should have location FENCE_LOCATION */
1178         action_list_t *list = obj_map.get(FENCE_LOCATION);
1179
1180         if (!list)
1181                 return NULL;
1182
1183         action_list_t::reverse_iterator rit = list->rbegin();
1184
1185         if (before_fence) {
1186                 for (;rit != list->rend();rit++)
1187                         if (*rit == before_fence)
1188                                 break;
1189
1190                 ASSERT(*rit == before_fence);
1191                 rit++;
1192         }
1193
1194         for (;rit != list->rend();rit++)
1195                 if ((*rit)->is_fence() && (tid == (*rit)->get_tid()) && (*rit)->is_seqcst())
1196                         return *rit;
1197         return NULL;
1198 }
1199
1200 /**
1201  * Gets the last unlock operation performed on a particular mutex (i.e., memory
1202  * location). This function identifies the mutex according to the current
1203  * action, which is presumed to perform on the same mutex.
1204  * @param curr The current ModelAction; also denotes the object location to
1205  * check
1206  * @return The last unlock operation
1207  */
1208 ModelAction * ModelExecution::get_last_unlock(ModelAction *curr) const
1209 {
1210         void *location = curr->get_location();
1211
1212         action_list_t *list = obj_map.get(location);
1213         /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
1214         action_list_t::reverse_iterator rit;
1215         for (rit = list->rbegin();rit != list->rend();rit++)
1216                 if ((*rit)->is_unlock() || (*rit)->is_wait())
1217                         return *rit;
1218         return NULL;
1219 }
1220
1221 ModelAction * ModelExecution::get_parent_action(thread_id_t tid) const
1222 {
1223         ModelAction *parent = get_last_action(tid);
1224         if (!parent)
1225                 parent = get_thread(tid)->get_creation();
1226         return parent;
1227 }
1228
1229 /**
1230  * Returns the clock vector for a given thread.
1231  * @param tid The thread whose clock vector we want
1232  * @return Desired clock vector
1233  */
1234 ClockVector * ModelExecution::get_cv(thread_id_t tid) const
1235 {
1236         ModelAction *firstaction=get_parent_action(tid);
1237         return firstaction != NULL ? firstaction->get_cv() : NULL;
1238 }
1239
1240 bool valequals(uint64_t val1, uint64_t val2, int size) {
1241         switch(size) {
1242         case 1:
1243                 return ((uint8_t)val1) == ((uint8_t)val2);
1244         case 2:
1245                 return ((uint16_t)val1) == ((uint16_t)val2);
1246         case 4:
1247                 return ((uint32_t)val1) == ((uint32_t)val2);
1248         case 8:
1249                 return val1==val2;
1250         default:
1251                 ASSERT(0);
1252                 return false;
1253         }
1254 }
1255
1256 /**
1257  * Build up an initial set of all past writes that this 'read' action may read
1258  * from, as well as any previously-observed future values that must still be valid.
1259  *
1260  * @param curr is the current ModelAction that we are exploring; it must be a
1261  * 'read' operation.
1262  */
1263 SnapVector<ModelAction *> *  ModelExecution::build_may_read_from(ModelAction *curr)
1264 {
1265         SnapVector<action_list_t> *thrd_lists = obj_wr_thrd_map.get(curr->get_location());
1266         unsigned int i;
1267         ASSERT(curr->is_read());
1268
1269         ModelAction *last_sc_write = NULL;
1270
1271         if (curr->is_seqcst())
1272                 last_sc_write = get_last_seq_cst_write(curr);
1273
1274         SnapVector<ModelAction *> * rf_set = new SnapVector<ModelAction *>();
1275
1276         /* Iterate over all threads */
1277         for (i = 0;i < thrd_lists->size();i++) {
1278                 /* Iterate over actions in thread, starting from most recent */
1279                 action_list_t *list = &(*thrd_lists)[i];
1280                 action_list_t::reverse_iterator rit;
1281                 for (rit = list->rbegin();rit != list->rend();rit++) {
1282                         ModelAction *act = *rit;
1283
1284                         if (act == curr)
1285                                 continue;
1286
1287                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
1288                         bool allow_read = true;
1289
1290                         if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
1291                                 allow_read = false;
1292
1293                         /* Need to check whether we will have two RMW reading from the same value */
1294                         if (curr->is_rmwr()) {
1295                                 /* It is okay if we have a failing CAS */
1296                                 if (!curr->is_rmwrcas() ||
1297                                                 valequals(curr->get_value(), act->get_value(), curr->getSize())) {
1298                                         //Need to make sure we aren't the second RMW
1299                                         CycleNode * node = mo_graph->getNode_noCreate(act);
1300                                         if (node != NULL && node->getRMW() != NULL) {
1301                                                 //we are the second RMW
1302                                                 allow_read = false;
1303                                         }
1304                                 }
1305                         }
1306
1307                         if (allow_read) {
1308                                 /* Only add feasible reads */
1309                                 rf_set->push_back(act);
1310                         }
1311
1312                         /* Include at most one act per-thread that "happens before" curr */
1313                         if (act->happens_before(curr))
1314                                 break;
1315                 }
1316         }
1317
1318         if (DBG_ENABLED()) {
1319                 model_print("Reached read action:\n");
1320                 curr->print();
1321                 model_print("End printing read_from_past\n");
1322         }
1323         return rf_set;
1324 }
1325
1326 /**
1327  * @brief Get an action representing an uninitialized atomic
1328  *
1329  * This function may create a new one.
1330  *
1331  * @param curr The current action, which prompts the creation of an UNINIT action
1332  * @return A pointer to the UNINIT ModelAction
1333  */
1334 ModelAction * ModelExecution::get_uninitialized_action(ModelAction *curr) const
1335 {
1336         ModelAction *act = curr->get_uninit_action();
1337         if (!act) {
1338                 act = new ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, curr->get_location(), params->uninitvalue, model_thread);
1339                 curr->set_uninit_action(act);
1340         }
1341         act->create_cv(NULL);
1342         return act;
1343 }
1344
1345 static void print_list(const action_list_t *list)
1346 {
1347         action_list_t::const_iterator it;
1348
1349         model_print("------------------------------------------------------------------------------------\n");
1350         model_print("#    t    Action type     MO       Location         Value               Rf  CV\n");
1351         model_print("------------------------------------------------------------------------------------\n");
1352
1353         unsigned int hash = 0;
1354
1355         for (it = list->begin();it != list->end();it++) {
1356                 const ModelAction *act = *it;
1357                 if (act->get_seq_number() > 0)
1358                         act->print();
1359                 hash = hash^(hash<<3)^((*it)->hash());
1360         }
1361         model_print("HASH %u\n", hash);
1362         model_print("------------------------------------------------------------------------------------\n");
1363 }
1364
1365 #if SUPPORT_MOD_ORDER_DUMP
1366 void ModelExecution::dumpGraph(char *filename) const
1367 {
1368         char buffer[200];
1369         sprintf(buffer, "%s.dot", filename);
1370         FILE *file = fopen(buffer, "w");
1371         fprintf(file, "digraph %s {\n", filename);
1372         mo_graph->dumpNodes(file);
1373         ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
1374
1375         for (action_list_t::const_iterator it = action_trace.begin();it != action_trace.end();it++) {
1376                 ModelAction *act = *it;
1377                 if (act->is_read()) {
1378                         mo_graph->dot_print_node(file, act);
1379                         mo_graph->dot_print_edge(file,
1380                                                                                                                          act->get_reads_from(),
1381                                                                                                                          act,
1382                                                                                                                          "label=\"rf\", color=red, weight=2");
1383                 }
1384                 if (thread_array[act->get_tid()]) {
1385                         mo_graph->dot_print_edge(file,
1386                                                                                                                          thread_array[id_to_int(act->get_tid())],
1387                                                                                                                          act,
1388                                                                                                                          "label=\"sb\", color=blue, weight=400");
1389                 }
1390
1391                 thread_array[act->get_tid()] = act;
1392         }
1393         fprintf(file, "}\n");
1394         model_free(thread_array);
1395         fclose(file);
1396 }
1397 #endif
1398
1399 /** @brief Prints an execution trace summary. */
1400 void ModelExecution::print_summary() const
1401 {
1402 #if SUPPORT_MOD_ORDER_DUMP
1403         char buffername[100];
1404         sprintf(buffername, "exec%04u", get_execution_number());
1405         mo_graph->dumpGraphToFile(buffername);
1406         sprintf(buffername, "graph%04u", get_execution_number());
1407         dumpGraph(buffername);
1408 #endif
1409
1410         model_print("Execution trace %d:", get_execution_number());
1411         if (isfeasibleprefix()) {
1412                 if (scheduler->all_threads_sleeping())
1413                         model_print(" SLEEP-SET REDUNDANT");
1414                 if (have_bug_reports())
1415                         model_print(" DETECTED BUG(S)");
1416         } else
1417                 print_infeasibility(" INFEASIBLE");
1418         model_print("\n");
1419
1420         print_list(&action_trace);
1421         model_print("\n");
1422
1423 }
1424
1425 /**
1426  * Add a Thread to the system for the first time. Should only be called once
1427  * per thread.
1428  * @param t The Thread to add
1429  */
1430 void ModelExecution::add_thread(Thread *t)
1431 {
1432         unsigned int i = id_to_int(t->get_id());
1433         if (i >= thread_map.size())
1434                 thread_map.resize(i + 1);
1435         thread_map[i] = t;
1436         if (!t->is_model_thread())
1437                 scheduler->add_thread(t);
1438 }
1439
1440 /**
1441  * @brief Get a Thread reference by its ID
1442  * @param tid The Thread's ID
1443  * @return A Thread reference
1444  */
1445 Thread * ModelExecution::get_thread(thread_id_t tid) const
1446 {
1447         unsigned int i = id_to_int(tid);
1448         if (i < thread_map.size())
1449                 return thread_map[i];
1450         return NULL;
1451 }
1452
1453 /**
1454  * @brief Get a reference to the Thread in which a ModelAction was executed
1455  * @param act The ModelAction
1456  * @return A Thread reference
1457  */
1458 Thread * ModelExecution::get_thread(const ModelAction *act) const
1459 {
1460         return get_thread(act->get_tid());
1461 }
1462
1463 /**
1464  * @brief Get a Thread reference by its pthread ID
1465  * @param index The pthread's ID
1466  * @return A Thread reference
1467  */
1468 Thread * ModelExecution::get_pthread(pthread_t pid) {
1469         union {
1470                 pthread_t p;
1471                 uint32_t v;
1472         } x;
1473         x.p = pid;
1474         uint32_t thread_id = x.v;
1475         if (thread_id < pthread_counter + 1) return pthread_map[thread_id];
1476         else return NULL;
1477 }
1478
1479 /**
1480  * @brief Check if a Thread is currently enabled
1481  * @param t The Thread to check
1482  * @return True if the Thread is currently enabled
1483  */
1484 bool ModelExecution::is_enabled(Thread *t) const
1485 {
1486         return scheduler->is_enabled(t);
1487 }
1488
1489 /**
1490  * @brief Check if a Thread is currently enabled
1491  * @param tid The ID of the Thread to check
1492  * @return True if the Thread is currently enabled
1493  */
1494 bool ModelExecution::is_enabled(thread_id_t tid) const
1495 {
1496         return scheduler->is_enabled(tid);
1497 }
1498
1499 /**
1500  * @brief Select the next thread to execute based on the curren action
1501  *
1502  * RMW actions occur in two parts, and we cannot split them. And THREAD_CREATE
1503  * actions should be followed by the execution of their child thread. In either
1504  * case, the current action should determine the next thread schedule.
1505  *
1506  * @param curr The current action
1507  * @return The next thread to run, if the current action will determine this
1508  * selection; otherwise NULL
1509  */
1510 Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) const
1511 {
1512         /* Do not split atomic RMW */
1513         if (curr->is_rmwr())
1514                 return get_thread(curr);
1515         /* Follow CREATE with the created thread */
1516         /* which is not needed, because model.cc takes care of this */
1517         if (curr->get_type() == THREAD_CREATE)
1518                 return curr->get_thread_operand();
1519         if (curr->get_type() == PTHREAD_CREATE) {
1520                 return curr->get_thread_operand();
1521         }
1522         return NULL;
1523 }
1524
1525 /**
1526  * Takes the next step in the execution, if possible.
1527  * @param curr The current step to take
1528  * @return Returns the next Thread to run, if any; NULL if this execution
1529  * should terminate
1530  */
1531 Thread * ModelExecution::take_step(ModelAction *curr)
1532 {
1533         Thread *curr_thrd = get_thread(curr);
1534         ASSERT(curr_thrd->get_state() == THREAD_READY);
1535
1536         ASSERT(check_action_enabled(curr));     /* May have side effects? */
1537         curr = check_current_action(curr);
1538         ASSERT(curr);
1539
1540         if (curr_thrd->is_blocked() || curr_thrd->is_complete())
1541                 scheduler->remove_thread(curr_thrd);
1542
1543         return action_select_next_thread(curr);
1544 }
1545
1546 Fuzzer * ModelExecution::getFuzzer() {
1547         return fuzzer;
1548 }