X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=model.cc;h=618b37e00ee86ad5fd03c03216218e7f36ed0067;hp=591d42a1ab3dbbc9aae2b8ea152e252c58379fd5;hb=6caada76d7318c7853dd334bccbfed0367c242ec;hpb=f5029d07e4fad5921f60108f5632fb2a5e4a52fb diff --git a/model.cc b/model.cc index 591d42a1..618b37e0 100644 --- a/model.cc +++ b/model.cc @@ -483,8 +483,16 @@ void ModelChecker::record_stats() stats.num_buggy_executions++; else if (is_complete_execution()) stats.num_complete++; - else + else { stats.num_redundant++; + + /** + * @todo We can violate this ASSERT() when fairness/sleep sets + * conflict to cause an execution to terminate, e.g. with: + * Scheduler: [0: disabled][1: disabled][2: sleep][3: current, enabled] + */ + //ASSERT(scheduler->all_threads_sleeping()); + } } /** @brief Print execution stats */ @@ -1020,7 +1028,7 @@ void ModelChecker::add_future_value(const ModelAction *writer, ModelAction *read write_thread = write_thread->get_parent(); struct future_value fv = { - writer->get_value(), + writer->get_write_value(), writer->get_seq_number() + params.maxfuturedelay, write_thread->get_id(), }; @@ -1037,7 +1045,11 @@ void ModelChecker::add_future_value(const ModelAction *writer, ModelAction *read bool ModelChecker::process_write(ModelAction *curr) { bool updated_mod_order = w_modification_order(curr); - bool updated_promises = resolve_promises(curr); + int promise_idx = get_promise_to_resolve(curr); + bool updated_promises = false; + + if (promise_idx >= 0) + updated_promises = resolve_promise(curr, promise_idx); if (promises->size() == 0) { for (unsigned int i = 0; i < futurevalues->size(); i++) { @@ -1322,8 +1334,9 @@ bool ModelChecker::initialize_curr_action(ModelAction **curr) */ bool ModelChecker::read_from(ModelAction *act, const ModelAction *rf) { + ASSERT(rf); act->set_read_from(rf); - if (rf != NULL && act->is_acquire()) { + if (act->is_acquire()) { rel_heads_list_t release_heads; get_release_seq_heads(act, act, &release_heads); int num_heads = release_heads.size(); @@ -2443,44 +2456,49 @@ ClockVector * ModelChecker::get_cv(thread_id_t tid) const } /** - * Resolve a set of Promises with a current write. The set is provided in the - * Node corresponding to @a write. + * @brief Find the promise, if any to resolve for the current action + * @param curr The current ModelAction. Should be a write. + * @return The (non-negative) index for the Promise to resolve, if any; + * otherwise -1 + */ +int ModelChecker::get_promise_to_resolve(const ModelAction *curr) const +{ + for (unsigned int i = 0; i < promises->size(); i++) + if (curr->get_node()->get_promise(i)) + return i; + return -1; +} + +/** + * Resolve a Promise with a current write. * @param write The ModelAction that is fulfilling Promises - * @return True if promises were resolved; false otherwise + * @param promise_idx The index corresponding to the promise + * @return True if the Promise was successfully resolved; false otherwise */ -bool ModelChecker::resolve_promises(ModelAction *write) +bool ModelChecker::resolve_promise(ModelAction *write, unsigned int promise_idx) { - bool haveResolved = false; std::vector< ModelAction *, ModelAlloc > actions_to_check; - promise_list_t mustResolve, resolved; - - for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) { - Promise *promise = (*promises)[promise_index]; - if (write->get_node()->get_promise(i)) { - for (unsigned int j = 0; j < promise->get_num_readers(); j++) { - ModelAction *read = promise->get_reader(j); - read_from(read, write); - actions_to_check.push_back(read); - } - //Make sure the promise's value matches the write's value - ASSERT(promise->is_compatible(write)); - mo_graph->resolvePromise(promise, write, &mustResolve); + promise_list_t mustResolve; + Promise *promise = (*promises)[promise_idx]; - resolved.push_back(promise); - promises->erase(promises->begin() + promise_index); - - haveResolved = true; - } else - promise_index++; + for (unsigned int i = 0; i < promise->get_num_readers(); i++) { + ModelAction *read = promise->get_reader(i); + read_from(read, write); + actions_to_check.push_back(read); } + /* Make sure the promise's value matches the write's value */ + ASSERT(promise->is_compatible(write) && promise->same_value(write)); + mo_graph->resolvePromise(promise, write, &mustResolve); + + promises->erase(promises->begin() + promise_idx); + + /** @todo simplify the 'mustResolve' stuff */ + ASSERT(mustResolve.size() <= 1); + + if (!mustResolve.empty() && mustResolve[0] != promise) + priv->failed_promise = true; + delete promise; - for (unsigned int i = 0; i < mustResolve.size(); i++) { - if (std::find(resolved.begin(), resolved.end(), mustResolve[i]) - == resolved.end()) - priv->failed_promise = true; - } - for (unsigned int i = 0; i < resolved.size(); i++) - delete resolved[i]; //Check whether reading these writes has made threads unable to //resolve promises @@ -2489,7 +2507,7 @@ bool ModelChecker::resolve_promises(ModelAction *write) mo_check_promises(read, true); } - return haveResolved; + return true; } /** @@ -2502,7 +2520,7 @@ void ModelChecker::compute_promises(ModelAction *curr) { for (unsigned int i = 0; i < promises->size(); i++) { Promise *promise = (*promises)[i]; - if (!promise->is_compatible(curr) || promise->get_value() != curr->get_value()) + if (!promise->is_compatible(curr) || !promise->same_value(curr)) continue; bool satisfy = true; @@ -2573,7 +2591,7 @@ void ModelChecker::mo_check_promises(const ModelAction *act, bool is_read_check) Promise *promise = (*promises)[i]; // Is this promise on the same location? - if (promise->get_value() != write->get_value()) + if (!promise->same_location(write)) continue; for (unsigned int j = 0; j < promise->get_num_readers(); j++) { @@ -2762,17 +2780,28 @@ void ModelChecker::dumpGraph(char *filename) const 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=\"N%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()); + ModelAction *act = *it; + if (act->is_read()) { + mo_graph->dot_print_node(file, act); + if (act->get_reads_from()) + mo_graph->dot_print_edge(file, + act->get_reads_from(), + act, + "label=\"rf\", color=red, weight=2"); + else + mo_graph->dot_print_edge(file, + act->get_reads_from_promise(), + act, + "label=\"rf\", color=red"); } - if (thread_array[action->get_tid()] != NULL) { - fprintf(file, "N%u -> N%u[label=\"sb\", color=blue];\n", thread_array[action->get_tid()]->get_seq_number(), action->get_seq_number()); + if (thread_array[act->get_tid()]) { + mo_graph->dot_print_edge(file, + thread_array[id_to_int(act->get_tid())], + act, + "label=\"sb\", color=blue, weight=400"); } - thread_array[action->get_tid()] = action; + thread_array[act->get_tid()] = act; } fprintf(file, "}\n"); model_free(thread_array); @@ -2792,9 +2821,11 @@ void ModelChecker::print_summary() const #endif model_print("Execution %d:", stats.num_total); - if (isfeasibleprefix()) + if (isfeasibleprefix()) { + if (scheduler->all_threads_sleeping()) + model_print(" SLEEP-SET REDUNDANT"); model_print("\n"); - else + } else print_infeasibility(" INFEASIBLE"); print_list(action_trace); model_print("\n");