mo_graph(new CycleGraph()),
failed_promise(false),
too_many_reads(false),
- asserted(false)
+ asserted(false),
+ rmw_cycle(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;
+ rmw_cycle=false;
reset_asserted();
snapshotObject->backTrackBeforeStep(0);
}
return next;
}
+
+/** Checks whether making the ModelAction read read_from the
+ ModelAction write will introduce a cycle in the reads_from
+ relation.
+
+@return true if making it read from will be fine, false otherwise.
+
+*/
+
+bool ModelChecker::ensure_rmw_acyclic(const ModelAction * read, const ModelAction *write) {
+ if (!read->is_rmw())
+ return true;
+ if (!write->is_rmw())
+ return true;
+ while(write!=NULL) {
+ if (write==read) {
+ rmw_cycle=true;
+ return false;
+ }
+ write=write->get_reads_from();
+ }
+ return true;
+}
+
/**
* Processes a read or rmw model action.
* @param curr is the read model action to process.
value = reads_from->get_value();
/* Assign reads_from, perform release/acquire synchronization */
- curr->read_from(reads_from);
+ if (ensure_rmw_acyclic(curr, reads_from))
+ curr->read_from(reads_from);
if (!second_part_of_rmw) {
check_recency(curr,false);
}
return !mo_graph->checkForRMWViolation() && isfeasibleotherthanRMW();
}
-/** @returns whether the current partial trace is feasible. */
+/** @returns whether the current partial trace is feasible other than
+ * multiple RMW reading from the same store. */
bool ModelChecker::isfeasibleotherthanRMW() {
- return !mo_graph->checkForCycles() && !failed_promise && !too_many_reads && !promises_expired();
+ return !mo_graph->checkForCycles() && !failed_promise && !too_many_reads && !rmw_cycle && !promises_expired();
}
/** Returns whether the current completed trace is feasible. */
Promise *promise = (*promises)[promise_index];
if (write->get_node()->get_promise(i)) {
ModelAction *read = promise->get_action();
- read->read_from(write);
+ if (ensure_rmw_acyclic(read, write))
+ read->read_from(write);
if (read->is_rmw()) {
mo_graph->addRMWEdge(write, read);
}
return resolved;
}
+
+
/**
* Compute the set of promises that could potentially be satisfied by this
* action. Note that the set computation actually appears in the Node, not in
/** The scheduler to use: tracks the running/ready Threads */
Scheduler *scheduler;
+ bool ensure_rmw_acyclic(const ModelAction * read, const ModelAction *write);
+
+
bool thin_air_constraint_may_allow(const ModelAction * writer, const ModelAction *reader);
bool has_asserted() {return asserted;}
void reset_asserted() {asserted=false;}
bool failed_promise;
bool too_many_reads;
bool asserted;
+ bool rmw_cycle;
};
extern ModelChecker *model;