X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=model.cc;h=f5f20dd75dcc0147fd4f62ee200d7674bf2df6fe;hp=3bac9039b4822475bb0226adcf4fd85cc8008ea1;hb=e16b141f84421c9823e9208240d2ba6eed4d87d9;hpb=a65e234b607444355eb6e34097ee55ba93d4c01b diff --git a/model.cc b/model.cc index 3bac9039..f5f20dd7 100644 --- a/model.cc +++ b/model.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "model.h" #include "action.h" @@ -20,17 +21,14 @@ ModelChecker *model; /** @brief Constructor */ -ModelChecker::ModelChecker(struct model_params params) : +ModelChecker::ModelChecker() : /* Initialize default scheduler */ - params(params), + params(), restart_flag(false), - exit_flag(false), scheduler(new Scheduler()), node_stack(new NodeStack()), - execution(new ModelExecution(this, &this->params, scheduler, node_stack)), + execution(new ModelExecution(this, scheduler, node_stack)), execution_number(1), - diverge(NULL), - earliest_diverge(NULL), trace_analyses(), inspect_plugin(NULL) { @@ -44,6 +42,12 @@ ModelChecker::~ModelChecker() delete scheduler; } +/** Method to set parameters */ +void ModelChecker::setParams(struct model_params params) { + this->params = params; + execution->setParams(¶ms); +} + /** * Restores user program to initial state and resets all model-checker data * structures. @@ -94,73 +98,12 @@ Thread * ModelChecker::get_current_thread() const */ Thread * ModelChecker::get_next_thread() { - thread_id_t tid; /* * Have we completed exploring the preselected path? Then let the * scheduler decide */ - if (diverge == NULL) - return scheduler->select_next_thread(node_stack->get_head()); - - - /* Else, we are trying to replay an execution */ - ModelAction *next = node_stack->get_next()->get_action(); - - if (next == diverge) { - if (earliest_diverge == NULL || *diverge < *earliest_diverge) - earliest_diverge = diverge; - - Node *nextnode = next->get_node(); - Node *prevnode = nextnode->get_parent(); - scheduler->update_sleep_set(prevnode); - - /* Reached divergence point */ - if (nextnode->increment_behaviors()) { - /* Execute the same thread with a new behavior */ - tid = next->get_tid(); - node_stack->pop_restofstack(2); - } else { - ASSERT(prevnode); - /* Make a different thread execute for next step */ - 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); - if (diverge == earliest_diverge) { - earliest_diverge = prevnode->get_action(); - } - } - /* Start the round robin scheduler from this thread id */ - scheduler->set_scheduler_thread(tid); - /* The correct sleep set is in the parent node. */ - execute_sleep_set(); - - DEBUG("*** Divergence point ***\n"); - - diverge = NULL; - } else { - tid = next->get_tid(); - } - DEBUG("*** ModelChecker chose next thread = %d ***\n", id_to_int(tid)); - ASSERT(tid != THREAD_ID_T_NONE); - return get_thread(id_to_int(tid)); -} - -/** - * We need to know what the next actions of all threads in the sleep - * set will be. This method computes them and stores the actions at - * the corresponding thread object's pending action. - */ -void ModelChecker::execute_sleep_set() -{ - for (unsigned int i = 0; i < get_num_threads(); i++) { - thread_id_t tid = int_to_id(i); - Thread *thr = get_thread(tid); - if (scheduler->is_sleep_set(thr) && thr->get_pending()) { - thr->get_pending()->set_sleep_flag(); - } - } + return scheduler->select_next_thread(node_stack->get_head()); } /** @@ -246,8 +189,6 @@ void ModelChecker::print_stats() const model_print("Number of buggy executions: %d\n", stats.num_buggy_executions); model_print("Number of infeasible executions: %d\n", stats.num_infeasible); model_print("Total executions: %d\n", stats.num_total); - if (params.verbose) - model_print("Total nodes created: %d\n", node_stack->get_total_nodes()); } /** @@ -261,13 +202,6 @@ void ModelChecker::print_execution(bool printbugs) const print_program_output(); if (params.verbose >= 3) { - model_print("\nEarliest divergence point since last feasible execution:\n"); - if (earliest_diverge) - earliest_diverge->print(); - else - model_print("(Not set)\n"); - - model_print("\n"); print_stats(); } @@ -303,45 +237,24 @@ bool ModelChecker::next_execution() checkDataRaces(); run_trace_analyses(); - } else if (inspect_plugin && !execution->is_complete_execution() && - (execution->too_many_steps())) { - inspect_plugin->analyze(execution->get_action_trace()); - } + } record_stats(); - /* Output */ if ( (complete && params.verbose) || params.verbose>1 || (complete && execution->have_bug_reports())) print_execution(complete); else clear_program_output(); - if (complete) - earliest_diverge = NULL; - if (restart_flag) { do_restart(); return true; } - - if (exit_flag) - return false; - - if ((diverge = execution->get_next_backtrack()) == NULL) - return false; - - if (DBG_ENABLED()) { - model_print("Next execution will diverge at:\n"); - diverge->print(); - } - +// test code execution_number++; - - if (params.maxexecutions != 0 && stats.num_complete >= params.maxexecutions) - return false; - reset_to_initial_state(); - return true; + node_stack->full_reset(); + return false; } /** @brief Run trace analyses on complete trace */ @@ -400,9 +313,10 @@ uint64_t ModelChecker::switch_to_master(ModelAction *act) Thread *old = thread_current(); scheduler->set_current_thread(NULL); ASSERT(!old->get_pending()); +/* W: No plugin if (inspect_plugin != NULL) { - inspect_plugin->inspectModelAction(act); - } + inspect_plugin->inspectModelAction(act); + }*/ old->set_pending(act); if (Thread::swap(old, &system_context) < 0) { perror("swap threads"); @@ -426,19 +340,9 @@ bool ModelChecker::should_terminate_execution() execution->set_assert(); return true; } - - if (execution->too_many_steps()) - return true; return false; } -/** @brief Exit ModelChecker upon returning to the run loop of the - * model checker. */ -void ModelChecker::exit_model_checker() -{ - exit_flag = true; -} - /** @brief Restart ModelChecker upon returning to the run loop of the * model checker. */ void ModelChecker::restart() @@ -449,8 +353,6 @@ void ModelChecker::restart() void ModelChecker::do_restart() { restart_flag = false; - diverge = NULL; - earliest_diverge = NULL; reset_to_initial_state(); node_stack->full_reset(); memset(&stats,0,sizeof(struct execution_stats)); @@ -460,12 +362,15 @@ void ModelChecker::do_restart() /** @brief Run ModelChecker for the user program */ void ModelChecker::run() { - bool has_next; - do { + //Need to initial random number generator state to avoid resets on rollback + char random_state[256]; + initstate(423121, random_state, sizeof(random_state)); + + for(int exec = 0; exec < params.maxexecutions; exec++) { thrd_t user_thread; - Thread *t = new Thread(execution->get_next_id(), &user_thread, &user_main_wrapper, NULL, NULL); + Thread *t = new Thread(execution->get_next_id(), &user_thread, &user_main_wrapper, NULL, NULL); // L: user_main_wrapper passes the user program execution->add_thread(t); - + //Need to seed random number generator, otherwise its state gets reset do { /* * Stash next pending action(s) for thread(s). There @@ -473,11 +378,12 @@ void ModelChecker::run() * thread which just took a step--plus the first step * for any newly-created thread */ + for (unsigned int i = 0; i < get_num_threads(); i++) { thread_id_t tid = int_to_id(i); Thread *thr = get_thread(tid); if (!thr->is_model_thread() && !thr->is_complete() && !thr->get_pending()) { - switch_from_master(thr); + switch_from_master(thr); // L: context swapped, and action type of thr changed. if (thr->is_waiting_on(thr)) assert_bug("Deadlock detected (thread %u)", i); } @@ -492,12 +398,33 @@ void ModelChecker::run() } } + for (unsigned int i = 1; i < get_num_threads(); i++) { + Thread *th = get_thread(int_to_id(i)); + ModelAction *act = th->get_pending(); + if (act && execution->is_enabled(th) && (th->get_state() != THREAD_BLOCKED) ){ + if (act->is_write()){ + std::memory_order order = act->get_mo(); + if (order == std::memory_order_relaxed || \ + order == std::memory_order_release) { + t = th; + break; + } + } else if (act->get_type() == THREAD_CREATE || \ + act->get_type() == PTHREAD_CREATE || \ + act->get_type() == THREAD_START || \ + act->get_type() == THREAD_FINISH) { + t = th; + break; + } + } + } + /* Catch assertions from prior take_step or from * between-ModelAction bugs (e.g., data races) */ + if (execution->has_asserted()) break; - - if (!t) + if (!t) t = get_next_thread(); if (!t || t->is_model_thread()) break; @@ -507,20 +434,10 @@ void ModelChecker::run() t->set_pending(NULL); t = execution->take_step(curr); } while (!should_terminate_execution()); - - has_next = next_execution(); - if (inspect_plugin != NULL && !has_next) { - inspect_plugin->actionAtModelCheckingFinish(); - // Check if the inpect plugin set the restart flag - if (restart_flag) { - model_print("******* Model-checking RESTART: *******\n"); - has_next = true; - do_restart(); - } - } - } while (has_next); - - execution->fixup_release_sequences(); + next_execution(); + //restore random number generator state after rollback + setstate(random_state); + } model_print("******* Model-checking complete: *******\n"); print_stats();