model: fix leaking "pending actions"
[c11tester.git] / model.cc
1 #include <stdio.h>
2 #include <algorithm>
3 #include <mutex>
4 #include <new>
5
6 #include "model.h"
7 #include "action.h"
8 #include "nodestack.h"
9 #include "schedule.h"
10 #include "snapshot-interface.h"
11 #include "common.h"
12 #include "clockvector.h"
13 #include "cyclegraph.h"
14 #include "promise.h"
15 #include "datarace.h"
16 #include "threads-model.h"
17 #include "output.h"
18
19 #define INITIAL_THREAD_ID       0
20
21 ModelChecker *model;
22
23 struct bug_message {
24         bug_message(const char *str) {
25                 const char *fmt = "  [BUG] %s\n";
26                 msg = (char *)snapshot_malloc(strlen(fmt) + strlen(str));
27                 sprintf(msg, fmt, str);
28         }
29         ~bug_message() { if (msg) snapshot_free(msg); }
30
31         char *msg;
32         void print() { model_print("%s", msg); }
33
34         SNAPSHOTALLOC
35 };
36
37 /**
38  * Structure for holding small ModelChecker members that should be snapshotted
39  */
40 struct model_snapshot_members {
41         model_snapshot_members() :
42                 /* First thread created will have id INITIAL_THREAD_ID */
43                 next_thread_id(INITIAL_THREAD_ID),
44                 used_sequence_numbers(0),
45                 next_backtrack(NULL),
46                 bugs(),
47                 stats(),
48                 failed_promise(false),
49                 too_many_reads(false),
50                 no_valid_reads(false),
51                 bad_synchronization(false),
52                 asserted(false)
53         { }
54
55         ~model_snapshot_members() {
56                 for (unsigned int i = 0; i < bugs.size(); i++)
57                         delete bugs[i];
58                 bugs.clear();
59         }
60
61         unsigned int next_thread_id;
62         modelclock_t used_sequence_numbers;
63         ModelAction *next_backtrack;
64         std::vector< bug_message *, SnapshotAlloc<bug_message *> > bugs;
65         struct execution_stats stats;
66         bool failed_promise;
67         bool too_many_reads;
68         bool no_valid_reads;
69         /** @brief Incorrectly-ordered synchronization was made */
70         bool bad_synchronization;
71         bool asserted;
72
73         SNAPSHOTALLOC
74 };
75
76 /** @brief Constructor */
77 ModelChecker::ModelChecker(struct model_params params) :
78         /* Initialize default scheduler */
79         params(params),
80         scheduler(new Scheduler()),
81         diverge(NULL),
82         earliest_diverge(NULL),
83         action_trace(new action_list_t()),
84         thread_map(new HashTable<int, Thread *, int>()),
85         obj_map(new HashTable<const void *, action_list_t *, uintptr_t, 4>()),
86         lock_waiters_map(new HashTable<const void *, action_list_t *, uintptr_t, 4>()),
87         condvar_waiters_map(new HashTable<const void *, action_list_t *, uintptr_t, 4>()),
88         obj_thrd_map(new HashTable<void *, std::vector<action_list_t> *, uintptr_t, 4 >()),
89         promises(new std::vector< Promise *, SnapshotAlloc<Promise *> >()),
90         futurevalues(new std::vector< struct PendingFutureValue, SnapshotAlloc<struct PendingFutureValue> >()),
91         pending_rel_seqs(new std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >()),
92         thrd_last_action(new std::vector< ModelAction *, SnapshotAlloc<ModelAction *> >(1)),
93         thrd_last_fence_release(new std::vector< ModelAction *, SnapshotAlloc<ModelAction *> >()),
94         node_stack(new NodeStack()),
95         priv(new struct model_snapshot_members()),
96         mo_graph(new CycleGraph())
97 {
98         /* Initialize a model-checker thread, for special ModelActions */
99         model_thread = new Thread(get_next_id());
100         thread_map->put(id_to_int(model_thread->get_id()), model_thread);
101 }
102
103 /** @brief Destructor */
104 ModelChecker::~ModelChecker()
105 {
106         for (unsigned int i = 0; i < get_num_threads(); i++)
107                 delete thread_map->get(i);
108         delete thread_map;
109
110         delete obj_thrd_map;
111         delete obj_map;
112         delete lock_waiters_map;
113         delete condvar_waiters_map;
114         delete action_trace;
115
116         for (unsigned int i = 0; i < promises->size(); i++)
117                 delete (*promises)[i];
118         delete promises;
119
120         delete pending_rel_seqs;
121
122         delete thrd_last_action;
123         delete thrd_last_fence_release;
124         delete node_stack;
125         delete scheduler;
126         delete mo_graph;
127         delete priv;
128 }
129
130 static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 4> * hash, void * ptr)
131 {
132         action_list_t *tmp = hash->get(ptr);
133         if (tmp == NULL) {
134                 tmp = new action_list_t();
135                 hash->put(ptr, tmp);
136         }
137         return tmp;
138 }
139
140 static std::vector<action_list_t> * get_safe_ptr_vect_action(HashTable<void *, std::vector<action_list_t> *, uintptr_t, 4> * hash, void * ptr)
141 {
142         std::vector<action_list_t> *tmp = hash->get(ptr);
143         if (tmp == NULL) {
144                 tmp = new std::vector<action_list_t>();
145                 hash->put(ptr, tmp);
146         }
147         return tmp;
148 }
149
150 /**
151  * Restores user program to initial state and resets all model-checker data
152  * structures.
153  */
154 void ModelChecker::reset_to_initial_state()
155 {
156         DEBUG("+++ Resetting to initial state +++\n");
157         node_stack->reset_execution();
158
159         /* Print all model-checker output before rollback */
160         fflush(model_out);
161
162         /**
163          * FIXME: if we utilize partial rollback, we will need to free only
164          * those pending actions which were NOT pending before the rollback
165          * point
166          */
167         for (unsigned int i = 0; i < get_num_threads(); i++)
168                 delete get_thread(int_to_id(i))->get_pending();
169
170         snapshot_backtrack_before(0);
171 }
172
173 /** @return a thread ID for a new Thread */
174 thread_id_t ModelChecker::get_next_id()
175 {
176         return priv->next_thread_id++;
177 }
178
179 /** @return the number of user threads created during this execution */
180 unsigned int ModelChecker::get_num_threads() const
181 {
182         return priv->next_thread_id;
183 }
184
185 /**
186  * Must be called from user-thread context (e.g., through the global
187  * thread_current() interface)
188  *
189  * @return The currently executing Thread.
190  */
191 Thread * ModelChecker::get_current_thread() const
192 {
193         return scheduler->get_current_thread();
194 }
195
196 /** @return a sequence number for a new ModelAction */
197 modelclock_t ModelChecker::get_next_seq_num()
198 {
199         return ++priv->used_sequence_numbers;
200 }
201
202 Node * ModelChecker::get_curr_node() const
203 {
204         return node_stack->get_head();
205 }
206
207 /**
208  * @brief Choose the next thread to execute.
209  *
210  * This function chooses the next thread that should execute. It can force the
211  * adjacency of read/write portions of a RMW action, force THREAD_CREATE to be
212  * followed by a THREAD_START, or it can enforce execution replay/backtracking.
213  * The model-checker may have no preference regarding the next thread (i.e.,
214  * when exploring a new execution ordering), in which case this will return
215  * NULL.
216  * @param curr The current ModelAction. This action might guide the choice of
217  * next thread.
218  * @return The next thread to run. If the model-checker has no preference, NULL.
219  */
220 Thread * ModelChecker::get_next_thread(ModelAction *curr)
221 {
222         thread_id_t tid;
223
224         if (curr != NULL) {
225                 /* Do not split atomic actions. */
226                 if (curr->is_rmwr())
227                         return get_thread(curr);
228                 else if (curr->get_type() == THREAD_CREATE)
229                         return curr->get_thread_operand();
230         }
231
232         /* Have we completed exploring the preselected path? */
233         if (diverge == NULL)
234                 return NULL;
235
236         /* Else, we are trying to replay an execution */
237         ModelAction *next = node_stack->get_next()->get_action();
238
239         if (next == diverge) {
240                 if (earliest_diverge == NULL || *diverge < *earliest_diverge)
241                         earliest_diverge = diverge;
242
243                 Node *nextnode = next->get_node();
244                 Node *prevnode = nextnode->get_parent();
245                 scheduler->update_sleep_set(prevnode);
246
247                 /* Reached divergence point */
248                 if (nextnode->increment_misc()) {
249                         /* The next node will try to satisfy a different misc_index values. */
250                         tid = next->get_tid();
251                         node_stack->pop_restofstack(2);
252                 } else if (nextnode->increment_promise()) {
253                         /* The next node will try to satisfy a different set of promises. */
254                         tid = next->get_tid();
255                         node_stack->pop_restofstack(2);
256                 } else if (nextnode->increment_read_from()) {
257                         /* The next node will read from a different value. */
258                         tid = next->get_tid();
259                         node_stack->pop_restofstack(2);
260                 } else if (nextnode->increment_future_value()) {
261                         /* The next node will try to read from a different future value. */
262                         tid = next->get_tid();
263                         node_stack->pop_restofstack(2);
264                 } else if (nextnode->increment_relseq_break()) {
265                         /* The next node will try to resolve a release sequence differently */
266                         tid = next->get_tid();
267                         node_stack->pop_restofstack(2);
268                 } else {
269                         ASSERT(prevnode);
270                         /* Make a different thread execute for next step */
271                         scheduler->add_sleep(get_thread(next->get_tid()));
272                         tid = prevnode->get_next_backtrack();
273                         /* Make sure the backtracked thread isn't sleeping. */
274                         node_stack->pop_restofstack(1);
275                         if (diverge == earliest_diverge) {
276                                 earliest_diverge = prevnode->get_action();
277                         }
278                 }
279                 /* The correct sleep set is in the parent node. */
280                 execute_sleep_set();
281
282                 DEBUG("*** Divergence point ***\n");
283
284                 diverge = NULL;
285         } else {
286                 tid = next->get_tid();
287         }
288         DEBUG("*** ModelChecker chose next thread = %d ***\n", id_to_int(tid));
289         ASSERT(tid != THREAD_ID_T_NONE);
290         return thread_map->get(id_to_int(tid));
291 }
292
293 /**
294  * We need to know what the next actions of all threads in the sleep
295  * set will be.  This method computes them and stores the actions at
296  * the corresponding thread object's pending action.
297  */
298
299 void ModelChecker::execute_sleep_set()
300 {
301         for (unsigned int i = 0; i < get_num_threads(); i++) {
302                 thread_id_t tid = int_to_id(i);
303                 Thread *thr = get_thread(tid);
304                 if (scheduler->is_sleep_set(thr) && thr->get_pending()) {
305                         thr->get_pending()->set_sleep_flag();
306                 }
307         }
308 }
309
310 void ModelChecker::wake_up_sleeping_actions(ModelAction *curr)
311 {
312         for (unsigned int i = 0; i < get_num_threads(); i++) {
313                 Thread *thr = get_thread(int_to_id(i));
314                 if (scheduler->is_sleep_set(thr)) {
315                         ModelAction *pending_act = thr->get_pending();
316                         if ((!curr->is_rmwr()) && pending_act->could_synchronize_with(curr))
317                                 //Remove this thread from sleep set
318                                 scheduler->remove_sleep(thr);
319                 }
320         }
321 }
322
323 /** @brief Alert the model-checker that an incorrectly-ordered
324  * synchronization was made */
325 void ModelChecker::set_bad_synchronization()
326 {
327         priv->bad_synchronization = true;
328 }
329
330 bool ModelChecker::has_asserted() const
331 {
332         return priv->asserted;
333 }
334
335 void ModelChecker::set_assert()
336 {
337         priv->asserted = true;
338 }
339
340 /**
341  * Check if we are in a deadlock. Should only be called at the end of an
342  * execution, although it should not give false positives in the middle of an
343  * execution (there should be some ENABLED thread).
344  *
345  * @return True if program is in a deadlock; false otherwise
346  */
347 bool ModelChecker::is_deadlocked() const
348 {
349         bool blocking_threads = false;
350         for (unsigned int i = 0; i < get_num_threads(); i++) {
351                 thread_id_t tid = int_to_id(i);
352                 if (is_enabled(tid))
353                         return false;
354                 Thread *t = get_thread(tid);
355                 if (!t->is_model_thread() && t->get_pending())
356                         blocking_threads = true;
357         }
358         return blocking_threads;
359 }
360
361 /**
362  * Check if this is a complete execution. That is, have all thread completed
363  * execution (rather than exiting because sleep sets have forced a redundant
364  * execution).
365  *
366  * @return True if the execution is complete.
367  */
368 bool ModelChecker::is_complete_execution() const
369 {
370         for (unsigned int i = 0; i < get_num_threads(); i++)
371                 if (is_enabled(int_to_id(i)))
372                         return false;
373         return true;
374 }
375
376 /**
377  * @brief Assert a bug in the executing program.
378  *
379  * Use this function to assert any sort of bug in the user program. If the
380  * current trace is feasible (actually, a prefix of some feasible execution),
381  * then this execution will be aborted, printing the appropriate message. If
382  * the current trace is not yet feasible, the error message will be stashed and
383  * printed if the execution ever becomes feasible.
384  *
385  * @param msg Descriptive message for the bug (do not include newline char)
386  * @return True if bug is immediately-feasible
387  */
388 bool ModelChecker::assert_bug(const char *msg)
389 {
390         priv->bugs.push_back(new bug_message(msg));
391
392         if (isfeasibleprefix()) {
393                 set_assert();
394                 return true;
395         }
396         return false;
397 }
398
399 /**
400  * @brief Assert a bug in the executing program, asserted by a user thread
401  * @see ModelChecker::assert_bug
402  * @param msg Descriptive message for the bug (do not include newline char)
403  */
404 void ModelChecker::assert_user_bug(const char *msg)
405 {
406         /* If feasible bug, bail out now */
407         if (assert_bug(msg))
408                 switch_to_master(NULL);
409 }
410
411 /** @return True, if any bugs have been reported for this execution */
412 bool ModelChecker::have_bug_reports() const
413 {
414         return priv->bugs.size() != 0;
415 }
416
417 /** @brief Print bug report listing for this execution (if any bugs exist) */
418 void ModelChecker::print_bugs() const
419 {
420         if (have_bug_reports()) {
421                 model_print("Bug report: %zu bug%s detected\n",
422                                 priv->bugs.size(),
423                                 priv->bugs.size() > 1 ? "s" : "");
424                 for (unsigned int i = 0; i < priv->bugs.size(); i++)
425                         priv->bugs[i]->print();
426         }
427 }
428
429 /**
430  * @brief Record end-of-execution stats
431  *
432  * Must be run when exiting an execution. Records various stats.
433  * @see struct execution_stats
434  */
435 void ModelChecker::record_stats()
436 {
437         stats.num_total++;
438         if (!isfeasibleprefix())
439                 stats.num_infeasible++;
440         else if (have_bug_reports())
441                 stats.num_buggy_executions++;
442         else if (is_complete_execution())
443                 stats.num_complete++;
444         else
445                 stats.num_redundant++;
446 }
447
448 /** @brief Print execution stats */
449 void ModelChecker::print_stats() const
450 {
451         model_print("Number of complete, bug-free executions: %d\n", stats.num_complete);
452         model_print("Number of redundant executions: %d\n", stats.num_redundant);
453         model_print("Number of buggy executions: %d\n", stats.num_buggy_executions);
454         model_print("Number of infeasible executions: %d\n", stats.num_infeasible);
455         model_print("Total executions: %d\n", stats.num_total);
456         model_print("Total nodes created: %d\n", node_stack->get_total_nodes());
457 }
458
459 /**
460  * @brief End-of-exeuction print
461  * @param printbugs Should any existing bugs be printed?
462  */
463 void ModelChecker::print_execution(bool printbugs) const
464 {
465         print_program_output();
466
467         if (DBG_ENABLED() || params.verbose) {
468                 model_print("Earliest divergence point since last feasible execution:\n");
469                 if (earliest_diverge)
470                         earliest_diverge->print();
471                 else
472                         model_print("(Not set)\n");
473
474                 model_print("\n");
475                 print_stats();
476         }
477
478         /* Don't print invalid bugs */
479         if (printbugs)
480                 print_bugs();
481
482         model_print("\n");
483         print_summary();
484 }
485
486 /**
487  * Queries the model-checker for more executions to explore and, if one
488  * exists, resets the model-checker state to execute a new execution.
489  *
490  * @return If there are more executions to explore, return true. Otherwise,
491  * return false.
492  */
493 bool ModelChecker::next_execution()
494 {
495         DBG();
496         /* Is this execution a feasible execution that's worth bug-checking? */
497         bool complete = isfeasibleprefix() && (is_complete_execution() ||
498                         have_bug_reports());
499
500         /* End-of-execution bug checks */
501         if (complete) {
502                 if (is_deadlocked())
503                         assert_bug("Deadlock detected");
504
505                 checkDataRaces();
506         }
507
508         record_stats();
509
510         /* Output */
511         if (DBG_ENABLED() || params.verbose || (complete && have_bug_reports()))
512                 print_execution(complete);
513         else
514                 clear_program_output();
515
516         if (complete)
517                 earliest_diverge = NULL;
518
519         if ((diverge = get_next_backtrack()) == NULL)
520                 return false;
521
522         if (DBG_ENABLED()) {
523                 model_print("Next execution will diverge at:\n");
524                 diverge->print();
525         }
526
527         reset_to_initial_state();
528         return true;
529 }
530
531 ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
532 {
533         switch (act->get_type()) {
534         case ATOMIC_FENCE:
535         case ATOMIC_READ:
536         case ATOMIC_WRITE:
537         case ATOMIC_RMW: {
538                 /* Optimization: relaxed operations don't need backtracking */
539                 if (act->is_relaxed())
540                         return NULL;
541                 /* linear search: from most recent to oldest */
542                 action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
543                 action_list_t::reverse_iterator rit;
544                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
545                         ModelAction *prev = *rit;
546                         if (prev->could_synchronize_with(act))
547                                 return prev;
548                 }
549                 break;
550         }
551         case ATOMIC_LOCK:
552         case ATOMIC_TRYLOCK: {
553                 /* linear search: from most recent to oldest */
554                 action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
555                 action_list_t::reverse_iterator rit;
556                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
557                         ModelAction *prev = *rit;
558                         if (act->is_conflicting_lock(prev))
559                                 return prev;
560                 }
561                 break;
562         }
563         case ATOMIC_UNLOCK: {
564                 /* linear search: from most recent to oldest */
565                 action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
566                 action_list_t::reverse_iterator rit;
567                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
568                         ModelAction *prev = *rit;
569                         if (!act->same_thread(prev) && prev->is_failed_trylock())
570                                 return prev;
571                 }
572                 break;
573         }
574         case ATOMIC_WAIT: {
575                 /* linear search: from most recent to oldest */
576                 action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
577                 action_list_t::reverse_iterator rit;
578                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
579                         ModelAction *prev = *rit;
580                         if (!act->same_thread(prev) && prev->is_failed_trylock())
581                                 return prev;
582                         if (!act->same_thread(prev) && prev->is_notify())
583                                 return prev;
584                 }
585                 break;
586         }
587
588         case ATOMIC_NOTIFY_ALL:
589         case ATOMIC_NOTIFY_ONE: {
590                 /* linear search: from most recent to oldest */
591                 action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
592                 action_list_t::reverse_iterator rit;
593                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
594                         ModelAction *prev = *rit;
595                         if (!act->same_thread(prev) && prev->is_wait())
596                                 return prev;
597                 }
598                 break;
599         }
600         default:
601                 break;
602         }
603         return NULL;
604 }
605
606 /** This method finds backtracking points where we should try to
607  * reorder the parameter ModelAction against.
608  *
609  * @param the ModelAction to find backtracking points for.
610  */
611 void ModelChecker::set_backtracking(ModelAction *act)
612 {
613         Thread *t = get_thread(act);
614         ModelAction *prev = get_last_conflict(act);
615         if (prev == NULL)
616                 return;
617
618         Node *node = prev->get_node()->get_parent();
619
620         int low_tid, high_tid;
621         if (node->enabled_status(t->get_id()) == THREAD_ENABLED) {
622                 low_tid = id_to_int(act->get_tid());
623                 high_tid = low_tid + 1;
624         } else {
625                 low_tid = 0;
626                 high_tid = get_num_threads();
627         }
628
629         for (int i = low_tid; i < high_tid; i++) {
630                 thread_id_t tid = int_to_id(i);
631
632                 /* Make sure this thread can be enabled here. */
633                 if (i >= node->get_num_threads())
634                         break;
635
636                 /* Don't backtrack into a point where the thread is disabled or sleeping. */
637                 if (node->enabled_status(tid) != THREAD_ENABLED)
638                         continue;
639
640                 /* Check if this has been explored already */
641                 if (node->has_been_explored(tid))
642                         continue;
643
644                 /* See if fairness allows */
645                 if (model->params.fairwindow != 0 && !node->has_priority(tid)) {
646                         bool unfair = false;
647                         for (int t = 0; t < node->get_num_threads(); t++) {
648                                 thread_id_t tother = int_to_id(t);
649                                 if (node->is_enabled(tother) && node->has_priority(tother)) {
650                                         unfair = true;
651                                         break;
652                                 }
653                         }
654                         if (unfair)
655                                 continue;
656                 }
657                 /* Cache the latest backtracking point */
658                 set_latest_backtrack(prev);
659
660                 /* If this is a new backtracking point, mark the tree */
661                 if (!node->set_backtrack(tid))
662                         continue;
663                 DEBUG("Setting backtrack: conflict = %d, instead tid = %d\n",
664                                         id_to_int(prev->get_tid()),
665                                         id_to_int(t->get_id()));
666                 if (DBG_ENABLED()) {
667                         prev->print();
668                         act->print();
669                 }
670         }
671 }
672
673 /**
674  * @brief Cache the a backtracking point as the "most recent", if eligible
675  *
676  * Note that this does not prepare the NodeStack for this backtracking
677  * operation, it only caches the action on a per-execution basis
678  *
679  * @param act The operation at which we should explore a different next action
680  * (i.e., backtracking point)
681  * @return True, if this action is now the most recent backtracking point;
682  * false otherwise
683  */
684 bool ModelChecker::set_latest_backtrack(ModelAction *act)
685 {
686         if (!priv->next_backtrack || *act > *priv->next_backtrack) {
687                 priv->next_backtrack = act;
688                 return true;
689         }
690         return false;
691 }
692
693 /**
694  * Returns last backtracking point. The model checker will explore a different
695  * path for this point in the next execution.
696  * @return The ModelAction at which the next execution should diverge.
697  */
698 ModelAction * ModelChecker::get_next_backtrack()
699 {
700         ModelAction *next = priv->next_backtrack;
701         priv->next_backtrack = NULL;
702         return next;
703 }
704
705 /**
706  * Processes a read or rmw model action.
707  * @param curr is the read model action to process.
708  * @param second_part_of_rmw is boolean that is true is this is the second action of a rmw.
709  * @return True if processing this read updates the mo_graph.
710  */
711 bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw)
712 {
713         uint64_t value = VALUE_NONE;
714         bool updated = false;
715         while (true) {
716                 const ModelAction *reads_from = curr->get_node()->get_read_from();
717                 if (reads_from != NULL) {
718                         mo_graph->startChanges();
719
720                         value = reads_from->get_value();
721                         bool r_status = false;
722
723                         if (!second_part_of_rmw) {
724                                 check_recency(curr, reads_from);
725                                 r_status = r_modification_order(curr, reads_from);
726                         }
727
728                         if (!second_part_of_rmw && is_infeasible() && (curr->get_node()->increment_read_from() || curr->get_node()->increment_future_value())) {
729                                 mo_graph->rollbackChanges();
730                                 priv->too_many_reads = false;
731                                 continue;
732                         }
733
734                         read_from(curr, reads_from);
735                         mo_graph->commitChanges();
736                         mo_check_promises(curr, true);
737
738                         updated |= r_status;
739                 } else if (!second_part_of_rmw) {
740                         /* Read from future value */
741                         struct future_value fv = curr->get_node()->get_future_value();
742                         Promise *promise = new Promise(curr, fv);
743                         value = fv.value;
744                         curr->set_read_from_promise(promise);
745                         promises->push_back(promise);
746                         mo_graph->startChanges();
747                         updated = r_modification_order(curr, promise);
748                         mo_graph->commitChanges();
749                 }
750                 get_thread(curr)->set_return_value(value);
751                 return updated;
752         }
753 }
754
755 /**
756  * Processes a lock, trylock, or unlock model action.  @param curr is
757  * the read model action to process.
758  *
759  * The try lock operation checks whether the lock is taken.  If not,
760  * it falls to the normal lock operation case.  If so, it returns
761  * fail.
762  *
763  * The lock operation has already been checked that it is enabled, so
764  * it just grabs the lock and synchronizes with the previous unlock.
765  *
766  * The unlock operation has to re-enable all of the threads that are
767  * waiting on the lock.
768  *
769  * @return True if synchronization was updated; false otherwise
770  */
771 bool ModelChecker::process_mutex(ModelAction *curr)
772 {
773         std::mutex *mutex = NULL;
774         struct std::mutex_state *state = NULL;
775
776         if (curr->is_trylock() || curr->is_lock() || curr->is_unlock()) {
777                 mutex = (std::mutex *)curr->get_location();
778                 state = mutex->get_state();
779         } else if (curr->is_wait()) {
780                 mutex = (std::mutex *)curr->get_value();
781                 state = mutex->get_state();
782         }
783
784         switch (curr->get_type()) {
785         case ATOMIC_TRYLOCK: {
786                 bool success = !state->islocked;
787                 curr->set_try_lock(success);
788                 if (!success) {
789                         get_thread(curr)->set_return_value(0);
790                         break;
791                 }
792                 get_thread(curr)->set_return_value(1);
793         }
794                 //otherwise fall into the lock case
795         case ATOMIC_LOCK: {
796                 if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock)
797                         assert_bug("Lock access before initialization");
798                 state->islocked = true;
799                 ModelAction *unlock = get_last_unlock(curr);
800                 //synchronize with the previous unlock statement
801                 if (unlock != NULL) {
802                         curr->synchronize_with(unlock);
803                         return true;
804                 }
805                 break;
806         }
807         case ATOMIC_UNLOCK: {
808                 //unlock the lock
809                 state->islocked = false;
810                 //wake up the other threads
811                 action_list_t *waiters = get_safe_ptr_action(lock_waiters_map, curr->get_location());
812                 //activate all the waiting threads
813                 for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
814                         scheduler->wake(get_thread(*rit));
815                 }
816                 waiters->clear();
817                 break;
818         }
819         case ATOMIC_WAIT: {
820                 //unlock the lock
821                 state->islocked = false;
822                 //wake up the other threads
823                 action_list_t *waiters = get_safe_ptr_action(lock_waiters_map, (void *) curr->get_value());
824                 //activate all the waiting threads
825                 for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
826                         scheduler->wake(get_thread(*rit));
827                 }
828                 waiters->clear();
829                 //check whether we should go to sleep or not...simulate spurious failures
830                 if (curr->get_node()->get_misc() == 0) {
831                         get_safe_ptr_action(condvar_waiters_map, curr->get_location())->push_back(curr);
832                         //disable us
833                         scheduler->sleep(get_thread(curr));
834                 }
835                 break;
836         }
837         case ATOMIC_NOTIFY_ALL: {
838                 action_list_t *waiters = get_safe_ptr_action(condvar_waiters_map, curr->get_location());
839                 //activate all the waiting threads
840                 for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
841                         scheduler->wake(get_thread(*rit));
842                 }
843                 waiters->clear();
844                 break;
845         }
846         case ATOMIC_NOTIFY_ONE: {
847                 action_list_t *waiters = get_safe_ptr_action(condvar_waiters_map, curr->get_location());
848                 int wakeupthread = curr->get_node()->get_misc();
849                 action_list_t::iterator it = waiters->begin();
850                 advance(it, wakeupthread);
851                 scheduler->wake(get_thread(*it));
852                 waiters->erase(it);
853                 break;
854         }
855
856         default:
857                 ASSERT(0);
858         }
859         return false;
860 }
861
862 void ModelChecker::add_future_value(const ModelAction *writer, ModelAction *reader)
863 {
864         /* Do more ambitious checks now that mo is more complete */
865         if (mo_may_allow(writer, reader)) {
866                 Node *node = reader->get_node();
867
868                 /* Find an ancestor thread which exists at the time of the reader */
869                 Thread *write_thread = get_thread(writer);
870                 while (id_to_int(write_thread->get_id()) >= node->get_num_threads())
871                         write_thread = write_thread->get_parent();
872
873                 struct future_value fv = {
874                         writer->get_value(),
875                         writer->get_seq_number() + params.maxfuturedelay,
876                         write_thread->get_id(),
877                 };
878                 if (node->add_future_value(fv))
879                         set_latest_backtrack(reader);
880         }
881 }
882
883 /**
884  * Process a write ModelAction
885  * @param curr The ModelAction to process
886  * @return True if the mo_graph was updated or promises were resolved
887  */
888 bool ModelChecker::process_write(ModelAction *curr)
889 {
890         bool updated_mod_order = w_modification_order(curr);
891         bool updated_promises = resolve_promises(curr);
892
893         if (promises->size() == 0) {
894                 for (unsigned int i = 0; i < futurevalues->size(); i++) {
895                         struct PendingFutureValue pfv = (*futurevalues)[i];
896                         add_future_value(pfv.writer, pfv.act);
897                 }
898                 futurevalues->clear();
899         }
900
901         mo_graph->commitChanges();
902         mo_check_promises(curr, false);
903
904         get_thread(curr)->set_return_value(VALUE_NONE);
905         return updated_mod_order || updated_promises;
906 }
907
908 /**
909  * Process a fence ModelAction
910  * @param curr The ModelAction to process
911  * @return True if synchronization was updated
912  */
913 bool ModelChecker::process_fence(ModelAction *curr)
914 {
915         /*
916          * fence-relaxed: no-op
917          * fence-release: only log the occurence (not in this function), for
918          *   use in later synchronization
919          * fence-acquire (this function): search for hypothetical release
920          *   sequences
921          */
922         bool updated = false;
923         if (curr->is_acquire()) {
924                 action_list_t *list = action_trace;
925                 action_list_t::reverse_iterator rit;
926                 /* Find X : is_read(X) && X --sb-> curr */
927                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
928                         ModelAction *act = *rit;
929                         if (act == curr)
930                                 continue;
931                         if (act->get_tid() != curr->get_tid())
932                                 continue;
933                         /* Stop at the beginning of the thread */
934                         if (act->is_thread_start())
935                                 break;
936                         /* Stop once we reach a prior fence-acquire */
937                         if (act->is_fence() && act->is_acquire())
938                                 break;
939                         if (!act->is_read())
940                                 continue;
941                         /* read-acquire will find its own release sequences */
942                         if (act->is_acquire())
943                                 continue;
944
945                         /* Establish hypothetical release sequences */
946                         rel_heads_list_t release_heads;
947                         get_release_seq_heads(curr, act, &release_heads);
948                         for (unsigned int i = 0; i < release_heads.size(); i++)
949                                 if (!curr->synchronize_with(release_heads[i]))
950                                         set_bad_synchronization();
951                         if (release_heads.size() != 0)
952                                 updated = true;
953                 }
954         }
955         return updated;
956 }
957
958 /**
959  * @brief Process the current action for thread-related activity
960  *
961  * Performs current-action processing for a THREAD_* ModelAction. Proccesses
962  * may include setting Thread status, completing THREAD_FINISH/THREAD_JOIN
963  * synchronization, etc.  This function is a no-op for non-THREAD actions
964  * (e.g., ATOMIC_{READ,WRITE,RMW,LOCK}, etc.)
965  *
966  * @param curr The current action
967  * @return True if synchronization was updated or a thread completed
968  */
969 bool ModelChecker::process_thread_action(ModelAction *curr)
970 {
971         bool updated = false;
972
973         switch (curr->get_type()) {
974         case THREAD_CREATE: {
975                 thrd_t *thrd = (thrd_t *)curr->get_location();
976                 struct thread_params *params = (struct thread_params *)curr->get_value();
977                 Thread *th = new Thread(thrd, params->func, params->arg);
978                 add_thread(th);
979                 th->set_creation(curr);
980                 /* Promises can be satisfied by children */
981                 for (unsigned int i = 0; i < promises->size(); i++) {
982                         Promise *promise = (*promises)[i];
983                         if (promise->thread_is_available(curr->get_tid()))
984                                 promise->add_thread(th->get_id());
985                 }
986                 break;
987         }
988         case THREAD_JOIN: {
989                 Thread *blocking = curr->get_thread_operand();
990                 ModelAction *act = get_last_action(blocking->get_id());
991                 curr->synchronize_with(act);
992                 updated = true; /* trigger rel-seq checks */
993                 break;
994         }
995         case THREAD_FINISH: {
996                 Thread *th = get_thread(curr);
997                 while (!th->wait_list_empty()) {
998                         ModelAction *act = th->pop_wait_list();
999                         scheduler->wake(get_thread(act));
1000                 }
1001                 th->complete();
1002                 /* Completed thread can't satisfy promises */
1003                 for (unsigned int i = 0; i < promises->size(); i++) {
1004                         Promise *promise = (*promises)[i];
1005                         if (promise->thread_is_available(th->get_id()))
1006                                 if (promise->eliminate_thread(th->get_id()))
1007                                         priv->failed_promise = true;
1008                 }
1009                 updated = true; /* trigger rel-seq checks */
1010                 break;
1011         }
1012         case THREAD_START: {
1013                 check_promises(curr->get_tid(), NULL, curr->get_cv());
1014                 break;
1015         }
1016         default:
1017                 break;
1018         }
1019
1020         return updated;
1021 }
1022
1023 /**
1024  * @brief Process the current action for release sequence fixup activity
1025  *
1026  * Performs model-checker release sequence fixups for the current action,
1027  * forcing a single pending release sequence to break (with a given, potential
1028  * "loose" write) or to complete (i.e., synchronize). If a pending release
1029  * sequence forms a complete release sequence, then we must perform the fixup
1030  * synchronization, mo_graph additions, etc.
1031  *
1032  * @param curr The current action; must be a release sequence fixup action
1033  * @param work_queue The work queue to which to add work items as they are
1034  * generated
1035  */
1036 void ModelChecker::process_relseq_fixup(ModelAction *curr, work_queue_t *work_queue)
1037 {
1038         const ModelAction *write = curr->get_node()->get_relseq_break();
1039         struct release_seq *sequence = pending_rel_seqs->back();
1040         pending_rel_seqs->pop_back();
1041         ASSERT(sequence);
1042         ModelAction *acquire = sequence->acquire;
1043         const ModelAction *rf = sequence->rf;
1044         const ModelAction *release = sequence->release;
1045         ASSERT(acquire);
1046         ASSERT(release);
1047         ASSERT(rf);
1048         ASSERT(release->same_thread(rf));
1049
1050         if (write == NULL) {
1051                 /**
1052                  * @todo Forcing a synchronization requires that we set
1053                  * modification order constraints. For instance, we can't allow
1054                  * a fixup sequence in which two separate read-acquire
1055                  * operations read from the same sequence, where the first one
1056                  * synchronizes and the other doesn't. Essentially, we can't
1057                  * allow any writes to insert themselves between 'release' and
1058                  * 'rf'
1059                  */
1060
1061                 /* Must synchronize */
1062                 if (!acquire->synchronize_with(release)) {
1063                         set_bad_synchronization();
1064                         return;
1065                 }
1066                 /* Re-check all pending release sequences */
1067                 work_queue->push_back(CheckRelSeqWorkEntry(NULL));
1068                 /* Re-check act for mo_graph edges */
1069                 work_queue->push_back(MOEdgeWorkEntry(acquire));
1070
1071                 /* propagate synchronization to later actions */
1072                 action_list_t::reverse_iterator rit = action_trace->rbegin();
1073                 for (; (*rit) != acquire; rit++) {
1074                         ModelAction *propagate = *rit;
1075                         if (acquire->happens_before(propagate)) {
1076                                 propagate->synchronize_with(acquire);
1077                                 /* Re-check 'propagate' for mo_graph edges */
1078                                 work_queue->push_back(MOEdgeWorkEntry(propagate));
1079                         }
1080                 }
1081         } else {
1082                 /* Break release sequence with new edges:
1083                  *   release --mo--> write --mo--> rf */
1084                 mo_graph->addEdge(release, write);
1085                 mo_graph->addEdge(write, rf);
1086         }
1087
1088         /* See if we have realized a data race */
1089         checkDataRaces();
1090 }
1091
1092 /**
1093  * Initialize the current action by performing one or more of the following
1094  * actions, as appropriate: merging RMWR and RMWC/RMW actions, stepping forward
1095  * in the NodeStack, manipulating backtracking sets, allocating and
1096  * initializing clock vectors, and computing the promises to fulfill.
1097  *
1098  * @param curr The current action, as passed from the user context; may be
1099  * freed/invalidated after the execution of this function, with a different
1100  * action "returned" its place (pass-by-reference)
1101  * @return True if curr is a newly-explored action; false otherwise
1102  */
1103 bool ModelChecker::initialize_curr_action(ModelAction **curr)
1104 {
1105         ModelAction *newcurr;
1106
1107         if ((*curr)->is_rmwc() || (*curr)->is_rmw()) {
1108                 newcurr = process_rmw(*curr);
1109                 delete *curr;
1110
1111                 if (newcurr->is_rmw())
1112                         compute_promises(newcurr);
1113
1114                 *curr = newcurr;
1115                 return false;
1116         }
1117
1118         (*curr)->set_seq_number(get_next_seq_num());
1119
1120         newcurr = node_stack->explore_action(*curr, scheduler->get_enabled_array());
1121         if (newcurr) {
1122                 /* First restore type and order in case of RMW operation */
1123                 if ((*curr)->is_rmwr())
1124                         newcurr->copy_typeandorder(*curr);
1125
1126                 ASSERT((*curr)->get_location() == newcurr->get_location());
1127                 newcurr->copy_from_new(*curr);
1128
1129                 /* Discard duplicate ModelAction; use action from NodeStack */
1130                 delete *curr;
1131
1132                 /* Always compute new clock vector */
1133                 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
1134
1135                 *curr = newcurr;
1136                 return false; /* Action was explored previously */
1137         } else {
1138                 newcurr = *curr;
1139
1140                 /* Always compute new clock vector */
1141                 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
1142
1143                 /* Assign most recent release fence */
1144                 newcurr->set_last_fence_release(get_last_fence_release(newcurr->get_tid()));
1145
1146                 /*
1147                  * Perform one-time actions when pushing new ModelAction onto
1148                  * NodeStack
1149                  */
1150                 if (newcurr->is_write())
1151                         compute_promises(newcurr);
1152                 else if (newcurr->is_relseq_fixup())
1153                         compute_relseq_breakwrites(newcurr);
1154                 else if (newcurr->is_wait())
1155                         newcurr->get_node()->set_misc_max(2);
1156                 else if (newcurr->is_notify_one()) {
1157                         newcurr->get_node()->set_misc_max(get_safe_ptr_action(condvar_waiters_map, newcurr->get_location())->size());
1158                 }
1159                 return true; /* This was a new ModelAction */
1160         }
1161 }
1162
1163 /**
1164  * @brief Establish reads-from relation between two actions
1165  *
1166  * Perform basic operations involved with establishing a concrete rf relation,
1167  * including setting the ModelAction data and checking for release sequences.
1168  *
1169  * @param act The action that is reading (must be a read)
1170  * @param rf The action from which we are reading (must be a write)
1171  *
1172  * @return True if this read established synchronization
1173  */
1174 bool ModelChecker::read_from(ModelAction *act, const ModelAction *rf)
1175 {
1176         act->set_read_from(rf);
1177         if (rf != NULL && act->is_acquire()) {
1178                 rel_heads_list_t release_heads;
1179                 get_release_seq_heads(act, act, &release_heads);
1180                 int num_heads = release_heads.size();
1181                 for (unsigned int i = 0; i < release_heads.size(); i++)
1182                         if (!act->synchronize_with(release_heads[i])) {
1183                                 set_bad_synchronization();
1184                                 num_heads--;
1185                         }
1186                 return num_heads > 0;
1187         }
1188         return false;
1189 }
1190
1191 /**
1192  * @brief Check whether a model action is enabled.
1193  *
1194  * Checks whether a lock or join operation would be successful (i.e., is the
1195  * lock already locked, or is the joined thread already complete). If not, put
1196  * the action in a waiter list.
1197  *
1198  * @param curr is the ModelAction to check whether it is enabled.
1199  * @return a bool that indicates whether the action is enabled.
1200  */
1201 bool ModelChecker::check_action_enabled(ModelAction *curr) {
1202         if (curr->is_lock()) {
1203                 std::mutex *lock = (std::mutex *)curr->get_location();
1204                 struct std::mutex_state *state = lock->get_state();
1205                 if (state->islocked) {
1206                         //Stick the action in the appropriate waiting queue
1207                         get_safe_ptr_action(lock_waiters_map, curr->get_location())->push_back(curr);
1208                         return false;
1209                 }
1210         } else if (curr->get_type() == THREAD_JOIN) {
1211                 Thread *blocking = (Thread *)curr->get_location();
1212                 if (!blocking->is_complete()) {
1213                         blocking->push_wait_list(curr);
1214                         return false;
1215                 }
1216         }
1217
1218         return true;
1219 }
1220
1221 /**
1222  * This is the heart of the model checker routine. It performs model-checking
1223  * actions corresponding to a given "current action." Among other processes, it
1224  * calculates reads-from relationships, updates synchronization clock vectors,
1225  * forms a memory_order constraints graph, and handles replay/backtrack
1226  * execution when running permutations of previously-observed executions.
1227  *
1228  * @param curr The current action to process
1229  * @return The ModelAction that is actually executed; may be different than
1230  * curr; may be NULL, if the current action is not enabled to run
1231  */
1232 ModelAction * ModelChecker::check_current_action(ModelAction *curr)
1233 {
1234         ASSERT(curr);
1235         bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
1236
1237         if (!check_action_enabled(curr)) {
1238                 /* Make the execution look like we chose to run this action
1239                  * much later, when a lock/join can succeed */
1240                 get_thread(curr)->set_pending(curr);
1241                 scheduler->sleep(get_thread(curr));
1242                 return NULL;
1243         }
1244
1245         bool newly_explored = initialize_curr_action(&curr);
1246
1247         DBG();
1248         if (DBG_ENABLED())
1249                 curr->print();
1250
1251         wake_up_sleeping_actions(curr);
1252
1253         /* Add the action to lists before any other model-checking tasks */
1254         if (!second_part_of_rmw)
1255                 add_action_to_lists(curr);
1256
1257         /* Build may_read_from set for newly-created actions */
1258         if (newly_explored && curr->is_read())
1259                 build_reads_from_past(curr);
1260
1261         /* Initialize work_queue with the "current action" work */
1262         work_queue_t work_queue(1, CheckCurrWorkEntry(curr));
1263         while (!work_queue.empty() && !has_asserted()) {
1264                 WorkQueueEntry work = work_queue.front();
1265                 work_queue.pop_front();
1266
1267                 switch (work.type) {
1268                 case WORK_CHECK_CURR_ACTION: {
1269                         ModelAction *act = work.action;
1270                         bool update = false; /* update this location's release seq's */
1271                         bool update_all = false; /* update all release seq's */
1272
1273                         if (process_thread_action(curr))
1274                                 update_all = true;
1275
1276                         if (act->is_read() && process_read(act, second_part_of_rmw))
1277                                 update = true;
1278
1279                         if (act->is_write() && process_write(act))
1280                                 update = true;
1281
1282                         if (act->is_fence() && process_fence(act))
1283                                 update_all = true;
1284
1285                         if (act->is_mutex_op() && process_mutex(act))
1286                                 update_all = true;
1287
1288                         if (act->is_relseq_fixup())
1289                                 process_relseq_fixup(curr, &work_queue);
1290
1291                         if (update_all)
1292                                 work_queue.push_back(CheckRelSeqWorkEntry(NULL));
1293                         else if (update)
1294                                 work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
1295                         break;
1296                 }
1297                 case WORK_CHECK_RELEASE_SEQ:
1298                         resolve_release_sequences(work.location, &work_queue);
1299                         break;
1300                 case WORK_CHECK_MO_EDGES: {
1301                         /** @todo Complete verification of work_queue */
1302                         ModelAction *act = work.action;
1303                         bool updated = false;
1304
1305                         if (act->is_read()) {
1306                                 const ModelAction *rf = act->get_reads_from();
1307                                 const Promise *promise = act->get_reads_from_promise();
1308                                 if (rf) {
1309                                         if (r_modification_order(act, rf))
1310                                                 updated = true;
1311                                 } else if (promise) {
1312                                         if (r_modification_order(act, promise))
1313                                                 updated = true;
1314                                 }
1315                         }
1316                         if (act->is_write()) {
1317                                 if (w_modification_order(act))
1318                                         updated = true;
1319                         }
1320                         mo_graph->commitChanges();
1321
1322                         if (updated)
1323                                 work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
1324                         break;
1325                 }
1326                 default:
1327                         ASSERT(false);
1328                         break;
1329                 }
1330         }
1331
1332         check_curr_backtracking(curr);
1333         set_backtracking(curr);
1334         return curr;
1335 }
1336
1337 void ModelChecker::check_curr_backtracking(ModelAction *curr)
1338 {
1339         Node *currnode = curr->get_node();
1340         Node *parnode = currnode->get_parent();
1341
1342         if ((parnode && !parnode->backtrack_empty()) ||
1343                          !currnode->misc_empty() ||
1344                          !currnode->read_from_empty() ||
1345                          !currnode->future_value_empty() ||
1346                          !currnode->promise_empty() ||
1347                          !currnode->relseq_break_empty()) {
1348                 set_latest_backtrack(curr);
1349         }
1350 }
1351
1352 bool ModelChecker::promises_expired() const
1353 {
1354         for (unsigned int i = 0; i < promises->size(); i++) {
1355                 Promise *promise = (*promises)[i];
1356                 if (promise->get_expiration() < priv->used_sequence_numbers)
1357                         return true;
1358         }
1359         return false;
1360 }
1361
1362 /**
1363  * This is the strongest feasibility check available.
1364  * @return whether the current trace (partial or complete) must be a prefix of
1365  * a feasible trace.
1366  */
1367 bool ModelChecker::isfeasibleprefix() const
1368 {
1369         return pending_rel_seqs->size() == 0 && is_feasible_prefix_ignore_relseq();
1370 }
1371
1372 /**
1373  * Print disagnostic information about an infeasible execution
1374  * @param prefix A string to prefix the output with; if NULL, then a default
1375  * message prefix will be provided
1376  */
1377 void ModelChecker::print_infeasibility(const char *prefix) const
1378 {
1379         char buf[100];
1380         char *ptr = buf;
1381         if (mo_graph->checkForCycles())
1382                 ptr += sprintf(ptr, "[mo cycle]");
1383         if (priv->failed_promise)
1384                 ptr += sprintf(ptr, "[failed promise]");
1385         if (priv->too_many_reads)
1386                 ptr += sprintf(ptr, "[too many reads]");
1387         if (priv->no_valid_reads)
1388                 ptr += sprintf(ptr, "[no valid reads-from]");
1389         if (priv->bad_synchronization)
1390                 ptr += sprintf(ptr, "[bad sw ordering]");
1391         if (promises_expired())
1392                 ptr += sprintf(ptr, "[promise expired]");
1393         if (promises->size() != 0)
1394                 ptr += sprintf(ptr, "[unresolved promise]");
1395         if (ptr != buf)
1396                 model_print("%s: %s\n", prefix ? prefix : "Infeasible", buf);
1397 }
1398
1399 /**
1400  * Returns whether the current completed trace is feasible, except for pending
1401  * release sequences.
1402  */
1403 bool ModelChecker::is_feasible_prefix_ignore_relseq() const
1404 {
1405         return !is_infeasible() && promises->size() == 0;
1406 }
1407
1408 /**
1409  * Check if the current partial trace is infeasible. Does not check any
1410  * end-of-execution flags, which might rule out the execution. Thus, this is
1411  * useful only for ruling an execution as infeasible.
1412  * @return whether the current partial trace is infeasible.
1413  */
1414 bool ModelChecker::is_infeasible() const
1415 {
1416         return mo_graph->checkForCycles() ||
1417                 priv->no_valid_reads ||
1418                 priv->failed_promise ||
1419                 priv->too_many_reads ||
1420                 priv->bad_synchronization ||
1421                 promises_expired();
1422 }
1423
1424 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
1425 ModelAction * ModelChecker::process_rmw(ModelAction *act) {
1426         ModelAction *lastread = get_last_action(act->get_tid());
1427         lastread->process_rmw(act);
1428         if (act->is_rmw()) {
1429                 if (lastread->get_reads_from())
1430                         mo_graph->addRMWEdge(lastread->get_reads_from(), lastread);
1431                 else
1432                         mo_graph->addRMWEdge(lastread->get_reads_from_promise(), lastread);
1433                 mo_graph->commitChanges();
1434         }
1435         return lastread;
1436 }
1437
1438 /**
1439  * Checks whether a thread has read from the same write for too many times
1440  * without seeing the effects of a later write.
1441  *
1442  * Basic idea:
1443  * 1) there must a different write that we could read from that would satisfy the modification order,
1444  * 2) we must have read from the same value in excess of maxreads times, and
1445  * 3) that other write must have been in the reads_from set for maxreads times.
1446  *
1447  * If so, we decide that the execution is no longer feasible.
1448  */
1449 void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf)
1450 {
1451         if (params.maxreads != 0) {
1452                 if (curr->get_node()->get_read_from_size() <= 1)
1453                         return;
1454                 //Must make sure that execution is currently feasible...  We could
1455                 //accidentally clear by rolling back
1456                 if (is_infeasible())
1457                         return;
1458                 std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
1459                 int tid = id_to_int(curr->get_tid());
1460
1461                 /* Skip checks */
1462                 if ((int)thrd_lists->size() <= tid)
1463                         return;
1464                 action_list_t *list = &(*thrd_lists)[tid];
1465
1466                 action_list_t::reverse_iterator rit = list->rbegin();
1467                 /* Skip past curr */
1468                 for (; (*rit) != curr; rit++)
1469                         ;
1470                 /* go past curr now */
1471                 rit++;
1472
1473                 action_list_t::reverse_iterator ritcopy = rit;
1474                 //See if we have enough reads from the same value
1475                 int count = 0;
1476                 for (; count < params.maxreads; rit++, count++) {
1477                         if (rit == list->rend())
1478                                 return;
1479                         ModelAction *act = *rit;
1480                         if (!act->is_read())
1481                                 return;
1482
1483                         if (act->get_reads_from() != rf)
1484                                 return;
1485                         if (act->get_node()->get_read_from_size() <= 1)
1486                                 return;
1487                 }
1488                 for (int i = 0; i < curr->get_node()->get_read_from_size(); i++) {
1489                         /* Get write */
1490                         const ModelAction *write = curr->get_node()->get_read_from_at(i);
1491
1492                         /* Need a different write */
1493                         if (write == rf)
1494                                 continue;
1495
1496                         /* Test to see whether this is a feasible write to read from */
1497                         /** NOTE: all members of read-from set should be
1498                          *  feasible, so we no longer check it here **/
1499
1500                         rit = ritcopy;
1501
1502                         bool feasiblewrite = true;
1503                         //new we need to see if this write works for everyone
1504
1505                         for (int loop = count; loop > 0; loop--, rit++) {
1506                                 ModelAction *act = *rit;
1507                                 bool foundvalue = false;
1508                                 for (int j = 0; j < act->get_node()->get_read_from_size(); j++) {
1509                                         if (act->get_node()->get_read_from_at(j) == write) {
1510                                                 foundvalue = true;
1511                                                 break;
1512                                         }
1513                                 }
1514                                 if (!foundvalue) {
1515                                         feasiblewrite = false;
1516                                         break;
1517                                 }
1518                         }
1519                         if (feasiblewrite) {
1520                                 priv->too_many_reads = true;
1521                                 return;
1522                         }
1523                 }
1524         }
1525 }
1526
1527 /**
1528  * Updates the mo_graph with the constraints imposed from the current
1529  * read.
1530  *
1531  * Basic idea is the following: Go through each other thread and find
1532  * the last action that happened before our read.  Two cases:
1533  *
1534  * (1) The action is a write => that write must either occur before
1535  * the write we read from or be the write we read from.
1536  *
1537  * (2) The action is a read => the write that that action read from
1538  * must occur before the write we read from or be the same write.
1539  *
1540  * @param curr The current action. Must be a read.
1541  * @param rf The ModelAction or Promise that curr reads from. Must be a write.
1542  * @return True if modification order edges were added; false otherwise
1543  */
1544 template <typename rf_type>
1545 bool ModelChecker::r_modification_order(ModelAction *curr, const rf_type *rf)
1546 {
1547         std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
1548         unsigned int i;
1549         bool added = false;
1550         ASSERT(curr->is_read());
1551
1552         /* Last SC fence in the current thread */
1553         ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
1554
1555         /* Iterate over all threads */
1556         for (i = 0; i < thrd_lists->size(); i++) {
1557                 /* Last SC fence in thread i */
1558                 ModelAction *last_sc_fence_thread_local = NULL;
1559                 if (int_to_id((int)i) != curr->get_tid())
1560                         last_sc_fence_thread_local = get_last_seq_cst_fence(int_to_id(i), NULL);
1561
1562                 /* Last SC fence in thread i, before last SC fence in current thread */
1563                 ModelAction *last_sc_fence_thread_before = NULL;
1564                 if (last_sc_fence_local)
1565                         last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(i), last_sc_fence_local);
1566
1567                 /* Iterate over actions in thread, starting from most recent */
1568                 action_list_t *list = &(*thrd_lists)[i];
1569                 action_list_t::reverse_iterator rit;
1570                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1571                         ModelAction *act = *rit;
1572
1573                         if (act->is_write() && !act->equals(rf) && act != curr) {
1574                                 /* C++, Section 29.3 statement 5 */
1575                                 if (curr->is_seqcst() && last_sc_fence_thread_local &&
1576                                                 *act < *last_sc_fence_thread_local) {
1577                                         added = mo_graph->addEdge(act, rf) || added;
1578                                         break;
1579                                 }
1580                                 /* C++, Section 29.3 statement 4 */
1581                                 else if (act->is_seqcst() && last_sc_fence_local &&
1582                                                 *act < *last_sc_fence_local) {
1583                                         added = mo_graph->addEdge(act, rf) || added;
1584                                         break;
1585                                 }
1586                                 /* C++, Section 29.3 statement 6 */
1587                                 else if (last_sc_fence_thread_before &&
1588                                                 *act < *last_sc_fence_thread_before) {
1589                                         added = mo_graph->addEdge(act, rf) || added;
1590                                         break;
1591                                 }
1592                         }
1593
1594                         /*
1595                          * Include at most one act per-thread that "happens
1596                          * before" curr. Don't consider reflexively.
1597                          */
1598                         if (act->happens_before(curr) && act != curr) {
1599                                 if (act->is_write()) {
1600                                         if (!act->equals(rf)) {
1601                                                 added = mo_graph->addEdge(act, rf) || added;
1602                                         }
1603                                 } else {
1604                                         const ModelAction *prevreadfrom = act->get_reads_from();
1605                                         //if the previous read is unresolved, keep going...
1606                                         if (prevreadfrom == NULL)
1607                                                 continue;
1608
1609                                         if (!prevreadfrom->equals(rf)) {
1610                                                 added = mo_graph->addEdge(prevreadfrom, rf) || added;
1611                                         }
1612                                 }
1613                                 break;
1614                         }
1615                 }
1616         }
1617
1618         /*
1619          * All compatible, thread-exclusive promises must be ordered after any
1620          * concrete loads from the same thread
1621          */
1622         for (unsigned int i = 0; i < promises->size(); i++)
1623                 if ((*promises)[i]->is_compatible_exclusive(curr))
1624                         added = mo_graph->addEdge(rf, (*promises)[i]) || added;
1625
1626         return added;
1627 }
1628
1629 /**
1630  * Updates the mo_graph with the constraints imposed from the current write.
1631  *
1632  * Basic idea is the following: Go through each other thread and find
1633  * the lastest action that happened before our write.  Two cases:
1634  *
1635  * (1) The action is a write => that write must occur before
1636  * the current write
1637  *
1638  * (2) The action is a read => the write that that action read from
1639  * must occur before the current write.
1640  *
1641  * This method also handles two other issues:
1642  *
1643  * (I) Sequential Consistency: Making sure that if the current write is
1644  * seq_cst, that it occurs after the previous seq_cst write.
1645  *
1646  * (II) Sending the write back to non-synchronizing reads.
1647  *
1648  * @param curr The current action. Must be a write.
1649  * @return True if modification order edges were added; false otherwise
1650  */
1651 bool ModelChecker::w_modification_order(ModelAction *curr)
1652 {
1653         std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
1654         unsigned int i;
1655         bool added = false;
1656         ASSERT(curr->is_write());
1657
1658         if (curr->is_seqcst()) {
1659                 /* We have to at least see the last sequentially consistent write,
1660                          so we are initialized. */
1661                 ModelAction *last_seq_cst = get_last_seq_cst_write(curr);
1662                 if (last_seq_cst != NULL) {
1663                         added = mo_graph->addEdge(last_seq_cst, curr) || added;
1664                 }
1665         }
1666
1667         /* Last SC fence in the current thread */
1668         ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
1669
1670         /* Iterate over all threads */
1671         for (i = 0; i < thrd_lists->size(); i++) {
1672                 /* Last SC fence in thread i, before last SC fence in current thread */
1673                 ModelAction *last_sc_fence_thread_before = NULL;
1674                 if (last_sc_fence_local && int_to_id((int)i) != curr->get_tid())
1675                         last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(i), last_sc_fence_local);
1676
1677                 /* Iterate over actions in thread, starting from most recent */
1678                 action_list_t *list = &(*thrd_lists)[i];
1679                 action_list_t::reverse_iterator rit;
1680                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1681                         ModelAction *act = *rit;
1682                         if (act == curr) {
1683                                 /*
1684                                  * 1) If RMW and it actually read from something, then we
1685                                  * already have all relevant edges, so just skip to next
1686                                  * thread.
1687                                  *
1688                                  * 2) If RMW and it didn't read from anything, we should
1689                                  * whatever edge we can get to speed up convergence.
1690                                  *
1691                                  * 3) If normal write, we need to look at earlier actions, so
1692                                  * continue processing list.
1693                                  */
1694                                 if (curr->is_rmw()) {
1695                                         if (curr->get_reads_from() != NULL)
1696                                                 break;
1697                                         else
1698                                                 continue;
1699                                 } else
1700                                         continue;
1701                         }
1702
1703                         /* C++, Section 29.3 statement 7 */
1704                         if (last_sc_fence_thread_before && act->is_write() &&
1705                                         *act < *last_sc_fence_thread_before) {
1706                                 added = mo_graph->addEdge(act, curr) || added;
1707                                 break;
1708                         }
1709
1710                         /*
1711                          * Include at most one act per-thread that "happens
1712                          * before" curr
1713                          */
1714                         if (act->happens_before(curr)) {
1715                                 /*
1716                                  * Note: if act is RMW, just add edge:
1717                                  *   act --mo--> curr
1718                                  * The following edge should be handled elsewhere:
1719                                  *   readfrom(act) --mo--> act
1720                                  */
1721                                 if (act->is_write())
1722                                         added = mo_graph->addEdge(act, curr) || added;
1723                                 else if (act->is_read()) {
1724                                         //if previous read accessed a null, just keep going
1725                                         if (act->get_reads_from() == NULL)
1726                                                 continue;
1727                                         added = mo_graph->addEdge(act->get_reads_from(), curr) || added;
1728                                 }
1729                                 break;
1730                         } else if (act->is_read() && !act->could_synchronize_with(curr) &&
1731                                                      !act->same_thread(curr)) {
1732                                 /* We have an action that:
1733                                    (1) did not happen before us
1734                                    (2) is a read and we are a write
1735                                    (3) cannot synchronize with us
1736                                    (4) is in a different thread
1737                                    =>
1738                                    that read could potentially read from our write.  Note that
1739                                    these checks are overly conservative at this point, we'll
1740                                    do more checks before actually removing the
1741                                    pendingfuturevalue.
1742
1743                                  */
1744                                 if (thin_air_constraint_may_allow(curr, act)) {
1745                                         if (!is_infeasible())
1746                                                 futurevalues->push_back(PendingFutureValue(curr, act));
1747                                         else if (curr->is_rmw() && act->is_rmw() && curr->get_reads_from() && curr->get_reads_from() == act->get_reads_from())
1748                                                 add_future_value(curr, act);
1749                                 }
1750                         }
1751                 }
1752         }
1753
1754         /*
1755          * All compatible, thread-exclusive promises must be ordered after any
1756          * concrete stores to the same thread, or else they can be merged with
1757          * this store later
1758          */
1759         for (unsigned int i = 0; i < promises->size(); i++)
1760                 if ((*promises)[i]->is_compatible_exclusive(curr))
1761                         added = mo_graph->addEdge(curr, (*promises)[i]) || added;
1762
1763         return added;
1764 }
1765
1766 /** Arbitrary reads from the future are not allowed.  Section 29.3
1767  * part 9 places some constraints.  This method checks one result of constraint
1768  * constraint.  Others require compiler support. */
1769 bool ModelChecker::thin_air_constraint_may_allow(const ModelAction *writer, const ModelAction *reader)
1770 {
1771         if (!writer->is_rmw())
1772                 return true;
1773
1774         if (!reader->is_rmw())
1775                 return true;
1776
1777         for (const ModelAction *search = writer->get_reads_from(); search != NULL; search = search->get_reads_from()) {
1778                 if (search == reader)
1779                         return false;
1780                 if (search->get_tid() == reader->get_tid() &&
1781                                 search->happens_before(reader))
1782                         break;
1783         }
1784
1785         return true;
1786 }
1787
1788 /**
1789  * Arbitrary reads from the future are not allowed. Section 29.3 part 9 places
1790  * some constraints. This method checks one the following constraint (others
1791  * require compiler support):
1792  *
1793  *   If X --hb-> Y --mo-> Z, then X should not read from Z.
1794  */
1795 bool ModelChecker::mo_may_allow(const ModelAction *writer, const ModelAction *reader)
1796 {
1797         std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, reader->get_location());
1798         unsigned int i;
1799         /* Iterate over all threads */
1800         for (i = 0; i < thrd_lists->size(); i++) {
1801                 const ModelAction *write_after_read = NULL;
1802
1803                 /* Iterate over actions in thread, starting from most recent */
1804                 action_list_t *list = &(*thrd_lists)[i];
1805                 action_list_t::reverse_iterator rit;
1806                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1807                         ModelAction *act = *rit;
1808
1809                         /* Don't disallow due to act == reader */
1810                         if (!reader->happens_before(act) || reader == act)
1811                                 break;
1812                         else if (act->is_write())
1813                                 write_after_read = act;
1814                         else if (act->is_read() && act->get_reads_from() != NULL)
1815                                 write_after_read = act->get_reads_from();
1816                 }
1817
1818                 if (write_after_read && write_after_read != writer && mo_graph->checkReachable(write_after_read, writer))
1819                         return false;
1820         }
1821         return true;
1822 }
1823
1824 /**
1825  * Finds the head(s) of the release sequence(s) containing a given ModelAction.
1826  * The ModelAction under consideration is expected to be taking part in
1827  * release/acquire synchronization as an object of the "reads from" relation.
1828  * Note that this can only provide release sequence support for RMW chains
1829  * which do not read from the future, as those actions cannot be traced until
1830  * their "promise" is fulfilled. Similarly, we may not even establish the
1831  * presence of a release sequence with certainty, as some modification order
1832  * constraints may be decided further in the future. Thus, this function
1833  * "returns" two pieces of data: a pass-by-reference vector of @a release_heads
1834  * and a boolean representing certainty.
1835  *
1836  * @param rf The action that might be part of a release sequence. Must be a
1837  * write.
1838  * @param release_heads A pass-by-reference style return parameter. After
1839  * execution of this function, release_heads will contain the heads of all the
1840  * relevant release sequences, if any exists with certainty
1841  * @param pending A pass-by-reference style return parameter which is only used
1842  * when returning false (i.e., uncertain). Returns most information regarding
1843  * an uncertain release sequence, including any write operations that might
1844  * break the sequence.
1845  * @return true, if the ModelChecker is certain that release_heads is complete;
1846  * false otherwise
1847  */
1848 bool ModelChecker::release_seq_heads(const ModelAction *rf,
1849                 rel_heads_list_t *release_heads,
1850                 struct release_seq *pending) const
1851 {
1852         /* Only check for release sequences if there are no cycles */
1853         if (mo_graph->checkForCycles())
1854                 return false;
1855
1856         while (rf) {
1857                 ASSERT(rf->is_write());
1858
1859                 if (rf->is_release())
1860                         release_heads->push_back(rf);
1861                 else if (rf->get_last_fence_release())
1862                         release_heads->push_back(rf->get_last_fence_release());
1863                 if (!rf->is_rmw())
1864                         break; /* End of RMW chain */
1865
1866                 /** @todo Need to be smarter here...  In the linux lock
1867                  * example, this will run to the beginning of the program for
1868                  * every acquire. */
1869                 /** @todo The way to be smarter here is to keep going until 1
1870                  * thread has a release preceded by an acquire and you've seen
1871                  *       both. */
1872
1873                 /* acq_rel RMW is a sufficient stopping condition */
1874                 if (rf->is_acquire() && rf->is_release())
1875                         return true; /* complete */
1876
1877                 rf = rf->get_reads_from();
1878         };
1879         if (!rf) {
1880                 /* read from future: need to settle this later */
1881                 pending->rf = NULL;
1882                 return false; /* incomplete */
1883         }
1884
1885         if (rf->is_release())
1886                 return true; /* complete */
1887
1888         /* else relaxed write
1889          * - check for fence-release in the same thread (29.8, stmt. 3)
1890          * - check modification order for contiguous subsequence
1891          *   -> rf must be same thread as release */
1892
1893         const ModelAction *fence_release = rf->get_last_fence_release();
1894         /* Synchronize with a fence-release unconditionally; we don't need to
1895          * find any more "contiguous subsequence..." for it */
1896         if (fence_release)
1897                 release_heads->push_back(fence_release);
1898
1899         int tid = id_to_int(rf->get_tid());
1900         std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, rf->get_location());
1901         action_list_t *list = &(*thrd_lists)[tid];
1902         action_list_t::const_reverse_iterator rit;
1903
1904         /* Find rf in the thread list */
1905         rit = std::find(list->rbegin(), list->rend(), rf);
1906         ASSERT(rit != list->rend());
1907
1908         /* Find the last {write,fence}-release */
1909         for (; rit != list->rend(); rit++) {
1910                 if (fence_release && *(*rit) < *fence_release)
1911                         break;
1912                 if ((*rit)->is_release())
1913                         break;
1914         }
1915         if (rit == list->rend()) {
1916                 /* No write-release in this thread */
1917                 return true; /* complete */
1918         } else if (fence_release && *(*rit) < *fence_release) {
1919                 /* The fence-release is more recent (and so, "stronger") than
1920                  * the most recent write-release */
1921                 return true; /* complete */
1922         } /* else, need to establish contiguous release sequence */
1923         ModelAction *release = *rit;
1924
1925         ASSERT(rf->same_thread(release));
1926
1927         pending->writes.clear();
1928
1929         bool certain = true;
1930         for (unsigned int i = 0; i < thrd_lists->size(); i++) {
1931                 if (id_to_int(rf->get_tid()) == (int)i)
1932                         continue;
1933                 list = &(*thrd_lists)[i];
1934
1935                 /* Can we ensure no future writes from this thread may break
1936                  * the release seq? */
1937                 bool future_ordered = false;
1938
1939                 ModelAction *last = get_last_action(int_to_id(i));
1940                 Thread *th = get_thread(int_to_id(i));
1941                 if ((last && rf->happens_before(last)) ||
1942                                 !is_enabled(th) ||
1943                                 th->is_complete())
1944                         future_ordered = true;
1945
1946                 ASSERT(!th->is_model_thread() || future_ordered);
1947
1948                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
1949                         const ModelAction *act = *rit;
1950                         /* Reach synchronization -> this thread is complete */
1951                         if (act->happens_before(release))
1952                                 break;
1953                         if (rf->happens_before(act)) {
1954                                 future_ordered = true;
1955                                 continue;
1956                         }
1957
1958                         /* Only non-RMW writes can break release sequences */
1959                         if (!act->is_write() || act->is_rmw())
1960                                 continue;
1961
1962                         /* Check modification order */
1963                         if (mo_graph->checkReachable(rf, act)) {
1964                                 /* rf --mo--> act */
1965                                 future_ordered = true;
1966                                 continue;
1967                         }
1968                         if (mo_graph->checkReachable(act, release))
1969                                 /* act --mo--> release */
1970                                 break;
1971                         if (mo_graph->checkReachable(release, act) &&
1972                                       mo_graph->checkReachable(act, rf)) {
1973                                 /* release --mo-> act --mo--> rf */
1974                                 return true; /* complete */
1975                         }
1976                         /* act may break release sequence */
1977                         pending->writes.push_back(act);
1978                         certain = false;
1979                 }
1980                 if (!future_ordered)
1981                         certain = false; /* This thread is uncertain */
1982         }
1983
1984         if (certain) {
1985                 release_heads->push_back(release);
1986                 pending->writes.clear();
1987         } else {
1988                 pending->release = release;
1989                 pending->rf = rf;
1990         }
1991         return certain;
1992 }
1993
1994 /**
1995  * An interface for getting the release sequence head(s) with which a
1996  * given ModelAction must synchronize. This function only returns a non-empty
1997  * result when it can locate a release sequence head with certainty. Otherwise,
1998  * it may mark the internal state of the ModelChecker so that it will handle
1999  * the release sequence at a later time, causing @a acquire to update its
2000  * synchronization at some later point in execution.
2001  *
2002  * @param acquire The 'acquire' action that may synchronize with a release
2003  * sequence
2004  * @param read The read action that may read from a release sequence; this may
2005  * be the same as acquire, or else an earlier action in the same thread (i.e.,
2006  * when 'acquire' is a fence-acquire)
2007  * @param release_heads A pass-by-reference return parameter. Will be filled
2008  * with the head(s) of the release sequence(s), if they exists with certainty.
2009  * @see ModelChecker::release_seq_heads
2010  */
2011 void ModelChecker::get_release_seq_heads(ModelAction *acquire,
2012                 ModelAction *read, rel_heads_list_t *release_heads)
2013 {
2014         const ModelAction *rf = read->get_reads_from();
2015         struct release_seq *sequence = (struct release_seq *)snapshot_calloc(1, sizeof(struct release_seq));
2016         sequence->acquire = acquire;
2017         sequence->read = read;
2018
2019         if (!release_seq_heads(rf, release_heads, sequence)) {
2020                 /* add act to 'lazy checking' list */
2021                 pending_rel_seqs->push_back(sequence);
2022         } else {
2023                 snapshot_free(sequence);
2024         }
2025 }
2026
2027 /**
2028  * Attempt to resolve all stashed operations that might synchronize with a
2029  * release sequence for a given location. This implements the "lazy" portion of
2030  * determining whether or not a release sequence was contiguous, since not all
2031  * modification order information is present at the time an action occurs.
2032  *
2033  * @param location The location/object that should be checked for release
2034  * sequence resolutions. A NULL value means to check all locations.
2035  * @param work_queue The work queue to which to add work items as they are
2036  * generated
2037  * @return True if any updates occurred (new synchronization, new mo_graph
2038  * edges)
2039  */
2040 bool ModelChecker::resolve_release_sequences(void *location, work_queue_t *work_queue)
2041 {
2042         bool updated = false;
2043         std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >::iterator it = pending_rel_seqs->begin();
2044         while (it != pending_rel_seqs->end()) {
2045                 struct release_seq *pending = *it;
2046                 ModelAction *acquire = pending->acquire;
2047                 const ModelAction *read = pending->read;
2048
2049                 /* Only resolve sequences on the given location, if provided */
2050                 if (location && read->get_location() != location) {
2051                         it++;
2052                         continue;
2053                 }
2054
2055                 const ModelAction *rf = read->get_reads_from();
2056                 rel_heads_list_t release_heads;
2057                 bool complete;
2058                 complete = release_seq_heads(rf, &release_heads, pending);
2059                 for (unsigned int i = 0; i < release_heads.size(); i++) {
2060                         if (!acquire->has_synchronized_with(release_heads[i])) {
2061                                 if (acquire->synchronize_with(release_heads[i]))
2062                                         updated = true;
2063                                 else
2064                                         set_bad_synchronization();
2065                         }
2066                 }
2067
2068                 if (updated) {
2069                         /* Re-check all pending release sequences */
2070                         work_queue->push_back(CheckRelSeqWorkEntry(NULL));
2071                         /* Re-check read-acquire for mo_graph edges */
2072                         if (acquire->is_read())
2073                                 work_queue->push_back(MOEdgeWorkEntry(acquire));
2074
2075                         /* propagate synchronization to later actions */
2076                         action_list_t::reverse_iterator rit = action_trace->rbegin();
2077                         for (; (*rit) != acquire; rit++) {
2078                                 ModelAction *propagate = *rit;
2079                                 if (acquire->happens_before(propagate)) {
2080                                         propagate->synchronize_with(acquire);
2081                                         /* Re-check 'propagate' for mo_graph edges */
2082                                         work_queue->push_back(MOEdgeWorkEntry(propagate));
2083                                 }
2084                         }
2085                 }
2086                 if (complete) {
2087                         it = pending_rel_seqs->erase(it);
2088                         snapshot_free(pending);
2089                 } else {
2090                         it++;
2091                 }
2092         }
2093
2094         // If we resolved promises or data races, see if we have realized a data race.
2095         checkDataRaces();
2096
2097         return updated;
2098 }
2099
2100 /**
2101  * Performs various bookkeeping operations for the current ModelAction. For
2102  * instance, adds action to the per-object, per-thread action vector and to the
2103  * action trace list of all thread actions.
2104  *
2105  * @param act is the ModelAction to add.
2106  */
2107 void ModelChecker::add_action_to_lists(ModelAction *act)
2108 {
2109         int tid = id_to_int(act->get_tid());
2110         ModelAction *uninit = NULL;
2111         int uninit_id = -1;
2112         action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
2113         if (list->empty() && act->is_atomic_var()) {
2114                 uninit = new_uninitialized_action(act->get_location());
2115                 uninit_id = id_to_int(uninit->get_tid());
2116                 list->push_back(uninit);
2117         }
2118         list->push_back(act);
2119
2120         action_trace->push_back(act);
2121         if (uninit)
2122                 action_trace->push_front(uninit);
2123
2124         std::vector<action_list_t> *vec = get_safe_ptr_vect_action(obj_thrd_map, act->get_location());
2125         if (tid >= (int)vec->size())
2126                 vec->resize(priv->next_thread_id);
2127         (*vec)[tid].push_back(act);
2128         if (uninit)
2129                 (*vec)[uninit_id].push_front(uninit);
2130
2131         if ((int)thrd_last_action->size() <= tid)
2132                 thrd_last_action->resize(get_num_threads());
2133         (*thrd_last_action)[tid] = act;
2134         if (uninit)
2135                 (*thrd_last_action)[uninit_id] = uninit;
2136
2137         if (act->is_fence() && act->is_release()) {
2138                 if ((int)thrd_last_fence_release->size() <= tid)
2139                         thrd_last_fence_release->resize(get_num_threads());
2140                 (*thrd_last_fence_release)[tid] = act;
2141         }
2142
2143         if (act->is_wait()) {
2144                 void *mutex_loc = (void *) act->get_value();
2145                 get_safe_ptr_action(obj_map, mutex_loc)->push_back(act);
2146
2147                 std::vector<action_list_t> *vec = get_safe_ptr_vect_action(obj_thrd_map, mutex_loc);
2148                 if (tid >= (int)vec->size())
2149                         vec->resize(priv->next_thread_id);
2150                 (*vec)[tid].push_back(act);
2151         }
2152 }
2153
2154 /**
2155  * @brief Get the last action performed by a particular Thread
2156  * @param tid The thread ID of the Thread in question
2157  * @return The last action in the thread
2158  */
2159 ModelAction * ModelChecker::get_last_action(thread_id_t tid) const
2160 {
2161         int threadid = id_to_int(tid);
2162         if (threadid < (int)thrd_last_action->size())
2163                 return (*thrd_last_action)[id_to_int(tid)];
2164         else
2165                 return NULL;
2166 }
2167
2168 /**
2169  * @brief Get the last fence release performed by a particular Thread
2170  * @param tid The thread ID of the Thread in question
2171  * @return The last fence release in the thread, if one exists; NULL otherwise
2172  */
2173 ModelAction * ModelChecker::get_last_fence_release(thread_id_t tid) const
2174 {
2175         int threadid = id_to_int(tid);
2176         if (threadid < (int)thrd_last_fence_release->size())
2177                 return (*thrd_last_fence_release)[id_to_int(tid)];
2178         else
2179                 return NULL;
2180 }
2181
2182 /**
2183  * Gets the last memory_order_seq_cst write (in the total global sequence)
2184  * performed on a particular object (i.e., memory location), not including the
2185  * current action.
2186  * @param curr The current ModelAction; also denotes the object location to
2187  * check
2188  * @return The last seq_cst write
2189  */
2190 ModelAction * ModelChecker::get_last_seq_cst_write(ModelAction *curr) const
2191 {
2192         void *location = curr->get_location();
2193         action_list_t *list = get_safe_ptr_action(obj_map, location);
2194         /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
2195         action_list_t::reverse_iterator rit;
2196         for (rit = list->rbegin(); rit != list->rend(); rit++)
2197                 if ((*rit)->is_write() && (*rit)->is_seqcst() && (*rit) != curr)
2198                         return *rit;
2199         return NULL;
2200 }
2201
2202 /**
2203  * Gets the last memory_order_seq_cst fence (in the total global sequence)
2204  * performed in a particular thread, prior to a particular fence.
2205  * @param tid The ID of the thread to check
2206  * @param before_fence The fence from which to begin the search; if NULL, then
2207  * search for the most recent fence in the thread.
2208  * @return The last prior seq_cst fence in the thread, if exists; otherwise, NULL
2209  */
2210 ModelAction * ModelChecker::get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const
2211 {
2212         /* All fences should have NULL location */
2213         action_list_t *list = get_safe_ptr_action(obj_map, NULL);
2214         action_list_t::reverse_iterator rit = list->rbegin();
2215
2216         if (before_fence) {
2217                 for (; rit != list->rend(); rit++)
2218                         if (*rit == before_fence)
2219                                 break;
2220
2221                 ASSERT(*rit == before_fence);
2222                 rit++;
2223         }
2224
2225         for (; rit != list->rend(); rit++)
2226                 if ((*rit)->is_fence() && (tid == (*rit)->get_tid()) && (*rit)->is_seqcst())
2227                         return *rit;
2228         return NULL;
2229 }
2230
2231 /**
2232  * Gets the last unlock operation performed on a particular mutex (i.e., memory
2233  * location). This function identifies the mutex according to the current
2234  * action, which is presumed to perform on the same mutex.
2235  * @param curr The current ModelAction; also denotes the object location to
2236  * check
2237  * @return The last unlock operation
2238  */
2239 ModelAction * ModelChecker::get_last_unlock(ModelAction *curr) const
2240 {
2241         void *location = curr->get_location();
2242         action_list_t *list = get_safe_ptr_action(obj_map, location);
2243         /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
2244         action_list_t::reverse_iterator rit;
2245         for (rit = list->rbegin(); rit != list->rend(); rit++)
2246                 if ((*rit)->is_unlock() || (*rit)->is_wait())
2247                         return *rit;
2248         return NULL;
2249 }
2250
2251 ModelAction * ModelChecker::get_parent_action(thread_id_t tid) const
2252 {
2253         ModelAction *parent = get_last_action(tid);
2254         if (!parent)
2255                 parent = get_thread(tid)->get_creation();
2256         return parent;
2257 }
2258
2259 /**
2260  * Returns the clock vector for a given thread.
2261  * @param tid The thread whose clock vector we want
2262  * @return Desired clock vector
2263  */
2264 ClockVector * ModelChecker::get_cv(thread_id_t tid) const
2265 {
2266         return get_parent_action(tid)->get_cv();
2267 }
2268
2269 /**
2270  * Resolve a set of Promises with a current write. The set is provided in the
2271  * Node corresponding to @a write.
2272  * @param write The ModelAction that is fulfilling Promises
2273  * @return True if promises were resolved; false otherwise
2274  */
2275 bool ModelChecker::resolve_promises(ModelAction *write)
2276 {
2277         bool haveResolved = false;
2278         std::vector< ModelAction *, ModelAlloc<ModelAction *> > actions_to_check;
2279         promise_list_t mustResolve, resolved;
2280
2281         for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
2282                 Promise *promise = (*promises)[promise_index];
2283                 if (write->get_node()->get_promise(i)) {
2284                         ModelAction *read = promise->get_action();
2285                         read_from(read, write);
2286                         //Make sure the promise's value matches the write's value
2287                         ASSERT(promise->is_compatible(write));
2288                         mo_graph->resolvePromise(read, write, &mustResolve);
2289
2290                         resolved.push_back(promise);
2291                         promises->erase(promises->begin() + promise_index);
2292                         actions_to_check.push_back(read);
2293
2294                         haveResolved = true;
2295                 } else
2296                         promise_index++;
2297         }
2298
2299         for (unsigned int i = 0; i < mustResolve.size(); i++) {
2300                 if (std::find(resolved.begin(), resolved.end(), mustResolve[i])
2301                                 == resolved.end())
2302                         priv->failed_promise = true;
2303         }
2304         for (unsigned int i = 0; i < resolved.size(); i++)
2305                 delete resolved[i];
2306         //Check whether reading these writes has made threads unable to
2307         //resolve promises
2308
2309         for (unsigned int i = 0; i < actions_to_check.size(); i++) {
2310                 ModelAction *read = actions_to_check[i];
2311                 mo_check_promises(read, true);
2312         }
2313
2314         return haveResolved;
2315 }
2316
2317 /**
2318  * Compute the set of promises that could potentially be satisfied by this
2319  * action. Note that the set computation actually appears in the Node, not in
2320  * ModelChecker.
2321  * @param curr The ModelAction that may satisfy promises
2322  */
2323 void ModelChecker::compute_promises(ModelAction *curr)
2324 {
2325         for (unsigned int i = 0; i < promises->size(); i++) {
2326                 Promise *promise = (*promises)[i];
2327                 const ModelAction *act = promise->get_action();
2328                 if (!act->happens_before(curr) &&
2329                                 act->is_read() &&
2330                                 !act->could_synchronize_with(curr) &&
2331                                 !act->same_thread(curr) &&
2332                                 act->get_location() == curr->get_location() &&
2333                                 promise->get_value() == curr->get_value()) {
2334                         curr->get_node()->set_promise(i, act->is_rmw());
2335                 }
2336         }
2337 }
2338
2339 /** Checks promises in response to change in ClockVector Threads. */
2340 void ModelChecker::check_promises(thread_id_t tid, ClockVector *old_cv, ClockVector *merge_cv)
2341 {
2342         for (unsigned int i = 0; i < promises->size(); i++) {
2343                 Promise *promise = (*promises)[i];
2344                 const ModelAction *act = promise->get_action();
2345                 if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
2346                                 merge_cv->synchronized_since(act)) {
2347                         if (promise->eliminate_thread(tid)) {
2348                                 //Promise has failed
2349                                 priv->failed_promise = true;
2350                                 return;
2351                         }
2352                 }
2353         }
2354 }
2355
2356 void ModelChecker::check_promises_thread_disabled()
2357 {
2358         for (unsigned int i = 0; i < promises->size(); i++) {
2359                 Promise *promise = (*promises)[i];
2360                 if (promise->has_failed()) {
2361                         priv->failed_promise = true;
2362                         return;
2363                 }
2364         }
2365 }
2366
2367 /**
2368  * @brief Checks promises in response to addition to modification order for
2369  * threads.
2370  *
2371  * We test whether threads are still available for satisfying promises after an
2372  * addition to our modification order constraints. Those that are unavailable
2373  * are "eliminated". Once all threads are eliminated from satisfying a promise,
2374  * that promise has failed.
2375  *
2376  * @param act The ModelAction which updated the modification order
2377  * @param is_read_check Should be true if act is a read and we must check for
2378  * updates to the store from which it read (there is a distinction here for
2379  * RMW's, which are both a load and a store)
2380  */
2381 void ModelChecker::mo_check_promises(const ModelAction *act, bool is_read_check)
2382 {
2383         const ModelAction *write = is_read_check ? act->get_reads_from() : act;
2384
2385         for (unsigned int i = 0; i < promises->size(); i++) {
2386                 Promise *promise = (*promises)[i];
2387                 const ModelAction *pread = promise->get_action();
2388
2389                 // Is this promise on the same location?
2390                 if (!pread->same_var(write))
2391                         continue;
2392
2393                 if (pread->happens_before(act) && mo_graph->checkPromise(write, promise)) {
2394                         priv->failed_promise = true;
2395                         return;
2396                 }
2397
2398                 // Don't do any lookups twice for the same thread
2399                 if (!promise->thread_is_available(act->get_tid()))
2400                         continue;
2401
2402                 if (mo_graph->checkReachable(promise, write)) {
2403                         if (mo_graph->checkPromise(write, promise)) {
2404                                 priv->failed_promise = true;
2405                                 return;
2406                         }
2407                 }
2408         }
2409 }
2410
2411 /**
2412  * Compute the set of writes that may break the current pending release
2413  * sequence. This information is extracted from previou release sequence
2414  * calculations.
2415  *
2416  * @param curr The current ModelAction. Must be a release sequence fixup
2417  * action.
2418  */
2419 void ModelChecker::compute_relseq_breakwrites(ModelAction *curr)
2420 {
2421         if (pending_rel_seqs->empty())
2422                 return;
2423
2424         struct release_seq *pending = pending_rel_seqs->back();
2425         for (unsigned int i = 0; i < pending->writes.size(); i++) {
2426                 const ModelAction *write = pending->writes[i];
2427                 curr->get_node()->add_relseq_break(write);
2428         }
2429
2430         /* NULL means don't break the sequence; just synchronize */
2431         curr->get_node()->add_relseq_break(NULL);
2432 }
2433
2434 /**
2435  * Build up an initial set of all past writes that this 'read' action may read
2436  * from. This set is determined by the clock vector's "happens before"
2437  * relationship.
2438  * @param curr is the current ModelAction that we are exploring; it must be a
2439  * 'read' operation.
2440  */
2441 void ModelChecker::build_reads_from_past(ModelAction *curr)
2442 {
2443         std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
2444         unsigned int i;
2445         ASSERT(curr->is_read());
2446
2447         ModelAction *last_sc_write = NULL;
2448
2449         if (curr->is_seqcst())
2450                 last_sc_write = get_last_seq_cst_write(curr);
2451
2452         /* Iterate over all threads */
2453         for (i = 0; i < thrd_lists->size(); i++) {
2454                 /* Iterate over actions in thread, starting from most recent */
2455                 action_list_t *list = &(*thrd_lists)[i];
2456                 action_list_t::reverse_iterator rit;
2457                 for (rit = list->rbegin(); rit != list->rend(); rit++) {
2458                         ModelAction *act = *rit;
2459
2460                         /* Only consider 'write' actions */
2461                         if (!act->is_write() || act == curr)
2462                                 continue;
2463
2464                         /* Don't consider more than one seq_cst write if we are a seq_cst read. */
2465                         bool allow_read = true;
2466
2467                         if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
2468                                 allow_read = false;
2469                         else if (curr->get_sleep_flag() && !curr->is_seqcst() && !sleep_can_read_from(curr, act))
2470                                 allow_read = false;
2471
2472                         if (allow_read) {
2473                                 /* Only add feasible reads */
2474                                 mo_graph->startChanges();
2475                                 r_modification_order(curr, act);
2476                                 if (!is_infeasible())
2477                                         curr->get_node()->add_read_from(act);
2478                                 mo_graph->rollbackChanges();
2479                         }
2480
2481                         /* Include at most one act per-thread that "happens before" curr */
2482                         if (act->happens_before(curr))
2483                                 break;
2484                 }
2485         }
2486         /* We may find no valid may-read-from only if the execution is doomed */
2487         if (!curr->get_node()->get_read_from_size()) {
2488                 priv->no_valid_reads = true;
2489                 set_assert();
2490         }
2491
2492         if (DBG_ENABLED()) {
2493                 model_print("Reached read action:\n");
2494                 curr->print();
2495                 model_print("Printing may_read_from\n");
2496                 curr->get_node()->print_may_read_from();
2497                 model_print("End printing may_read_from\n");
2498         }
2499 }
2500
2501 bool ModelChecker::sleep_can_read_from(ModelAction *curr, const ModelAction *write)
2502 {
2503         while (true) {
2504                 /* UNINIT actions don't have a Node, and they never sleep */
2505                 if (write->is_uninitialized())
2506                         return true;
2507                 Node *prevnode = write->get_node()->get_parent();
2508
2509                 bool thread_sleep = prevnode->enabled_status(curr->get_tid()) == THREAD_SLEEP_SET;
2510                 if (write->is_release() && thread_sleep)
2511                         return true;
2512                 if (!write->is_rmw()) {
2513                         return false;
2514                 }
2515                 if (write->get_reads_from() == NULL)
2516                         return true;
2517                 write = write->get_reads_from();
2518         }
2519 }
2520
2521 /**
2522  * @brief Create a new action representing an uninitialized atomic
2523  * @param location The memory location of the atomic object
2524  * @return A pointer to a new ModelAction
2525  */
2526 ModelAction * ModelChecker::new_uninitialized_action(void *location) const
2527 {
2528         ModelAction *act = (ModelAction *)snapshot_malloc(sizeof(class ModelAction));
2529         act = new (act) ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, location, 0, model_thread);
2530         act->create_cv(NULL);
2531         return act;
2532 }
2533
2534 static void print_list(action_list_t *list)
2535 {
2536         action_list_t::iterator it;
2537
2538         model_print("---------------------------------------------------------------------\n");
2539
2540         unsigned int hash = 0;
2541
2542         for (it = list->begin(); it != list->end(); it++) {
2543                 (*it)->print();
2544                 hash = hash^(hash<<3)^((*it)->hash());
2545         }
2546         model_print("HASH %u\n", hash);
2547         model_print("---------------------------------------------------------------------\n");
2548 }
2549
2550 #if SUPPORT_MOD_ORDER_DUMP
2551 void ModelChecker::dumpGraph(char *filename) const
2552 {
2553         char buffer[200];
2554         sprintf(buffer, "%s.dot", filename);
2555         FILE *file = fopen(buffer, "w");
2556         fprintf(file, "digraph %s {\n", filename);
2557         mo_graph->dumpNodes(file);
2558         ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
2559
2560         for (action_list_t::iterator it = action_trace->begin(); it != action_trace->end(); it++) {
2561                 ModelAction *action = *it;
2562                 if (action->is_read()) {
2563                         fprintf(file, "N%u [label=\"N%u, T%u\"];\n", action->get_seq_number(), action->get_seq_number(), action->get_tid());
2564                         if (action->get_reads_from() != NULL)
2565                                 fprintf(file, "N%u -> N%u[label=\"rf\", color=red];\n", action->get_seq_number(), action->get_reads_from()->get_seq_number());
2566                 }
2567                 if (thread_array[action->get_tid()] != NULL) {
2568                         fprintf(file, "N%u -> N%u[label=\"sb\", color=blue];\n", thread_array[action->get_tid()]->get_seq_number(), action->get_seq_number());
2569                 }
2570
2571                 thread_array[action->get_tid()] = action;
2572         }
2573         fprintf(file, "}\n");
2574         model_free(thread_array);
2575         fclose(file);
2576 }
2577 #endif
2578
2579 /** @brief Prints an execution trace summary. */
2580 void ModelChecker::print_summary() const
2581 {
2582 #if SUPPORT_MOD_ORDER_DUMP
2583         char buffername[100];
2584         sprintf(buffername, "exec%04u", stats.num_total);
2585         mo_graph->dumpGraphToFile(buffername);
2586         sprintf(buffername, "graph%04u", stats.num_total);
2587         dumpGraph(buffername);
2588 #endif
2589
2590         model_print("Execution %d:", stats.num_total);
2591         if (isfeasibleprefix())
2592                 model_print("\n");
2593         else
2594                 print_infeasibility(" INFEASIBLE");
2595         print_list(action_trace);
2596         model_print("\n");
2597 }
2598
2599 /**
2600  * Add a Thread to the system for the first time. Should only be called once
2601  * per thread.
2602  * @param t The Thread to add
2603  */
2604 void ModelChecker::add_thread(Thread *t)
2605 {
2606         thread_map->put(id_to_int(t->get_id()), t);
2607         scheduler->add_thread(t);
2608 }
2609
2610 /**
2611  * Removes a thread from the scheduler.
2612  * @param the thread to remove.
2613  */
2614 void ModelChecker::remove_thread(Thread *t)
2615 {
2616         scheduler->remove_thread(t);
2617 }
2618
2619 /**
2620  * @brief Get a Thread reference by its ID
2621  * @param tid The Thread's ID
2622  * @return A Thread reference
2623  */
2624 Thread * ModelChecker::get_thread(thread_id_t tid) const
2625 {
2626         return thread_map->get(id_to_int(tid));
2627 }
2628
2629 /**
2630  * @brief Get a reference to the Thread in which a ModelAction was executed
2631  * @param act The ModelAction
2632  * @return A Thread reference
2633  */
2634 Thread * ModelChecker::get_thread(const ModelAction *act) const
2635 {
2636         return get_thread(act->get_tid());
2637 }
2638
2639 /**
2640  * @brief Check if a Thread is currently enabled
2641  * @param t The Thread to check
2642  * @return True if the Thread is currently enabled
2643  */
2644 bool ModelChecker::is_enabled(Thread *t) const
2645 {
2646         return scheduler->is_enabled(t);
2647 }
2648
2649 /**
2650  * @brief Check if a Thread is currently enabled
2651  * @param tid The ID of the Thread to check
2652  * @return True if the Thread is currently enabled
2653  */
2654 bool ModelChecker::is_enabled(thread_id_t tid) const
2655 {
2656         return scheduler->is_enabled(tid);
2657 }
2658
2659 /**
2660  * Switch from a user-context to the "master thread" context (a.k.a. system
2661  * context). This switch is made with the intention of exploring a particular
2662  * model-checking action (described by a ModelAction object). Must be called
2663  * from a user-thread context.
2664  *
2665  * @param act The current action that will be explored. May be NULL only if
2666  * trace is exiting via an assertion (see ModelChecker::set_assert and
2667  * ModelChecker::has_asserted).
2668  * @return Return the value returned by the current action
2669  */
2670 uint64_t ModelChecker::switch_to_master(ModelAction *act)
2671 {
2672         DBG();
2673         Thread *old = thread_current();
2674         ASSERT(!old->get_pending());
2675         old->set_pending(act);
2676         if (Thread::swap(old, &system_context) < 0) {
2677                 perror("swap threads");
2678                 exit(EXIT_FAILURE);
2679         }
2680         return old->get_return_value();
2681 }
2682
2683 /**
2684  * Takes the next step in the execution, if possible.
2685  * @param curr The current step to take
2686  * @return Returns the next Thread to run, if any; NULL if this execution
2687  * should terminate
2688  */
2689 Thread * ModelChecker::take_step(ModelAction *curr)
2690 {
2691         Thread *curr_thrd = get_thread(curr);
2692         ASSERT(curr_thrd->get_state() == THREAD_READY);
2693
2694         curr = check_current_action(curr);
2695
2696         /* Infeasible -> don't take any more steps */
2697         if (is_infeasible())
2698                 return NULL;
2699         else if (isfeasibleprefix() && have_bug_reports()) {
2700                 set_assert();
2701                 return NULL;
2702         }
2703
2704         if (params.bound != 0 && priv->used_sequence_numbers > params.bound)
2705                 return NULL;
2706
2707         if (curr_thrd->is_blocked() || curr_thrd->is_complete())
2708                 scheduler->remove_thread(curr_thrd);
2709
2710         Thread *next_thrd = get_next_thread(curr);
2711         next_thrd = scheduler->next_thread(next_thrd);
2712
2713         DEBUG("(%d, %d)\n", curr_thrd ? id_to_int(curr_thrd->get_id()) : -1,
2714                         next_thrd ? id_to_int(next_thrd->get_id()) : -1);
2715
2716         /*
2717          * Launch end-of-execution release sequence fixups only when there are:
2718          *
2719          * (1) no more user threads to run (or when execution replay chooses
2720          *     the 'model_thread')
2721          * (2) pending release sequences
2722          * (3) pending assertions (i.e., data races)
2723          * (4) no pending promises
2724          */
2725         if (!pending_rel_seqs->empty() && (!next_thrd || next_thrd->is_model_thread()) &&
2726                         is_feasible_prefix_ignore_relseq() && !unrealizedraces.empty()) {
2727                 model_print("*** WARNING: release sequence fixup action (%zu pending release seuqences) ***\n",
2728                                 pending_rel_seqs->size());
2729                 ModelAction *fixup = new ModelAction(MODEL_FIXUP_RELSEQ,
2730                                 std::memory_order_seq_cst, NULL, VALUE_NONE,
2731                                 model_thread);
2732                 model_thread->set_pending(fixup);
2733                 return model_thread;
2734         }
2735
2736         /* next_thrd == NULL -> don't take any more steps */
2737         if (!next_thrd)
2738                 return NULL;
2739
2740         return next_thrd;
2741 }
2742
2743 /** Wrapper to run the user's main function, with appropriate arguments */
2744 void user_main_wrapper(void *)
2745 {
2746         user_main(model->params.argc, model->params.argv);
2747 }
2748
2749 /** @brief Run ModelChecker for the user program */
2750 void ModelChecker::run()
2751 {
2752         do {
2753                 thrd_t user_thread;
2754                 Thread *t = new Thread(&user_thread, &user_main_wrapper, NULL);
2755                 add_thread(t);
2756
2757                 do {
2758                         for (unsigned int i = 0; i < get_num_threads(); i++) {
2759                                 thread_id_t tid = int_to_id(i);
2760                                 Thread *thr = get_thread(tid);
2761                                 if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) {
2762                                         scheduler->next_thread(thr);
2763                                         Thread::swap(&system_context, thr);
2764                                 }
2765                         }
2766
2767                         /* Catch assertions from prior take_step or from
2768                          * between-ModelAction bugs (e.g., data races) */
2769                         if (has_asserted())
2770                                 break;
2771
2772                         /* Consume the next action for a Thread */
2773                         ModelAction *curr = t->get_pending();
2774                         t->set_pending(NULL);
2775                         t = take_step(curr);
2776                 } while (t && !t->is_model_thread());
2777                 /** @TODO Re-write release sequence fixups here */
2778         } while (next_execution());
2779
2780         print_stats();
2781 }