model: remove ModelChecker::is_infeasible_ignoreRMW()
[c11tester.git] / model.cc
index d6b84c3ef457ddbaf3c6838d1efe243487f24d16..9e611fae96367283e33d7b927224eb259b52a27e 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -159,7 +159,7 @@ void ModelChecker::reset_to_initial_state()
        /* Print all model-checker output before rollback */
        fflush(model_out);
 
-       snapshotObject->backTrackBeforeStep(0);
+       snapshot_backtrack_before(0);
 }
 
 /** @return a thread ID for a new Thread */
@@ -174,7 +174,12 @@ unsigned int ModelChecker::get_num_threads() const
        return priv->next_thread_id;
 }
 
-/** @return The currently executing Thread. */
+/**
+ * Must be called from user-thread context (e.g., through the global
+ * thread_current() interface)
+ *
+ * @return The currently executing Thread.
+ */
 Thread * ModelChecker::get_current_thread() const
 {
        return scheduler->get_current_thread();
@@ -212,9 +217,8 @@ Thread * ModelChecker::get_next_thread(ModelAction *curr)
                /* Do not split atomic actions. */
                if (curr->is_rmwr())
                        return thread_current();
-               /* The THREAD_CREATE action points to the created Thread */
                else if (curr->get_type() == THREAD_CREATE)
-                       return (Thread *)curr->get_location();
+                       return curr->get_thread_operand();
        }
 
        /* Have we completed exploring the preselected path? */
@@ -254,8 +258,9 @@ Thread * ModelChecker::get_next_thread(ModelAction *curr)
                        tid = next->get_tid();
                        node_stack->pop_restofstack(2);
                } else {
+                       ASSERT(prevnode);
                        /* Make a different thread execute for next step */
-                       scheduler->add_sleep(thread_map->get(id_to_int(next->get_tid())));
+                       scheduler->add_sleep(get_thread(next->get_tid()));
                        tid = prevnode->get_next_backtrack();
                        /* Make sure the backtracked thread isn't sleeping. */
                        node_stack->pop_restofstack(1);
@@ -557,7 +562,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
-                       if (!act->same_thread(prev)&&prev->is_failed_trylock())
+                       if (!act->same_thread(prev) && prev->is_failed_trylock())
                                return prev;
                }
                break;
@@ -568,9 +573,9 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
-                       if (!act->same_thread(prev)&&prev->is_failed_trylock())
+                       if (!act->same_thread(prev) && prev->is_failed_trylock())
                                return prev;
-                       if (!act->same_thread(prev)&&prev->is_notify())
+                       if (!act->same_thread(prev) && prev->is_notify())
                                return prev;
                }
                break;
@@ -583,7 +588,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
-                       if (!act->same_thread(prev)&&prev->is_wait())
+                       if (!act->same_thread(prev) && prev->is_wait())
                                return prev;
                }
                break;
@@ -609,7 +614,7 @@ void ModelChecker::set_backtracking(ModelAction *act)
        Node *node = prev->get_node()->get_parent();
 
        int low_tid, high_tid;
