mo_graph(new CycleGraph()),
failed_promise(false),
too_many_reads(false),
- asserted(false)
+ asserted(false),
+ bad_synchronization(false)
{
/* Allocate this "size" on the snapshotting heap */
priv = (struct model_snapshot_members *)calloc(1, sizeof(*priv));
node_stack->reset_execution();
failed_promise = false;
too_many_reads = false;
+ bad_synchronization = false;
reset_asserted();
snapshotObject->backTrackBeforeStep(0);
}
bool r_status = false;
if (!second_part_of_rmw) {
- check_recency(curr);
+ check_recency(curr, reads_from);
r_status = r_modification_order(curr, reads_from);
}
if (curr->is_rmwc() || curr->is_rmw()) {
newcurr = process_rmw(curr);
delete curr;
- compute_promises(newcurr);
+
+ if (newcurr->is_rmw())
+ compute_promises(newcurr);
return newcurr;
}
delete curr;
/* If we have diverged, we need to reset the clock vector. */
- if (diverge == NULL)
+ if (diverge == NULL) {
newcurr->create_cv(get_parent_action(newcurr->get_tid()));
+ }
} else {
newcurr = curr;
/*
if (w_modification_order(act))
updated = true;
}
+ mo_graph->commitChanges();
if (updated)
work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
/** @return whether the current partial trace is feasible. */
bool ModelChecker::isfeasible() {
+ if (DBG_ENABLED() && mo_graph->checkForRMWViolation())
+ DEBUG("Infeasible: RMW violation\n");
+
return !mo_graph->checkForRMWViolation() && isfeasibleotherthanRMW();
}
DEBUG("Infeasible: failed promise\n");
if (too_many_reads)
DEBUG("Infeasible: too many reads\n");
+ if (bad_synchronization)
+ DEBUG("Infeasible: bad synchronization ordering\n");
if (promises_expired())
DEBUG("Infeasible: promises expired\n");
}
- return !mo_graph->checkForCycles() && !failed_promise && !too_many_reads && !promises_expired();
+ return !mo_graph->checkForCycles() && !failed_promise && !too_many_reads && !bad_synchronization && !promises_expired();
}
/** Returns whether the current completed trace is feasible. */
*
* If so, we decide that the execution is no longer feasible.
*/
-void ModelChecker::check_recency(ModelAction *curr) {
+void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) {
if (params.maxreads != 0) {
+
if (curr->get_node()->get_read_from_size() <= 1)
return;
-
//Must make sure that execution is currently feasible... We could
//accidentally clear by rolling back
if (!isfeasible())
return;
-
std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
int tid = id_to_int(curr->get_tid());
/* Skip checks */
if ((int)thrd_lists->size() <= tid)
return;
-
action_list_t *list = &(*thrd_lists)[tid];
action_list_t::reverse_iterator rit = list->rbegin();
ModelAction *act = *rit;
if (!act->is_read())
return;
- if (act->get_reads_from() != curr->get_reads_from())
+
+ if (act->get_reads_from() != rf)
return;
if (act->get_node()->get_read_from_size() <= 1)
return;
}
-
for (int i = 0; i<curr->get_node()->get_read_from_size(); i++) {
//Get write
const ModelAction * write = curr->get_node()->get_read_from_at(i);
+
//Need a different write
- if (write==curr->get_reads_from())
+ if (write==rf)
continue;
/* Test to see whether this is a feasible write to read from*/
*/
bool ModelChecker::release_seq_head(const ModelAction *rf, rel_heads_list_t *release_heads) const
{
+ /* Only check for release sequences if there are no cycles */
+ if (mo_graph->checkForCycles())
+ return false;
+
while (rf) {
ASSERT(rf->is_write());
complete = release_seq_head(rf, &release_heads);
for (unsigned int i = 0; i < release_heads.size(); i++) {
if (!act->has_synchronized_with(release_heads[i])) {
- updated = true;
- act->synchronize_with(release_heads[i]);
+ if (act->synchronize_with(release_heads[i]))
+ updated = true;
+ else
+ set_bad_synchronization();
}
}
if (read->is_rmw()) {
mo_graph->addRMWEdge(write, read);
}
-
- /* Only read (and check for release sequences) if this
- * write (esp. RMW) doesn't create cycles */
- if (!mo_graph->checkForCycles())
- read->read_from(write);
-
+ read->read_from(write);
//First fix up the modification order for actions that happened
//before the read
r_modification_order(read, write);
//Next fix up the modification order for actions that happened
//after the read.
post_r_modification_order(read, write);
+ //Make sure the promise's value matches the write's value
+ ASSERT(promise->get_value() == write->get_value());
promises->erase(promises->begin() + promise_index);
resolved = true;
priv->nextThread = check_current_action(priv->current_action);
priv->current_action = NULL;
+
if (curr->is_blocked() || curr->is_complete())
scheduler->remove_thread(curr);
} else {