Optimize SC lookup
[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         }
1069         list->push_back(act);
1070
1071         // Update action trace, a total order of all actions
1072         action_trace.push_back(act);
1073         if (uninit)
1074                 action_trace.push_front(uninit);
1075
1076         // Update obj_thrd_map, a per location, per thread, order of actions
1077         SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
1078         if (tid >= (int)vec->size())
1079                 vec->resize(priv->next_thread_id);
1080         (*vec)[tid].push_back(act);
1081         if (uninit)
1082                 (*vec)[uninit_id].push_front(uninit);
1083
1084         // Update thrd_last_action, the last action taken by each thrad
1085         if ((int)thrd_last_action.size() <= tid)
1086                 thrd_last_action.resize(get_num_threads());
1087         thrd_last_action[tid] = act;
1088         if (uninit)
1089                 thrd_last_action[uninit_id] = uninit;
1090
1091         // Update thrd_last_fence_release, the last release fence taken by each thread
1092         if (act->is_fence() && act->is_release()) {
1093                 if ((int)thrd_last_fence_release.size() <= tid)
1094                         thrd_last_fence_release.resize(get_num_threads());
1095                 thrd_last_fence_release[tid] = act;
1096         }
1097
1098         if (act->is_wait()) {
1099                 void *mutex_loc = (void *) act->get_value();
1100                 get_safe_ptr_action(&obj_map, mutex_loc)->push_back(act);
1101
1102                 SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, mutex_loc);
1103                 if (tid >= (int)vec->size())
1104                         vec->resize(priv->next_thread_id);
1105                 (*vec)[tid].push_back(act);
1106         }
1107 }
1108
1109 void ModelExecution::add_write_to_lists(ModelAction *write) {
1110         // Update seq_cst map
1111         if (write->is_seqcst())
1112                 obj_last_sc_map.put(write->get_location(), write);
1113 }
1114
1115 /**
1116  * @brief Get the last action performed by a particular Thread
1117  * @param tid The thread ID of the Thread in question
1118  * @return The last action in the thread
1119  */
1120 ModelAction * ModelExecution::get_last_action(thread_id_t tid) const
1121 {
1122         int threadid = id_to_int(tid);
1123         if (threadid < (int)thrd_last_action.size())
1124                 return thrd_last_action[id_to_int(tid)];
1125         else
1126                 return NULL;
1127 }
1128
1129 /**
1130  * @brief Get the last fence release performed by a particular Thread
1131  * @param tid The thread ID of the Thread in question
1132  * @return The last fence release in the thread, if one exists; NULL otherwise
1133  */
1134 ModelAction * ModelExecution::get_last_fence_release(thread_id_t tid) const
1135 {
1136         int threadid = id_to_int(tid);
1137         if (threadid < (int)thrd_last_fence_release.size())
1138                 return thrd_last_fence_release[id_to_int(tid)];
1139         else
1140                 return NULL;
1141 }
1142
1143 /**
1144  * Gets the last memory_order_seq_cst write (in the total global sequence)
1145  * performed on a particular object (i.e., memory location), not including the
1146  * current action.
1147  * @param curr The current ModelAction; also denotes the object location to
1148  * check
1149  * @return The last seq_cst write
1150  */
1151 ModelAction * ModelExecution::get_last_seq_cst_write(ModelAction *curr) const
1152 {
1153         void *location = curr->get_location();
1154         return obj_last_sc_map.get(location);
1155 }
1156
1157 /**
1158  * Gets the last memory_order_seq_cst fence (in the total global sequence)
1159  * performed in a particular thread, prior to a particular fence.
1160  * @param tid The ID of the thread to check
1161  * @param before_fence The fence from which to begin the search; if NULL, then
1162  * search for the most recent fence in the thread.
1163  * @return The last prior seq_cst fence in the thread, if exists; otherwise, NULL
1164  */
1165 ModelAction * ModelExecution::get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const
1166 {
1167         /* All fences should have location FENCE_LOCATION */
1168         action_list_t *list = obj_map.get(FENCE_LOCATION);
1169
1170         if (!list)
1171                 return NULL;
1172
1173         action_list_t::reverse_iterator rit = list->rbegin();
1174
1175         if (before_fence) {
1176                 for (;rit != list->rend();rit++)
1177                         if (*rit == before_fence)
1178                                 break;
1179
1180                 ASSERT(*rit == before_fence);
1181                 rit++;
1182         }
1183
1184         for (;rit != list->rend();rit++)
1185                 if ((*rit)->is_fence() && (tid == (*rit)->get_tid()) && (*rit)->is_seqcst())
1186                         return *rit;
1187         return NULL;
1188 }
1189
1190 /**
1191  * Gets the last unlock operation performed on a particular mutex (i.e., memory
1192  * location). This function identifies the mutex according to the current
1193  * action, which is presumed to perform on the same mutex.
1194  * @param curr The current ModelAction; also denotes the object location to
1195  * check
1196  * @return The last unlock operation
1197  */
1198 ModelAction * ModelExecution::get_last_unlock(ModelAction *curr) const
1199 {
1200         void *location = curr->get_location();
1201
1202         action_list_t *list = obj_map.get(location);
1203         /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
1204         action_list_t::reverse_iterator rit;
1205         for (rit = list->rbegin();rit != list->rend();rit++)
1206                 if ((*rit)->is_unlock() || (*rit)->is_wait())
1207                         return *rit;
1208         return NULL;
1209 }
1210
1211 ModelAction * ModelExecution::get_parent_action(thread_id_t tid) const
1212 {
1213         ModelAction *parent = get_last_action(tid);
1214         if (!parent)
1215                 parent = get_thread(tid)->get_creation();
1216         return parent;
1217 }
1218
1219 /**
1220  * Returns the clock vector for a given thread.
1221  * @param tid The thread whose clock vector we want
1222  * @return Desired clock vector
1223  */
1224 ClockVector * ModelExecution::get_cv(thread_id_t tid) const
1225 {
1226         ModelAction *firstaction=get_parent_action(tid);
1227         return firstaction != NULL ? firstaction->get_cv() : NULL;
1228 }
1229
1230 bool valequals(uint64_t val1, uint64_t val2, int size) {
1231         switch(size) {
1232         case 1:
1233                 return ((uint8_t)val1) == ((uint8_t)val2);
1234         case 2:
1235                 return ((uint16_t)val1) == ((uint16_t)val2);
1236         case 4:
1237                 return ((uint32_t)val1) == ((uint32_t)val2);
1238         case 8:
1239                 return val1==val2;
1240         default:
1241                 ASSERT(0);
1242                 return false;
1243         }
1244 }
1245
1246 /**
1247  * Build up an initial set of all past writes that this 'read' action may read
1248  * from, as well as any previously-observed future values that must still be valid.
1249  *
1250  * @param curr is the current ModelAction that we are exploring; it must be a
1251  * 'read' operation.
1252  */
1253 SnapVector<ModelAction *> *  ModelExecution::build_may_read_from(ModelAction *curr)
1254 {
1255         SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
1256         unsigned int i;
1257         ASSERT(curr->is_read());
1258
1259         ModelAction *last_sc_write = NULL;
1260
1261         if (curr->is_seqcst())
1262                 last_sc_write = get_last_seq_cst_write(curr);
1263
1264         SnapVector<ModelAction *> * rf_set = new SnapVector<ModelAction *>();
1265
1266         /* Iterate over all threads */
1267         for (i = 0;i < thrd_lists->size();i++) {
1268                 /* Iterate over actions in thread, starting from most recent */
1269                 action_list_t *list = &(*thrd_lists)[i];
1270                 action_list_t::reverse_iterator rit;
1271                 for (rit = list->rbegin();rit != list->rend();rit++) {
1272                         ModelAction *act = *rit;
1273
1274                         /* Only consider 'write' actions */
1275                         if (!act->is_write()) {
1276                                 if (act != curr && act->is_read() && act->happens_before(curr)) {
1277                                         ModelAction *tmp = act->get_reads_from();
1278                                         if (((unsigned int) id_to_int(tmp->get_tid()))==i)
1279                                                 act = tmp;
1280                                         else
1281                                                 break;
1282                                 } else
1283                                         continue;
1284                         }
1285
1286                         if (act == curr)
1287                                 continue;
1288
1289                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
1290                         bool allow_read = true;
1291
1292                         if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
1293                                 allow_read = false;
1294
1295                         /* Need to check whether we will have two RMW reading from the same value */
1296                         if (curr->is_rmwr()) {
1297                                 /* It is okay if we have a failing CAS */
1298                                 if (!curr->is_rmwrcas() ||
1299                                                 valequals(curr->get_value(), act->get_value(), curr->getSize())) {
1300                                         //Need to make sure we aren't the second RMW
1301                                         CycleNode * node = mo_graph->getNode_noCreate(act);
1302                                         if (node != NULL && node->getRMW() != NULL) {
1303                                                 //we are the second RMW
1304                                                 allow_read = false;
1305                                         }
1306                                 }
1307                         }
1308
1309                         if (allow_read) {
1310                                 /* Only add feasible reads */
1311                                 rf_set->push_back(act);
1312                         }
1313
1314                         /* Include at most one act per-thread that "happens before" curr */
1315                         if (act->happens_before(curr))
1316                                 break;
1317                 }
1318         }
1319
1320         if (DBG_ENABLED()) {
1321                 model_print("Reached read action:\n");
1322                 curr->print();
1323                 model_print("End printing read_from_past\n");
1324         }
1325         return rf_set;
1326 }
1327
1328 /**
1329  * @brief Get an action representing an uninitialized atomic
1330  *
1331  * This function may create a new one.
1332  *
1333  * @param curr The current action, which prompts the creation of an UNINIT action
1334  * @return A pointer to the UNINIT ModelAction
1335  */
1336 ModelAction * ModelExecution::get_uninitialized_action(ModelAction *curr) const
1337 {
1338         ModelAction *act = curr->get_uninit_action();
1339         if (!act) {
1340                 act = new ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, curr->get_location(), params->uninitvalue, model_thread);
1341                 curr->set_uninit_action(act);
1342         }
1343         act->create_cv(NULL);
1344         return act;
1345 }
1346
1347 static void print_list(const action_list_t *list)
1348 {
1349         action_list_t::const_iterator it;
1350
1351         model_print("------------------------------------------------------------------------------------\n");
1352         model_print("#    t    Action type     MO       Location         Value               Rf  CV\n");
1353         model_print("------------------------------------------------------------------------------------\n");
1354
1355         unsigned int hash = 0;
1356
1357         for (it = list->begin();it != list->end();it++) {
1358                 const ModelAction *act = *it;
1359                 if (act->get_seq_number() > 0)
1360                         act->print();
1361                 hash = hash^(hash<<3)^((*it)->hash());
1362         }
1363         model_print("HASH %u\n", hash);
1364         model_print("------------------------------------------------------------------------------------\n");
1365 }
1366
1367 #if SUPPORT_MOD_ORDER_DUMP
1368 void ModelExecution::dumpGraph(char *filename) const
1369 {
1370         char buffer[200];
1371         sprintf(buffer, "%s.dot", filename);
1372         FILE *file = fopen(buffer, "w");
1373         fprintf(file, "digraph %s {\n", filename);
1374         mo_graph->dumpNodes(file);
1375         ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
1376
1377         for (action_list_t::const_iterator it = action_trace.begin();it != action_trace.end();it++) {
1378                 ModelAction *act = *it;
1379                 if (act->is_read()) {
1380                         mo_graph->dot_print_node(file, act);
1381                         mo_graph->dot_print_edge(file,
1382                                                                                                                          act->get_reads_from(),
1383                                                                                                                          act,
1384                                                                                                                          "label=\"rf\", color=red, weight=2");
1385                 }
1386                 if (thread_array[act->get_tid()]) {
1387                         mo_graph->dot_print_edge(file,
1388                                                                                                                          thread_array[id_to_int(act->get_tid())],
1389                                                                                                                          act,
1390                                                                                                                          "label=\"sb\", color=blue, weight=400");
1391                 }
1392
1393                 thread_array[act->get_tid()] = act;
1394         }
1395         fprintf(file, "}\n");
1396         model_free(thread_array);
1397         fclose(file);
1398 }
1399 #endif
1400
1401 /** @brief Prints an execution trace summary. */
1402 void ModelExecution::print_summary() const
1403 {
1404 #if SUPPORT_MOD_ORDER_DUMP
1405         char buffername[100];
1406         sprintf(buffername, "exec%04u", get_execution_number());
1407         mo_graph->dumpGraphToFile(buffername);
1408         sprintf(buffername, "graph%04u", get_execution_number());
1409         dumpGraph(buffername);
1410 #endif
1411
1412         model_print("Execution trace %d:", get_execution_number());
1413         if (isfeasibleprefix()) {
1414                 if (scheduler->all_threads_sleeping())
1415                         model_print(" SLEEP-SET REDUNDANT");
1416                 if (have_bug_reports())
1417                         model_print(" DETECTED BUG(S)");
1418         } else
1419                 print_infeasibility(" INFEASIBLE");
1420         model_print("\n");
1421
1422         print_list(&action_trace);
1423         model_print("\n");
1424
1425 }
1426
1427 /**
1428  * Add a Thread to the system for the first time. Should only be called once
1429  * per thread.
1430  * @param t The Thread to add
1431  */
1432 void ModelExecution::add_thread(Thread *t)
1433 {
1434         unsigned int i = id_to_int(t->get_id());
1435         if (i >= thread_map.size())
1436                 thread_map.resize(i + 1);
1437         thread_map[i] = t;
1438         if (!t->is_model_thread())
1439                 scheduler->add_thread(t);
1440 }
1441
1442 /**
1443  * @brief Get a Thread reference by its ID
1444  * @param tid The Thread's ID
1445  * @return A Thread reference
1446  */
1447 Thread * ModelExecution::get_thread(thread_id_t tid) const
1448 {
1449         unsigned int i = id_to_int(tid);
1450         if (i < thread_map.size())
1451                 return thread_map[i];
1452         return NULL;
1453 }
1454
1455 /**
1456  * @brief Get a reference to the Thread in which a ModelAction was executed
1457  * @param act The ModelAction
1458  * @return A Thread reference
1459  */
1460 Thread * ModelExecution::get_thread(const ModelAction *act) const
1461 {
1462         return get_thread(act->get_tid());
1463 }
1464
1465 /**
1466  * @brief Get a Thread reference by its pthread ID
1467  * @param index The pthread's ID
1468  * @return A Thread reference
1469  */
1470 Thread * ModelExecution::get_pthread(pthread_t pid) {
1471         union {
1472                 pthread_t p;
1473                 uint32_t v;
1474         } x;
1475         x.p = pid;
1476         uint32_t thread_id = x.v;
1477         if (thread_id < pthread_counter + 1) return pthread_map[thread_id];
1478         else return NULL;
1479 }
1480
1481 /**
1482  * @brief Check if a Thread is currently enabled
1483  * @param t The Thread to check
1484  * @return True if the Thread is currently enabled
1485  */
1486 bool ModelExecution::is_enabled(Thread *t) const
1487 {
1488         return scheduler->is_enabled(t);
1489 }
1490
1491 /**
1492  * @brief Check if a Thread is currently enabled
1493  * @param tid The ID of the Thread to check
1494  * @return True if the Thread is currently enabled
1495  */
1496 bool ModelExecution::is_enabled(thread_id_t tid) const
1497 {
1498         return scheduler->is_enabled(tid);
1499 }
1500
1501 /**
1502  * @brief Select the next thread to execute based on the curren action
1503  *
1504  * RMW actions occur in two parts, and we cannot split them. And THREAD_CREATE
1505  * actions should be followed by the execution of their child thread. In either
1506  * case, the current action should determine the next thread schedule.
1507  *
1508  * @param curr The current action
1509  * @return The next thread to run, if the current action will determine this
1510  * selection; otherwise NULL
1511  */
1512 Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) const
1513 {
1514         /* Do not split atomic RMW */
1515         if (curr->is_rmwr())
1516                 return get_thread(curr);
1517         /* Follow CREATE with the created thread */
1518         /* which is not needed, because model.cc takes care of this */
1519         if (curr->get_type() == THREAD_CREATE)
1520                 return curr->get_thread_operand();
1521         if (curr->get_type() == PTHREAD_CREATE) {
1522                 return curr->get_thread_operand();
1523         }
1524         return NULL;
1525 }
1526
1527 /**
1528  * Takes the next step in the execution, if possible.
1529  * @param curr The current step to take
1530  * @return Returns the next Thread to run, if any; NULL if this execution
1531  * should terminate
1532  */
1533 Thread * ModelExecution::take_step(ModelAction *curr)
1534 {
1535         Thread *curr_thrd = get_thread(curr);
1536         ASSERT(curr_thrd->get_state() == THREAD_READY);
1537
1538         ASSERT(check_action_enabled(curr));     /* May have side effects? */
1539         curr = check_current_action(curr);
1540         ASSERT(curr);
1541
1542         if (curr_thrd->is_blocked() || curr_thrd->is_complete())
1543                 scheduler->remove_thread(curr_thrd);
1544
1545         return action_select_next_thread(curr);
1546 }
1547
1548 Fuzzer * ModelExecution::getFuzzer() {
1549         return fuzzer;
1550 }