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