-       if (node->is_enabled(t)) {
+       if (node->enabled_status(t->get_id()) == THREAD_ENABLED) {
                low_tid = id_to_int(act->get_tid());
                high_tid = low_tid + 1;
        } else {
@@ -617,7 +622,7 @@ void ModelChecker::set_backtracking(ModelAction *act)
                high_tid = get_num_threads();
        }
 
-       for(int i = low_tid; i < high_tid; i++) {
+       for (int i = low_tid; i < high_tid; i++) {
                thread_id_t tid = int_to_id(i);
 
                /* Make sure this thread can be enabled here. */
@@ -716,8 +721,7 @@ bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw)
                                r_status = r_modification_order(curr, reads_from);
                        }
 
-
-                       if (!second_part_of_rmw&&is_infeasible()&&(curr->get_node()->increment_read_from()||curr->get_node()->increment_future_value())) {
+                       if (!second_part_of_rmw && is_infeasible() && (curr->get_node()->increment_read_from() || curr->get_node()->increment_future_value())) {
                                mo_graph->rollbackChanges();
                                priv->too_many_reads = false;
                                continue;
@@ -725,16 +729,16 @@ bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw)
 
                        read_from(curr, reads_from);
                        mo_graph->commitChanges();
-                       mo_check_promises(curr->get_tid(), reads_from);
+                       mo_check_promises(curr->get_tid(), reads_from, NULL);
 
                        updated |= r_status;
                } else if (!second_part_of_rmw) {
                        /* Read from future value */
-                       value = curr->get_node()->get_future_value();
-                       modelclock_t expiration = curr->get_node()->get_future_value_expiration();
+                       struct future_value fv = curr->get_node()->get_future_value();
+                       value = fv.value;
+                       curr->set_value(fv.value);
                        curr->set_read_from(NULL);
-                       Promise *valuepromise = new Promise(curr, value, expiration);
-                       promises->push_back(valuepromise);
+                       promises->push_back(new Promise(curr, fv));
                }
                get_thread(curr)->set_return_value(value);
                return updated;
@@ -765,7 +769,7 @@ bool ModelChecker::process_mutex(ModelAction *curr)
        if (curr->is_trylock() || curr->is_lock() || curr->is_unlock()) {
                mutex = (std::mutex *)curr->get_location();
                state = mutex->get_state();
-       } else if(curr->is_wait()) {
+       } else if (curr->is_wait()) {
                mutex = (std::mutex *)curr->get_value();
                state = mutex->get_state();
        }
@@ -819,7 +823,7 @@ bool ModelChecker::process_mutex(ModelAction *curr)
                if (curr->get_node()->get_misc() == 0) {
                        get_safe_ptr_action(condvar_waiters_map, curr->get_location())->push_back(curr);
                        //disable us
-                       scheduler->sleep(get_current_thread());
+                       scheduler->sleep(get_thread(curr));
                }
                break;
        }
@@ -848,6 +852,27 @@ bool ModelChecker::process_mutex(ModelAction *curr)
        return false;
 }
 
+void ModelChecker::add_future_value(const ModelAction *writer, ModelAction *reader)
+{
+       /* Do more ambitious checks now that mo is more complete */
+       if (mo_may_allow(writer, reader)) {
+               Node *node = reader->get_node();
+
+               /* Find an ancestor thread which exists at the time of the reader */
+               Thread *write_thread = get_thread(writer);
+               while (id_to_int(write_thread->get_id()) >= node->get_num_threads())
+                       write_thread = write_thread->get_parent();
+
+               struct future_value fv = {
+                       writer->get_value(),
+                       writer->get_seq_number() + params.maxfuturedelay,
+                       write_thread->get_id(),
+               };
+               if (node->add_future_value(fv))
+                       set_latest_backtrack(reader);
+       }
+}
+
 /**
  * Process a write ModelAction
  * @param curr The ModelAction to process
@@ -861,16 +886,13 @@ bool ModelChecker::process_write(ModelAction *curr)
        if (promises->size() == 0) {
                for (unsigned int i = 0; i < futurevalues->size(); i++) {
                        struct PendingFutureValue pfv = (*futurevalues)[i];
-                       //Do more ambitious checks now that mo is more complete
-                       if (mo_may_allow(pfv.writer, pfv.act) &&
-                                       pfv.act->get_node()->add_future_value(pfv.writer->get_value(), pfv.writer->get_seq_number() + params.maxfuturedelay))
-                               set_latest_backtrack(pfv.act);
+                       add_future_value(pfv.writer, pfv.act);
                }
-               futurevalues->resize(0);
+               futurevalues->clear();
        }
 
        mo_graph->commitChanges();
-       mo_check_promises(curr->get_tid(), curr);
+       mo_check_promises(curr->get_tid(), curr, NULL);
 
        get_thread(curr)->set_return_value(VALUE_NONE);
        return updated_mod_order || updated_promises;
@@ -943,12 +965,18 @@ bool ModelChecker::process_thread_action(ModelAction *curr)
 
        switch (curr->get_type()) {
        case THREAD_CREATE: {
-               Thread *th = (Thread *)curr->get_location();
+               Thread *th = curr->get_thread_operand();
                th->set_creation(curr);
+               /* Promises can be satisfied by children */
+               for (unsigned int i = 0; i < promises->size(); i++) {
+                       Promise *promise = (*promises)[i];
+                       if (promise->thread_is_available(curr->get_tid()))
+                               promise->add_thread(th->get_id());
+               }
                break;
        }
        case THREAD_JOIN: {
-               Thread *blocking = (Thread *)curr->get_location();
+               Thread *blocking = curr->get_thread_operand();
                ModelAction *act = get_last_action(blocking->get_id());
                curr->synchronize_with(act);
                updated = true; /* trigger rel-seq checks */
@@ -961,6 +989,13 @@ bool ModelChecker::process_thread_action(ModelAction *curr)
                        scheduler->wake(get_thread(act));
                }
                th->complete();
