12 #include "clockvector.h"
13 #include "cyclegraph.h"
15 #include "threads-model.h"
16 #include "bugmessage.h"
20 #define INITIAL_THREAD_ID 0
23 * Structure for holding small ModelChecker members that should be snapshotted
25 struct model_snapshot_members {
26 model_snapshot_members() :
27 /* First thread created will have id INITIAL_THREAD_ID */
28 next_thread_id(INITIAL_THREAD_ID),
29 used_sequence_numbers(0),
31 bad_synchronization(false),
35 ~model_snapshot_members() {
36 for (unsigned int i = 0;i < bugs.size();i++)
41 unsigned int next_thread_id;
42 modelclock_t used_sequence_numbers;
43 SnapVector<bug_message *> bugs;
44 /** @brief Incorrectly-ordered synchronization was made */
45 bool bad_synchronization;
51 /** @brief Constructor */
52 ModelExecution::ModelExecution(ModelChecker *m, Scheduler *scheduler, NodeStack *node_stack) :
57 thread_map(2), /* We'll always need at least 2 threads */
61 condvar_waiters_map(),
65 thrd_last_fence_release(),
66 node_stack(node_stack),
67 priv(new struct model_snapshot_members ()),
68 mo_graph(new CycleGraph()),
71 /* Initialize a model-checker thread, for special ModelActions */
72 model_thread = new Thread(get_next_id());
73 add_thread(model_thread);
74 scheduler->register_engine(this);
75 node_stack->register_engine(this);
78 /** @brief Destructor */
79 ModelExecution::~ModelExecution()
81 for (unsigned int i = 0;i < get_num_threads();i++)
82 delete get_thread(int_to_id(i));
88 int ModelExecution::get_execution_number() const
90 return model->get_execution_number();
93 static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 4> * hash, void * ptr)
95 action_list_t *tmp = hash->get(ptr);
97 tmp = new action_list_t();
103 static SnapVector<action_list_t> * get_safe_ptr_vect_action(HashTable<void *, SnapVector<action_list_t> *, uintptr_t, 4> * hash, void * ptr)
105 SnapVector<action_list_t> *tmp = hash->get(ptr);
107 tmp = new SnapVector<action_list_t>();
113 /** @return a thread ID for a new Thread */
114 thread_id_t ModelExecution::get_next_id()
116 return priv->next_thread_id++;
119 /** @return the number of user threads created during this execution */
120 unsigned int ModelExecution::get_num_threads() const
122 return priv->next_thread_id;
125 /** @return a sequence number for a new ModelAction */
126 modelclock_t ModelExecution::get_next_seq_num()
128 return ++priv->used_sequence_numbers;
132 * @brief Should the current action wake up a given thread?
134 * @param curr The current action
135 * @param thread The thread that we might wake up
136 * @return True, if we should wake up the sleeping thread; false otherwise
138 bool ModelExecution::should_wake_up(const ModelAction *curr, const Thread *thread) const
140 const ModelAction *asleep = thread->get_pending();
141 /* Don't allow partial RMW to wake anyone up */
144 /* Synchronizing actions may have been backtracked */
145 if (asleep->could_synchronize_with(curr))
147 /* All acquire/release fences and fence-acquire/store-release */
148 if (asleep->is_fence() && asleep->is_acquire() && curr->is_release())
150 /* Fence-release + store can awake load-acquire on the same location */
151 if (asleep->is_read() && asleep->is_acquire() && curr->same_var(asleep) && curr->is_write()) {
152 ModelAction *fence_release = get_last_fence_release(curr->get_tid());
153 if (fence_release && *(get_last_action(thread->get_id())) < *fence_release)
159 void ModelExecution::wake_up_sleeping_actions(ModelAction *curr)
161 for (unsigned int i = 0;i < get_num_threads();i++) {
162 Thread *thr = get_thread(int_to_id(i));
163 if (scheduler->is_sleep_set(thr)) {
164 if (should_wake_up(curr, thr))
165 /* Remove this thread from sleep set */
166 scheduler->remove_sleep(thr);
171 /** @brief Alert the model-checker that an incorrectly-ordered
172 * synchronization was made */
173 void ModelExecution::set_bad_synchronization()
175 priv->bad_synchronization = true;
178 bool ModelExecution::assert_bug(const char *msg)
180 priv->bugs.push_back(new bug_message(msg));
182 if (isfeasibleprefix()) {
189 /** @return True, if any bugs have been reported for this execution */
190 bool ModelExecution::have_bug_reports() const
192 return priv->bugs.size() != 0;
195 SnapVector<bug_message *> * ModelExecution::get_bugs() const
201 * Check whether the current trace has triggered an assertion which should halt
204 * @return True, if the execution should be aborted; false otherwise
206 bool ModelExecution::has_asserted() const
208 return priv->asserted;
212 * Trigger a trace assertion which should cause this execution to be halted.
213 * This can be due to a detected bug or due to an infeasibility that should
216 void ModelExecution::set_assert()
218 priv->asserted = true;
222 * Check if we are in a deadlock. Should only be called at the end of an
223 * execution, although it should not give false positives in the middle of an
224 * execution (there should be some ENABLED thread).
226 * @return True if program is in a deadlock; false otherwise
228 bool ModelExecution::is_deadlocked() const
230 bool blocking_threads = false;
231 for (unsigned int i = 0;i < get_num_threads();i++) {
232 thread_id_t tid = int_to_id(i);
235 Thread *t = get_thread(tid);
236 if (!t->is_model_thread() && t->get_pending())
237 blocking_threads = true;
239 return blocking_threads;
243 * Check if this is a complete execution. That is, have all thread completed
244 * execution (rather than exiting because sleep sets have forced a redundant
247 * @return True if the execution is complete.
249 bool ModelExecution::is_complete_execution() const
251 for (unsigned int i = 0;i < get_num_threads();i++)
252 if (is_enabled(int_to_id(i)))
259 * Processes a read model action.
260 * @param curr is the read model action to process.
261 * @param rf_set is the set of model actions we can possibly read from
262 * @return True if processing this read updates the mo_graph.
264 void ModelExecution::process_read(ModelAction *curr, SnapVector<const ModelAction *> * rf_set)
266 SnapVector<const ModelAction *> * priorset = new SnapVector<const ModelAction *>();
269 int index = fuzzer->selectWrite(curr, rf_set);
270 const ModelAction *rf = (*rf_set)[index];
274 bool canprune = false;
275 if (r_modification_order(curr, rf, priorset, &canprune)) {
276 for(unsigned int i=0;i<priorset->size();i++) {
277 mo_graph->addEdge((*priorset)[i], rf);
280 get_thread(curr)->set_return_value(curr->get_return_value());
282 if (canprune && curr->get_type() == ATOMIC_READ) {
283 int tid = id_to_int(curr->get_tid());
284 (*obj_thrd_map.get(curr->get_location()))[tid].pop_back();
289 (*rf_set)[index] = rf_set->back();
295 * Processes a lock, trylock, or unlock model action. @param curr is
296 * the read model action to process.
298 * The try lock operation checks whether the lock is taken. If not,
299 * it falls to the normal lock operation case. If so, it returns
302 * The lock operation has already been checked that it is enabled, so
303 * it just grabs the lock and synchronizes with the previous unlock.
305 * The unlock operation has to re-enable all of the threads that are
306 * waiting on the lock.
308 * @return True if synchronization was updated; false otherwise
310 bool ModelExecution::process_mutex(ModelAction *curr)
312 cdsc::mutex *mutex = curr->get_mutex();
313 struct cdsc::mutex_state *state = NULL;
316 state = mutex->get_state();
318 switch (curr->get_type()) {
319 case ATOMIC_TRYLOCK: {
320 bool success = !state->locked;
321 curr->set_try_lock(success);
323 get_thread(curr)->set_return_value(0);
326 get_thread(curr)->set_return_value(1);
328 //otherwise fall into the lock case
330 //TODO: FIND SOME BETTER WAY TO CHECK LOCK INITIALIZED OR NOT
331 //if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock)
332 // assert_bug("Lock access before initialization");
333 state->locked = get_thread(curr);
334 ModelAction *unlock = get_last_unlock(curr);
335 //synchronize with the previous unlock statement
336 if (unlock != NULL) {
337 synchronize(unlock, curr);
343 case ATOMIC_UNLOCK: {
344 //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME AS NORMAL WAITS...THINK ABOUT PROBABILITIES THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY FAILS AND IN THE CASE IT DOESN'T... TIMED WAITS MUST EVENMTUALLY RELEASE...
346 /* wake up the other threads */
347 for (unsigned int i = 0;i < get_num_threads();i++) {
348 Thread *t = get_thread(int_to_id(i));
349 Thread *curr_thrd = get_thread(curr);
350 if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
354 /* unlock the lock - after checking who was waiting on it */
355 state->locked = NULL;
357 if (!curr->is_wait())
358 break;/* The rest is only for ATOMIC_WAIT */
362 case ATOMIC_NOTIFY_ALL: {
363 action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
364 //activate all the waiting threads
365 for (action_list_t::iterator rit = waiters->begin();rit != waiters->end();rit++) {
366 scheduler->wake(get_thread(*rit));
371 case ATOMIC_NOTIFY_ONE: {
372 action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location());
373 if (waiters->size() != 0) {
374 Thread * thread = fuzzer->selectNotify(waiters);
375 scheduler->wake(thread);
387 * Process a write ModelAction
388 * @param curr The ModelAction to process
389 * @return True if the mo_graph was updated or promises were resolved
391 void ModelExecution::process_write(ModelAction *curr)
393 w_modification_order(curr);
394 get_thread(curr)->set_return_value(VALUE_NONE);
398 * Process a fence ModelAction
399 * @param curr The ModelAction to process
400 * @return True if synchronization was updated
402 bool ModelExecution::process_fence(ModelAction *curr)
405 * fence-relaxed: no-op
406 * fence-release: only log the occurence (not in this function), for
407 * use in later synchronization
408 * fence-acquire (this function): search for hypothetical release
410 * fence-seq-cst: MO constraints formed in {r,w}_modification_order
412 bool updated = false;
413 if (curr->is_acquire()) {
414 action_list_t *list = &action_trace;
415 action_list_t::reverse_iterator rit;
416 /* Find X : is_read(X) && X --sb-> curr */
417 for (rit = list->rbegin();rit != list->rend();rit++) {
418 ModelAction *act = *rit;
421 if (act->get_tid() != curr->get_tid())
423 /* Stop at the beginning of the thread */
424 if (act->is_thread_start())
426 /* Stop once we reach a prior fence-acquire */
427 if (act->is_fence() && act->is_acquire())
431 /* read-acquire will find its own release sequences */
432 if (act->is_acquire())
435 /* Establish hypothetical release sequences */
436 rel_heads_list_t release_heads;
437 get_release_seq_heads(curr, act, &release_heads);
438 for (unsigned int i = 0;i < release_heads.size();i++)
439 synchronize(release_heads[i], curr);
440 if (release_heads.size() != 0)
448 * @brief Process the current action for thread-related activity
450 * Performs current-action processing for a THREAD_* ModelAction. Proccesses
451 * may include setting Thread status, completing THREAD_FINISH/THREAD_JOIN
452 * synchronization, etc. This function is a no-op for non-THREAD actions
453 * (e.g., ATOMIC_{READ,WRITE,RMW,LOCK}, etc.)
455 * @param curr The current action
456 * @return True if synchronization was updated or a thread completed
458 bool ModelExecution::process_thread_action(ModelAction *curr)
460 bool updated = false;
462 switch (curr->get_type()) {
463 case THREAD_CREATE: {
464 thrd_t *thrd = (thrd_t *)curr->get_location();
465 struct thread_params *params = (struct thread_params *)curr->get_value();
466 Thread *th = new Thread(get_next_id(), thrd, params->func, params->arg, get_thread(curr));
467 curr->set_thread_operand(th);
469 th->set_creation(curr);
472 case PTHREAD_CREATE: {
473 (*(uint32_t *)curr->get_location()) = pthread_counter++;
475 struct pthread_params *params = (struct pthread_params *)curr->get_value();
476 Thread *th = new Thread(get_next_id(), NULL, params->func, params->arg, get_thread(curr));
477 curr->set_thread_operand(th);
479 th->set_creation(curr);
481 if ( pthread_map.size() < pthread_counter )
482 pthread_map.resize( pthread_counter );
483 pthread_map[ pthread_counter-1 ] = th;
488 Thread *blocking = curr->get_thread_operand();
489 ModelAction *act = get_last_action(blocking->get_id());
490 synchronize(act, curr);
491 updated = true; /* trigger rel-seq checks */
495 Thread *blocking = curr->get_thread_operand();
496 ModelAction *act = get_last_action(blocking->get_id());
497 synchronize(act, curr);
498 updated = true; /* trigger rel-seq checks */
499 break; // WL: to be add (modified)
502 case THREAD_FINISH: {
503 Thread *th = get_thread(curr);
504 /* Wake up any joining threads */
505 for (unsigned int i = 0;i < get_num_threads();i++) {
506 Thread *waiting = get_thread(int_to_id(i));
507 if (waiting->waiting_on() == th &&
508 waiting->get_pending()->is_thread_join())
509 scheduler->wake(waiting);
512 updated = true; /* trigger rel-seq checks */
526 * Initialize the current action by performing one or more of the following
527 * actions, as appropriate: merging RMWR and RMWC/RMW actions, stepping forward
528 * in the NodeStack, manipulating backtracking sets, allocating and
529 * initializing clock vectors, and computing the promises to fulfill.
531 * @param curr The current action, as passed from the user context; may be
532 * freed/invalidated after the execution of this function, with a different
533 * action "returned" its place (pass-by-reference)
534 * @return True if curr is a newly-explored action; false otherwise
536 bool ModelExecution::initialize_curr_action(ModelAction **curr)
538 ModelAction *newcurr;
540 if ((*curr)->is_rmwc() || (*curr)->is_rmw()) {
541 newcurr = process_rmw(*curr);
548 (*curr)->set_seq_number(get_next_seq_num());
550 newcurr = node_stack->explore_action(*curr);
552 /* First restore type and order in case of RMW operation */
553 if ((*curr)->is_rmwr())
554 newcurr->copy_typeandorder(*curr);
556 ASSERT((*curr)->get_location() == newcurr->get_location());
557 newcurr->copy_from_new(*curr);
559 /* Discard duplicate ModelAction; use action from NodeStack */
562 /* Always compute new clock vector */
563 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
566 return false; /* Action was explored previously */
570 /* Always compute new clock vector */
571 newcurr->create_cv(get_parent_action(newcurr->get_tid()));
573 /* Assign most recent release fence */
574 newcurr->set_last_fence_release(get_last_fence_release(newcurr->get_tid()));
576 return true; /* This was a new ModelAction */
581 * @brief Establish reads-from relation between two actions
583 * Perform basic operations involved with establishing a concrete rf relation,
584 * including setting the ModelAction data and checking for release sequences.
586 * @param act The action that is reading (must be a read)
587 * @param rf The action from which we are reading (must be a write)
589 * @return True if this read established synchronization
592 bool ModelExecution::read_from(ModelAction *act, const ModelAction *rf)
595 ASSERT(rf->is_write());
597 act->set_read_from(rf);
598 if (act->is_acquire()) {
599 rel_heads_list_t release_heads;
600 get_release_seq_heads(act, act, &release_heads);
601 int num_heads = release_heads.size();
602 for (unsigned int i = 0;i < release_heads.size();i++)
603 if (!synchronize(release_heads[i], act))
605 return num_heads > 0;
611 * @brief Synchronizes two actions
613 * When A synchronizes with B (or A --sw-> B), B inherits A's clock vector.
614 * This function performs the synchronization as well as providing other hooks
615 * for other checks along with synchronization.
617 * @param first The left-hand side of the synchronizes-with relation
618 * @param second The right-hand side of the synchronizes-with relation
619 * @return True if the synchronization was successful (i.e., was consistent
620 * with the execution order); false otherwise
622 bool ModelExecution::synchronize(const ModelAction *first, ModelAction *second)
624 if (*second < *first) {
625 set_bad_synchronization();
628 return second->synchronize_with(first);
632 * @brief Check whether a model action is enabled.
634 * Checks whether an operation would be successful (i.e., is a lock already
635 * locked, or is the joined thread already complete).
637 * For yield-blocking, yields are never enabled.
639 * @param curr is the ModelAction to check whether it is enabled.
640 * @return a bool that indicates whether the action is enabled.
642 bool ModelExecution::check_action_enabled(ModelAction *curr) {
643 if (curr->is_lock()) {
644 cdsc::mutex *lock = curr->get_mutex();
645 struct cdsc::mutex_state *state = lock->get_state();
648 } else if (curr->is_thread_join()) {
649 Thread *blocking = curr->get_thread_operand();
650 if (!blocking->is_complete()) {
659 * This is the heart of the model checker routine. It performs model-checking
660 * actions corresponding to a given "current action." Among other processes, it
661 * calculates reads-from relationships, updates synchronization clock vectors,
662 * forms a memory_order constraints graph, and handles replay/backtrack
663 * execution when running permutations of previously-observed executions.
665 * @param curr The current action to process
666 * @return The ModelAction that is actually executed; may be different than
669 ModelAction * ModelExecution::check_current_action(ModelAction *curr)
672 bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
673 bool newly_explored = initialize_curr_action(&curr);
677 wake_up_sleeping_actions(curr);
679 /* Add the action to lists before any other model-checking tasks */
680 if (!second_part_of_rmw && curr->get_type() != NOOP)
681 add_action_to_lists(curr);
683 SnapVector<const ModelAction *> * rf_set = NULL;
684 /* Build may_read_from set for newly-created actions */
685 if (newly_explored && curr->is_read())
686 rf_set = build_may_read_from(curr);
688 process_thread_action(curr);
690 if (curr->is_read() && !second_part_of_rmw) {
691 process_read(curr, rf_set);
694 ASSERT(rf_set == NULL);
697 if (curr->is_write())
700 if (curr->is_fence())
703 if (curr->is_mutex_op())
710 * This is the strongest feasibility check available.
711 * @return whether the current trace (partial or complete) must be a prefix of
714 bool ModelExecution::isfeasibleprefix() const
716 return !is_infeasible();
720 * Print disagnostic information about an infeasible execution
721 * @param prefix A string to prefix the output with; if NULL, then a default
722 * message prefix will be provided
724 void ModelExecution::print_infeasibility(const char *prefix) const
728 if (priv->bad_synchronization)
729 ptr += sprintf(ptr, "[bad sw ordering]");
731 model_print("%s: %s", prefix ? prefix : "Infeasible", buf);
735 * Check if the current partial trace is infeasible. Does not check any
736 * end-of-execution flags, which might rule out the execution. Thus, this is
737 * useful only for ruling an execution as infeasible.
738 * @return whether the current partial trace is infeasible.
740 bool ModelExecution::is_infeasible() const
742 return priv->bad_synchronization;
745 /** Close out a RMWR by converting previous RMWR into a RMW or READ. */
746 ModelAction * ModelExecution::process_rmw(ModelAction *act) {
747 ModelAction *lastread = get_last_action(act->get_tid());
748 lastread->process_rmw(act);
750 mo_graph->addRMWEdge(lastread->get_reads_from(), lastread);
756 * @brief Updates the mo_graph with the constraints imposed from the current
759 * Basic idea is the following: Go through each other thread and find
760 * the last action that happened before our read. Two cases:
762 * -# The action is a write: that write must either occur before
763 * the write we read from or be the write we read from.
764 * -# The action is a read: the write that that action read from
765 * must occur before the write we read from or be the same write.
767 * @param curr The current action. Must be a read.
768 * @param rf The ModelAction or Promise that curr reads from. Must be a write.
769 * @return True if modification order edges were added; false otherwise
772 bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf, SnapVector<const ModelAction *> * priorset, bool * canprune)
774 SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
776 ASSERT(curr->is_read());
778 /* Last SC fence in the current thread */
779 ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
781 int tid = curr->get_tid();
782 ModelAction *prev_same_thread = NULL;
783 /* Iterate over all threads */
784 for (i = 0;i < thrd_lists->size();i++, tid = (((unsigned int)(tid+1)) == thrd_lists->size()) ? 0 : tid + 1) {
785 /* Last SC fence in thread tid */
786 ModelAction *last_sc_fence_thread_local = NULL;
788 last_sc_fence_thread_local = get_last_seq_cst_fence(int_to_id(tid), NULL);
790 /* Last SC fence in thread tid, before last SC fence in current thread */
791 ModelAction *last_sc_fence_thread_before = NULL;
792 if (last_sc_fence_local)
793 last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(tid), last_sc_fence_local);
795 //Only need to iterate if either hb has changed for thread in question or SC fence after last operation...
796 if (prev_same_thread != NULL &&
797 (prev_same_thread->get_cv()->getClock(tid) == curr->get_cv()->getClock(tid)) &&
798 (last_sc_fence_thread_local == NULL || *last_sc_fence_thread_local < *prev_same_thread)) {
802 /* Iterate over actions in thread, starting from most recent */
803 action_list_t *list = &(*thrd_lists)[tid];
804 action_list_t::reverse_iterator rit;
805 for (rit = list->rbegin();rit != list->rend();rit++) {
806 ModelAction *act = *rit;
811 /* Don't want to add reflexive edges on 'rf' */
812 if (act->equals(rf)) {
813 if (act->happens_before(curr))
819 if (act->is_write()) {
820 /* C++, Section 29.3 statement 5 */
821 if (curr->is_seqcst() && last_sc_fence_thread_local &&
822 *act < *last_sc_fence_thread_local) {
823 if (mo_graph->checkReachable(rf, act))
825 priorset->push_back(act);
828 /* C++, Section 29.3 statement 4 */
829 else if (act->is_seqcst() && last_sc_fence_local &&
830 *act < *last_sc_fence_local) {
831 if (mo_graph->checkReachable(rf, act))
833 priorset->push_back(act);
836 /* C++, Section 29.3 statement 6 */
837 else if (last_sc_fence_thread_before &&
838 *act < *last_sc_fence_thread_before) {
839 if (mo_graph->checkReachable(rf, act))
841 priorset->push_back(act);
847 * Include at most one act per-thread that "happens
850 if (act->happens_before(curr)) {
852 if (last_sc_fence_local == NULL ||
853 (*last_sc_fence_local < *prev_same_thread)) {
854 prev_same_thread = act;
857 if (act->is_write()) {
858 if (mo_graph->checkReachable(rf, act))
860 priorset->push_back(act);
862 const ModelAction *prevrf = act->get_reads_from();
863 if (!prevrf->equals(rf)) {
864 if (mo_graph->checkReachable(rf, prevrf))
866 priorset->push_back(prevrf);
868 if (act->get_tid() == curr->get_tid()) {
869 //Can prune curr from obj list
882 * Updates the mo_graph with the constraints imposed from the current write.
884 * Basic idea is the following: Go through each other thread and find
885 * the lastest action that happened before our write. Two cases:
887 * (1) The action is a write => that write must occur before
890 * (2) The action is a read => the write that that action read from
891 * must occur before the current write.
893 * This method also handles two other issues:
895 * (I) Sequential Consistency: Making sure that if the current write is
896 * seq_cst, that it occurs after the previous seq_cst write.
898 * (II) Sending the write back to non-synchronizing reads.
900 * @param curr The current action. Must be a write.
901 * @param send_fv A vector for stashing reads to which we may pass our future
902 * value. If NULL, then don't record any future values.
903 * @return True if modification order edges were added; false otherwise
905 void ModelExecution::w_modification_order(ModelAction *curr)
907 SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
909 ASSERT(curr->is_write());
911 if (curr->is_seqcst()) {
912 /* We have to at least see the last sequentially consistent write,
913 so we are initialized. */
914 ModelAction *last_seq_cst = get_last_seq_cst_write(curr);
915 if (last_seq_cst != NULL) {
916 mo_graph->addEdge(last_seq_cst, curr);
920 /* Last SC fence in the current thread */
921 ModelAction *last_sc_fence_local = get_last_seq_cst_fence(curr->get_tid(), NULL);
923 /* Iterate over all threads */
924 for (i = 0;i < thrd_lists->size();i++) {
925 /* Last SC fence in thread i, before last SC fence in current thread */
926 ModelAction *last_sc_fence_thread_before = NULL;
927 if (last_sc_fence_local && int_to_id((int)i) != curr->get_tid())
928 last_sc_fence_thread_before = get_last_seq_cst_fence(int_to_id(i), last_sc_fence_local);
930 /* Iterate over actions in thread, starting from most recent */
931 action_list_t *list = &(*thrd_lists)[i];
932 action_list_t::reverse_iterator rit;
933 bool force_edge = false;
934 for (rit = list->rbegin();rit != list->rend();rit++) {
935 ModelAction *act = *rit;
938 * 1) If RMW and it actually read from something, then we
939 * already have all relevant edges, so just skip to next
942 * 2) If RMW and it didn't read from anything, we should
943 * whatever edge we can get to speed up convergence.
945 * 3) If normal write, we need to look at earlier actions, so
946 * continue processing list.
949 if (curr->is_rmw()) {
950 if (curr->get_reads_from() != NULL)
958 /* C++, Section 29.3 statement 7 */
959 if (last_sc_fence_thread_before && act->is_write() &&
960 *act < *last_sc_fence_thread_before) {
961 mo_graph->addEdge(act, curr, force_edge);
966 * Include at most one act per-thread that "happens
969 if (act->happens_before(curr)) {
971 * Note: if act is RMW, just add edge:
973 * The following edge should be handled elsewhere:
974 * readfrom(act) --mo--> act
977 mo_graph->addEdge(act, curr, force_edge);
978 else if (act->is_read()) {
979 //if previous read accessed a null, just keep going
980 mo_graph->addEdge(act->get_reads_from(), curr, force_edge);
983 } else if (act->is_read() && !act->could_synchronize_with(curr) &&
984 !act->same_thread(curr)) {
985 /* We have an action that:
986 (1) did not happen before us
987 (2) is a read and we are a write
988 (3) cannot synchronize with us
989 (4) is in a different thread
991 that read could potentially read from our write. Note that
992 these checks are overly conservative at this point, we'll
993 do more checks before actually removing the
1004 * Arbitrary reads from the future are not allowed. Section 29.3 part 9 places
1005 * some constraints. This method checks one the following constraint (others
1006 * require compiler support):
1008 * If X --hb-> Y --mo-> Z, then X should not read from Z.
1009 * If X --hb-> Y, A --rf-> Y, and A --mo-> Z, then X should not read from Z.
1011 bool ModelExecution::mo_may_allow(const ModelAction *writer, const ModelAction *reader)
1013 SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(reader->get_location());
1015 /* Iterate over all threads */
1016 for (i = 0;i < thrd_lists->size();i++) {
1017 const ModelAction *write_after_read = NULL;
1019 /* Iterate over actions in thread, starting from most recent */
1020 action_list_t *list = &(*thrd_lists)[i];
1021 action_list_t::reverse_iterator rit;
1022 for (rit = list->rbegin();rit != list->rend();rit++) {
1023 ModelAction *act = *rit;
1025 /* Don't disallow due to act == reader */
1026 if (!reader->happens_before(act) || reader == act)
1028 else if (act->is_write())
1029 write_after_read = act;
1030 else if (act->is_read() && act->get_reads_from() != NULL)
1031 write_after_read = act->get_reads_from();
1034 if (write_after_read && write_after_read != writer && mo_graph->checkReachable(write_after_read, writer))
1041 * Finds the head(s) of the release sequence(s) containing a given ModelAction.
1042 * The ModelAction under consideration is expected to be taking part in
1043 * release/acquire synchronization as an object of the "reads from" relation.
1044 * Note that this can only provide release sequence support for RMW chains
1045 * which do not read from the future, as those actions cannot be traced until
1046 * their "promise" is fulfilled. Similarly, we may not even establish the
1047 * presence of a release sequence with certainty, as some modification order
1048 * constraints may be decided further in the future. Thus, this function
1049 * "returns" two pieces of data: a pass-by-reference vector of @a release_heads
1050 * and a boolean representing certainty.
1052 * @param rf The action that might be part of a release sequence. Must be a
1054 * @param release_heads A pass-by-reference style return parameter. After
1055 * execution of this function, release_heads will contain the heads of all the
1056 * relevant release sequences, if any exists with certainty
1057 * @return true, if the ModelExecution is certain that release_heads is complete;
1060 bool ModelExecution::release_seq_heads(const ModelAction *rf, rel_heads_list_t *release_heads) const
1063 for ( ;rf != NULL;rf = rf->get_reads_from()) {
1064 ASSERT(rf->is_write());
1066 if (rf->is_release())
1067 release_heads->push_back(rf);
1068 else if (rf->get_last_fence_release())
1069 release_heads->push_back(rf->get_last_fence_release());
1071 break;/* End of RMW chain */
1073 /** @todo Need to be smarter here... In the linux lock
1074 * example, this will run to the beginning of the program for
1076 /** @todo The way to be smarter here is to keep going until 1
1077 * thread has a release preceded by an acquire and you've seen
1080 /* acq_rel RMW is a sufficient stopping condition */
1081 if (rf->is_acquire() && rf->is_release())
1082 return true;/* complete */
1084 ASSERT(rf); // Needs to be real write
1086 if (rf->is_release())
1087 return true;/* complete */
1089 /* else relaxed write
1090 * - check for fence-release in the same thread (29.8, stmt. 3)
1091 * - check modification order for contiguous subsequence
1092 * -> rf must be same thread as release */
1094 const ModelAction *fence_release = rf->get_last_fence_release();
1095 /* Synchronize with a fence-release unconditionally; we don't need to
1096 * find any more "contiguous subsequence..." for it */
1098 release_heads->push_back(fence_release);
1100 return true; /* complete */
1104 * An interface for getting the release sequence head(s) with which a
1105 * given ModelAction must synchronize. This function only returns a non-empty
1106 * result when it can locate a release sequence head with certainty. Otherwise,
1107 * it may mark the internal state of the ModelExecution so that it will handle
1108 * the release sequence at a later time, causing @a acquire to update its
1109 * synchronization at some later point in execution.
1111 * @param acquire The 'acquire' action that may synchronize with a release
1113 * @param read The read action that may read from a release sequence; this may
1114 * be the same as acquire, or else an earlier action in the same thread (i.e.,
1115 * when 'acquire' is a fence-acquire)
1116 * @param release_heads A pass-by-reference return parameter. Will be filled
1117 * with the head(s) of the release sequence(s), if they exists with certainty.
1118 * @see ModelExecution::release_seq_heads
1120 void ModelExecution::get_release_seq_heads(ModelAction *acquire,
1121 ModelAction *read, rel_heads_list_t *release_heads)
1123 const ModelAction *rf = read->get_reads_from();
1125 release_seq_heads(rf, release_heads);
1129 * Performs various bookkeeping operations for the current ModelAction. For
1130 * instance, adds action to the per-object, per-thread action vector and to the
1131 * action trace list of all thread actions.
1133 * @param act is the ModelAction to add.
1135 void ModelExecution::add_action_to_lists(ModelAction *act)
1137 int tid = id_to_int(act->get_tid());
1138 ModelAction *uninit = NULL;
1140 action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
1141 if (list->empty() && act->is_atomic_var()) {
1142 uninit = get_uninitialized_action(act);
1143 uninit_id = id_to_int(uninit->get_tid());
1144 list->push_front(uninit);
1146 list->push_back(act);
1148 action_trace.push_back(act);
1150 action_trace.push_front(uninit);
1152 SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
1153 if (tid >= (int)vec->size())
1154 vec->resize(priv->next_thread_id);
1155 (*vec)[tid].push_back(act);
1157 (*vec)[uninit_id].push_front(uninit);
1159 if ((int)thrd_last_action.size() <= tid)
1160 thrd_last_action.resize(get_num_threads());
1161 thrd_last_action[tid] = act;
1163 thrd_last_action[uninit_id] = uninit;
1165 if (act->is_fence() && act->is_release()) {
1166 if ((int)thrd_last_fence_release.size() <= tid)
1167 thrd_last_fence_release.resize(get_num_threads());
1168 thrd_last_fence_release[tid] = act;
1171 if (act->is_wait()) {
1172 void *mutex_loc = (void *) act->get_value();
1173 get_safe_ptr_action(&obj_map, mutex_loc)->push_back(act);
1175 SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, mutex_loc);
1176 if (tid >= (int)vec->size())
1177 vec->resize(priv->next_thread_id);
1178 (*vec)[tid].push_back(act);
1183 * @brief Get the last action performed by a particular Thread
1184 * @param tid The thread ID of the Thread in question
1185 * @return The last action in the thread
1187 ModelAction * ModelExecution::get_last_action(thread_id_t tid) const
1189 int threadid = id_to_int(tid);
1190 if (threadid < (int)thrd_last_action.size())
1191 return thrd_last_action[id_to_int(tid)];
1197 * @brief Get the last fence release performed by a particular Thread
1198 * @param tid The thread ID of the Thread in question
1199 * @return The last fence release in the thread, if one exists; NULL otherwise
1201 ModelAction * ModelExecution::get_last_fence_release(thread_id_t tid) const
1203 int threadid = id_to_int(tid);
1204 if (threadid < (int)thrd_last_fence_release.size())
1205 return thrd_last_fence_release[id_to_int(tid)];
1211 * Gets the last memory_order_seq_cst write (in the total global sequence)
1212 * performed on a particular object (i.e., memory location), not including the
1214 * @param curr The current ModelAction; also denotes the object location to
1216 * @return The last seq_cst write
1218 ModelAction * ModelExecution::get_last_seq_cst_write(ModelAction *curr) const
1220 void *location = curr->get_location();
1221 action_list_t *list = obj_map.get(location);
1222 /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
1223 action_list_t::reverse_iterator rit;
1224 for (rit = list->rbegin();(*rit) != curr;rit++)
1226 rit++; /* Skip past curr */
1227 for ( ;rit != list->rend();rit++)
1228 if ((*rit)->is_write() && (*rit)->is_seqcst())
1234 * Gets the last memory_order_seq_cst fence (in the total global sequence)
1235 * performed in a particular thread, prior to a particular fence.
1236 * @param tid The ID of the thread to check
1237 * @param before_fence The fence from which to begin the search; if NULL, then
1238 * search for the most recent fence in the thread.
1239 * @return The last prior seq_cst fence in the thread, if exists; otherwise, NULL
1241 ModelAction * ModelExecution::get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const
1243 /* All fences should have location FENCE_LOCATION */
1244 action_list_t *list = obj_map.get(FENCE_LOCATION);
1249 action_list_t::reverse_iterator rit = list->rbegin();
1252 for (;rit != list->rend();rit++)
1253 if (*rit == before_fence)
1256 ASSERT(*rit == before_fence);
1260 for (;rit != list->rend();rit++)
1261 if ((*rit)->is_fence() && (tid == (*rit)->get_tid()) && (*rit)->is_seqcst())
1267 * Gets the last unlock operation performed on a particular mutex (i.e., memory
1268 * location). This function identifies the mutex according to the current
1269 * action, which is presumed to perform on the same mutex.
1270 * @param curr The current ModelAction; also denotes the object location to
1272 * @return The last unlock operation
1274 ModelAction * ModelExecution::get_last_unlock(ModelAction *curr) const
1276 void *location = curr->get_location();
1278 action_list_t *list = obj_map.get(location);
1279 /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
1280 action_list_t::reverse_iterator rit;
1281 for (rit = list->rbegin();rit != list->rend();rit++)
1282 if ((*rit)->is_unlock() || (*rit)->is_wait())
1287 ModelAction * ModelExecution::get_parent_action(thread_id_t tid) const
1289 ModelAction *parent = get_last_action(tid);
1291 parent = get_thread(tid)->get_creation();
1296 * Returns the clock vector for a given thread.
1297 * @param tid The thread whose clock vector we want
1298 * @return Desired clock vector
1300 ClockVector * ModelExecution::get_cv(thread_id_t tid) const
1302 ModelAction *firstaction=get_parent_action(tid);
1303 return firstaction != NULL ? firstaction->get_cv() : NULL;
1306 bool valequals(uint64_t val1, uint64_t val2, int size) {
1309 return ((uint8_t)val1) == ((uint8_t)val2);
1311 return ((uint16_t)val1) == ((uint16_t)val2);
1313 return ((uint32_t)val1) == ((uint32_t)val2);
1323 * Build up an initial set of all past writes that this 'read' action may read
1324 * from, as well as any previously-observed future values that must still be valid.
1326 * @param curr is the current ModelAction that we are exploring; it must be a
1329 SnapVector<const ModelAction *> * ModelExecution::build_may_read_from(ModelAction *curr)
1331 SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
1333 ASSERT(curr->is_read());
1335 ModelAction *last_sc_write = NULL;
1337 if (curr->is_seqcst())
1338 last_sc_write = get_last_seq_cst_write(curr);
1340 SnapVector<const ModelAction *> * rf_set = new SnapVector<const ModelAction *>();
1342 /* Iterate over all threads */
1343 for (i = 0;i < thrd_lists->size();i++) {
1344 /* Iterate over actions in thread, starting from most recent */
1345 action_list_t *list = &(*thrd_lists)[i];
1346 action_list_t::reverse_iterator rit;
1347 for (rit = list->rbegin();rit != list->rend();rit++) {
1348 const ModelAction *act = *rit;
1350 /* Only consider 'write' actions */
1351 if (!act->is_write()) {
1352 if (act != curr && act->is_read() && act->happens_before(curr)) {
1353 const ModelAction *tmp = act->get_reads_from();
1354 if (((unsigned int) id_to_int(tmp->get_tid()))==i)
1365 /* Don't consider more than one seq_cst write if we are a seq_cst read. */
1366 bool allow_read = true;
1368 if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
1371 /* Need to check whether we will have two RMW reading from the same value */
1372 if (curr->is_rmwr()) {
1373 /* It is okay if we have a failing CAS */
1374 if (!curr->is_rmwrcas() ||
1375 valequals(curr->get_value(), act->get_value(), curr->getSize())) {
1376 //Need to make sure we aren't the second RMW
1377 CycleNode * node = mo_graph->getNode_noCreate(act);
1378 if (node != NULL && node->getRMW() != NULL) {
1379 //we are the second RMW
1386 /* Only add feasible reads */
1387 rf_set->push_back(act);
1390 /* Include at most one act per-thread that "happens before" curr */
1391 if (act->happens_before(curr))
1396 if (DBG_ENABLED()) {
1397 model_print("Reached read action:\n");
1399 model_print("End printing read_from_past\n");
1405 * @brief Get an action representing an uninitialized atomic
1407 * This function may create a new one or try to retrieve one from the NodeStack
1409 * @param curr The current action, which prompts the creation of an UNINIT action
1410 * @return A pointer to the UNINIT ModelAction
1412 ModelAction * ModelExecution::get_uninitialized_action(const ModelAction *curr) const
1414 Node *node = curr->get_node();
1415 ModelAction *act = node->get_uninit_action();
1417 act = new ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, curr->get_location(), params->uninitvalue, model_thread);
1418 node->set_uninit_action(act);
1420 act->create_cv(NULL);
1424 static void print_list(const action_list_t *list)
1426 action_list_t::const_iterator it;
1428 model_print("------------------------------------------------------------------------------------\n");
1429 model_print("# t Action type MO Location Value Rf CV\n");
1430 model_print("------------------------------------------------------------------------------------\n");
1432 unsigned int hash = 0;
1434 for (it = list->begin();it != list->end();it++) {
1435 const ModelAction *act = *it;
1436 if (act->get_seq_number() > 0)
1438 hash = hash^(hash<<3)^((*it)->hash());
1440 model_print("HASH %u\n", hash);
1441 model_print("------------------------------------------------------------------------------------\n");
1444 #if SUPPORT_MOD_ORDER_DUMP
1445 void ModelExecution::dumpGraph(char *filename) const
1448 sprintf(buffer, "%s.dot", filename);
1449 FILE *file = fopen(buffer, "w");
1450 fprintf(file, "digraph %s {\n", filename);
1451 mo_graph->dumpNodes(file);
1452 ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
1454 for (action_list_t::const_iterator it = action_trace.begin();it != action_trace.end();it++) {
1455 ModelAction *act = *it;
1456 if (act->is_read()) {
1457 mo_graph->dot_print_node(file, act);
1458 mo_graph->dot_print_edge(file,
1459 act->get_reads_from(),
1461 "label=\"rf\", color=red, weight=2");
1463 if (thread_array[act->get_tid()]) {
1464 mo_graph->dot_print_edge(file,
1465 thread_array[id_to_int(act->get_tid())],
1467 "label=\"sb\", color=blue, weight=400");
1470 thread_array[act->get_tid()] = act;
1472 fprintf(file, "}\n");
1473 model_free(thread_array);
1478 /** @brief Prints an execution trace summary. */
1479 void ModelExecution::print_summary() const
1481 #if SUPPORT_MOD_ORDER_DUMP
1482 char buffername[100];
1483 sprintf(buffername, "exec%04u", get_execution_number());
1484 mo_graph->dumpGraphToFile(buffername);
1485 sprintf(buffername, "graph%04u", get_execution_number());
1486 dumpGraph(buffername);
1489 model_print("Execution trace %d:", get_execution_number());
1490 if (isfeasibleprefix()) {
1491 if (scheduler->all_threads_sleeping())
1492 model_print(" SLEEP-SET REDUNDANT");
1493 if (have_bug_reports())
1494 model_print(" DETECTED BUG(S)");
1496 print_infeasibility(" INFEASIBLE");
1499 print_list(&action_trace);
1505 * Add a Thread to the system for the first time. Should only be called once
1507 * @param t The Thread to add
1509 void ModelExecution::add_thread(Thread *t)
1511 unsigned int i = id_to_int(t->get_id());
1512 if (i >= thread_map.size())
1513 thread_map.resize(i + 1);
1515 if (!t->is_model_thread())
1516 scheduler->add_thread(t);
1520 * @brief Get a Thread reference by its ID
1521 * @param tid The Thread's ID
1522 * @return A Thread reference
1524 Thread * ModelExecution::get_thread(thread_id_t tid) const
1526 unsigned int i = id_to_int(tid);
1527 if (i < thread_map.size())
1528 return thread_map[i];
1533 * @brief Get a reference to the Thread in which a ModelAction was executed
1534 * @param act The ModelAction
1535 * @return A Thread reference
1537 Thread * ModelExecution::get_thread(const ModelAction *act) const
1539 return get_thread(act->get_tid());
1543 * @brief Get a Thread reference by its pthread ID
1544 * @param index The pthread's ID
1545 * @return A Thread reference
1547 Thread * ModelExecution::get_pthread(pthread_t pid) {
1553 uint32_t thread_id = x.v;
1554 if (thread_id < pthread_counter + 1) return pthread_map[thread_id];
1559 * @brief Check if a Thread is currently enabled
1560 * @param t The Thread to check
1561 * @return True if the Thread is currently enabled
1563 bool ModelExecution::is_enabled(Thread *t) const
1565 return scheduler->is_enabled(t);
1569 * @brief Check if a Thread is currently enabled
1570 * @param tid The ID of the Thread to check
1571 * @return True if the Thread is currently enabled
1573 bool ModelExecution::is_enabled(thread_id_t tid) const
1575 return scheduler->is_enabled(tid);
1579 * @brief Select the next thread to execute based on the curren action
1581 * RMW actions occur in two parts, and we cannot split them. And THREAD_CREATE
1582 * actions should be followed by the execution of their child thread. In either
1583 * case, the current action should determine the next thread schedule.
1585 * @param curr The current action
1586 * @return The next thread to run, if the current action will determine this
1587 * selection; otherwise NULL
1589 Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) const
1591 /* Do not split atomic RMW */
1592 if (curr->is_rmwr())
1593 return get_thread(curr);
1594 /* Follow CREATE with the created thread */
1595 /* which is not needed, because model.cc takes care of this */
1596 if (curr->get_type() == THREAD_CREATE)
1597 return curr->get_thread_operand();
1598 if (curr->get_type() == PTHREAD_CREATE) {
1599 return curr->get_thread_operand();
1605 * Takes the next step in the execution, if possible.
1606 * @param curr The current step to take
1607 * @return Returns the next Thread to run, if any; NULL if this execution
1610 Thread * ModelExecution::take_step(ModelAction *curr)
1612 Thread *curr_thrd = get_thread(curr);
1613 ASSERT(curr_thrd->get_state() == THREAD_READY);
1615 ASSERT(check_action_enabled(curr)); /* May have side effects? */
1616 curr = check_current_action(curr);
1619 // model_print("poitner loc: %p, thread: %d, type: %d, order: %d, position: %s\n", curr, curr->get_tid(), curr->get_type(), curr->get_mo(), curr->get_position() );
1620 model->get_history()->add_func_atomic( curr, curr_thrd->get_id() );
1622 if (curr_thrd->is_blocked() || curr_thrd->is_complete())
1623 scheduler->remove_thread(curr_thrd);
1625 return action_select_next_thread(curr);
1628 Fuzzer * ModelExecution::getFuzzer() {