02f290d0a4e29efe8954eaf56f1075955182e9ea
[model-checker.git] / model.cc
1 #include <stdio.h>
2 #include <algorithm>
3
4 #include "model.h"
5 #include "action.h"
6 #include "nodestack.h"
7 #include "schedule.h"
8 #include "snapshot-interface.h"
9 #include "common.h"
10 #include "clockvector.h"
11 #include "cyclegraph.h"
12 #include "promise.h"
13 #include "datarace.h"
14 #include "mutex.h"
15 #include "threads.h"
16
17 #define INITIAL_THREAD_ID       0
18
19 ModelChecker *model;
20
21 /** @brief Constructor */
22 ModelChecker::ModelChecker(struct model_params params) :
23         /* Initialize default scheduler */
24         params(params),
25         scheduler(new Scheduler()),
26         num_executions(0),
27         num_feasible_executions(0),
28         diverge(NULL),
29         earliest_diverge(NULL),
30         action_trace(new action_list_t()),
31         thread_map(new HashTable<int, Thread *, int>()),
32         obj_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
33         lock_waiters_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
34         obj_thrd_map(new HashTable<void *, std::vector<action_list_t>, uintptr_t, 4 >()),
35         promises(new std::vector< Promise *, SnapshotAlloc<Promise *> >()),
36         futurevalues(new std::vector< struct PendingFutureValue, SnapshotAlloc<struct PendingFutureValue> >()),
37         pending_rel_seqs(new std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >()),
38         thrd_last_action(new std::vector< ModelAction *, SnapshotAlloc<ModelAction *> >(1)),
39         node_stack(new NodeStack()),
40         mo_graph(new CycleGraph()),
41         failed_promise(false),
42         too_many_reads(false),
43         asserted(false),
44         bad_synchronization(false)
45 {
46         /* Allocate this "size" on the snapshotting heap */
47         priv = (struct model_snapshot_members *)calloc(1, sizeof(*priv));
48         /* First thread created will have id INITIAL_THREAD_ID */
49         priv->next_thread_id = INITIAL_THREAD_ID;
50
51         /* Initialize a model-checker thread, for special ModelActions */
52         model_thread = new Thread(get_next_id());
53         thread_map->put(id_to_int(model_thread->get_id()), model_thread);
54 }
55
56 /** @brief Destructor */
57 ModelChecker::~ModelChecker()
58 {
59         for (unsigned int i = 0; i < get_num_threads(); i++)
60                 delete thread_map->get(i);
61         delete thread_map;
62
63         delete obj_thrd_map;
64         delete obj_map;
65         delete lock_waiters_map;
66         delete action_trace;
67
68         for (unsigned int i = 0; i < promises->size(); i++)
69                 delete (*promises)[i];
70         delete promises;
71
72         delete pending_rel_seqs;
73
74         delete thrd_last_action;
75         delete node_stack;
76         delete scheduler;
77         delete mo_graph;
78 }
79
80 /**
81  * Restores user program to initial state and resets all model-checker data
82  * structures.
83  */
84 void ModelChecker::reset_to_initial_state()
85 {
86         DEBUG("+++ Resetting to initial state +++\n");
87         node_stack->reset_execution();
88         failed_promise = false;
89         too_many_reads = false;
90         bad_synchronization = false;
91         reset_asserted();
92         snapshotObject->backTrackBeforeStep(0);
93 }
94
95 /** @return a thread ID for a new Thread */
96 thread_id_t ModelChecker::get_next_id()
97 {
98         return priv->next_thread_id++;
99 }
100
101 /** @return the number of user threads created during this execution */
102 unsigned int ModelChecker::get_num_threads()
103 {
104         return priv->next_thread_id;
105 }
106
107 /** @return The currently executing Thread. */
108 Thread * ModelChecker::get_current_thread()
109 {
110         return scheduler->get_current_thread();
111 }
112
113 /** @return a sequence number for a new ModelAction */
114 modelclock_t ModelChecker::get_next_seq_num()
115 {
116         return ++priv->used_sequence_numbers;
117 }
118
119 /**
120  * @brief Choose the next thread to execute.
121  *
122  * This function chooses the next thread that should execute. It can force the
123  * adjacency of read/write portions of a RMW action, force THREAD_CREATE to be
124  * followed by a THREAD_START, or it can enforce execution replay/backtracking.
125  * The model-checker may have no preference regarding the next thread (i.e.,
126  * when exploring a new execution ordering), in which case this will return
127  * NULL.
128  * @param curr The current ModelAction. This action might guide the choice of
129  * next thread.
130  * @return The next thread to run. If the model-checker has no preference, NULL.
131  */
132 Thread * ModelChecker::get_next_thread(ModelAction *curr)
133 {
134         thread_id_t tid;
135
136         if (curr!=NULL) {
137                 /* Do not split atomic actions. */
138                 if (curr->is_rmwr())
139                         return thread_current();
140                 /* The THREAD_CREATE action points to the created Thread */
141                 else if (curr->get_type() == THREAD_CREATE)
142                         return (Thread *)curr->get_location();
143         }
144
145         /* Have we completed exploring the preselected path? */
146         if (diverge == NULL)
147                 return NULL;
148
149         /* Else, we are trying to replay an execution */
150         ModelAction *next = node_stack->get_next()->get_action();
151
152         if (next == diverge) {
153                 if (earliest_diverge == NULL || *diverge < *earliest_diverge)
154                         earliest_diverge=diverge;
155
156                 Node *nextnode = next->get_node();
157                 Node *prevnode = nextnode->get_parent();
158                 scheduler->update_sleep_set(prevnode);
159
160                 /* Reached divergence point */
161                 if (nextnode->increment_promise()) {
162                         /* The next node will try to satisfy a different set of promises. */
163                         tid = next->get_tid();
164                         node_stack->pop_restofstack(2);
165                 } else if (nextnode->increment_read_from()) {
166                         /* The next node will read from a different value. */
167                         tid = next->get_tid();
168                         node_stack->pop_restofstack(2);
169                 } else if (nextnode->increment_future_value()) {
170                         /* The next node will try to read from a different future value. */
171                         tid = next->get_tid();
172                         node_stack->pop_restofstack(2);
173                 } else if (nextnode->increment_relseq_break()) {
174                         /* The next node will try to resolve a release sequence differently */
175                         tid = next->get_tid();
176                         node_stack->pop_restofstack(2);
177                 } else {
178                         /* Make a different thread execute for next step */
179                         scheduler->add_sleep(thread_map->get(id_to_int(next->get_tid())));
180                         tid = prevnode->get_next_backtrack();
181                         /* Make sure the backtracked thread isn't sleeping. */
182                         node_stack->pop_restofstack(1);
183                         if (diverge==earliest_diverge) {
184                                 earliest_diverge=prevnode->get_action();
185                         }
186                 }
187                 /* The correct sleep set is in the parent node. */
188                 execute_sleep_set();
189
190                 DEBUG("*** Divergence point ***\n");
191
192                 diverge = NULL;
193         } else {
194                 tid = next->get_tid();
195         }
196         DEBUG("*** ModelChecker chose next thread = %d ***\n", id_to_int(tid));
197         ASSERT(tid != THREAD_ID_T_NONE);
198         return thread_map->get(id_to_int(tid));
199 }
200
201 /** 
202  * We need to know what the next actions of all threads in the sleep
203  * set will be.  This method computes them and stores the actions at
204  * the corresponding thread object's pending action.
205  */
206
207 void ModelChecker::execute_sleep_set() {
208         for(unsigned int i=0;i<get_num_threads();i++) {
209                 thread_id_t tid=int_to_id(i);
210                 Thread *thr=get_thread(tid);
211                 if ( scheduler->get_enabled(thr) == THREAD_SLEEP_SET ) {
212                         thr->set_state(THREAD_RUNNING);
213                         scheduler->next_thread(thr);
214                         Thread::swap(&system_context, thr);
215                         priv->current_action->set_sleep_flag();
216                         thr->set_pending(priv->current_action);
217                 }
218         }
219         priv->current_action = NULL;
220 }
221
222 void ModelChecker::wake_up_sleeping_actions(ModelAction * curr) {
223         for(unsigned int i=0;i<get_num_threads();i++) {
224                 thread_id_t tid=int_to_id(i);
225                 Thread *thr=get_thread(tid);
226                 if ( scheduler->get_enabled(thr) == THREAD_SLEEP_SET ) {
227                         ModelAction *pending_act=thr->get_pending();
228                         if (pending_act->could_synchronize_with(curr)) {
229                                 //Remove this thread from sleep set
230                                 scheduler->remove_sleep(thr);
231                         }
232                 }
233         }       
234 }
235
236 /**
237  * Queries the model-checker for more executions to explore and, if one
238  * exists, resets the model-checker state to execute a new execution.
239  *
240  * @return If there are more executions to explore, return true. Otherwise,
241  * return false.
242  */
243 bool ModelChecker::next_execution()
244 {
245         DBG();
246
247         num_executions++;
248
249         if (isfinalfeasible()) {
250                 printf("Earliest divergence point since last feasible execution:\n");
251                 if (earliest_diverge)
252                         earliest_diverge->print();
253                 else
254                         printf("(Not set)\n");
255
256                 earliest_diverge = NULL;
257                 num_feasible_executions++;
258         }
259
260         DEBUG("Number of acquires waiting on pending release sequences: %zu\n",
261                         pending_rel_seqs->size());
262
263         if (isfinalfeasible() || DBG_ENABLED())
264                 print_summary();
265
266         if ((diverge = get_next_backtrack()) == NULL)
267                 return false;
268
269         if (DBG_ENABLED()) {
270                 printf("Next execution will diverge at:\n");
271                 diverge->print();
272         }
273
274         reset_to_initial_state();
275         return true;
276 }
277
278 ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
279 {
280         switch (act->get_type()) {
281         case ATOMIC_READ:
282         case ATOMIC_WRITE:
283         case ATOMIC_RMW: {
284                 /* linear search: from most recent to oldest */
285                 action_list_t *list = obj_map->get_safe_ptr(act->get_location());
286                 action_list_t::reverse_iterator rit;
287                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
288                         ModelAction *prev = *rit;
289                         if (prev->could_synchronize_with(act))
290                                 return prev;
291                 }
292                 break;
293         }
294         case ATOMIC_LOCK:
295         case ATOMIC_TRYLOCK: {
296                 /* linear search: from most recent to oldest */
297                 action_list_t *list = obj_map->get_safe_ptr(act->get_location());
298                 action_list_t::reverse_iterator rit;
299                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
300                         ModelAction *prev = *rit;
301                         if (act->is_conflicting_lock(prev))
302                                 return prev;
303                 }
304                 break;
305         }
306         case ATOMIC_UNLOCK: {
307                 /* linear search: from most recent to oldest */
308                 action_list_t *list = obj_map->get_safe_ptr(act->get_location());
309                 action_list_t::reverse_iterator rit;
310                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
311                         ModelAction *prev = *rit;
312                         if (!act->same_thread(prev)&&prev->is_failed_trylock())
313                                 return prev;
314                 }
315                 break;
316         }
317         default:
318                 break;
319         }
320         return NULL;
321 }
322
323 /** This method finds backtracking points where we should try to
324  * reorder the parameter ModelAction against.
325  *
326  * @param the ModelAction to find backtracking points for.
327  */
328 void ModelChecker::set_backtracking(ModelAction *act)
329 {
330         Thread *t = get_thread(act);
331         ModelAction * prev = get_last_conflict(act);
332         if (prev == NULL)
333                 return;
334
335         Node * node = prev->get_node()->get_parent();
336
337         int low_tid, high_tid;
338         if (node->is_enabled(t)) {
339                 low_tid = id_to_int(act->get_tid());
340                 high_tid = low_tid+1;
341         } else {
342                 low_tid = 0;
343                 high_tid = get_num_threads();
344         }
345
346         for(int i = low_tid; i < high_tid; i++) {
347                 thread_id_t tid = int_to_id(i);
348
349                 /* Don't backtrack into a point where the thread is disabled or sleeping. */
350                 if (node->get_enabled_array()[i]!=THREAD_ENABLED)
351                         continue;
352         
353                 /* Check if this has been explored already */
354                 if (node->has_been_explored(tid))
355                         continue;
356
357                 /* See if fairness allows */
358                 if (model->params.fairwindow != 0 && !node->has_priority(tid)) {
359                         bool unfair=false;
360                         for(int t=0;t<node->get_num_threads();t++) {
361                                 thread_id_t tother=int_to_id(t);
362                                 if (node->is_enabled(tother) && node->has_priority(tother)) {
363                                         unfair=true;
364                                         break;
365                                 }
366                         }
367                         if (unfair)
368                                 continue;
369                 }
370                 /* Cache the latest backtracking point */
371                 if (!priv->next_backtrack || *prev > *priv->next_backtrack)
372                         priv->next_backtrack = prev;
373
374                 /* If this is a new backtracking point, mark the tree */
375                 if (!node->set_backtrack(tid))
376                         continue;
377                 DEBUG("Setting backtrack: conflict = %d, instead tid = %d\n",
378                                         id_to_int(prev->get_tid()),
379                                         id_to_int(t->get_id()));
380                 if (DBG_ENABLED()) {
381                         prev->print();
382                         act->print();
383                 }
384         }
385 }
386
387 /**
388  * Returns last backtracking point. The model checker will explore a different
389  * path for this point in the next execution.
390  * @return The ModelAction at which the next execution should diverge.
391  */
392 ModelAction * ModelChecker::get_next_backtrack()
393 {
394         ModelAction *next = priv->next_backtrack;
395         priv->next_backtrack = NULL;
396         return next;
397 }
398
399 /**
400  * Processes a read or rmw model action.
401  * @param curr is the read model action to process.
402  * @param second_part_of_rmw is boolean that is true is this is the second action of a rmw.
403  * @return True if processing this read updates the mo_graph.
404  */
405 bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw)
406 {
407         uint64_t value;
408         bool updated = false;
409         while (true) {
410                 const ModelAction *reads_from = curr->get_node()->get_read_from();
411                 if (reads_from != NULL) {
412                         mo_graph->startChanges();
413
414                         value = reads_from->get_value();
415                         bool r_status = false;
416
417                         if (!second_part_of_rmw) {
418                                 check_recency(curr, reads_from);
419                                 r_status = r_modification_order(curr, reads_from);
420                         }
421
422
423                         if (!second_part_of_rmw&&!isfeasible()&&(curr->get_node()->increment_read_from()||curr->get_node()->increment_future_value())) {
424                                 mo_graph->rollbackChanges();
425                                 too_many_reads = false;
426                                 continue;
427                         }
428
429                         curr->read_from(reads_from);
430                         mo_graph->commitChanges();
431                         mo_check_promises(curr->get_tid(), reads_from);
432
433                         updated |= r_status;
434                 } else if (!second_part_of_rmw) {
435                         /* Read from future value */
436                         value = curr->get_node()->get_future_value();
437                         modelclock_t expiration = curr->get_node()->get_future_value_expiration();
438                         curr->read_from(NULL);
439                         Promise *valuepromise = new Promise(curr, value, expiration);
440                         promises->push_back(valuepromise);
441                 }
442                 get_thread(curr)->set_return_value(value);
443                 return updated;
444         }
445 }
446
447 /**
448  * Processes a lock, trylock, or unlock model action.  @param curr is
449  * the read model action to process.
450  *
451  * The try lock operation checks whether the lock is taken.  If not,
452  * it falls to the normal lock operation case.  If so, it returns
453  * fail.
454  *
455  * The lock operation has already been checked that it is enabled, so
456  * it just grabs the lock and synchronizes with the previous unlock.
457  *
458  * The unlock operation has to re-enable all of the threads that are
459  * waiting on the lock.
460  *
461  * @return True if synchronization was updated; false otherwise
462  */
463 bool ModelChecker::process_mutex(ModelAction *curr) {
464         std::mutex *mutex = (std::mutex *)curr->get_location();
465         struct std::mutex_state *state = mutex->get_state();
466         switch (curr->get_type()) {
467         case ATOMIC_TRYLOCK: {
468                 bool success = !state->islocked;
469                 curr->set_try_lock(success);
470                 if (!success) {
471                         get_thread(curr)->set_return_value(0);
472                         break;
473                 }
474                 get_thread(curr)->set_return_value(1);
475         }
476                 //otherwise fall into the lock case
477         case ATOMIC_LOCK: {
478                 if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock) {
479                         printf("Lock access before initialization\n");
480                         set_assert();
481                 }
482                 state->islocked = true;
483                 ModelAction *unlock = get_last_unlock(curr);
484                 //synchronize with the previous unlock statement
485                 if (unlock != NULL) {
486                         curr->synchronize_with(unlock);
487                         return true;
488                 }
489                 break;
490         }
491         case ATOMIC_UNLOCK: {
492                 //unlock the lock
493                 state->islocked = false;
494                 //wake up the other threads
495                 action_list_t *waiters = lock_waiters_map->get_safe_ptr(curr->get_location());
496                 //activate all the waiting threads
497                 for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
498                         scheduler->wake(get_thread(*rit));
499                 }
500                 waiters->clear();
501                 break;
502         }
503         default:
504                 ASSERT(0);
505         }
506         return false;
507 }
508
509 /**
510  * Process a write ModelAction
511  * @param curr The ModelAction to process
512  * @return True if the mo_graph was updated or promises were resolved
513  */
514 bool ModelChecker::process_write(ModelAction *curr)
515 {
516         bool updated_mod_order = w_modification_order(curr);
517         bool updated_promises = resolve_promises(curr);
518
519         if (promises->size() == 0) {
520                 for (unsigned int i = 0; i < futurevalues->size(); i++) {
521                         struct PendingFutureValue pfv = (*futurevalues)[i];
522                         //Do more ambitious checks now that mo is more complete
523                         if (mo_may_allow(pfv.writer, pfv.act)&&
524                                         pfv.act->get_node()->add_future_value(pfv.writer->get_value(), pfv.writer->get_seq_number()+params.maxfuturedelay) &&
525                                         (!priv->next_backtrack || *pfv.act > *priv->next_backtrack))
526                                 priv->next_backtrack = pfv.act;
527                 }
528                 futurevalues->resize(0);
529         }
530
531         mo_graph->commitChanges();
532         mo_check_promises(curr->get_tid(), curr);
533
534         get_thread(curr)->set_return_value(VALUE_NONE);
535         return updated_mod_order || updated_promises;
536 }
537
538 /**
539  * @brief Process the current action for thread-related activity
540  *
541  * Performs current-action processing for a THREAD_* ModelAction. Proccesses
542  * may include setting Thread status, completing THREAD_FINISH/THREAD_JOIN
543  * synchronization, etc.  This function is a no-op for non-THREAD actions
544  * (e.g., ATOMIC_{READ,WRITE,RMW,LOCK}, etc.)
545  *
546  * @param curr The current action
547  * @return True if synchronization was updated or a thread completed
548  */
549 bool ModelChecker::process_thread_action(ModelAction *curr)
550 {
551         bool updated = false;
552
553         switch (curr->get_type()) {
554         case THREAD_CREATE: {
555                 Thread *th = (Thread *)curr->get_location();
556                 th->set_creation(curr);
557                 break;
558         }
559         case THREAD_JOIN: {
560                 Thread *waiting, *blocking;
561                 waiting = get_thread(curr);
562                 blocking = (Thread *)curr->get_location();
563                 if (!blocking->is_complete()) {
564                         blocking->push_wait_list(curr);
565                         scheduler->sleep(waiting);
566                 } else {
567                         do_complete_join(curr);
568                         updated = true; /* trigger rel-seq checks */
569                 }
570                 break;
571         }
572         case THREAD_FINISH: {
573                 Thread *th = get_thread(curr);
574                 while (!th->wait_list_empty()) {
575                         ModelAction *act = th->pop_wait_list();
576                         Thread *wake = get_thread(act);
577                         scheduler->wake(wake);
578                         do_complete_join(act);
579                         updated = true; /* trigger rel-seq checks */
580                 }
581                 th->complete();
582                 updated = true; /* trigger rel-seq checks */
583                 break;
584         }
585         case THREAD_START: {
586                 check_promises(curr->get_tid(), NULL, curr->get_cv());
587                 break;
588         }
589         default:
590                 break;
591         }
592
593         return updated;
594 }
595
596 /**
597  * @brief Process the current action for release sequence fixup activity
598  *
599  * Performs model-checker release sequence fixups for the current action,
600  * forcing a single pending release sequence to break (with a given, potential
601  * "loose" write) or to complete (i.e., synchronize). If a pending release
602  * sequence forms a complete release sequence, then we must perform the fixup
603  * synchronization, mo_graph additions, etc.
604  *
605  * @param curr The current action; must be a release sequence fixup action
606  * @param work_queue The work queue to which to add work items as they are
607  * generated
608  */
609 void ModelChecker::process_relseq_fixup(ModelAction *curr, work_queue_t *work_queue)
610 {
611         const ModelAction *write = curr->get_node()->get_relseq_break();
612         struct release_seq *sequence = pending_rel_seqs->back();
613         pending_rel_seqs->pop_back();
614         ASSERT(sequence);
615         ModelAction *acquire = sequence->acquire;
616         const ModelAction *rf = sequence->rf;
617         const ModelAction *release = sequence->release;
618         ASSERT(acquire);
619         ASSERT(release);
620         ASSERT(rf);
621         ASSERT(release->same_thread(rf));
622
623         if (write == NULL) {
624                 /**
625                  * @todo Forcing a synchronization requires that we set
626                  * modification order constraints. For instance, we can't allow
627                  * a fixup sequence in which two separate read-acquire
628                  * operations read from the same sequence, where the first one
629                  * synchronizes and the other doesn't. Essentially, we can't
630                  * allow any writes to insert themselves between 'release' and
631                  * 'rf'
632                  */
633
634                 /* Must synchronize */
635                 if (!acquire->synchronize_with(release)) {
636                         set_bad_synchronization();
637                         return;
638                 }
639                 /* Re-check all pending release sequences */
640                 work_queue->push_back(CheckRelSeqWorkEntry(NULL));
641                 /* Re-check act for mo_graph edges */
642                 work_queue->push_back(MOEdgeWorkEntry(acquire));
643
644                 /* propagate synchronization to later actions */
645                 action_list_t::reverse_iterator rit = action_trace->rbegin();
646                 for (; (*rit) != acquire; rit++) {
647                         ModelAction *propagate = *rit;
648                         if (acquire->happens_before(propagate)) {
649                                 propagate->synchronize_with(acquire);
650                                 /* Re-check 'propagate' for mo_graph edges */
651                                 work_queue->push_back(MOEdgeWorkEntry(propagate));
652                         }
653                 }
654         } else {
655                 /* Break release sequence with new edges:
656                  *   release --mo--> write --mo--> rf */
657                 mo_graph->addEdge(release, write);
658                 mo_graph->addEdge(write, rf);
659         }
660
661         /* See if we have realized a data race */
662         if (checkDataRaces())
663                 set_assert();
664 }
665
666 /**
667  * Initialize the current action by performing one or more of the following
668  * actions, as appropriate: merging RMWR and RMWC/RMW actions, stepping forward
669  * in the NodeStack, manipulating backtracking sets, allocating and
670  * initializing clock vectors, and computing the promises to fulfill.
671  *
672  * @param curr The current action, as passed from the user context; may be
673  * freed/invalidated after the execution of this function
674  * @return The current action, as processed by the ModelChecker. Is only the
675  * same as the parameter @a curr if this is a newly-explored action.
676  */
677 ModelAction * ModelChecker::initialize_curr_action(ModelAction *curr)
678 {
679         ModelAction *newcurr;
680
681         if (curr->is_rmwc() || curr->is_rmw()) {
682                 newcurr = process_rmw(curr);
683                 delete curr;
684
685                 if (newcurr->is_rmw())
686                         compute_promises(newcurr);
687                 return newcurr;
688         }
689
690         curr->set_seq_number(get_next_seq_num());
691
692         newcurr = node_stack->explore_action(curr, scheduler->get_enabled());
693         if (newcurr) {
694                 /* First restore type and order in case of RMW operation */
695                 if (curr->is_rmwr())
696                         newcurr->copy_typeandorder(curr);
697
698                 ASSERT(curr->get_location() == newcurr->get_location());
699                 newcurr->copy_from_new(curr);
700
701                 /* Discard duplicate ModelAction; use action from NodeStack */
702                 delete curr;
703
704                 /* Always compute new clock vector */
705                 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
706         } else {
707                 newcurr = curr;
708
709                 /* Always compute new clock vector */
710                 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
711                 /*
712                  * Perform one-time actions when pushing new ModelAction onto
713                  * NodeStack
714                  */
715                 if (newcurr->is_write())
716                         compute_promises(newcurr);
717                 else if (newcurr->is_relseq_fixup())
718                         compute_relseq_breakwrites(newcurr);
719         }
720         return newcurr;
721 }
722
723 /**
724  * This method checks whether a model action is enabled at the given point.
725  * At this point, it checks whether a lock operation would be successful at this point.
726  * If not, it puts the thread in a waiter list.
727  * @param curr is the ModelAction to check whether it is enabled.
728  * @return a bool that indicates whether the action is enabled.
729  */
730 bool ModelChecker::check_action_enabled(ModelAction *curr) {
731         if (curr->is_lock()) {
732                 std::mutex * lock = (std::mutex *)curr->get_location();
733                 struct std::mutex_state * state = lock->get_state();
734                 if (state->islocked) {
735                         //Stick the action in the appropriate waiting queue
736                         lock_waiters_map->get_safe_ptr(curr->get_location())->push_back(curr);
737                         return false;
738                 }
739         }
740
741         return true;
742 }
743
744 /**
745  * This is the heart of the model checker routine. It performs model-checking
746  * actions corresponding to a given "current action." Among other processes, it
747  * calculates reads-from relationships, updates synchronization clock vectors,
748  * forms a memory_order constraints graph, and handles replay/backtrack
749  * execution when running permutations of previously-observed executions.
750  *
751  * @param curr The current action to process
752  * @return The next Thread that must be executed. May be NULL if ModelChecker
753  * makes no choice (e.g., according to replay execution, combining RMW actions,
754  * etc.)
755  */
756 Thread * ModelChecker::check_current_action(ModelAction *curr)
757 {
758         ASSERT(curr);
759         bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
760
761         if (!check_action_enabled(curr)) {
762                 /* Make the execution look like we chose to run this action
763                  * much later, when a lock is actually available to release */
764                 get_current_thread()->set_pending(curr);
765                 scheduler->sleep(get_current_thread());
766                 return get_next_thread(NULL);
767         }
768
769         wake_up_sleeping_actions(curr);
770
771         ModelAction *newcurr = initialize_curr_action(curr);
772
773
774         /* Add the action to lists before any other model-checking tasks */
775         if (!second_part_of_rmw)
776                 add_action_to_lists(newcurr);
777
778         /* Build may_read_from set for newly-created actions */
779         if (curr == newcurr && curr->is_read())
780                 build_reads_from_past(curr);
781         curr = newcurr;
782
783         /* Initialize work_queue with the "current action" work */
784         work_queue_t work_queue(1, CheckCurrWorkEntry(curr));
785         while (!work_queue.empty()) {
786                 WorkQueueEntry work = work_queue.front();
787                 work_queue.pop_front();
788
789                 switch (work.type) {
790                 case WORK_CHECK_CURR_ACTION: {
791                         ModelAction *act = work.action;
792                         bool update = false; /* update this location's release seq's */
793                         bool update_all = false; /* update all release seq's */
794
795                         if (process_thread_action(curr))
796                                 update_all = true;
797
798                         if (act->is_read() && process_read(act, second_part_of_rmw))
799                                 update = true;
800
801                         if (act->is_write() && process_write(act))
802                                 update = true;
803
804                         if (act->is_mutex_op() && process_mutex(act))
805                                 update_all = true;
806
807                         if (act->is_relseq_fixup())
808                                 process_relseq_fixup(curr, &work_queue);
809
810                         if (update_all)
811                                 work_queue.push_back(CheckRelSeqWorkEntry(NULL));
812                         else if (update)
813                                 work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
814                         break;
815                 }
816                 case WORK_CHECK_RELEASE_SEQ:
817                         resolve_release_sequences(work.location, &work_queue);
818                         break;
819                 case WORK_CHECK_MO_EDGES: {
820                         /** @todo Complete verification of work_queue */
821                         ModelAction *act = work.action;
822                         bool updated = false;
823
824                         if (act->is_read()) {
825                                 const ModelAction *rf = act->get_reads_from();
826                                 if (rf != NULL && r_modification_order(act, rf))
827                                         updated = true;
828                         }
829                         if (act->is_write()) {
830                                 if (w_modification_order(act))
831                                         updated = true;
832                         }
833                         mo_graph->commitChanges();
834
835                         if (updated)
836                                 work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
837                         break;
838                 }
839                 default:
840                         ASSERT(false);
841                         break;
842                 }
843         }
844
845         check_curr_backtracking(curr);
846         set_backtracking(curr);
847         return get_next_thread(curr);
848 }
849
850 /**
851  * Complete a THREAD_JOIN operation, by synchronizing with the THREAD_FINISH
852  * operation from the Thread it is joining with. Must be called after the
853  * completion of the Thread in question.
854  * @param join The THREAD_JOIN action
855  */
856 void ModelChecker::do_complete_join(ModelAction *join)
857 {
858         Thread *blocking = (Thread *)join->get_location();
859         ModelAction *act = get_last_action(blocking->get_id());
860         join->synchronize_with(act);
861 }
862
863 void ModelChecker::check_curr_backtracking(ModelAction * curr) {
864         Node *currnode = curr->get_node();
865         Node *parnode = currnode->get_parent();
866
867         if ((!parnode->backtrack_empty() ||
868                          !currnode->read_from_empty() ||
869                          !currnode->future_value_empty() ||
870                          !currnode->promise_empty() ||
871                          !currnode->relseq_break_empty())
872                         && (!priv->next_backtrack ||
873                                         *curr > *priv->next_backtrack)) {
874                 priv->next_backtrack = curr;
875         }
876 }
877
878 bool ModelChecker::promises_expired() {
879         for (unsigned int promise_index = 0; promise_index < promises->size(); promise_index++) {
880                 Promise *promise = (*promises)[promise_index];
881                 if (promise->get_expiration()<priv->used_sequence_numbers) {
882                         return true;
883                 }
884         }
885         return false;
886 }
887
888 /** @return whether the current partial trace must be a prefix of a
889  * feasible trace. */
890 bool ModelChecker::isfeasibleprefix() {
891         return promises->size() == 0 && pending_rel_seqs->size() == 0;
892 }
893
894 /** @return whether the current partial trace is feasible. */
895 bool ModelChecker::isfeasible() {
896         if (DBG_ENABLED() && mo_graph->checkForRMWViolation())
897                 DEBUG("Infeasible: RMW violation\n");
898
899         return !mo_graph->checkForRMWViolation() && isfeasibleotherthanRMW();
900 }
901
902 /** @return whether the current partial trace is feasible other than
903  * multiple RMW reading from the same store. */
904 bool ModelChecker::isfeasibleotherthanRMW() {
905         if (DBG_ENABLED()) {
906                 if (mo_graph->checkForCycles())
907                         DEBUG("Infeasible: modification order cycles\n");
908                 if (failed_promise)
909                         DEBUG("Infeasible: failed promise\n");
910                 if (too_many_reads)
911                         DEBUG("Infeasible: too many reads\n");
912                 if (bad_synchronization)
913                         DEBUG("Infeasible: bad synchronization ordering\n");
914                 if (promises_expired())
915                         DEBUG("Infeasible: promises expired\n");
916         }
917         return !mo_graph->checkForCycles() && !failed_promise && !too_many_reads && !bad_synchronization && !promises_expired();
918 }
919
920 /** Returns whether the current completed trace is feasible. */
921 bool ModelChecker::isfinalfeasible() {
922         if (DBG_ENABLED() && promises->size() != 0)
923                 DEBUG("Infeasible: unrevolved promises\n");
924
925         return isfeasible() && promises->size() == 0;
926 }
927
928 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
929 ModelAction * ModelChecker::process_rmw(ModelAction *act) {
930         ModelAction *lastread = get_last_action(act->get_tid());
931         lastread->process_rmw(act);
932         if (act->is_rmw() && lastread->get_reads_from()!=NULL) {
933                 mo_graph->addRMWEdge(lastread->get_reads_from(), lastread);
934                 mo_graph->commitChanges();
935         }
936         return lastread;
937 }
938
939 /**
940  * Checks whether a thread has read from the same write for too many times
941  * without seeing the effects of a later write.
942  *
943  * Basic idea:
944  * 1) there must a different write that we could read from that would satisfy the modification order,
945  * 2) we must have read from the same value in excess of maxreads times, and
946  * 3) that other write must have been in the reads_from set for maxreads times.
947  *
948  * If so, we decide that the execution is no longer feasible.
949  */
950 void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) {
951         if (params.maxreads != 0) {
952
953                 if (curr->get_node()->get_read_from_size() <= 1)
954                         return;
955                 //Must make sure that execution is currently feasible...  We could
956                 //accidentally clear by rolling back
957                 if (!isfeasible())
958                         return;
959                 std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
960                 int tid = id_to_int(curr->get_tid());
961
962                 /* Skip checks */
963                 if ((int)thrd_lists->size() <= tid)
964                         return;
965                 action_list_t *list = &(*thrd_lists)[tid];
966
967                 action_list_t::reverse_iterator rit = list->rbegin();
968                 /* Skip past curr */
969                 for (; (*rit) != curr; rit++)
970                         ;
971                 /* go past curr now */
972                 rit++;
973
974                 action_list_t::reverse_iterator ritcopy = rit;
975                 //See if we have enough reads from the same value
976                 int count = 0;
977                 for (; count < params.maxreads; rit++,count++) {
978                         if (rit==list->rend())
979                                 return;
980                         ModelAction *act = *rit;
981                         if (!act->is_read())
982                                 return;
983                         
984                         if (act->get_reads_from() != rf)
985                                 return;
986                         if (act->get_node()->get_read_from_size() <= 1)
987                                 return;
988                 }
989                 for (int i = 0; i<curr->get_node()->get_read_from_size(); i++) {
990                         //Get write
991                         const ModelAction * write = curr->get_node()->get_read_from_at(i);
992
993                         //Need a different write
994                         if (write==rf)
995                                 continue;
996
997                         /* Test to see whether this is a feasible write to read from*/
998                         mo_graph->startChanges();
999                         r_modification_order(curr, write);
1000                         bool feasiblereadfrom = isfeasible();
1001                         mo_graph->rollbackChanges();
1002
1003                         if (!feasiblereadfrom)
1004                                 continue;
1005                         rit = ritcopy;
1006
1007                         bool feasiblewrite = true;
1008                         //new we need to see if this write works for everyone
1009
1010                         for (int loop = count; loop>0; loop--,rit++) {
1011                                 ModelAction *act=*rit;
1012                                 bool foundvalue = false;
1013                                 for (int j = 0; j<act->get_node()->get_read_from_size(); j++) {
1014                                         if (act->get_node()->get_read_from_at(i)==write) {
1015                                                 foundvalue = true;
1016                                                 break;
1017                                         }
1018                                 }
1019                                 if (!foundvalue) {
1020                                         feasiblewrite = false;
1021                                         break;
1022                                 }
1023                         }
1024                         if (feasiblewrite) {
1025                                 too_many_reads = true;
1026                                 return;
1027                         }
1028                 }
1029         }
1030 }
1031
1032 /**
1033  * Updates the mo_graph with the constraints imposed from the current
1034  * read.
1035  *
1036  * Basic idea is the following: Go through each other thread and find
1037  * the lastest action that happened before our read.  Two cases:
1038  *
1039  * (1) The action is a write => that write must either occur before
1040  * the write we read from or be the write we read from.
1041  *
1042  * (2) The action is a read => the write that that action read from
1043  * must occur before the write we read from or be the same write.
1044  *
1045  * @param curr The current action. Must be a read.
1046  * @param rf The action that curr reads from. Must be a write.
1047  * @return True if modification order edges were added; false otherwise
1048  */
1049 bool ModelChecker::r_modification_order(ModelAction *curr, const ModelAction *rf)
1050 {
1051         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
1052         unsigned int i;
1053         bool added = false;
1054         ASSERT(curr->is_read());
1055
1056         /* Iterate over all threads */
1057         for (i = 0; i < thrd_lists->size(); i++) {
1058                 /* Iterate over actions in thread, starting from most recent */
1059                 action_list_t *list = &(*thrd_lists)[i];
1060                 action_list_t::reverse_iterator rit;
1061                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1062                         ModelAction *act = *rit;
1063
1064                         /*
1065                          * Include at most one act per-thread that "happens
1066                          * before" curr. Don't consider reflexively.
1067                          */
1068                         if (act->happens_before(curr) && act != curr) {
1069                                 if (act->is_write()) {
1070                                         if (rf != act) {
1071                                                 mo_graph->addEdge(act, rf);
1072                                                 added = true;
1073                                         }
1074                                 } else {
1075                                         const ModelAction *prevreadfrom = act->get_reads_from();
1076                                         //if the previous read is unresolved, keep going...
1077                                         if (prevreadfrom == NULL)
1078                                                 continue;
1079
1080                                         if (rf != prevreadfrom) {
1081                                                 mo_graph->addEdge(prevreadfrom, rf);
1082                                                 added = true;
1083                                         }
1084                                 }
1085                                 break;
1086                         }
1087                 }
1088         }
1089
1090         return added;
1091 }
1092
1093 /** This method fixes up the modification order when we resolve a
1094  *  promises.  The basic problem is that actions that occur after the
1095  *  read curr could not property add items to the modification order
1096  *  for our read.
1097  *
1098  *  So for each thread, we find the earliest item that happens after
1099  *  the read curr.  This is the item we have to fix up with additional
1100  *  constraints.  If that action is write, we add a MO edge between
1101  *  the Action rf and that action.  If the action is a read, we add a
1102  *  MO edge between the Action rf, and whatever the read accessed.
1103  *
1104  * @param curr is the read ModelAction that we are fixing up MO edges for.
1105  * @param rf is the write ModelAction that curr reads from.
1106  *
1107  */
1108 void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelAction *rf)
1109 {
1110         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
1111         unsigned int i;
1112         ASSERT(curr->is_read());
1113
1114         /* Iterate over all threads */
1115         for (i = 0; i < thrd_lists->size(); i++) {
1116                 /* Iterate over actions in thread, starting from most recent */
1117                 action_list_t *list = &(*thrd_lists)[i];
1118                 action_list_t::reverse_iterator rit;
1119                 ModelAction *lastact = NULL;
1120
1121                 /* Find last action that happens after curr that is either not curr or a rmw */
1122                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1123                         ModelAction *act = *rit;
1124                         if (curr->happens_before(act) && (curr != act || curr->is_rmw())) {
1125                                 lastact = act;
1126                         } else
1127                                 break;
1128                 }
1129
1130                         /* Include at most one act per-thread that "happens before" curr */
1131                 if (lastact != NULL) {
1132                         if (lastact==curr) {
1133                                 //Case 1: The resolved read is a RMW, and we need to make sure
1134                                 //that the write portion of the RMW mod order after rf
1135
1136                                 mo_graph->addEdge(rf, lastact);
1137                         } else if (lastact->is_read()) {
1138                                 //Case 2: The resolved read is a normal read and the next
1139                                 //operation is a read, and we need to make sure the value read
1140                                 //is mod ordered after rf
1141
1142                                 const ModelAction *postreadfrom = lastact->get_reads_from();
1143                                 if (postreadfrom != NULL&&rf != postreadfrom)
1144                                         mo_graph->addEdge(rf, postreadfrom);
1145                         } else {
1146                                 //Case 3: The resolved read is a normal read and the next
1147                                 //operation is a write, and we need to make sure that the
1148                                 //write is mod ordered after rf
1149                                 if (lastact!=rf)
1150                                         mo_graph->addEdge(rf, lastact);
1151                         }
1152                         break;
1153                 }
1154         }
1155 }
1156
1157 /**
1158  * Updates the mo_graph with the constraints imposed from the current write.
1159  *
1160  * Basic idea is the following: Go through each other thread and find
1161  * the lastest action that happened before our write.  Two cases:
1162  *
1163  * (1) The action is a write => that write must occur before
1164  * the current write
1165  *
1166  * (2) The action is a read => the write that that action read from
1167  * must occur before the current write.
1168  *
1169  * This method also handles two other issues:
1170  *
1171  * (I) Sequential Consistency: Making sure that if the current write is
1172  * seq_cst, that it occurs after the previous seq_cst write.
1173  *
1174  * (II) Sending the write back to non-synchronizing reads.
1175  *
1176  * @param curr The current action. Must be a write.
1177  * @return True if modification order edges were added; false otherwise
1178  */
1179 bool ModelChecker::w_modification_order(ModelAction *curr)
1180 {
1181         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
1182         unsigned int i;
1183         bool added = false;
1184         ASSERT(curr->is_write());
1185
1186         if (curr->is_seqcst()) {
1187                 /* We have to at least see the last sequentially consistent write,
1188                          so we are initialized. */
1189                 ModelAction *last_seq_cst = get_last_seq_cst(curr);
1190                 if (last_seq_cst != NULL) {
1191                         mo_graph->addEdge(last_seq_cst, curr);
1192                         added = true;
1193                 }
1194         }
1195
1196         /* Iterate over all threads */
1197         for (i = 0; i < thrd_lists->size(); i++) {
1198                 /* Iterate over actions in thread, starting from most recent */
1199                 action_list_t *list = &(*thrd_lists)[i];
1200                 action_list_t::reverse_iterator rit;
1201                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1202                         ModelAction *act = *rit;
1203                         if (act == curr) {
1204                                 /*
1205                                  * 1) If RMW and it actually read from something, then we
1206                                  * already have all relevant edges, so just skip to next
1207                                  * thread.
1208                                  * 
1209                                  * 2) If RMW and it didn't read from anything, we should
1210                                  * whatever edge we can get to speed up convergence.
1211                                  *
1212                                  * 3) If normal write, we need to look at earlier actions, so
1213                                  * continue processing list.
1214                                  */
1215                                 if (curr->is_rmw()) {
1216                                         if (curr->get_reads_from()!=NULL)
1217                                                 break;
1218                                         else 
1219                                                 continue;
1220                                 } else
1221                                         continue;
1222                         }
1223
1224                         /*
1225                          * Include at most one act per-thread that "happens
1226                          * before" curr
1227                          */
1228                         if (act->happens_before(curr)) {
1229                                 /*
1230                                  * Note: if act is RMW, just add edge:
1231                                  *   act --mo--> curr
1232                                  * The following edge should be handled elsewhere:
1233                                  *   readfrom(act) --mo--> act
1234                                  */
1235                                 if (act->is_write())
1236                                         mo_graph->addEdge(act, curr);
1237                                 else if (act->is_read()) { 
1238                                         //if previous read accessed a null, just keep going
1239                                         if (act->get_reads_from() == NULL)
1240                                                 continue;
1241                                         mo_graph->addEdge(act->get_reads_from(), curr);
1242                                 }
1243                                 added = true;
1244                                 break;
1245                         } else if (act->is_read() && !act->could_synchronize_with(curr) &&
1246                                                      !act->same_thread(curr)) {
1247                                 /* We have an action that:
1248                                    (1) did not happen before us
1249                                    (2) is a read and we are a write
1250                                    (3) cannot synchronize with us
1251                                    (4) is in a different thread
1252                                    =>
1253                                    that read could potentially read from our write.  Note that
1254                                    these checks are overly conservative at this point, we'll
1255                                    do more checks before actually removing the
1256                                    pendingfuturevalue.
1257
1258                                  */
1259                                 if (thin_air_constraint_may_allow(curr, act)) {
1260                                         if (isfeasible() ||
1261                                                         (curr->is_rmw() && act->is_rmw() && curr->get_reads_from() == act->get_reads_from() && isfeasibleotherthanRMW())) {
1262                                                 struct PendingFutureValue pfv = {curr,act};
1263                                                 futurevalues->push_back(pfv);
1264                                         }
1265                                 }
1266                         }
1267                 }
1268         }
1269
1270         return added;
1271 }
1272
1273 /** Arbitrary reads from the future are not allowed.  Section 29.3
1274  * part 9 places some constraints.  This method checks one result of constraint
1275  * constraint.  Others require compiler support. */
1276 bool ModelChecker::thin_air_constraint_may_allow(const ModelAction * writer, const ModelAction *reader) {
1277         if (!writer->is_rmw())
1278                 return true;
1279
1280         if (!reader->is_rmw())
1281                 return true;
1282
1283         for (const ModelAction *search = writer->get_reads_from(); search != NULL; search = search->get_reads_from()) {
1284                 if (search == reader)
1285                         return false;
1286                 if (search->get_tid() == reader->get_tid() &&
1287                                 search->happens_before(reader))
1288                         break;
1289         }
1290
1291         return true;
1292 }
1293
1294 /** Arbitrary reads from the future are not allowed.  Section 29.3
1295  * part 9 places some constraints.  This method checks one result of constraint
1296  * constraint.  Others require compiler support. */
1297 bool ModelChecker::mo_may_allow(const ModelAction * writer, const ModelAction *reader) {
1298         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(reader->get_location());
1299
1300         //Get write that follows reader action
1301         action_list_t *list = &(*thrd_lists)[id_to_int(reader->get_tid())];
1302         action_list_t::reverse_iterator rit;
1303         ModelAction *first_write_after_read=NULL;
1304
1305         for (rit = list->rbegin(); rit != list->rend(); rit++) {
1306                 ModelAction *act = *rit;
1307                 if (act==reader)
1308                         break;
1309                 if (act->is_write())
1310                         first_write_after_read=act;
1311         }
1312
1313         if (first_write_after_read==NULL)
1314                 return true;
1315
1316         return !mo_graph->checkReachable(first_write_after_read, writer);
1317 }
1318
1319
1320
1321 /**
1322  * Finds the head(s) of the release sequence(s) containing a given ModelAction.
1323  * The ModelAction under consideration is expected to be taking part in
1324  * release/acquire synchronization as an object of the "reads from" relation.
1325  * Note that this can only provide release sequence support for RMW chains
1326  * which do not read from the future, as those actions cannot be traced until
1327  * their "promise" is fulfilled. Similarly, we may not even establish the
1328  * presence of a release sequence with certainty, as some modification order
1329  * constraints may be decided further in the future. Thus, this function
1330  * "returns" two pieces of data: a pass-by-reference vector of @a release_heads
1331  * and a boolean representing certainty.
1332  *
1333  * @param rf The action that might be part of a release sequence. Must be a
1334  * write.
1335  * @param release_heads A pass-by-reference style return parameter. After
1336  * execution of this function, release_heads will contain the heads of all the
1337  * relevant release sequences, if any exists with certainty
1338  * @param pending A pass-by-reference style return parameter which is only used
1339  * when returning false (i.e., uncertain). Returns most information regarding
1340  * an uncertain release sequence, including any write operations that might
1341  * break the sequence.
1342  * @return true, if the ModelChecker is certain that release_heads is complete;
1343  * false otherwise
1344  */
1345 bool ModelChecker::release_seq_heads(const ModelAction *rf,
1346                 rel_heads_list_t *release_heads,
1347                 struct release_seq *pending) const
1348 {
1349         /* Only check for release sequences if there are no cycles */
1350         if (mo_graph->checkForCycles())
1351                 return false;
1352
1353         while (rf) {
1354                 ASSERT(rf->is_write());
1355
1356                 if (rf->is_release())
1357                         release_heads->push_back(rf);
1358                 if (!rf->is_rmw())
1359                         break; /* End of RMW chain */
1360
1361                 /** @todo Need to be smarter here...  In the linux lock
1362                  * example, this will run to the beginning of the program for
1363                  * every acquire. */
1364                 /** @todo The way to be smarter here is to keep going until 1
1365                  * thread has a release preceded by an acquire and you've seen
1366                  *       both. */
1367
1368                 /* acq_rel RMW is a sufficient stopping condition */
1369                 if (rf->is_acquire() && rf->is_release())
1370                         return true; /* complete */
1371
1372                 rf = rf->get_reads_from();
1373         };
1374         if (!rf) {
1375                 /* read from future: need to settle this later */
1376                 pending->rf = NULL;
1377                 return false; /* incomplete */
1378         }
1379
1380         if (rf->is_release())
1381                 return true; /* complete */
1382
1383         /* else relaxed write; check modification order for contiguous subsequence
1384          * -> rf must be same thread as release */
1385         int tid = id_to_int(rf->get_tid());
1386         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(rf->get_location());
1387         action_list_t *list = &(*thrd_lists)[tid];
1388         action_list_t::const_reverse_iterator rit;
1389
1390         /* Find rf in the thread list */
1391         rit = std::find(list->rbegin(), list->rend(), rf);
1392         ASSERT(rit != list->rend());
1393
1394         /* Find the last write/release */
1395         for (; rit != list->rend(); rit++)
1396                 if ((*rit)->is_release())
1397                         break;
1398         if (rit == list->rend()) {
1399                 /* No write-release in this thread */
1400                 return true; /* complete */
1401         }
1402         ModelAction *release = *rit;
1403
1404         ASSERT(rf->same_thread(release));
1405
1406         pending->writes.clear();
1407
1408         bool certain = true;
1409         for (unsigned int i = 0; i < thrd_lists->size(); i++) {
1410                 if (id_to_int(rf->get_tid()) == (int)i)
1411                         continue;
1412                 list = &(*thrd_lists)[i];
1413
1414                 /* Can we ensure no future writes from this thread may break
1415                  * the release seq? */
1416                 bool future_ordered = false;
1417
1418                 ModelAction *last = get_last_action(int_to_id(i));
1419                 Thread *th = get_thread(int_to_id(i));
1420                 if ((last && rf->happens_before(last)) ||
1421                                 !scheduler->is_enabled(th) ||
1422                                 th->is_complete())
1423                         future_ordered = true;
1424
1425                 ASSERT(!th->is_model_thread() || future_ordered);
1426
1427                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1428                         const ModelAction *act = *rit;
1429                         /* Reach synchronization -> this thread is complete */
1430                         if (act->happens_before(release))
1431                                 break;
1432                         if (rf->happens_before(act)) {
1433                                 future_ordered = true;
1434                                 continue;
1435                         }
1436
1437                         /* Only writes can break release sequences */
1438                         if (!act->is_write())
1439                                 continue;
1440
1441                         /* Check modification order */
1442                         if (mo_graph->checkReachable(rf, act)) {
1443                                 /* rf --mo--> act */
1444                                 future_ordered = true;
1445                                 continue;
1446                         }
1447                         if (mo_graph->checkReachable(act, release))
1448                                 /* act --mo--> release */
1449                                 break;
1450                         if (mo_graph->checkReachable(release, act) &&
1451                                       mo_graph->checkReachable(act, rf)) {
1452                                 /* release --mo-> act --mo--> rf */
1453                                 return true; /* complete */
1454                         }
1455                         /* act may break release sequence */
1456                         pending->writes.push_back(act);
1457                         certain = false;
1458                 }
1459                 if (!future_ordered)
1460                         certain = false; /* This thread is uncertain */
1461         }
1462
1463         if (certain) {
1464                 release_heads->push_back(release);
1465                 pending->writes.clear();
1466         } else {
1467                 pending->release = release;
1468                 pending->rf = rf;
1469         }
1470         return certain;
1471 }
1472
1473 /**
1474  * A public interface for getting the release sequence head(s) with which a
1475  * given ModelAction must synchronize. This function only returns a non-empty
1476  * result when it can locate a release sequence head with certainty. Otherwise,
1477  * it may mark the internal state of the ModelChecker so that it will handle
1478  * the release sequence at a later time, causing @a act to update its
1479  * synchronization at some later point in execution.
1480  * @param act The 'acquire' action that may read from a release sequence
1481  * @param release_heads A pass-by-reference return parameter. Will be filled
1482  * with the head(s) of the release sequence(s), if they exists with certainty.
1483  * @see ModelChecker::release_seq_heads
1484  */
1485 void ModelChecker::get_release_seq_heads(ModelAction *act, rel_heads_list_t *release_heads)
1486 {
1487         const ModelAction *rf = act->get_reads_from();
1488         struct release_seq *sequence = (struct release_seq *)snapshot_calloc(1, sizeof(struct release_seq));
1489         sequence->acquire = act;
1490
1491         if (!release_seq_heads(rf, release_heads, sequence)) {
1492                 /* add act to 'lazy checking' list */
1493                 pending_rel_seqs->push_back(sequence);
1494         } else {
1495                 snapshot_free(sequence);
1496         }
1497 }
1498
1499 /**
1500  * Attempt to resolve all stashed operations that might synchronize with a
1501  * release sequence for a given location. This implements the "lazy" portion of
1502  * determining whether or not a release sequence was contiguous, since not all
1503  * modification order information is present at the time an action occurs.
1504  *
1505  * @param location The location/object that should be checked for release
1506  * sequence resolutions. A NULL value means to check all locations.
1507  * @param work_queue The work queue to which to add work items as they are
1508  * generated
1509  * @return True if any updates occurred (new synchronization, new mo_graph
1510  * edges)
1511  */
1512 bool ModelChecker::resolve_release_sequences(void *location, work_queue_t *work_queue)
1513 {
1514         bool updated = false;
1515         std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >::iterator it = pending_rel_seqs->begin();
1516         while (it != pending_rel_seqs->end()) {
1517                 struct release_seq *pending = *it;
1518                 ModelAction *act = pending->acquire;
1519
1520                 /* Only resolve sequences on the given location, if provided */
1521                 if (location && act->get_location() != location) {
1522                         it++;
1523                         continue;
1524                 }
1525
1526                 const ModelAction *rf = act->get_reads_from();
1527                 rel_heads_list_t release_heads;
1528                 bool complete;
1529                 complete = release_seq_heads(rf, &release_heads, pending);
1530                 for (unsigned int i = 0; i < release_heads.size(); i++) {
1531                         if (!act->has_synchronized_with(release_heads[i])) {
1532                                 if (act->synchronize_with(release_heads[i]))
1533                                         updated = true;
1534                                 else
1535                                         set_bad_synchronization();
1536                         }
1537                 }
1538
1539                 if (updated) {
1540                         /* Re-check all pending release sequences */
1541                         work_queue->push_back(CheckRelSeqWorkEntry(NULL));
1542                         /* Re-check act for mo_graph edges */
1543                         work_queue->push_back(MOEdgeWorkEntry(act));
1544
1545                         /* propagate synchronization to later actions */
1546                         action_list_t::reverse_iterator rit = action_trace->rbegin();
1547                         for (; (*rit) != act; rit++) {
1548                                 ModelAction *propagate = *rit;
1549                                 if (act->happens_before(propagate)) {
1550                                         propagate->synchronize_with(act);
1551                                         /* Re-check 'propagate' for mo_graph edges */
1552                                         work_queue->push_back(MOEdgeWorkEntry(propagate));
1553                                 }
1554                         }
1555                 }
1556                 if (complete) {
1557                         it = pending_rel_seqs->erase(it);
1558                         snapshot_free(pending);
1559                 } else {
1560                         it++;
1561                 }
1562         }
1563
1564         // If we resolved promises or data races, see if we have realized a data race.
1565         if (checkDataRaces()) {
1566                 set_assert();
1567         }
1568
1569         return updated;
1570 }
1571
1572 /**
1573  * Performs various bookkeeping operations for the current ModelAction. For
1574  * instance, adds action to the per-object, per-thread action vector and to the
1575  * action trace list of all thread actions.
1576  *
1577  * @param act is the ModelAction to add.
1578  */
1579 void ModelChecker::add_action_to_lists(ModelAction *act)
1580 {
1581         int tid = id_to_int(act->get_tid());
1582         action_trace->push_back(act);
1583
1584         obj_map->get_safe_ptr(act->get_location())->push_back(act);
1585
1586         std::vector<action_list_t> *vec = obj_thrd_map->get_safe_ptr(act->get_location());
1587         if (tid >= (int)vec->size())
1588                 vec->resize(priv->next_thread_id);
1589         (*vec)[tid].push_back(act);
1590
1591         if ((int)thrd_last_action->size() <= tid)
1592                 thrd_last_action->resize(get_num_threads());
1593         (*thrd_last_action)[tid] = act;
1594 }
1595
1596 /**
1597  * @brief Get the last action performed by a particular Thread
1598  * @param tid The thread ID of the Thread in question
1599  * @return The last action in the thread
1600  */
1601 ModelAction * ModelChecker::get_last_action(thread_id_t tid) const
1602 {
1603         int threadid = id_to_int(tid);
1604         if (threadid < (int)thrd_last_action->size())
1605                 return (*thrd_last_action)[id_to_int(tid)];
1606         else
1607                 return NULL;
1608 }
1609
1610 /**
1611  * Gets the last memory_order_seq_cst write (in the total global sequence)
1612  * performed on a particular object (i.e., memory location), not including the
1613  * current action.
1614  * @param curr The current ModelAction; also denotes the object location to
1615  * check
1616  * @return The last seq_cst write
1617  */
1618 ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr) const
1619 {
1620         void *location = curr->get_location();
1621         action_list_t *list = obj_map->get_safe_ptr(location);
1622         /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
1623         action_list_t::reverse_iterator rit;
1624         for (rit = list->rbegin(); rit != list->rend(); rit++)
1625                 if ((*rit)->is_write() && (*rit)->is_seqcst() && (*rit) != curr)
1626                         return *rit;
1627         return NULL;
1628 }
1629
1630 /**
1631  * Gets the last unlock operation performed on a particular mutex (i.e., memory
1632  * location). This function identifies the mutex according to the current
1633  * action, which is presumed to perform on the same mutex.
1634  * @param curr The current ModelAction; also denotes the object location to
1635  * check
1636  * @return The last unlock operation
1637  */
1638 ModelAction * ModelChecker::get_last_unlock(ModelAction *curr) const
1639 {
1640         void *location = curr->get_location();
1641         action_list_t *list = obj_map->get_safe_ptr(location);
1642         /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
1643         action_list_t::reverse_iterator rit;
1644         for (rit = list->rbegin(); rit != list->rend(); rit++)
1645                 if ((*rit)->is_unlock())
1646                         return *rit;
1647         return NULL;
1648 }
1649
1650 ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
1651 {
1652         ModelAction *parent = get_last_action(tid);
1653         if (!parent)
1654                 parent = get_thread(tid)->get_creation();
1655         return parent;
1656 }
1657
1658 /**
1659  * Returns the clock vector for a given thread.
1660  * @param tid The thread whose clock vector we want
1661  * @return Desired clock vector
1662  */
1663 ClockVector * ModelChecker::get_cv(thread_id_t tid)
1664 {
1665         return get_parent_action(tid)->get_cv();
1666 }
1667
1668 /**
1669  * Resolve a set of Promises with a current write. The set is provided in the
1670  * Node corresponding to @a write.
1671  * @param write The ModelAction that is fulfilling Promises
1672  * @return True if promises were resolved; false otherwise
1673  */
1674 bool ModelChecker::resolve_promises(ModelAction *write)
1675 {
1676         bool resolved = false;
1677         std::vector< thread_id_t, ModelAlloc<thread_id_t> > threads_to_check;
1678
1679         for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
1680                 Promise *promise = (*promises)[promise_index];
1681                 if (write->get_node()->get_promise(i)) {
1682                         ModelAction *read = promise->get_action();
1683                         if (read->is_rmw()) {
1684                                 mo_graph->addRMWEdge(write, read);
1685                         }
1686                         read->read_from(write);
1687                         //First fix up the modification order for actions that happened
1688                         //before the read
1689                         r_modification_order(read, write);
1690                         //Next fix up the modification order for actions that happened
1691                         //after the read.
1692                         post_r_modification_order(read, write);
1693                         //Make sure the promise's value matches the write's value
1694                         ASSERT(promise->get_value() == write->get_value());
1695                         delete(promise);
1696                         
1697                         promises->erase(promises->begin() + promise_index);
1698                         threads_to_check.push_back(read->get_tid());
1699
1700                         resolved = true;
1701                 } else
1702                         promise_index++;
1703         }
1704
1705         //Check whether reading these writes has made threads unable to
1706         //resolve promises
1707
1708         for(unsigned int i=0;i<threads_to_check.size();i++)
1709                 mo_check_promises(threads_to_check[i], write);
1710
1711         return resolved;
1712 }
1713
1714 /**
1715  * Compute the set of promises that could potentially be satisfied by this
1716  * action. Note that the set computation actually appears in the Node, not in
1717  * ModelChecker.
1718  * @param curr The ModelAction that may satisfy promises
1719  */
1720 void ModelChecker::compute_promises(ModelAction *curr)
1721 {
1722         for (unsigned int i = 0; i < promises->size(); i++) {
1723                 Promise *promise = (*promises)[i];
1724                 const ModelAction *act = promise->get_action();
1725                 if (!act->happens_before(curr) &&
1726                                 act->is_read() &&
1727                                 !act->could_synchronize_with(curr) &&
1728                                 !act->same_thread(curr) &&
1729                                 promise->get_value() == curr->get_value()) {
1730                         curr->get_node()->set_promise(i);
1731                 }
1732         }
1733 }
1734
1735 /** Checks promises in response to change in ClockVector Threads. */
1736 void ModelChecker::check_promises(thread_id_t tid, ClockVector *old_cv, ClockVector *merge_cv)
1737 {
1738         for (unsigned int i = 0; i < promises->size(); i++) {
1739                 Promise *promise = (*promises)[i];
1740                 const ModelAction *act = promise->get_action();
1741                 if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
1742                                 merge_cv->synchronized_since(act)) {
1743                         if (promise->increment_threads(tid)) {
1744                                 //Promise has failed
1745                                 failed_promise = true;
1746                                 return;
1747                         }
1748                 }
1749         }
1750 }
1751
1752 /** Checks promises in response to addition to modification order for threads.
1753  * Definitions:
1754  * pthread is the thread that performed the read that created the promise
1755  * 
1756  * pread is the read that created the promise
1757  *
1758  * pwrite is either the first write to same location as pread by
1759  * pthread that is sequenced after pread or the value read by the
1760  * first read to the same lcoation as pread by pthread that is
1761  * sequenced after pread..
1762  *
1763  *      1. If tid=pthread, then we check what other threads are reachable
1764  * through the mode order starting with pwrite.  Those threads cannot
1765  * perform a write that will resolve the promise due to modification
1766  * order constraints.
1767  *
1768  * 2. If the tid is not pthread, we check whether pwrite can reach the
1769  * action write through the modification order.  If so, that thread
1770  * cannot perform a future write that will resolve the promise due to
1771  * modificatin order constraints.
1772  *
1773  *      @parem tid The thread that either read from the model action
1774  *      write, or actually did the model action write.
1775  *
1776  *      @parem write The ModelAction representing the relevant write.
1777  */
1778
1779 void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write) {
1780         void * location = write->get_location();
1781         for (unsigned int i = 0; i < promises->size(); i++) {
1782                 Promise *promise = (*promises)[i];
1783                 const ModelAction *act = promise->get_action();
1784                 
1785                 //Is this promise on the same location?
1786                 if ( act->get_location() != location )
1787                         continue;
1788
1789                 //same thread as the promise
1790                 if ( act->get_tid()==tid ) {
1791
1792                         //do we have a pwrite for the promise, if not, set it
1793                         if (promise->get_write() == NULL ) {
1794                                 promise->set_write(write);
1795                         }
1796                         if (mo_graph->checkPromise(write, promise)) {
1797                                 failed_promise = true;
1798                                 return;
1799                         }
1800                 }
1801                 
1802                 //Don't do any lookups twice for the same thread
1803                 if (promise->has_sync_thread(tid))
1804                         continue;
1805                 
1806                 if (mo_graph->checkReachable(promise->get_write(), write)) {
1807                         if (promise->increment_threads(tid)) {
1808                                 failed_promise = true;
1809                                 return;
1810                         }
1811                 }
1812         }
1813 }
1814
1815 /**
1816  * Compute the set of writes that may break the current pending release
1817  * sequence. This information is extracted from previou release sequence
1818  * calculations.
1819  *
1820  * @param curr The current ModelAction. Must be a release sequence fixup
1821  * action.
1822  */
1823 void ModelChecker::compute_relseq_breakwrites(ModelAction *curr)
1824 {
1825         if (pending_rel_seqs->empty())
1826                 return;
1827
1828         struct release_seq *pending = pending_rel_seqs->back();
1829         for (unsigned int i = 0; i < pending->writes.size(); i++) {
1830                 const ModelAction *write = pending->writes[i];
1831                 curr->get_node()->add_relseq_break(write);
1832         }
1833
1834         /* NULL means don't break the sequence; just synchronize */
1835         curr->get_node()->add_relseq_break(NULL);
1836 }
1837
1838 /**
1839  * Build up an initial set of all past writes that this 'read' action may read
1840  * from. This set is determined by the clock vector's "happens before"
1841  * relationship.
1842  * @param curr is the current ModelAction that we are exploring; it must be a
1843  * 'read' operation.
1844  */
1845 void ModelChecker::build_reads_from_past(ModelAction *curr)
1846 {
1847         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
1848         unsigned int i;
1849         ASSERT(curr->is_read());
1850
1851         ModelAction *last_seq_cst = NULL;
1852
1853         /* Track whether this object has been initialized */
1854         bool initialized = false;
1855
1856         if (curr->is_seqcst()) {
1857                 last_seq_cst = get_last_seq_cst(curr);
1858                 /* We have to at least see the last sequentially consistent write,
1859                          so we are initialized. */
1860                 if (last_seq_cst != NULL)
1861                         initialized = true;
1862         }
1863
1864         /* Iterate over all threads */
1865         for (i = 0; i < thrd_lists->size(); i++) {
1866                 /* Iterate over actions in thread, starting from most recent */
1867                 action_list_t *list = &(*thrd_lists)[i];
1868                 action_list_t::reverse_iterator rit;
1869                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1870                         ModelAction *act = *rit;
1871
1872                         /* Only consider 'write' actions */
1873                         if (!act->is_write() || act == curr)
1874                                 continue;
1875
1876                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
1877                         if (!curr->is_seqcst() || (!act->is_seqcst() && (last_seq_cst == NULL || !act->happens_before(last_seq_cst))) || act == last_seq_cst) {
1878                                 DEBUG("Adding action to may_read_from:\n");
1879                                 if (DBG_ENABLED()) {
1880                                         act->print();
1881                                         curr->print();
1882                                 }
1883
1884                                 if (curr->get_sleep_flag()) {
1885                                         if (sleep_can_read_from(curr, act))
1886                                                 curr->get_node()->add_read_from(act);
1887                                 } else
1888                                         curr->get_node()->add_read_from(act);
1889                         }
1890
1891                         /* Include at most one act per-thread that "happens before" curr */
1892                         if (act->happens_before(curr)) {
1893                                 initialized = true;
1894                                 break;
1895                         }
1896                 }
1897         }
1898
1899         if (!initialized) {
1900                 /** @todo Need a more informative way of reporting errors. */
1901                 printf("ERROR: may read from uninitialized atomic\n");
1902         }
1903
1904         if (DBG_ENABLED() || !initialized) {
1905                 printf("Reached read action:\n");
1906                 curr->print();
1907                 printf("Printing may_read_from\n");
1908                 curr->get_node()->print_may_read_from();
1909                 printf("End printing may_read_from\n");
1910         }
1911
1912         ASSERT(initialized);
1913 }
1914
1915 bool ModelChecker::sleep_can_read_from(ModelAction * curr, const ModelAction *write) {
1916         while(true) {
1917                 Node *prevnode=write->get_node()->get_parent();
1918                 bool thread_sleep=prevnode->get_enabled_array()[id_to_int(curr->get_tid())]==THREAD_SLEEP_SET;
1919                 if (write->is_release()&&thread_sleep)
1920                         return true;
1921                 if (!write->is_rmw()) {
1922                         return false;
1923                 }
1924                 if (write->get_reads_from()==NULL)
1925                         return true;
1926                 write=write->get_reads_from();
1927         }
1928 }
1929
1930 static void print_list(action_list_t *list)
1931 {
1932         action_list_t::iterator it;
1933
1934         printf("---------------------------------------------------------------------\n");
1935         printf("Trace:\n");
1936         unsigned int hash=0;
1937         
1938         for (it = list->begin(); it != list->end(); it++) {
1939                 (*it)->print();
1940                 hash=hash^(hash<<3)^((*it)->hash());
1941         }
1942         printf("HASH %u\n", hash);
1943         printf("---------------------------------------------------------------------\n");
1944 }
1945
1946 #if SUPPORT_MOD_ORDER_DUMP
1947 void ModelChecker::dumpGraph(char *filename) {
1948         char buffer[200];
1949   sprintf(buffer, "%s.dot",filename);
1950   FILE *file=fopen(buffer, "w");
1951   fprintf(file, "digraph %s {\n",filename);
1952         mo_graph->dumpNodes(file);
1953         ModelAction ** thread_array=(ModelAction **)model_calloc(1, sizeof(ModelAction *)*get_num_threads());
1954         
1955         for (action_list_t::iterator it = action_trace->begin(); it != action_trace->end(); it++) {
1956                 ModelAction *action=*it;
1957                 if (action->is_read()) {
1958                         fprintf(file, "N%u [label=\"%u, T%u\"];\n", action->get_seq_number(),action->get_seq_number(), action->get_tid());
1959                         if (action->get_reads_from()!=NULL)
1960                                 fprintf(file, "N%u -> N%u[label=\"rf\", color=red];\n", action->get_seq_number(), action->get_reads_from()->get_seq_number());
1961                 }
1962                 if (thread_array[action->get_tid()] != NULL) {
1963                         fprintf(file, "N%u -> N%u[label=\"sb\", color=blue];\n", thread_array[action->get_tid()]->get_seq_number(), action->get_seq_number());
1964                 }
1965                 
1966                 thread_array[action->get_tid()]=action;
1967         }
1968   fprintf(file,"}\n");
1969         model_free(thread_array);
1970   fclose(file); 
1971 }
1972 #endif
1973
1974 void ModelChecker::print_summary()
1975 {
1976         printf("\n");
1977         printf("Number of executions: %d\n", num_executions);
1978         printf("Number of feasible executions: %d\n", num_feasible_executions);
1979         printf("Total nodes created: %d\n", node_stack->get_total_nodes());
1980
1981 #if SUPPORT_MOD_ORDER_DUMP
1982         scheduler->print();
1983         char buffername[100];
1984         sprintf(buffername, "exec%04u", num_executions);
1985         mo_graph->dumpGraphToFile(buffername);
1986         sprintf(buffername, "graph%04u", num_executions);
1987   dumpGraph(buffername);
1988 #endif
1989
1990         if (!isfinalfeasible())
1991                 printf("INFEASIBLE EXECUTION!\n");
1992         print_list(action_trace);
1993         printf("\n");
1994 }
1995
1996 /**
1997  * Add a Thread to the system for the first time. Should only be called once
1998  * per thread.
1999  * @param t The Thread to add
2000  */
2001 void ModelChecker::add_thread(Thread *t)
2002 {
2003         thread_map->put(id_to_int(t->get_id()), t);
2004         scheduler->add_thread(t);
2005 }
2006
2007 /**
2008  * Removes a thread from the scheduler. 
2009  * @param the thread to remove.
2010  */
2011 void ModelChecker::remove_thread(Thread *t)
2012 {
2013         scheduler->remove_thread(t);
2014 }
2015
2016 /**
2017  * @brief Get a Thread reference by its ID
2018  * @param tid The Thread's ID
2019  * @return A Thread reference
2020  */
2021 Thread * ModelChecker::get_thread(thread_id_t tid) const
2022 {
2023         return thread_map->get(id_to_int(tid));
2024 }
2025
2026 /**
2027  * @brief Get a reference to the Thread in which a ModelAction was executed
2028  * @param act The ModelAction
2029  * @return A Thread reference
2030  */
2031 Thread * ModelChecker::get_thread(ModelAction *act) const
2032 {
2033         return get_thread(act->get_tid());
2034 }
2035
2036 /**
2037  * Switch from a user-context to the "master thread" context (a.k.a. system
2038  * context). This switch is made with the intention of exploring a particular
2039  * model-checking action (described by a ModelAction object). Must be called
2040  * from a user-thread context.
2041  *
2042  * @param act The current action that will be explored. May be NULL only if
2043  * trace is exiting via an assertion (see ModelChecker::set_assert and
2044  * ModelChecker::has_asserted).
2045  * @return Return status from the 'swap' call (i.e., success/fail, 0/-1)
2046  */
2047 int ModelChecker::switch_to_master(ModelAction *act)
2048 {
2049         DBG();
2050         Thread *old = thread_current();
2051         set_current_action(act);
2052         old->set_state(THREAD_READY);
2053         return Thread::swap(old, &system_context);
2054 }
2055
2056 /**
2057  * Takes the next step in the execution, if possible.
2058  * @return Returns true (success) if a step was taken and false otherwise.
2059  */
2060 bool ModelChecker::take_step() {
2061         if (has_asserted())
2062                 return false;
2063
2064         Thread *curr = priv->current_action ? get_thread(priv->current_action) : NULL;
2065         if (curr) {
2066                 if (curr->get_state() == THREAD_READY) {
2067                         ASSERT(priv->current_action);
2068
2069                         priv->nextThread = check_current_action(priv->current_action);
2070                         priv->current_action = NULL;
2071
2072                         if (curr->is_blocked() || curr->is_complete())
2073                                 scheduler->remove_thread(curr);
2074                 } else {
2075                         ASSERT(false);
2076                 }
2077         }
2078         Thread *next = scheduler->next_thread(priv->nextThread);
2079
2080         /* Infeasible -> don't take any more steps */
2081         if (!isfeasible())
2082                 return false;
2083
2084         DEBUG("(%d, %d)\n", curr ? id_to_int(curr->get_id()) : -1,
2085                         next ? id_to_int(next->get_id()) : -1);
2086
2087         /*
2088          * Launch end-of-execution release sequence fixups only when there are:
2089          *
2090          * (1) no more user threads to run (or when execution replay chooses
2091          *     the 'model_thread')
2092          * (2) pending release sequences
2093          * (3) pending assertions (i.e., data races)
2094          * (4) no pending promises
2095          */
2096         if (!pending_rel_seqs->empty() && (!next || next->is_model_thread()) &&
2097                         isfinalfeasible() && !unrealizedraces.empty()) {
2098                 printf("*** WARNING: release sequence fixup action (%zu pending release seuqences) ***\n",
2099                                 pending_rel_seqs->size());
2100                 ModelAction *fixup = new ModelAction(MODEL_FIXUP_RELSEQ,
2101                                 std::memory_order_seq_cst, NULL, VALUE_NONE,
2102                                 model_thread);
2103                 set_current_action(fixup);
2104                 return true;
2105         }
2106
2107         /* next == NULL -> don't take any more steps */
2108         if (!next)
2109                 return false;
2110
2111         next->set_state(THREAD_RUNNING);
2112
2113         if (next->get_pending() != NULL) {
2114                 /* restart a pending action */
2115                 set_current_action(next->get_pending());
2116                 next->set_pending(NULL);
2117                 next->set_state(THREAD_READY);
2118                 return true;
2119         }
2120
2121         /* Return false only if swap fails with an error */
2122         return (Thread::swap(&system_context, next) == 0);
2123 }
2124
2125 /** Runs the current execution until threre are no more steps to take. */
2126 void ModelChecker::finish_execution() {
2127         DBG();
2128
2129         while (take_step());
2130 }