X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=model.cc;h=29b88c1171aa1873d34b98a19dad43c0b6c6a035;hb=d225d983eb6b52f032fcdc54b7dc612cd4e061fb;hp=6a79ad4a90f80ff1ee3177511683cd96c67ebb54;hpb=34890ed433f2d30ac5c49342e94d3c5e5f47dbfb;p=model-checker.git diff --git a/model.cc b/model.cc index 6a79ad4..29b88c1 100644 --- a/model.cc +++ b/model.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "model.h" #include "action.h" @@ -154,9 +155,6 @@ void ModelChecker::reset_to_initial_state() DEBUG("+++ Resetting to initial state +++\n"); node_stack->reset_execution(); - /* Print all model-checker output before rollback */ - fflush(model_out); - /** * FIXME: if we utilize partial rollback, we will need to free only * those pending actions which were NOT pending before the rollback @@ -422,9 +420,16 @@ bool ModelChecker::is_complete_execution() const * @param msg Descriptive message for the bug (do not include newline char) * @return True if bug is immediately-feasible */ -bool ModelChecker::assert_bug(const char *msg) +bool ModelChecker::assert_bug(const char *msg, ...) { - priv->bugs.push_back(new bug_message(msg)); + char str[800]; + + va_list ap; + va_start(ap, msg); + vsnprintf(str, sizeof(str), msg, ap); + va_end(ap); + + priv->bugs.push_back(new bug_message(str)); if (isfeasibleprefix()) { set_assert(); @@ -755,6 +760,7 @@ void ModelChecker::set_backtracking(ModelAction *act) Node *node = prev->get_node()->get_parent(); + /* See Dynamic Partial Order Reduction (addendum), POPL '05 */ int low_tid, high_tid; if (node->enabled_status(t->get_id()) == THREAD_ENABLED) { low_tid = id_to_int(act->get_tid()); @@ -771,6 +777,7 @@ void ModelChecker::set_backtracking(ModelAction *act) if (i >= node->get_num_threads()) break; + /* See Dynamic Partial Order Reduction (addendum), POPL '05 */ /* Don't backtrack into a point where the thread is disabled or sleeping. */ if (node->enabled_status(tid) != THREAD_ENABLED) continue; @@ -1490,20 +1497,9 @@ ModelAction * ModelChecker::check_current_action(ModelAction *curr) { ASSERT(curr); bool second_part_of_rmw = curr->is_rmwc() || curr->is_rmw(); - - 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_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); @@ -3078,32 +3074,14 @@ Thread * ModelChecker::take_step(ModelAction *curr) Thread *curr_thrd = get_thread(curr); ASSERT(curr_thrd->get_state() == THREAD_READY); + ASSERT(check_action_enabled(curr)); /* May have side effects? */ curr = check_current_action(curr); - - /* Infeasible -> don't take any more steps */ - if (is_infeasible()) - return NULL; - else if (isfeasibleprefix() && have_bug_reports()) { - set_assert(); - return NULL; - } - - if (params.bound != 0 && priv->used_sequence_numbers > params.bound) - return NULL; + ASSERT(curr); if (curr_thrd->is_blocked() || curr_thrd->is_complete()) scheduler->remove_thread(curr_thrd); - Thread *next_thrd = NULL; - if (curr) - next_thrd = action_select_next_thread(curr); - if (!next_thrd) - next_thrd = get_next_thread(); - - DEBUG("(%d, %d)\n", curr_thrd ? id_to_int(curr_thrd->get_id()) : -1, - next_thrd ? id_to_int(next_thrd->get_id()) : -1); - - return next_thrd; + return action_select_next_thread(curr); } /** Wrapper to run the user's main function, with appropriate arguments */ @@ -3112,6 +3090,21 @@ void user_main_wrapper(void *) user_main(model->params.argc, model->params.argv); } +bool ModelChecker::should_terminate_execution() +{ + /* Infeasible -> don't take any more steps */ + if (is_infeasible()) + return true; + else if (isfeasibleprefix() && have_bug_reports()) { + set_assert(); + return true; + } + + if (params.bound != 0 && priv->used_sequence_numbers > params.bound) + return true; + return false; +} + /** @brief Run ModelChecker for the user program */ void ModelChecker::run() { @@ -3133,7 +3126,16 @@ void ModelChecker::run() if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) { switch_from_master(thr); if (thr->is_waiting_on(thr)) - assert_bug("Deadlock detected"); + assert_bug("Deadlock detected (thread %u)", i); + } + } + + /* Don't schedule threads which should be disabled */ + for (unsigned int i = 0; i < get_num_threads(); i++) { + Thread *th = get_thread(int_to_id(i)); + ModelAction *act = th->get_pending(); + if (act && is_enabled(th) && !check_action_enabled(act)) { + scheduler->sleep(th); } } @@ -3142,11 +3144,16 @@ void ModelChecker::run() if (has_asserted()) break; + if (!t) + t = get_next_thread(); + if (!t || t->is_model_thread()) + break; + /* Consume the next action for a Thread */ ModelAction *curr = t->get_pending(); t->set_pending(NULL); t = take_step(curr); - } while (t && !t->is_model_thread()); + } while (!should_terminate_execution()); /* * Launch end-of-execution release sequence fixups only when