Now we need to use the cyclegraph to eliminate bad executions...
next = node_stack->get_next()->get_action();
if (next == diverge) {
- Node *node = next->get_node()->get_parent();
-
+ Node *nextnode = next->get_node();
/* Reached divergence point */
+ if (nextnode->increment_read_from()) {
+ /* The next node will read from a different value */
+ tid = next->get_tid();
+ node_stack->pop_restofstack(2);
+ } else {
+ /* Make a different thread execute for next step */
+ Node *node = nextnode->get_parent();
+ tid = node->get_next_backtrack();
+ node_stack->pop_restofstack(1);
+ }
DEBUG("*** Divergence point ***\n");
- tid = node->get_next_backtrack();
diverge = NULL;
- node_stack->pop_restofstack();
} else {
tid = next->get_tid();
}
void ModelChecker::check_current_action(void)
{
- Node *currnode;
-
ModelAction *curr = this->current_action;
ModelAction *tmp;
current_action = NULL;
nextThread = get_next_replay_thread();
- currnode = curr->get_node()->get_parent();
+ Node *currnode = curr->get_node();
+ Node *parnode = currnode->get_parent();
- if (!currnode->backtrack_empty())
+ if (!parnode->backtrack_empty()||!currnode->readsfrom_empty())
if (!next_backtrack || *curr > *next_backtrack)
next_backtrack = curr;
Thread *th = get_thread(curr->get_tid());
uint64_t value = VALUE_NONE;
if (curr->is_read()) {
- const ModelAction *reads_from = curr->get_node()->get_next_read_from();
+ const ModelAction *reads_from = curr->get_node()->get_read_from();
value = reads_from->get_value();
/* Assign reads_from, perform release/acquire synchronization */
curr->read_from(reads_from);
{
std::vector<action_list_t> *thrd_lists = &(*obj_thrd_map)[curr->get_location()];
unsigned int i;
-
ASSERT(curr->is_read());
ModelAction *last_seq_cst = NULL;
if (!act->is_write())
continue;
- /* Don't consider more than one seq_cst write */
- if (!act->is_seqcst() || act == last_seq_cst) {
+ /* Don't consider more than one seq_cst write if we are a seq_cst read. */
+ if (!act->is_seqcst() || !curr->is_seqcst() || act == last_seq_cst) {
DEBUG("Adding action to may_read_from:\n");
if (DBG_ENABLED()) {
act->print();
explored_children(num_threads),
backtrack(num_threads),
numBacktracks(0),
- may_read_from()
+ may_read_from(),
+ read_from_index(0)
{
if (act)
act->set_node(this);
*/
bool Node::backtrack_empty()
{
- return numBacktracks == 0;
+ return (numBacktracks == 0);
+}
+
+bool Node::readsfrom_empty() {
+ return ((read_from_index+1)>=may_read_from.size());
}
/**
* may remove elements from may_read_from
* @return The first element in may_read_from
*/
-const ModelAction * Node::get_next_read_from() {
- const ModelAction *act;
- ASSERT(!may_read_from.empty());
- act = may_read_from.front();
- /* TODO: perform reads_from replay properly */
- /* may_read_from.pop_front(); */
- return act;
+const ModelAction * Node::get_read_from() {
+ ASSERT(read_from_index<may_read_from.size());
+ return may_read_from[read_from_index];
+}
+
+bool Node::increment_read_from() {
+ read_from_index++;
+ return (read_from_index<may_read_from.size());
}
void Node::explore(thread_id_t tid)
}
-void NodeStack::pop_restofstack()
+void NodeStack::pop_restofstack(int numAhead)
{
/* Diverging from previous execution; clear out remainder of list */
node_list_t::iterator it = iter;
- it++;
+ while (numAhead--)
+ it++;
clear_node_list(&node_list, it, node_list.end());
}
class ModelAction;
-typedef std::list< const ModelAction *, MyAlloc< const ModelAction * > > readfrom_set_t;
+typedef std::vector< const ModelAction *, MyAlloc< const ModelAction * > > readfrom_set_t;
/**
* @brief A single node in a NodeStack
bool has_been_explored(thread_id_t tid);
/* return true = backtrack set is empty */
bool backtrack_empty();
+ bool readsfrom_empty();
void explore_child(ModelAction *act);
/* return false = thread was already in backtrack */
bool set_backtrack(thread_id_t id);
Node * get_parent() const { return parent; }
void add_read_from(const ModelAction *act);
- const ModelAction * get_next_read_from();
+ const ModelAction * get_read_from();
+ bool increment_read_from();
void print();
void print_may_read_from();
/** The set of ModelActions that this the action at this Node may read
* from. Only meaningful if this Node represents a 'read' action. */
readfrom_set_t may_read_from;
+ unsigned int read_from_index;
};
typedef std::list< Node *, MyAlloc< Node * > > node_list_t;
Node * get_head();
Node * get_next();
void reset_execution();
- void pop_restofstack();
+ void pop_restofstack(int numAhead);
int get_total_nodes() { return total_nodes; }
void print();