7e8211daf523f37e2c110d3852912c203decb331
[c11tester.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         return true;
1316
1317         //return !mo_graph->checkReachable(first_write_after_read, writer);
1318 }
1319
1320
1321
1322 /**
1323  * Finds the head(s) of the release sequence(s) containing a given ModelAction.
1324  * The ModelAction under consideration is expected to be taking part in
1325  * release/acquire synchronization as an object of the "reads from" relation.
1326  * Note that this can only provide release sequence support for RMW chains
1327  * which do not read from the future, as those actions cannot be traced until
1328  * their "promise" is fulfilled. Similarly, we may not even establish the
1329  * presence of a release sequence with certainty, as some modification order
1330  * constraints may be decided further in the future. Thus, this function
1331  * "returns" two pieces of data: a pass-by-reference vector of @a release_heads
1332  * and a boolean representing certainty.
1333  *
1334  * @param rf The action that might be part of a release sequence. Must be a
1335  * write.
1336  * @param release_heads A pass-by-reference style return parameter. After
1337  * execution of this function, release_heads will contain the heads of all the
1338  * relevant release sequences, if any exists with certainty
1339  * @param pending A pass-by-reference style return parameter which is only used
1340  * when returning false (i.e., uncertain). Returns most information regarding
1341  * an uncertain release sequence, including any write operations that might
1342  * break the sequence.
1343  * @return true, if the ModelChecker is certain that release_heads is complete;
1344  * false otherwise
1345  */
1346 bool ModelChecker::release_seq_heads(const ModelAction *rf,
1347                 rel_heads_list_t *release_heads,
1348                 struct release_seq *pending) const
1349 {
1350         /* Only check for release sequences if there are no cycles */
1351         if (mo_graph->checkForCycles())
1352                 return false;
1353
1354         while (rf) {
1355                 ASSERT(rf->is_write());
1356
1357                 if (rf->is_release())
1358                         release_heads->push_back(rf);
1359                 if (!rf->is_rmw())
1360                         break; /* End of RMW chain */
1361
1362                 /** @todo Need to be smarter here...  In the linux lock
1363                  * example, this will run to the beginning of the program for
1364                  * every acquire. */
1365                 /** @todo The way to be smarter here is to keep going until 1
1366                  * thread has a release preceded by an acquire and you've seen
1367                  *       both. */
1368
1369                 /* acq_rel RMW is a sufficient stopping condition */
1370                 if (rf->is_acquire() && rf->is_release())
1371                         return true; /* complete */
1372
1373                 rf = rf->get_reads_from();
1374         };
1375         if (!rf) {
1376                 /* read from future: need to settle this later */
1377                 pending->rf = NULL;
1378                 return false; /* incomplete */
1379         }
1380
1381         if (rf->is_release())
1382                 return true; /* complete */
1383
1384         /* else relaxed write; check modification order for contiguous subsequence
1385          * -> rf must be same thread as release */
1386         int tid = id_to_int(rf->get_tid());
1387         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(rf->get_location());
1388         action_list_t *list = &(*thrd_lists)[tid];
1389         action_list_t::const_reverse_iterator rit;
1390
1391         /* Find rf in the thread list */
1392         rit = std::find(list->rbegin(), list->rend(), rf);
1393         ASSERT(rit != list->rend());
1394
1395         /* Find the last write/release */
1396         for (; rit != list->rend(); rit++)
1397                 if ((*rit)->is_release())
1398                         break;
1399         if (rit == list->rend()) {
1400                 /* No write-release in this thread */
1401                 return true; /* complete */
1402         }
1403         ModelAction *release = *rit;
1404
1405         ASSERT(rf->same_thread(release));
1406
1407         pending->writes.clear();
1408
1409         bool certain = true;
1410         for (unsigned int i = 0; i < thrd_lists->size(); i++) {
1411                 if (id_to_int(rf->get_tid()) == (int)i)
1412                         continue;
1413                 list = &(*thrd_lists)[i];
1414
1415                 /* Can we ensure no future writes from this thread may break
1416                  * the release seq? */
1417                 bool future_ordered = false;
1418
1419                 ModelAction *last = get_last_action(int_to_id(i));
1420                 Thread *th = get_thread(int_to_id(i));
1421                 if ((last && rf->happens_before(last)) ||
1422                                 !scheduler->is_enabled(th) ||
1423                                 th->is_complete())
1424                         future_ordered = true;
1425
1426                 ASSERT(!th->is_model_thread() || future_ordered);
1427
1428                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1429                         const ModelAction *act = *rit;
1430                         /* Reach synchronization -> this thread is complete */
1431                         if (act->happens_before(release))
1432                                 break;
1433                         if (rf->happens_before(act)) {
1434                                 future_ordered = true;
1435                                 continue;
1436                         }
1437
1438                         /* Only writes can break release sequences */
1439                         if (!act->is_write())
1440                                 continue;
1441
1442                         /* Check modification order */
1443                         if (mo_graph->checkReachable(rf, act)) {
1444                                 /* rf --mo--> act */
1445                                 future_ordered = true;
1446                                 continue;
1447                         }
1448                         if (mo_graph->checkReachable(act, release))
1449                                 /* act --mo--> release */
1450                                 break;
1451                         if (mo_graph->checkReachable(release, act) &&
1452                                       mo_graph->checkReachable(act, rf)) {
1453                                 /* release --mo-> act --mo--> rf */
1454                                 return true; /* complete */
1455                         }
1456                         /* act may break release sequence */
1457                         pending->writes.push_back(act);
1458                         certain = false;
1459                 }
1460                 if (!future_ordered)
1461                         certain = false; /* This thread is uncertain */
1462         }
1463
1464         if (certain) {
1465                 release_heads->push_back(release);
1466                 pending->writes.clear();
1467         } else {
1468                 pending->release = release;
1469                 pending->rf = rf;
1470         }
1471         return certain;
1472 }
1473
1474 /**
1475  * A public interface for getting the release sequence head(s) with which a
1476  * given ModelAction must synchronize. This function only returns a non-empty
1477  * result when it can locate a release sequence head with certainty. Otherwise,
1478  * it may mark the internal state of the ModelChecker so that it will handle
1479  * the release sequence at a later time, causing @a act to update its
1480  * synchronization at some later point in execution.
1481  * @param act The 'acquire' action that may read from a release sequence
1482  * @param release_heads A pass-by-reference return parameter. Will be filled
1483  * with the head(s) of the release sequence(s), if they exists with certainty.
1484  * @see ModelChecker::release_seq_heads
1485  */
1486 void ModelChecker::get_release_seq_heads(ModelAction *act, rel_heads_list_t *release_heads)
1487 {
1488         const ModelAction *rf = act->get_reads_from();
1489         struct release_seq *sequence = (struct release_seq *)snapshot_calloc(1, sizeof(struct release_seq));
1490         sequence->acquire = act;
1491
1492         if (!release_seq_heads(rf, release_heads, sequence)) {
1493                 /* add act to 'lazy checking' list */
1494                 pending_rel_seqs->push_back(sequence);
1495         } else {
1496                 snapshot_free(sequence);
1497         }
1498 }
1499
1500 /**
1501  * Attempt to resolve all stashed operations that might synchronize with a
1502  * release sequence for a given location. This implements the "lazy" portion of
1503  * determining whether or not a release sequence was contiguous, since not all
1504  * modification order information is present at the time an action occurs.
1505  *
1506  * @param location The location/object that should be checked for release
1507  * sequence resolutions. A NULL value means to check all locations.
1508  * @param work_queue The work queue to which to add work items as they are
1509  * generated
1510  * @return True if any updates occurred (new synchronization, new mo_graph
1511  * edges)
1512  */
1513 bool ModelChecker::resolve_release_sequences(void *location, work_queue_t *work_queue)
1514 {
1515         bool updated = false;
1516         std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >::iterator it = pending_rel_seqs->begin();
1517         while (it != pending_rel_seqs->end()) {
1518                 struct release_seq *pending = *it;
1519                 ModelAction *act = pending->acquire;
1520
1521                 /* Only resolve sequences on the given location, if provided */
1522                 if (location && act->get_location() != location) {
1523                         it++;
1524                         continue;
1525                 }
1526
1527                 const ModelAction *rf = act->get_reads_from();
1528                 rel_heads_list_t release_heads;
1529                 bool complete;
1530                 complete = release_seq_heads(rf, &release_heads, pending);
1531                 for (unsigned int i = 0; i < release_heads.size(); i++) {
1532                         if (!act->has_synchronized_with(release_heads[i])) {
1533                                 if (act->synchronize_with(release_heads[i]))
1534                                         updated = true;
1535                                 else
1536                                         set_bad_synchronization();
1537                         }
1538                 }
1539
1540                 if (updated) {
1541                         /* Re-check all pending release sequences */
1542                         work_queue->push_back(CheckRelSeqWorkEntry(NULL));
1543                         /* Re-check act for mo_graph edges */
1544                         work_queue->push_back(MOEdgeWorkEntry(act));
1545
1546                         /* propagate synchronization to later actions */
1547                         action_list_t::reverse_iterator rit = action_trace->rbegin();
1548                         for (; (*rit) != act; rit++) {
1549                                 ModelAction *propagate = *rit;
1550                                 if (act->happens_before(propagate)) {
1551                                         propagate->synchronize_with(act);
1552                                         /* Re-check 'propagate' for mo_graph edges */
1553                                         work_queue->push_back(MOEdgeWorkEntry(propagate));
1554                                 }
1555                         }
1556                 }
1557                 if (complete) {
1558                         it = pending_rel_seqs->erase(it);
1559                         snapshot_free(pending);
1560                 } else {
1561                         it++;
1562                 }
1563         }
1564
1565         // If we resolved promises or data races, see if we have realized a data race.
1566         if (checkDataRaces()) {
1567                 set_assert();
1568         }
1569
1570         return updated;
1571 }
1572
1573 /**
1574  * Performs various bookkeeping operations for the current ModelAction. For
1575  * instance, adds action to the per-object, per-thread action vector and to the
1576  * action trace list of all thread actions.
1577  *
1578  * @param act is the ModelAction to add.
1579  */
1580 void ModelChecker::add_action_to_lists(ModelAction *act)
1581 {
1582         int tid = id_to_int(act->get_tid());
1583         action_trace->push_back(act);
1584
1585         obj_map->get_safe_ptr(act->get_location())->push_back(act);
1586
1587         std::vector<action_list_t> *vec = obj_thrd_map->get_safe_ptr(act->get_location());
1588         if (tid >= (int)vec->size())
1589                 vec->resize(priv->next_thread_id);
1590         (*vec)[tid].push_back(act);
1591
1592         if ((int)thrd_last_action->size() <= tid)
1593                 thrd_last_action->resize(get_num_threads());
1594         (*thrd_last_action)[tid] = act;
1595 }
1596
1597 /**
1598  * @brief Get the last action performed by a particular Thread
1599  * @param tid The thread ID of the Thread in question
1600  * @return The last action in the thread
1601  */
1602 ModelAction * ModelChecker::get_last_action(thread_id_t tid) const
1603 {
1604         int threadid = id_to_int(tid);
1605         if (threadid < (int)thrd_last_action->size())
1606                 return (*thrd_last_action)[id_to_int(tid)];
1607         else
1608                 return NULL;
1609 }
1610
1611 /**
1612  * Gets the last memory_order_seq_cst write (in the total global sequence)
1613  * performed on a particular object (i.e., memory location), not including the
1614  * current action.
1615  * @param curr The current ModelAction; also denotes the object location to
1616  * check
1617  * @return The last seq_cst write
1618  */
1619 ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr) const
1620 {
1621         void *location = curr->get_location();
1622         action_list_t *list = obj_map->get_safe_ptr(location);
1623         /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
1624         action_list_t::reverse_iterator rit;
1625         for (rit = list->rbegin(); rit != list->rend(); rit++)
1626                 if ((*rit)->is_write() && (*rit)->is_seqcst() && (*rit) != curr)
1627                         return *rit;
1628         return NULL;
1629 }
1630
1631 /**
1632  * Gets the last unlock operation performed on a particular mutex (i.e., memory
1633  * location). This function identifies the mutex according to the current
1634  * action, which is presumed to perform on the same mutex.
1635  * @param curr The current ModelAction; also denotes the object location to
1636  * check
1637  * @return The last unlock operation
1638  */
1639 ModelAction * ModelChecker::get_last_unlock(ModelAction *curr) const
1640 {
1641         void *location = curr->get_location();
1642         action_list_t *list = obj_map->get_safe_ptr(location);
1643         /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
1644         action_list_t::reverse_iterator rit;
1645         for (rit = list->rbegin(); rit != list->rend(); rit++)
1646                 if ((*rit)->is_unlock())
1647                         return *rit;
1648         return NULL;
1649 }
1650
1651 ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
1652 {
1653         ModelAction *parent = get_last_action(tid);
1654         if (!parent)
1655                 parent = get_thread(tid)->get_creation();
1656         return parent;
1657 }
1658
1659 /**
1660  * Returns the clock vector for a given thread.
1661  * @param tid The thread whose clock vector we want
1662  * @return Desired clock vector
1663  */
1664 ClockVector * ModelChecker::get_cv(thread_id_t tid)
1665 {
1666         return get_parent_action(tid)->get_cv();
1667 }
1668
1669 /**
1670  * Resolve a set of Promises with a current write. The set is provided in the
1671  * Node corresponding to @a write.
1672  * @param write The ModelAction that is fulfilling Promises
1673  * @return True if promises were resolved; false otherwise
1674  */
1675 bool ModelChecker::resolve_promises(ModelAction *write)
1676 {
1677         bool resolved = false;
1678         std::vector< thread_id_t, ModelAlloc<thread_id_t> > threads_to_check;
1679
1680         for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
1681                 Promise *promise = (*promises)[promise_index];
1682                 if (write->get_node()->get_promise(i)) {
1683                         ModelAction *read = promise->get_action();
1684                         if (read->is_rmw()) {
1685                                 mo_graph->addRMWEdge(write, read);
1686                         }
1687                         read->read_from(write);
1688                         //First fix up the modification order for actions that happened
1689                         //before the read
1690                         r_modification_order(read, write);
1691                         //Next fix up the modification order for actions that happened
1692                         //after the read.
1693                         post_r_modification_order(read, write);
1694                         //Make sure the promise's value matches the write's value
1695                         ASSERT(promise->get_value() == write->get_value());
1696                         delete(promise);
1697                         
1698                         promises->erase(promises->begin() + promise_index);
1699                         threads_to_check.push_back(read->get_tid());
1700
1701                         resolved = true;
1702                 } else
1703                         promise_index++;
1704         }
1705
1706         //Check whether reading these writes has made threads unable to
1707         //resolve promises
1708
1709         for(unsigned int i=0;i<threads_to_check.size();i++)
1710                 mo_check_promises(threads_to_check[i], write);
1711
1712         return resolved;
1713 }
1714
1715 /**
1716  * Compute the set of promises that could potentially be satisfied by this
1717  * action. Note that the set computation actually appears in the Node, not in
1718  * ModelChecker.
1719  * @param curr The ModelAction that may satisfy promises
1720  */
1721 void ModelChecker::compute_promises(ModelAction *curr)
1722 {
1723         for (unsigned int i = 0; i < promises->size(); i++) {
1724                 Promise *promise = (*promises)[i];
1725                 const ModelAction *act = promise->get_action();
1726                 if (!act->happens_before(curr) &&
1727                                 act->is_read() &&
1728                                 !act->could_synchronize_with(curr) &&
1729                                 !act->same_thread(curr) &&
1730                                 promise->get_value() == curr->get_value()) {
1731                         curr->get_node()->set_promise(i);
1732                 }
1733         }
1734 }
1735
1736 /** Checks promises in response to change in ClockVector Threads. */
1737 void ModelChecker::check_promises(thread_id_t tid, ClockVector *old_cv, ClockVector *merge_cv)
1738 {
1739         for (unsigned int i = 0; i < promises->size(); i++) {
1740                 Promise *promise = (*promises)[i];
1741                 const ModelAction *act = promise->get_action();
1742                 if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
1743                                 merge_cv->synchronized_since(act)) {
1744                         if (promise->increment_threads(tid)) {
1745                                 //Promise has failed
1746                                 failed_promise = true;
1747                                 return;
1748                         }
1749                 }
1750         }
1751 }
1752
1753 /** Checks promises in response to addition to modification order for threads.
1754  * Definitions:
1755  * pthread is the thread that performed the read that created the promise
1756  * 
1757  * pread is the read that created the promise
1758  *
1759  * pwrite is either the first write to same location as pread by
1760  * pthread that is sequenced after pread or the value read by the
1761  * first read to the same lcoation as pread by pthread that is
1762  * sequenced after pread..
1763  *
1764  *      1. If tid=pthread, then we check what other threads are reachable
1765  * through the mode order starting with pwrite.  Those threads cannot
1766  * perform a write that will resolve the promise due to modification
1767  * order constraints.
1768  *
1769  * 2. If the tid is not pthread, we check whether pwrite can reach the
1770  * action write through the modification order.  If so, that thread
1771  * cannot perform a future write that will resolve the promise due to
1772  * modificatin order constraints.
1773  *
1774  *      @parem tid The thread that either read from the model action
1775  *      write, or actually did the model action write.
1776  *
1777  *      @parem write The ModelAction representing the relevant write.
1778  */
1779
1780 void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write) {
1781         void * location = write->get_location();
1782         for (unsigned int i = 0; i < promises->size(); i++) {
1783                 Promise *promise = (*promises)[i];
1784                 const ModelAction *act = promise->get_action();
1785                 
1786                 //Is this promise on the same location?
1787                 if ( act->get_location() != location )
1788                         continue;
1789
1790                 //same thread as the promise
1791                 if ( act->get_tid()==tid ) {
1792
1793                         //do we have a pwrite for the promise, if not, set it
1794                         if (promise->get_write() == NULL ) {
1795                                 promise->set_write(write);
1796                         }
1797                         if (mo_graph->checkPromise(write, promise)) {
1798                                 failed_promise = true;
1799                                 return;
1800                         }
1801                 }
1802                 
1803                 //Don't do any lookups twice for the same thread
1804                 if (promise->has_sync_thread(tid))
1805                         continue;
1806                 
1807                 if (mo_graph->checkReachable(promise->get_write(), write)) {
1808                         if (promise->increment_threads(tid)) {
1809                                 failed_promise = true;
1810                                 return;
1811                         }
1812                 }
1813         }
1814 }
1815
1816 /**
1817  * Compute the set of writes that may break the current pending release
1818  * sequence. This information is extracted from previou release sequence
1819  * calculations.
1820  *
1821  * @param curr The current ModelAction. Must be a release sequence fixup
1822  * action.
1823  */
1824 void ModelChecker::compute_relseq_breakwrites(ModelAction *curr)
1825 {
1826         if (pending_rel_seqs->empty())
1827                 return;
1828
1829         struct release_seq *pending = pending_rel_seqs->back();
1830         for (unsigned int i = 0; i < pending->writes.size(); i++) {
1831                 const ModelAction *write = pending->writes[i];
1832                 curr->get_node()->add_relseq_break(write);
1833         }
1834
1835         /* NULL means don't break the sequence; just synchronize */
1836         curr->get_node()->add_relseq_break(NULL);
1837 }
1838
1839 /**
1840  * Build up an initial set of all past writes that this 'read' action may read
1841  * from. This set is determined by the clock vector's "happens before"
1842  * relationship.
1843  * @param curr is the current ModelAction that we are exploring; it must be a
1844  * 'read' operation.
1845  */
1846 void ModelChecker::build_reads_from_past(ModelAction *curr)
1847 {
1848         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
1849         unsigned int i;
1850         ASSERT(curr->is_read());
1851
1852         ModelAction *last_seq_cst = NULL;
1853
1854         /* Track whether this object has been initialized */
1855         bool initialized = false;
1856
1857         if (curr->is_seqcst()) {
1858                 last_seq_cst = get_last_seq_cst(curr);
1859                 /* We have to at least see the last sequentially consistent write,
1860                          so we are initialized. */
1861                 if (last_seq_cst != NULL)
1862                         initialized = true;
1863         }
1864
1865         /* Iterate over all threads */
1866         for (i = 0; i < thrd_lists->size(); i++) {
1867                 /* Iterate over actions in thread, starting from most recent */
1868                 action_list_t *list = &(*thrd_lists)[i];
1869                 action_list_t::reverse_iterator rit;
1870                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1871                         ModelAction *act = *rit;
1872
1873                         /* Only consider 'write' actions */
1874                         if (!act->is_write() || act == curr)
1875                                 continue;
1876
1877                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
1878                         if (!curr->is_seqcst() || (!act->is_seqcst() && (last_seq_cst == NULL || !act->happens_before(last_seq_cst))) || act == last_seq_cst) {
1879                                 DEBUG("Adding action to may_read_from:\n");
1880                                 if (DBG_ENABLED()) {
1881                                         act->print();
1882                                         curr->print();
1883                                 }
1884
1885                                 if (curr->get_sleep_flag()) {
1886                                         if (sleep_can_read_from(curr, act))
1887                                                 curr->get_node()->add_read_from(act);
1888                                 } else
1889                                         curr->get_node()->add_read_from(act);
1890                         }
1891
1892                         /* Include at most one act per-thread that "happens before" curr */
1893                         if (act->happens_before(curr)) {
1894                                 initialized = true;
1895                                 break;
1896                         }
1897                 }
1898         }
1899
1900         if (!initialized) {
1901                 /** @todo Need a more informative way of reporting errors. */
1902                 printf("ERROR: may read from uninitialized atomic\n");
1903         }
1904
1905         if (DBG_ENABLED() || !initialized) {
1906                 printf("Reached read action:\n");
1907                 curr->print();
1908                 printf("Printing may_read_from\n");
1909                 curr->get_node()->print_may_read_from();
1910                 printf("End printing may_read_from\n");
1911         }
1912
1913         ASSERT(initialized);
1914 }
1915
1916 bool ModelChecker::sleep_can_read_from(ModelAction * curr, const ModelAction *write) {
1917         while(true) {
1918                 Node *prevnode=write->get_node()->get_parent();
1919                 bool thread_sleep=prevnode->get_enabled_array()[id_to_int(curr->get_tid())]==THREAD_SLEEP_SET;
1920                 if (write->is_release()&&thread_sleep)
1921                         return true;
1922                 if (!write->is_rmw()) {
1923                         return false;
1924                 }
1925                 if (write->get_reads_from()==NULL)
1926                         return true;
1927                 write=write->get_reads_from();
1928         }
1929 }
1930
1931 static void print_list(action_list_t *list)
1932 {
1933         action_list_t::iterator it;
1934
1935         printf("---------------------------------------------------------------------\n");
1936         printf("Trace:\n");
1937         unsigned int hash=0;
1938         
1939         for (it = list->begin(); it != list->end(); it++) {
1940                 (*it)->print();
1941                 hash=hash^(hash<<3)^((*it)->hash());
1942         }
1943         printf("HASH %u\n", hash);
1944         printf("---------------------------------------------------------------------\n");
1945 }
1946
1947 #if SUPPORT_MOD_ORDER_DUMP
1948 void ModelChecker::dumpGraph(char *filename) {
1949         char buffer[200];
1950   sprintf(buffer, "%s.dot",filename);
1951   FILE *file=fopen(buffer, "w");
1952   fprintf(file, "digraph %s {\n",filename);
1953         mo_graph->dumpNodes(file);
1954         ModelAction ** thread_array=(ModelAction **)model_calloc(1, sizeof(ModelAction *)*get_num_threads());
1955         
1956         for (action_list_t::iterator it = action_trace->begin(); it != action_trace->end(); it++) {
1957                 ModelAction *action=*it;
1958                 if (action->is_read()) {
1959                         fprintf(file, "N%u [label=\"%u, T%u\"];\n", action->get_seq_number(),action->get_seq_number(), action->get_tid());
1960                         if (action->get_reads_from()!=NULL)
1961                                 fprintf(file, "N%u -> N%u[label=\"rf\", color=red];\n", action->get_seq_number(), action->get_reads_from()->get_seq_number());
1962                 }
1963                 if (thread_array[action->get_tid()] != NULL) {
1964                         fprintf(file, "N%u -> N%u[label=\"sb\", color=blue];\n", thread_array[action->get_tid()]->get_seq_number(), action->get_seq_number());
1965                 }
1966                 
1967                 thread_array[action->get_tid()]=action;
1968         }
1969   fprintf(file,"}\n");
1970         model_free(thread_array);
1971   fclose(file); 
1972 }
1973 #endif
1974
1975 void ModelChecker::print_summary()
1976 {
1977         printf("\n");
1978         printf("Number of executions: %d\n", num_executions);
1979         printf("Number of feasible executions: %d\n", num_feasible_executions);
1980         printf("Total nodes created: %d\n", node_stack->get_total_nodes());
1981
1982 #if SUPPORT_MOD_ORDER_DUMP
1983         scheduler->print();
1984         char buffername[100];
1985         sprintf(buffername, "exec%04u", num_executions);
1986         mo_graph->dumpGraphToFile(buffername);
1987         sprintf(buffername, "graph%04u", num_executions);
1988   dumpGraph(buffername);
1989 #endif
1990
1991         if (!isfinalfeasible())
1992                 printf("INFEASIBLE EXECUTION!\n");
1993         print_list(action_trace);
1994         printf("\n");
1995 }
1996
1997 /**
1998  * Add a Thread to the system for the first time. Should only be called once
1999  * per thread.
2000  * @param t The Thread to add
2001  */
2002 void ModelChecker::add_thread(Thread *t)
2003 {
2004         thread_map->put(id_to_int(t->get_id()), t);
2005         scheduler->add_thread(t);
2006 }
2007
2008 /**
2009  * Removes a thread from the scheduler. 
2010  * @param the thread to remove.
2011  */
2012 void ModelChecker::remove_thread(Thread *t)
2013 {
2014         scheduler->remove_thread(t);
2015 }
2016
2017 /**
2018  * @brief Get a Thread reference by its ID
2019  * @param tid The Thread's ID
2020  * @return A Thread reference
2021  */
2022 Thread * ModelChecker::get_thread(thread_id_t tid) const
2023 {
2024         return thread_map->get(id_to_int(tid));
2025 }
2026
2027 /**
2028  * @brief Get a reference to the Thread in which a ModelAction was executed
2029  * @param act The ModelAction
2030  * @return A Thread reference
2031  */
2032 Thread * ModelChecker::get_thread(ModelAction *act) const
2033 {
2034         return get_thread(act->get_tid());
2035 }
2036
2037 /**
2038  * Switch from a user-context to the "master thread" context (a.k.a. system
2039  * context). This switch is made with the intention of exploring a particular
2040  * model-checking action (described by a ModelAction object). Must be called
2041  * from a user-thread context.
2042  *
2043  * @param act The current action that will be explored. May be NULL only if
2044  * trace is exiting via an assertion (see ModelChecker::set_assert and
2045  * ModelChecker::has_asserted).
2046  * @return Return status from the 'swap' call (i.e., success/fail, 0/-1)
2047  */
2048 int ModelChecker::switch_to_master(ModelAction *act)
2049 {
2050         DBG();
2051         Thread *old = thread_current();
2052         set_current_action(act);
2053         old->set_state(THREAD_READY);
2054         return Thread::swap(old, &system_context);
2055 }
2056
2057 /**
2058  * Takes the next step in the execution, if possible.
2059  * @return Returns true (success) if a step was taken and false otherwise.
2060  */
2061 bool ModelChecker::take_step() {
2062         if (has_asserted())
2063                 return false;
2064
2065         Thread *curr = priv->current_action ? get_thread(priv->current_action) : NULL;
2066         if (curr) {
2067                 if (curr->get_state() == THREAD_READY) {
2068                         ASSERT(priv->current_action);
2069
2070                         priv->nextThread = check_current_action(priv->current_action);
2071                         priv->current_action = NULL;
2072
2073                         if (curr->is_blocked() || curr->is_complete())
2074                                 scheduler->remove_thread(curr);
2075                 } else {
2076                         ASSERT(false);
2077                 }
2078         }
2079         Thread *next = scheduler->next_thread(priv->nextThread);
2080
2081         /* Infeasible -> don't take any more steps */
2082         if (!isfeasible())
2083                 return false;
2084
2085         DEBUG("(%d, %d)\n", curr ? id_to_int(curr->get_id()) : -1,
2086                         next ? id_to_int(next->get_id()) : -1);
2087
2088         /*
2089          * Launch end-of-execution release sequence fixups only when there are:
2090          *
2091          * (1) no more user threads to run (or when execution replay chooses
2092          *     the 'model_thread')
2093          * (2) pending release sequences
2094          * (3) pending assertions (i.e., data races)
2095          * (4) no pending promises
2096          */
2097         if (!pending_rel_seqs->empty() && (!next || next->is_model_thread()) &&
2098                         isfinalfeasible() && !unrealizedraces.empty()) {
2099                 printf("*** WARNING: release sequence fixup action (%zu pending release seuqences) ***\n",
2100                                 pending_rel_seqs->size());
2101                 ModelAction *fixup = new ModelAction(MODEL_FIXUP_RELSEQ,
2102                                 std::memory_order_seq_cst, NULL, VALUE_NONE,
2103                                 model_thread);
2104                 set_current_action(fixup);
2105                 return true;
2106         }
2107
2108         /* next == NULL -> don't take any more steps */
2109         if (!next)
2110                 return false;
2111
2112         next->set_state(THREAD_RUNNING);
2113
2114         if (next->get_pending() != NULL) {
2115                 /* restart a pending action */
2116                 set_current_action(next->get_pending());
2117                 next->set_pending(NULL);
2118                 next->set_state(THREAD_READY);
2119                 return true;
2120         }
2121
2122         /* Return false only if swap fails with an error */
2123         return (Thread::swap(&system_context, next) == 0);
2124 }
2125
2126 /** Runs the current execution until threre are no more steps to take. */
2127 void ModelChecker::finish_execution() {
2128         DBG();
2129
2130         while (take_step());
2131 }