+               /* Completed thread can't satisfy promises */
+               for (unsigned int i = 0; i < promises->size(); i++) {
+                       Promise *promise = (*promises)[i];
+                       if (promise->thread_is_available(th->get_id()))
+                               if (promise->eliminate_thread(th->get_id()))
+                                       priv->failed_promise = true;
+               }
                updated = true; /* trigger rel-seq checks */
                break;
        }
@@ -1191,11 +1226,10 @@ void ModelChecker::set_current_action(ModelAction *act) {
  * execution when running permutations of previously-observed executions.
  *
  * @param curr The current action to process
- * @return The next Thread that must be executed. May be NULL if ModelChecker
- * makes no choice (e.g., according to replay execution, combining RMW actions,
- * etc.)
+ * @return The ModelAction that is actually executed; may be different than
+ * curr; may be NULL, if the current action is not enabled to run
  */
-Thread * ModelChecker::check_current_action(ModelAction *curr)
+ModelAction * ModelChecker::check_current_action(ModelAction *curr)
 {
        ASSERT(curr);
        bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw();
@@ -1203,13 +1237,17 @@ Thread * ModelChecker::check_current_action(ModelAction *curr)
        if (!check_action_enabled(curr)) {
                /* Make the execution look like we chose to run this action
                 * much later, when a lock/join can succeed */
-               get_current_thread()->set_pending(curr);
-               scheduler->sleep(get_current_thread());
-               return get_next_thread(NULL);
+               get_thread(curr)->set_pending(curr);
+               scheduler->sleep(get_thread(curr));
+               return NULL;
        }
 
        bool newly_explored = initialize_curr_action(&curr);
 
+       DBG();
+       if (DBG_ENABLED())
+               curr->print();
+
        wake_up_sleeping_actions(curr);
 
        /* Add the action to lists before any other model-checking tasks */
@@ -1287,7 +1325,7 @@ Thread * ModelChecker::check_current_action(ModelAction *curr)
 
        check_curr_backtracking(curr);
        set_backtracking(curr);
-       return get_next_thread(curr);
+       return curr;
 }
 
 void ModelChecker::check_curr_backtracking(ModelAction *curr)
@@ -1295,7 +1333,7 @@ void ModelChecker::check_curr_backtracking(ModelAction *curr)
        Node *currnode = curr->get_node();
        Node *parnode = currnode->get_parent();
 
-       if (!parnode->backtrack_empty() ||
+       if ((parnode && !parnode->backtrack_empty()) ||
                         !currnode->misc_empty() ||
                         !currnode->read_from_empty() ||
                         !currnode->future_value_empty() ||
@@ -1325,15 +1363,39 @@ bool ModelChecker::isfeasibleprefix() const
        return pending_rel_seqs->size() == 0 && is_feasible_prefix_ignore_relseq();
 }
 
+/**
+ * Print disagnostic information about an infeasible execution
+ * @param prefix A string to prefix the output with; if NULL, then a default
+ * message prefix will be provided
+ */
+void ModelChecker::print_infeasibility(const char *prefix) const
+{
+       char buf[100];
+       char *ptr = buf;
+       if (mo_graph->checkForRMWViolation())
+               ptr += sprintf(ptr, "[RMW atomicity]");
+       if (mo_graph->checkForCycles())
+               ptr += sprintf(ptr, "[mo cycle]");
+       if (priv->failed_promise)
+               ptr += sprintf(ptr, "[failed promise]");
+       if (priv->too_many_reads)
+               ptr += sprintf(ptr, "[too many reads]");
+       if (priv->bad_synchronization)
+               ptr += sprintf(ptr, "[bad sw ordering]");
+       if (promises_expired())
+               ptr += sprintf(ptr, "[promise expired]");
+       if (promises->size() != 0)
+               ptr += sprintf(ptr, "[unresolved promise]");
+       if (ptr != buf)
+               model_print("%s: %s\n", prefix ? prefix : "Infeasible", buf);
+}
+
 /**
  * Returns whether the current completed trace is feasible, except for pending
  * release sequences.
  */
 bool ModelChecker::is_feasible_prefix_ignore_relseq() const
 {
-       if (DBG_ENABLED() && promises->size() != 0)
-               DEBUG("Infeasible: unrevolved promises\n");
-
        return !is_infeasible() && promises->size() == 0;
 }
 
@@ -1345,36 +1407,11 @@ bool ModelChecker::is_feasible_prefix_ignore_relseq() const
  */
 bool ModelChecker::is_infeasible() const
 {
-       if (DBG_ENABLED() && mo_graph->checkForRMWViolation())
-               DEBUG("Infeasible: RMW violation\n");
-
-       return mo_graph->checkForRMWViolation() || is_infeasible_ignoreRMW();
-}
-
-/**
- * Check If the current partial trace is infeasible, while ignoring
- * infeasibility related to 2 RMW's reading from the same store. It does not
- * check end-of-execution feasibility.
- * @see ModelChecker::is_infeasible
- * @return whether the current partial trace is infeasible, ignoring multiple
- * RMWs reading from the same store.
- * */
-bool ModelChecker::is_infeasible_ignoreRMW() const
-{
-       if (DBG_ENABLED()) {
-               if (mo_graph->checkForCycles())
-                       DEBUG("Infeasible: modification order cycles\n");
-               if (priv->failed_promise)
-                       DEBUG("Infeasible: failed promise\n");
-               if (priv->too_many_reads)
-                       DEBUG("Infeasible: too many reads\n");
-               if (priv->bad_synchronization)
-                       DEBUG("Infeasible: bad synchronization ordering\n");
-               if (promises_expired())
-                       DEBUG("Infeasible: promises expired\n");
-       }
-       return mo_graph->checkForCycles() || priv->failed_promise ||
-               priv->too_many_reads || priv->bad_synchronization ||
+       return mo_graph->checkForRMWViolation() ||
+               mo_graph->checkForCycles() ||
+               priv->failed_promise ||
+               priv->too_many_reads ||
+               priv->bad_synchronization ||
                promises_expired();
 }
 
@@ -1427,7 +1464,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf)
                action_list_t::reverse_iterator ritcopy = rit;
                //See if we have enough reads from the same value
                int count = 0;
-               for (; count < params.maxreads; rit++,count++) {
+               for (; count < params.maxreads; rit++, count++) {
                        if (rit == list->rend())
                                return;
                        ModelAction *act = *rit;
@@ -1447,7 +1484,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf)
                        if (write == rf)
                                continue;
 
-                       /* Test to see whether this is a feasible write to read from*/
+                       /* Test to see whether this is a feasible write to read from */
                        mo_graph->startChanges();
                        r_modification_order(curr, write);
                        bool feasiblereadfrom = !is_infeasible();
@@ -1460,10 +1497,10 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf)
                        bool feasiblewrite = true;
                        //new we need to see if this write works for everyone
 
-                       for (int loop = count; loop>0; loop--,rit++) {
+                       for (int loop = count; loop > 0; loop--, rit++) {
                                ModelAction *act = *rit;
                                bool foundvalue = false;
-                               for (int j = 0; j<act->get_node()->get_read_from_size(); j++) {
+                               for (int j = 0; j < act->get_node()->get_read_from_size(); j++) {
                                        if (act->get_node()->get_read_from_at(j) == write) {
                                                foundvalue = true;
                                                break;
@@ -1619,7 +1656,7 @@ void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelActio
 
                        /* Include at most one act per-thread that "happens before" curr */
                if (lastact != NULL) {
-                       if (lastact== curr) {
+                       if (lastact == curr) {
                                //Case 1: The resolved read is a RMW, and we need to make sure
                                //that the write portion of the RMW mod order after rf
 
@@ -1763,11 +1800,10 @@ bool ModelChecker::w_modification_order(ModelAction *curr)
 
                                 */
                                if (thin_air_constraint_may_allow(curr, act)) {
-                                       if (!is_infeasible() ||
-                                                       (curr->is_rmw() && act->is_rmw() && curr->get_reads_from() == act->get_reads_from() && !is_infeasible_ignoreRMW())) {
-                                               struct PendingFutureValue pfv = {curr,act};
-                                               futurevalues->push_back(pfv);
-                                       }
+                                       if (!is_infeasible())
+                                               futurevalues->push_back(PendingFutureValue(curr, act));
+                                       else if (curr->is_rmw() && act->is_rmw() && curr->get_reads_from() && curr->get_reads_from() == act->get_reads_from())
+                                               add_future_value(curr, act);
                                }
                        }
                }
@@ -2288,7 +2324,7 @@ ClockVector * ModelChecker::get_cv(thread_id_t tid) const
 bool ModelChecker::resolve_promises(ModelAction *write)
 {
        bool resolved = false;
-       std::vector< thread_id_t, ModelAlloc<thread_id_t> > threads_to_check;
+       std::vector< ModelAction *, ModelAlloc<ModelAction *> > actions_to_check;
 
        for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
                Promise *promise = (*promises)[promise_index];
@@ -2309,7 +2345,7 @@ bool ModelChecker::resolve_promises(ModelAction *write)
                        delete(promise);
 
                        promises->erase(promises->begin() + promise_index);
-                       threads_to_check.push_back(read->get_tid());
+                       actions_to_check.push_back(read);
 
                        resolved = true;
                } else
@@ -2319,8 +2355,10 @@ bool ModelChecker::resolve_promises(ModelAction *write)
        //Check whether reading these writes has made threads unable to
        //resolve promises
 
-       for (unsigned int i = 0; i < threads_to_check.size(); i++)
-               mo_check_promises(threads_to_check[i], write);
+       for (unsigned int i = 0; i < actions_to_check.size(); i++) {
+               ModelAction *read=actions_to_check[i];
+               mo_check_promises(read->get_tid(), write, read);
+       }
 
        return resolved;
 }
@@ -2355,7 +2393,7 @@ void ModelChecker::check_promises(thread_id_t tid, ClockVector *old_cv, ClockVec
                const ModelAction *act = promise->get_action();
                if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
                                merge_cv->synchronized_since(act)) {
-                       if (promise->increment_threads(tid)) {
+                       if (promise->eliminate_thread(tid)) {
                                //Promise has failed
                                priv->failed_promise = true;
                                return;
@@ -2364,29 +2402,34 @@ void ModelChecker::check_promises(thread_id_t tid, ClockVector *old_cv, ClockVec
        }
 }
 
-void ModelChecker::check_promises_thread_disabled() {
+void ModelChecker::check_promises_thread_disabled()
+{
        for (unsigned int i = 0; i < promises->size(); i++) {
                Promise *promise = (*promises)[i];
-               if (promise->check_promise()) {
+               if (promise->has_failed()) {
                        priv->failed_promise = true;
                        return;
                }
        }
 }
 
-/** Checks promises in response to addition to modification order for threads.
+/**
+ * @brief Checks promises in response to addition to modification order for
+ * threads.
+ *
  * Definitions:
+ *
  * pthread is the thread that performed the read that created the promise
  *
  * pread is the read that created the promise
  *
  * pwrite is either the first write to same location as pread by
- * pthread that is sequenced after pread or the value read by the
- * first read to the same lcoation as pread by pthread that is
- * sequenced after pread..
+ * pthread that is sequenced after pread or the write read by the
+ * first read to the same location as pread by pthread that is
+ * sequenced after pread.
  *
- *     1. If tid=pthread, then we check what other threads are reachable
- * through the mode order starting with pwrite.  Those threads cannot
+ * 1. If tid=pthread, then we check what other threads are reachable
+ * through the mod order starting with pwrite.  Those threads cannot
  * perform a write that will resolve the promise due to modification
  * order constraints.
  *
@@ -2395,46 +2438,50 @@ void ModelChecker::check_promises_thread_disabled() {
  * cannot perform a future write that will resolve the promise due to
  * modificatin order constraints.
  *
- *     @param tid The thread that either read from the model action
- *     write, or actually did the model action write.
+ * @param tid The thread that either read from the model action write, or
+ * actually did the model action write.
  *
- *     @param write The ModelAction representing the relevant write.
+ * @param write The ModelAction representing the relevant write.
+ * @param read  The ModelAction that reads a promised write, or NULL otherwise.
  */
-void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write)
+void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write, const ModelAction *read)
 {
        void *location = write->get_location();
        for (unsigned int i = 0; i < promises->size(); i++) {
                Promise *promise = (*promises)[i];
                const ModelAction *act = promise->get_action();
 
-               //Is this promise on the same location?
-               if ( act->get_location() != location )
+               // Is this promise on the same location?
+               if (act->get_location() != location)
                        continue;
 
-               //same thread as the promise
-               if ( act->get_tid() == tid ) {
+               // same thread as the promise
+               if (act->get_tid() == tid) {
+                       // make sure that the reader of this write happens after the promise
+                       if ((read == NULL) || (promise->get_action()->happens_before(read))) {
+                               // do we have a pwrite for the promise, if not, set it
+                               if (promise->get_write() == NULL) {
+                                       promise->set_write(write);
+                                       // The pwrite cannot happen before the promise
+                                       if (write->happens_before(act) && (write != act)) {
+                                               priv->failed_promise = true;
+                                               return;
+                                       }
+                               }
 
-                       //do we have a pwrite for the promise, if not, set it
-                       if (promise->get_write() == NULL ) {
-                               promise->set_write(write);
-                               //The pwrite cannot happen before the promise
-                               if (write->happens_before(act) && (write != act)) {
+                               if (mo_graph->checkPromise(write, promise)) {
                                        priv->failed_promise = true;
                                        return;
                                }
                        }
-                       if (mo_graph->checkPromise(write, promise)) {
-                               priv->failed_promise = true;
-                               return;
-                       }
                }
 
-               //Don't do any lookups twice for the same thread
-               if (promise->has_sync_thread(tid))
+               // Don't do any lookups twice for the same thread
+               if (!promise->thread_is_available(tid))
                        continue;
 
-               if (promise->get_write()&&mo_graph->checkReachable(promise->get_write(), write)) {
-                       if (promise->increment_threads(tid)) {
+               if (promise->get_write() && mo_graph->checkReachable(promise->get_write(), write)) {
+                       if (promise->eliminate_thread(tid)) {
                                priv->failed_promise = true;
                                return;
                        }
@@ -2503,14 +2550,8 @@ void ModelChecker::build_reads_from_past(ModelAction *curr)
                        else if (curr->get_sleep_flag() && !curr->is_seqcst() && !sleep_can_read_from(curr, act))
                                allow_read = false;
 
-                       if (allow_read) {
-                               DEBUG("Adding action to may_read_from:\n");
-                               if (DBG_ENABLED()) {
-                                       act->print();
-                                       curr->print();
-                               }
+                       if (allow_read)
                                curr->get_node()->add_read_from(act);
-                       }
 
                        /* Include at most one act per-thread that "happens before" curr */
                        if (act->happens_before(curr))
@@ -2560,13 +2601,11 @@ ModelAction * ModelChecker::new_uninitialized_action(void *location) const
        return act;
 }
 
-static void print_list(action_list_t *list, int exec_num = -1)
+static void print_list(action_list_t *list)
 {
        action_list_t::iterator it;
 
        model_print("---------------------------------------------------------------------\n");
-       if (exec_num >= 0)
-               model_print("Execution %d:\n", exec_num);
 
        unsigned int hash = 0;
 
@@ -2582,16 +2621,16 @@ static void print_list(action_list_t *list, int exec_num = -1)
 void ModelChecker::dumpGraph(char *filename) const
 {
        char buffer[200];
-       sprintf(buffer, "%s.dot",filename);
+       sprintf(buffer, "%s.dot", filename);
        FILE *file = fopen(buffer, "w");
-       fprintf(file, "digraph %s {\n",filename);
+       fprintf(file, "digraph %s {\n", filename);
        mo_graph->dumpNodes(file);
-       ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *)*get_num_threads());
+       ModelAction **thread_array = (ModelAction **)model_calloc(1, sizeof(ModelAction *) * get_num_threads());
 
        for (action_list_t::iterator it = action_trace->begin(); it != action_trace->end(); it++) {
                ModelAction *action = *it;
                if (action->is_read()) {
-                       fprintf(file, "N%u [label=\"%u, T%u\"];\n", action->get_seq_number(),action->get_seq_number(), action->get_tid());
+                       fprintf(file, "N%u [label=\"%u, T%u\"];\n", action->get_seq_number(), action->get_seq_number(), action->get_tid());
                        if (action->get_reads_from() != NULL)
                                fprintf(file, "N%u -> N%u[label=\"rf\", color=red];\n", action->get_seq_number(), action->get_reads_from()->get_seq_number());
                }
@@ -2601,7 +2640,7 @@ void ModelChecker::dumpGraph(char *filename) const
 
                thread_array[action->get_tid()] = action;
        }
-       fprintf(file,"}\n");
+       fprintf(file, "}\n");
        model_free(thread_array);
        fclose(file);
 }
@@ -2619,9 +2658,12 @@ void ModelChecker::print_summary() const
        dumpGraph(buffername);
 #endif
 
-       if (!isfeasibleprefix())
-               model_print("INFEASIBLE EXECUTION!\n");
-       print_list(action_trace, stats.num_total);
+       model_print("Execution %d:", stats.num_total);
+       if (isfeasibleprefix())
+               model_print("\n");
+       else
+               print_infeasibility(" INFEASIBLE");
+       print_list(action_trace);
        model_print("\n");
 }
 
@@ -2660,7 +2702,7 @@ Thread * ModelChecker::get_thread(thread_id_t tid) const
  * @param act The ModelAction
  * @return A Thread reference
  */
-Thread * ModelChecker::get_thread(ModelAction *act) const
+Thread * ModelChecker::get_thread(const ModelAction *act) const
 {
        return get_thread(act->get_tid());
 }
@@ -2722,12 +2764,7 @@ bool ModelChecker::take_step(ModelAction *curr)
        Thread *curr_thrd = get_thread(curr);
        ASSERT(curr_thrd->get_state() == THREAD_READY);
 
-       Thread *next_thrd = check_current_action(curr);
-
-       if (curr_thrd->is_blocked() || curr_thrd->is_complete())
-               scheduler->remove_thread(curr_thrd);
-
-       next_thrd = scheduler->next_thread(next_thrd);
+       curr = check_current_action(curr);
 
        /* Infeasible -> don't take any more steps */
        if (is_infeasible())
@@ -2737,11 +2774,15 @@ bool ModelChecker::take_step(ModelAction *curr)
                return false;
        }
 
-       if (params.bound != 0) {
-               if (priv->used_sequence_numbers > params.bound) {
+       if (params.bound != 0)
+               if (priv->used_sequence_numbers > params.bound)
                        return false;
-               }
-       }
+
+       if (curr_thrd->is_blocked() || curr_thrd->is_complete())
+               scheduler->remove_thread(curr_thrd);
+
+       Thread *next_thrd = get_next_thread(curr);
+       next_thrd = scheduler->next_thread(next_thrd);
 
        DEBUG("(%d, %d)\n", curr_thrd ? id_to_int(curr_thrd->get_id()) : -1,
                        next_thrd ? id_to_int(next_thrd->get_id()) : -1);