nodestack: add get_read_from_size()
[model-checker.git] / model.cc
1 #include <stdio.h>
2 #include <algorithm>
3
4 #include "model.h"
5 #include "action.h"
6 #include "nodestack.h"
7 #include "schedule.h"
8 #include "snapshot-interface.h"
9 #include "common.h"
10 #include "clockvector.h"
11 #include "cyclegraph.h"
12 #include "promise.h"
13 #include "datarace.h"
14
15 #define INITIAL_THREAD_ID       0
16
17 ModelChecker *model;
18
19 /** @brief Constructor */
20 ModelChecker::ModelChecker(struct model_params params) :
21         /* Initialize default scheduler */
22         scheduler(new Scheduler()),
23         num_executions(0),
24         params(params),
25         diverge(NULL),
26         action_trace(new action_list_t()),
27         thread_map(new HashTable<int, Thread *, int>()),
28         obj_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
29         obj_thrd_map(new HashTable<void *, std::vector<action_list_t>, uintptr_t, 4 >()),
30         promises(new std::vector<Promise *>()),
31         lazy_sync_with_release(new HashTable<void *, std::list<ModelAction *>, uintptr_t, 4>()),
32         thrd_last_action(new std::vector<ModelAction *>(1)),
33         node_stack(new NodeStack()),
34         mo_graph(new CycleGraph()),
35         failed_promise(false),
36         asserted(false)
37 {
38         /* Allocate this "size" on the snapshotting heap */
39         priv = (struct model_snapshot_members *)calloc(1, sizeof(*priv));
40         /* First thread created will have id INITIAL_THREAD_ID */
41         priv->next_thread_id = INITIAL_THREAD_ID;
42
43         lazy_sync_size = &priv->lazy_sync_size;
44 }
45
46 /** @brief Destructor */
47 ModelChecker::~ModelChecker()
48 {
49         for (int i = 0; i < get_num_threads(); i++)
50                 delete thread_map->get(i);
51         delete thread_map;
52
53         delete obj_thrd_map;
54         delete obj_map;
55         delete action_trace;
56
57         for (unsigned int i = 0; i < promises->size(); i++)
58                 delete (*promises)[i];
59         delete promises;
60
61         delete lazy_sync_with_release;
62
63         delete thrd_last_action;
64         delete node_stack;
65         delete scheduler;
66         delete mo_graph;
67 }
68
69 /**
70  * Restores user program to initial state and resets all model-checker data
71  * structures.
72  */
73 void ModelChecker::reset_to_initial_state()
74 {
75         DEBUG("+++ Resetting to initial state +++\n");
76         node_stack->reset_execution();
77         failed_promise = false;
78         reset_asserted();
79         snapshotObject->backTrackBeforeStep(0);
80 }
81
82 /** @returns a thread ID for a new Thread */
83 thread_id_t ModelChecker::get_next_id()
84 {
85         return priv->next_thread_id++;
86 }
87
88 /** @returns the number of user threads created during this execution */
89 int ModelChecker::get_num_threads()
90 {
91         return priv->next_thread_id;
92 }
93
94 /** @returns a sequence number for a new ModelAction */
95 modelclock_t ModelChecker::get_next_seq_num()
96 {
97         return ++priv->used_sequence_numbers;
98 }
99
100 /**
101  * Choose the next thread in the replay sequence.
102  *
103  * If the replay sequence has reached the 'diverge' point, returns a thread
104  * from the backtracking set. Otherwise, simply returns the next thread in the
105  * sequence that is being replayed.
106  */
107 Thread * ModelChecker::get_next_replay_thread()
108 {
109         thread_id_t tid;
110
111         /* Have we completed exploring the preselected path? */
112         if (diverge == NULL)
113                 return NULL;
114
115         /* Else, we are trying to replay an execution */
116         ModelAction *next = node_stack->get_next()->get_action();
117
118         if (next == diverge) {
119                 Node *nextnode = next->get_node();
120                 /* Reached divergence point */
121                 if (nextnode->increment_promise()) {
122                         /* The next node will try to satisfy a different set of promises. */
123                         tid = next->get_tid();
124                         node_stack->pop_restofstack(2);
125                 } else if (nextnode->increment_read_from()) {
126                         /* The next node will read from a different value. */
127                         tid = next->get_tid();
128                         node_stack->pop_restofstack(2);
129                 } else if (nextnode->increment_future_value()) {
130                         /* The next node will try to read from a different future value. */
131                         tid = next->get_tid();
132                         node_stack->pop_restofstack(2);
133                 } else {
134                         /* Make a different thread execute for next step */
135                         Node *node = nextnode->get_parent();
136                         tid = node->get_next_backtrack();
137                         node_stack->pop_restofstack(1);
138                 }
139                 DEBUG("*** Divergence point ***\n");
140                 diverge = NULL;
141         } else {
142                 tid = next->get_tid();
143         }
144         DEBUG("*** ModelChecker chose next thread = %d ***\n", tid);
145         ASSERT(tid != THREAD_ID_T_NONE);
146         return thread_map->get(id_to_int(tid));
147 }
148
149 /**
150  * Queries the model-checker for more executions to explore and, if one
151  * exists, resets the model-checker state to execute a new execution.
152  *
153  * @return If there are more executions to explore, return true. Otherwise,
154  * return false.
155  */
156 bool ModelChecker::next_execution()
157 {
158         DBG();
159
160         num_executions++;
161
162         if (isfinalfeasible() || DBG_ENABLED())
163                 print_summary();
164
165         if ((diverge = get_next_backtrack()) == NULL)
166                 return false;
167
168         if (DBG_ENABLED()) {
169                 printf("Next execution will diverge at:\n");
170                 diverge->print();
171         }
172
173         reset_to_initial_state();
174         return true;
175 }
176
177 ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
178 {
179         action_type type = act->get_type();
180
181         switch (type) {
182                 case ATOMIC_READ:
183                 case ATOMIC_WRITE:
184                 case ATOMIC_RMW:
185                         break;
186                 default:
187                         return NULL;
188         }
189         /* linear search: from most recent to oldest */
190         action_list_t *list = obj_map->get_safe_ptr(act->get_location());
191         action_list_t::reverse_iterator rit;
192         for (rit = list->rbegin(); rit != list->rend(); rit++) {
193                 ModelAction *prev = *rit;
194                 if (act->is_synchronizing(prev))
195                         return prev;
196         }
197         return NULL;
198 }
199
200 void ModelChecker::set_backtracking(ModelAction *act)
201 {
202         ModelAction *prev;
203         Node *node;
204         Thread *t = get_thread(act->get_tid());
205
206         prev = get_last_conflict(act);
207         if (prev == NULL)
208                 return;
209
210         node = prev->get_node()->get_parent();
211
212         while (!node->is_enabled(t))
213                 t = t->get_parent();
214
215         /* Check if this has been explored already */
216         if (node->has_been_explored(t->get_id()))
217                 return;
218
219         /* Cache the latest backtracking point */
220         if (!priv->next_backtrack || *prev > *priv->next_backtrack)
221                 priv->next_backtrack = prev;
222
223         /* If this is a new backtracking point, mark the tree */
224         if (!node->set_backtrack(t->get_id()))
225                 return;
226         DEBUG("Setting backtrack: conflict = %d, instead tid = %d\n",
227                         prev->get_tid(), t->get_id());
228         if (DBG_ENABLED()) {
229                 prev->print();
230                 act->print();
231         }
232 }
233
234 /**
235  * Returns last backtracking point. The model checker will explore a different
236  * path for this point in the next execution.
237  * @return The ModelAction at which the next execution should diverge.
238  */
239 ModelAction * ModelChecker::get_next_backtrack()
240 {
241         ModelAction *next = priv->next_backtrack;
242         priv->next_backtrack = NULL;
243         return next;
244 }
245
246 /**
247  * This is the heart of the model checker routine. It performs model-checking
248  * actions corresponding to a given "current action." Among other processes, it
249  * calculates reads-from relationships, updates synchronization clock vectors,
250  * forms a memory_order constraints graph, and handles replay/backtrack
251  * execution when running permutations of previously-observed executions.
252  *
253  * @param curr The current action to process
254  * @return The next Thread that must be executed. May be NULL if ModelChecker
255  * makes no choice (e.g., according to replay execution, combining RMW actions,
256  * etc.)
257  */
258 Thread * ModelChecker::check_current_action(ModelAction *curr)
259 {
260         bool already_added = false;
261
262         ASSERT(curr);
263
264         if (curr->is_rmwc() || curr->is_rmw()) {
265                 ModelAction *tmp = process_rmw(curr);
266                 already_added = true;
267                 delete curr;
268                 curr = tmp;
269         } else {
270                 ModelAction *tmp = node_stack->explore_action(curr);
271                 if (tmp) {
272                         /* Discard duplicate ModelAction; use action from NodeStack */
273                         /* First restore type and order in case of RMW operation */
274                         if (curr->is_rmwr())
275                                 tmp->copy_typeandorder(curr);
276
277                         /* If we have diverged, we need to reset the clock vector. */
278                         if (diverge == NULL)
279                                 tmp->create_cv(get_parent_action(tmp->get_tid()));
280
281                         delete curr;
282                         curr = tmp;
283                 } else {
284                         /*
285                          * Perform one-time actions when pushing new ModelAction onto
286                          * NodeStack
287                          */
288                         curr->create_cv(get_parent_action(curr->get_tid()));
289                         /* Build may_read_from set */
290                         if (curr->is_read())
291                                 build_reads_from_past(curr);
292                         if (curr->is_write())
293                                 compute_promises(curr);
294                 }
295         }
296
297         /* Assign 'creation' parent */
298         if (curr->get_type() == THREAD_CREATE) {
299                 Thread *th = (Thread *)curr->get_location();
300                 th->set_creation(curr);
301         } else if (curr->get_type() == THREAD_JOIN) {
302                 Thread *wait, *join;
303                 wait = get_thread(curr->get_tid());
304                 join = (Thread *)curr->get_location();
305                 if (!join->is_complete())
306                         scheduler->wait(wait, join);
307         } else if (curr->get_type() == THREAD_FINISH) {
308                 Thread *th = get_thread(curr->get_tid());
309                 while (!th->wait_list_empty()) {
310                         Thread *wake = th->pop_wait_list();
311                         scheduler->wake(wake);
312                 }
313                 th->complete();
314         }
315
316         /* Deal with new thread */
317         if (curr->get_type() == THREAD_START)
318                 check_promises(NULL, curr->get_cv());
319
320         /* Assign reads_from values */
321         Thread *th = get_thread(curr->get_tid());
322         uint64_t value = VALUE_NONE;
323         bool updated = false;
324         if (curr->is_read()) {
325                 const ModelAction *reads_from = curr->get_node()->get_read_from();
326                 if (reads_from != NULL) {
327                         value = reads_from->get_value();
328                         /* Assign reads_from, perform release/acquire synchronization */
329                         curr->read_from(reads_from);
330                         if (r_modification_order(curr,reads_from))
331                                 updated = true;
332                 } else {
333                         /* Read from future value */
334                         value = curr->get_node()->get_future_value();
335                         curr->read_from(NULL);
336                         Promise *valuepromise = new Promise(curr, value);
337                         promises->push_back(valuepromise);
338                 }
339         } else if (curr->is_write()) {
340                 if (w_modification_order(curr))
341                         updated = true;
342                 if (resolve_promises(curr))
343                         updated = true;
344         }
345
346         if (updated)
347                 resolve_release_sequences(curr->get_location());
348
349         th->set_return_value(value);
350
351         /* Add action to list.  */
352         if (!already_added)
353                 add_action_to_lists(curr);
354
355         Node *currnode = curr->get_node();
356         Node *parnode = currnode->get_parent();
357
358         if (!parnode->backtrack_empty() || !currnode->read_from_empty() ||
359                   !currnode->future_value_empty() || !currnode->promise_empty())
360                 if (!priv->next_backtrack || *curr > *priv->next_backtrack)
361                         priv->next_backtrack = curr;
362
363         set_backtracking(curr);
364
365         /* Do not split atomic actions. */
366         if (curr->is_rmwr())
367                 return thread_current();
368         /* The THREAD_CREATE action points to the created Thread */
369         else if (curr->get_type() == THREAD_CREATE)
370                 return (Thread *)curr->get_location();
371         else
372                 return get_next_replay_thread();
373 }
374
375 /** @returns whether the current partial trace must be a prefix of a
376  * feasible trace. */
377 bool ModelChecker::isfeasibleprefix() {
378         return promises->size() == 0 && *lazy_sync_size == 0;
379 }
380
381 /** @returns whether the current partial trace is feasible. */
382 bool ModelChecker::isfeasible() {
383         return !mo_graph->checkForCycles() && !failed_promise;
384 }
385
386 /** Returns whether the current completed trace is feasible. */
387 bool ModelChecker::isfinalfeasible() {
388         return isfeasible() && promises->size() == 0;
389 }
390
391 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
392 ModelAction * ModelChecker::process_rmw(ModelAction *act) {
393         int tid = id_to_int(act->get_tid());
394         ModelAction *lastread = get_last_action(tid);
395         lastread->process_rmw(act);
396         if (act->is_rmw())
397                 mo_graph->addRMWEdge(lastread->get_reads_from(), lastread);
398         return lastread;
399 }
400
401 /**
402  * Updates the mo_graph with the constraints imposed from the current read.
403  * @param curr The current action. Must be a read.
404  * @param rf The action that curr reads from. Must be a write.
405  * @return True if modification order edges were added; false otherwise
406  */
407 bool ModelChecker::r_modification_order(ModelAction *curr, const ModelAction *rf)
408 {
409         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
410         unsigned int i;
411         bool added = false;
412         ASSERT(curr->is_read());
413
414         /* Iterate over all threads */
415         for (i = 0; i < thrd_lists->size(); i++) {
416                 /* Iterate over actions in thread, starting from most recent */
417                 action_list_t *list = &(*thrd_lists)[i];
418                 action_list_t::reverse_iterator rit;
419                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
420                         ModelAction *act = *rit;
421
422                         /* Include at most one act per-thread that "happens before" curr */
423                         if (act->happens_before(curr)) {
424                                 if (act->is_read()) {
425                                         const ModelAction *prevreadfrom = act->get_reads_from();
426                                         if (prevreadfrom != NULL && rf != prevreadfrom) {
427                                                 mo_graph->addEdge(prevreadfrom, rf);
428                                                 added = true;
429                                         }
430                                 } else if (rf != act) {
431                                         mo_graph->addEdge(act, rf);
432                                         added = true;
433                                 }
434                                 break;
435                         }
436                 }
437         }
438
439         return added;
440 }
441
442 /** Updates the mo_graph with the constraints imposed from the current read. */
443 void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelAction *rf)
444 {
445         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
446         unsigned int i;
447         ASSERT(curr->is_read());
448
449         /* Iterate over all threads */
450         for (i = 0; i < thrd_lists->size(); i++) {
451                 /* Iterate over actions in thread, starting from most recent */
452                 action_list_t *list = &(*thrd_lists)[i];
453                 action_list_t::reverse_iterator rit;
454                 ModelAction *lastact = NULL;
455
456                 /* Find last action that happens after curr */
457                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
458                         ModelAction *act = *rit;
459                         if (curr->happens_before(act)) {
460                                 lastact = act;
461                         } else
462                                 break;
463                 }
464
465                         /* Include at most one act per-thread that "happens before" curr */
466                 if (lastact != NULL) {
467                         if (lastact->is_read()) {
468                                 const ModelAction *postreadfrom = lastact->get_reads_from();
469                                 if (postreadfrom != NULL&&rf != postreadfrom)
470                                         mo_graph->addEdge(rf, postreadfrom);
471                         } else if (rf != lastact) {
472                                 mo_graph->addEdge(rf, lastact);
473                         }
474                         break;
475                 }
476         }
477 }
478
479 /**
480  * Updates the mo_graph with the constraints imposed from the current write.
481  * @param curr The current action. Must be a write.
482  * @return True if modification order edges were added; false otherwise
483  */
484 bool ModelChecker::w_modification_order(ModelAction *curr)
485 {
486         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
487         unsigned int i;
488         bool added = false;
489         ASSERT(curr->is_write());
490
491         if (curr->is_seqcst()) {
492                 /* We have to at least see the last sequentially consistent write,
493                          so we are initialized. */
494                 ModelAction *last_seq_cst = get_last_seq_cst(curr->get_location());
495                 if (last_seq_cst != NULL) {
496                         mo_graph->addEdge(last_seq_cst, curr);
497                         added = true;
498                 }
499         }
500
501         /* Iterate over all threads */
502         for (i = 0; i < thrd_lists->size(); i++) {
503                 /* Iterate over actions in thread, starting from most recent */
504                 action_list_t *list = &(*thrd_lists)[i];
505                 action_list_t::reverse_iterator rit;
506                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
507                         ModelAction *act = *rit;
508
509                         /* Include at most one act per-thread that "happens before" curr */
510                         if (act->happens_before(curr)) {
511                                 if (act->is_read())
512                                         mo_graph->addEdge(act->get_reads_from(), curr);
513                                 else
514                                         mo_graph->addEdge(act, curr);
515                                 added = true;
516                                 break;
517                         } else if (act->is_read() && !act->is_synchronizing(curr) &&
518                                                      !act->same_thread(curr)) {
519                                 /* We have an action that:
520                                    (1) did not happen before us
521                                    (2) is a read and we are a write
522                                    (3) cannot synchronize with us
523                                    (4) is in a different thread
524                                    =>
525                                    that read could potentially read from our write.
526                                  */
527                                 if (act->get_node()->add_future_value(curr->get_value()) &&
528                                                 (!priv->next_backtrack || *act > *priv->next_backtrack))
529                                         priv->next_backtrack = act;
530                         }
531                 }
532         }
533
534         return added;
535 }
536
537 /**
538  * Finds the head(s) of the release sequence(s) containing a given ModelAction.
539  * The ModelAction under consideration is expected to be taking part in
540  * release/acquire synchronization as an object of the "reads from" relation.
541  * Note that this can only provide release sequence support for RMW chains
542  * which do not read from the future, as those actions cannot be traced until
543  * their "promise" is fulfilled. Similarly, we may not even establish the
544  * presence of a release sequence with certainty, as some modification order
545  * constraints may be decided further in the future. Thus, this function
546  * "returns" two pieces of data: a pass-by-reference vector of @a release_heads
547  * and a boolean representing certainty.
548  *
549  * @todo Finish lazy updating, when promises are fulfilled in the future
550  * @param rf The action that might be part of a release sequence. Must be a
551  * write.
552  * @param release_heads A pass-by-reference style return parameter.  After
553  * execution of this function, release_heads will contain the heads of all the
554  * relevant release sequences, if any exists
555  * @return true, if the ModelChecker is certain that release_heads is complete;
556  * false otherwise
557  */
558 bool ModelChecker::release_seq_head(const ModelAction *rf,
559                 std::vector<const ModelAction *> *release_heads) const
560 {
561         ASSERT(rf->is_write());
562         if (!rf) {
563                 /* read from future: need to settle this later */
564                 return false; /* incomplete */
565         }
566         if (rf->is_release())
567                 release_heads->push_back(rf);
568         if (rf->is_rmw()) {
569                 /* We need a RMW action that is both an acquire and release to stop */
570                 /** @todo Need to be smarter here...  In the linux lock
571                  * example, this will run to the beginning of the program for
572                  * every acquire. */
573                 if (rf->is_acquire() && rf->is_release())
574                         return true; /* complete */
575                 return release_seq_head(rf->get_reads_from(), release_heads);
576         }
577         if (rf->is_release())
578                 return true; /* complete */
579
580         /* else relaxed write; check modification order for contiguous subsequence
581          * -> rf must be same thread as release */
582         int tid = id_to_int(rf->get_tid());
583         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(rf->get_location());
584         action_list_t *list = &(*thrd_lists)[tid];
585         action_list_t::const_reverse_iterator rit;
586
587         /* Find rf in the thread list */
588         rit = std::find(list->rbegin(), list->rend(), rf);
589         ASSERT(rit != list->rend());
590
591         /* Find the last write/release */
592         for (; rit != list->rend(); rit++)
593                 if ((*rit)->is_release())
594                         break;
595         if (rit == list->rend()) {
596                 /* No write-release in this thread */
597                 return true; /* complete */
598         }
599         ModelAction *release = *rit;
600
601         ASSERT(rf->same_thread(release));
602
603         bool certain = true;
604         for (unsigned int i = 0; i < thrd_lists->size(); i++) {
605                 if (id_to_int(rf->get_tid()) == (int)i)
606                         continue;
607                 list = &(*thrd_lists)[i];
608
609                 /* Can we ensure no future writes from this thread may break
610                  * the release seq? */
611                 bool future_ordered = false;
612
613                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
614                         const ModelAction *act = *rit;
615                         if (!act->is_write())
616                                 continue;
617                         /* Reach synchronization -> this thread is complete */
618                         if (act->happens_before(release))
619                                 break;
620                         if (rf->happens_before(act)) {
621                                 future_ordered = true;
622                                 continue;
623                         }
624
625                         /* Check modification order */
626                         if (mo_graph->checkReachable(rf, act)) {
627                                 /* rf --mo--> act */
628                                 future_ordered = true;
629                                 continue;
630                         }
631                         if (mo_graph->checkReachable(act, release))
632                                 /* act --mo--> release */
633                                 break;
634                         if (mo_graph->checkReachable(release, act) &&
635                                       mo_graph->checkReachable(act, rf)) {
636                                 /* release --mo-> act --mo--> rf */
637                                 return true; /* complete */
638                         }
639                         certain = false;
640                 }
641                 if (!future_ordered)
642                         return false; /* This thread is uncertain */
643         }
644
645         if (certain)
646                 release_heads->push_back(release);
647         return certain;
648 }
649
650 /**
651  * A public interface for getting the release sequence head(s) with which a
652  * given ModelAction must synchronize. This function only returns a non-empty
653  * result when it can locate a release sequence head with certainty. Otherwise,
654  * it may mark the internal state of the ModelChecker so that it will handle
655  * the release sequence at a later time, causing @a act to update its
656  * synchronization at some later point in execution.
657  * @param act The 'acquire' action that may read from a release sequence
658  * @param release_heads A pass-by-reference return parameter. Will be filled
659  * with the head(s) of the release sequence(s), if they exists with certainty.
660  * @see ModelChecker::release_seq_head
661  */
662 void ModelChecker::get_release_seq_heads(ModelAction *act,
663                 std::vector<const ModelAction *> *release_heads)
664 {
665         const ModelAction *rf = act->get_reads_from();
666         bool complete;
667         complete = release_seq_head(rf, release_heads);
668         if (!complete) {
669                 /* add act to 'lazy checking' list */
670                 std::list<ModelAction *> *list;
671                 list = lazy_sync_with_release->get_safe_ptr(act->get_location());
672                 list->push_back(act);
673                 (*lazy_sync_size)++;
674         }
675 }
676
677 /**
678  * Attempt to resolve all stashed operations that might synchronize with a
679  * release sequence for a given location. This implements the "lazy" portion of
680  * determining whether or not a release sequence was contiguous, since not all
681  * modification order information is present at the time an action occurs.
682  *
683  * @param location The location/object that should be checked for release
684  * sequence resolutions
685  * @return True if any updates occurred (new synchronization, new mo_graph edges)
686  */
687 bool ModelChecker::resolve_release_sequences(void *location)
688 {
689         std::list<ModelAction *> *list;
690         list = lazy_sync_with_release->getptr(location);
691         if (!list)
692                 return false;
693
694         bool updated = false;
695         std::list<ModelAction *>::iterator it = list->begin();
696         while (it != list->end()) {
697                 ModelAction *act = *it;
698                 const ModelAction *rf = act->get_reads_from();
699                 std::vector<const ModelAction *> release_heads;
700                 bool complete;
701                 complete = release_seq_head(rf, &release_heads);
702                 for (unsigned int i = 0; i < release_heads.size(); i++) {
703                         if (!act->has_synchronized_with(release_heads[i])) {
704                                 updated = true;
705                                 act->synchronize_with(release_heads[i]);
706                         }
707                 }
708
709                 if (updated) {
710                         /* propagate synchronization to later actions */
711                         action_list_t::reverse_iterator it = action_trace->rbegin();
712                         while ((*it) != act) {
713                                 ModelAction *propagate = *it;
714                                 if (act->happens_before(propagate))
715                                         /** @todo new mo_graph edges along with
716                                          * this synchronization? */
717                                         propagate->synchronize_with(act);
718                         }
719                 }
720                 if (complete) {
721                         it = list->erase(it);
722                         (*lazy_sync_size)--;
723                 } else
724                         it++;
725         }
726
727         // If we resolved promises or data races, see if we have realized a data race.
728         if (checkDataRaces()) {
729                 set_assert();
730         }
731
732         return updated;
733 }
734
735 /**
736  * Performs various bookkeeping operations for the current ModelAction. For
737  * instance, adds action to the per-object, per-thread action vector and to the
738  * action trace list of all thread actions.
739  *
740  * @param act is the ModelAction to add.
741  */
742 void ModelChecker::add_action_to_lists(ModelAction *act)
743 {
744         int tid = id_to_int(act->get_tid());
745         action_trace->push_back(act);
746
747         obj_map->get_safe_ptr(act->get_location())->push_back(act);
748
749         std::vector<action_list_t> *vec = obj_thrd_map->get_safe_ptr(act->get_location());
750         if (tid >= (int)vec->size())
751                 vec->resize(priv->next_thread_id);
752         (*vec)[tid].push_back(act);
753
754         if ((int)thrd_last_action->size() <= tid)
755                 thrd_last_action->resize(get_num_threads());
756         (*thrd_last_action)[tid] = act;
757 }
758
759 ModelAction * ModelChecker::get_last_action(thread_id_t tid)
760 {
761         int nthreads = get_num_threads();
762         if ((int)thrd_last_action->size() < nthreads)
763                 thrd_last_action->resize(nthreads);
764         return (*thrd_last_action)[id_to_int(tid)];
765 }
766
767 /**
768  * Gets the last memory_order_seq_cst action (in the total global sequence)
769  * performed on a particular object (i.e., memory location).
770  * @param location The object location to check
771  * @return The last seq_cst action performed
772  */
773 ModelAction * ModelChecker::get_last_seq_cst(const void *location)
774 {
775         action_list_t *list = obj_map->get_safe_ptr(location);
776         /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
777         action_list_t::reverse_iterator rit;
778         for (rit = list->rbegin(); rit != list->rend(); rit++)
779                 if ((*rit)->is_write() && (*rit)->is_seqcst())
780                         return *rit;
781         return NULL;
782 }
783
784 ModelAction * ModelChecker::get_parent_action(thread_id_t tid)
785 {
786         ModelAction *parent = get_last_action(tid);
787         if (!parent)
788                 parent = get_thread(tid)->get_creation();
789         return parent;
790 }
791
792 /**
793  * Returns the clock vector for a given thread.
794  * @param tid The thread whose clock vector we want
795  * @return Desired clock vector
796  */
797 ClockVector * ModelChecker::get_cv(thread_id_t tid)
798 {
799         return get_parent_action(tid)->get_cv();
800 }
801
802 /**
803  * Resolve a set of Promises with a current write. The set is provided in the
804  * Node corresponding to @a write.
805  * @param write The ModelAction that is fulfilling Promises
806  * @return True if promises were resolved; false otherwise
807  */
808 bool ModelChecker::resolve_promises(ModelAction *write)
809 {
810         bool resolved = false;
811         for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
812                 Promise *promise = (*promises)[promise_index];
813                 if (write->get_node()->get_promise(i)) {
814                         ModelAction *read = promise->get_action();
815                         read->read_from(write);
816                         r_modification_order(read, write);
817                         post_r_modification_order(read, write);
818                         promises->erase(promises->begin() + promise_index);
819                         resolved = true;
820                 } else
821                         promise_index++;
822         }
823
824         return resolved;
825 }
826
827 /**
828  * Compute the set of promises that could potentially be satisfied by this
829  * action. Note that the set computation actually appears in the Node, not in
830  * ModelChecker.
831  * @param curr The ModelAction that may satisfy promises
832  */
833 void ModelChecker::compute_promises(ModelAction *curr)
834 {
835         for (unsigned int i = 0; i < promises->size(); i++) {
836                 Promise *promise = (*promises)[i];
837                 const ModelAction *act = promise->get_action();
838                 if (!act->happens_before(curr) &&
839                                 act->is_read() &&
840                                 !act->is_synchronizing(curr) &&
841                                 !act->same_thread(curr) &&
842                                 promise->get_value() == curr->get_value()) {
843                         curr->get_node()->set_promise(i);
844                 }
845         }
846 }
847
848 /** Checks promises in response to change in ClockVector Threads. */
849 void ModelChecker::check_promises(ClockVector *old_cv, ClockVector *merge_cv)
850 {
851         for (unsigned int i = 0; i < promises->size(); i++) {
852                 Promise *promise = (*promises)[i];
853                 const ModelAction *act = promise->get_action();
854                 if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
855                                 merge_cv->synchronized_since(act)) {
856                         //This thread is no longer able to send values back to satisfy the promise
857                         int num_synchronized_threads = promise->increment_threads();
858                         if (num_synchronized_threads == get_num_threads()) {
859                                 //Promise has failed
860                                 failed_promise = true;
861                                 return;
862                         }
863                 }
864         }
865 }
866
867 /**
868  * Build up an initial set of all past writes that this 'read' action may read
869  * from. This set is determined by the clock vector's "happens before"
870  * relationship.
871  * @param curr is the current ModelAction that we are exploring; it must be a
872  * 'read' operation.
873  */
874 void ModelChecker::build_reads_from_past(ModelAction *curr)
875 {
876         std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
877         unsigned int i;
878         ASSERT(curr->is_read());
879
880         ModelAction *last_seq_cst = NULL;
881
882         /* Track whether this object has been initialized */
883         bool initialized = false;
884
885         if (curr->is_seqcst()) {
886                 last_seq_cst = get_last_seq_cst(curr->get_location());
887                 /* We have to at least see the last sequentially consistent write,
888                          so we are initialized. */
889                 if (last_seq_cst != NULL)
890                         initialized = true;
891         }
892
893         /* Iterate over all threads */
894         for (i = 0; i < thrd_lists->size(); i++) {
895                 /* Iterate over actions in thread, starting from most recent */
896                 action_list_t *list = &(*thrd_lists)[i];
897                 action_list_t::reverse_iterator rit;
898                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
899                         ModelAction *act = *rit;
900
901                         /* Only consider 'write' actions */
902                         if (!act->is_write())
903                                 continue;
904
905                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
906                         if (!act->is_seqcst() || !curr->is_seqcst() || act == last_seq_cst) {
907                                 DEBUG("Adding action to may_read_from:\n");
908                                 if (DBG_ENABLED()) {
909                                         act->print();
910                                         curr->print();
911                                 }
912                                 curr->get_node()->add_read_from(act);
913                         }
914
915                         /* Include at most one act per-thread that "happens before" curr */
916                         if (act->happens_before(curr)) {
917                                 initialized = true;
918                                 break;
919                         }
920                 }
921         }
922
923         if (!initialized) {
924                 /** @todo Need a more informative way of reporting errors. */
925                 printf("ERROR: may read from uninitialized atomic\n");
926         }
927
928         if (DBG_ENABLED() || !initialized) {
929                 printf("Reached read action:\n");
930                 curr->print();
931                 printf("Printing may_read_from\n");
932                 curr->get_node()->print_may_read_from();
933                 printf("End printing may_read_from\n");
934         }
935
936         ASSERT(initialized);
937 }
938
939 static void print_list(action_list_t *list)
940 {
941         action_list_t::iterator it;
942
943         printf("---------------------------------------------------------------------\n");
944         printf("Trace:\n");
945
946         for (it = list->begin(); it != list->end(); it++) {
947                 (*it)->print();
948         }
949         printf("---------------------------------------------------------------------\n");
950 }
951
952 void ModelChecker::print_summary()
953 {
954         printf("\n");
955         printf("Number of executions: %d\n", num_executions);
956         printf("Total nodes created: %d\n", node_stack->get_total_nodes());
957
958         scheduler->print();
959
960         if (!isfinalfeasible())
961                 printf("INFEASIBLE EXECUTION!\n");
962         print_list(action_trace);
963         printf("\n");
964 }
965
966 /**
967  * Add a Thread to the system for the first time. Should only be called once
968  * per thread.
969  * @param t The Thread to add
970  */
971 void ModelChecker::add_thread(Thread *t)
972 {
973         thread_map->put(id_to_int(t->get_id()), t);
974         scheduler->add_thread(t);
975 }
976
977 void ModelChecker::remove_thread(Thread *t)
978 {
979         scheduler->remove_thread(t);
980 }
981
982 /**
983  * Switch from a user-context to the "master thread" context (a.k.a. system
984  * context). This switch is made with the intention of exploring a particular
985  * model-checking action (described by a ModelAction object). Must be called
986  * from a user-thread context.
987  * @param act The current action that will be explored. Must not be NULL.
988  * @return Return status from the 'swap' call (i.e., success/fail, 0/-1)
989  */
990 int ModelChecker::switch_to_master(ModelAction *act)
991 {
992         DBG();
993         Thread *old = thread_current();
994         set_current_action(act);
995         old->set_state(THREAD_READY);
996         return Thread::swap(old, &system_context);
997 }
998
999 /**
1000  * Takes the next step in the execution, if possible.
1001  * @return Returns true (success) if a step was taken and false otherwise.
1002  */
1003 bool ModelChecker::take_step() {
1004         Thread *curr, *next;
1005
1006         if (has_asserted())
1007                 return false;
1008
1009         curr = thread_current();
1010         if (curr) {
1011                 if (curr->get_state() == THREAD_READY) {
1012                         ASSERT(priv->current_action);
1013                         priv->nextThread = check_current_action(priv->current_action);
1014                         priv->current_action = NULL;
1015                         if (!curr->is_blocked() && !curr->is_complete())
1016                                 scheduler->add_thread(curr);
1017                 } else {
1018                         ASSERT(false);
1019                 }
1020         }
1021         next = scheduler->next_thread(priv->nextThread);
1022
1023         /* Infeasible -> don't take any more steps */
1024         if (!isfeasible())
1025                 return false;
1026
1027         if (next)
1028                 next->set_state(THREAD_RUNNING);
1029         DEBUG("(%d, %d)\n", curr ? curr->get_id() : -1, next ? next->get_id() : -1);
1030
1031         /* next == NULL -> don't take any more steps */
1032         if (!next)
1033                 return false;
1034         /* Return false only if swap fails with an error */
1035         return (Thread::swap(&system_context, next) == 0);
1036 }
1037
1038 /** Runs the current execution until threre are no more steps to take. */
1039 void ModelChecker::finish_execution() {
1040         DBG();
1041
1042         while (take_step());
1043 }