X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=nodestack.cc;h=3db80e8f6b4f8931ad3a238215c4294c86cd9708;hb=9db4729d3e6ab5f3ec5fd8a2560d95026332fecf;hp=b33d24739ca89399ffb363c1ba3bdecd61ca6dc2;hpb=ae7fcd2e5e499f72d9d1530bdc293f4fbc5f0644;p=model-checker.git diff --git a/nodestack.cc b/nodestack.cc index b33d247..3db80e8 100644 --- a/nodestack.cc +++ b/nodestack.cc @@ -4,6 +4,7 @@ #include "action.h" #include "common.h" #include "model.h" +#include "threads.h" /** * @brief Node constructor @@ -31,7 +32,9 @@ Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) may_read_from(), read_from_index(0), future_values(), - future_index(-1) + future_index(-1), + relseq_break_writes(), + relseq_break_index(0) { if (act) { act->set_node(this); @@ -46,7 +49,7 @@ Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) if (prevfi) { *fi=*prevfi; } - if (parent->enabled_array[i]) { + if (parent->enabled_array[i]==THREAD_ENABLED) { fi->enabled_count++; } if (i==currtid) { @@ -55,7 +58,7 @@ Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) } //Do window processing if (prevfairness != NULL) { - if (prevfairness -> parent->enabled_array[i]) + if (prevfairness -> parent->enabled_array[i] == THREAD_ENABLED) fi->enabled_count--; if (i==prevtid) { fi->turns--; @@ -215,15 +218,15 @@ bool Node::read_from_empty() { * Mark the appropriate backtracking information for exploring a thread choice. * @param act The ModelAction to explore */ -void Node::explore_child(ModelAction *act, bool * is_enabled) +void Node::explore_child(ModelAction *act, enabled_type_t * is_enabled) { if ( ! enabled_array ) - enabled_array=(bool *)model_malloc(sizeof(bool)*num_threads); + enabled_array=(enabled_type_t *)model_malloc(sizeof(enabled_type_t)*num_threads); if (is_enabled != NULL) - memcpy(enabled_array, is_enabled, sizeof(bool)*num_threads); + memcpy(enabled_array, is_enabled, sizeof(enabled_type_t)*num_threads); else { for(int i=0;iget_tid()); @@ -264,13 +267,18 @@ thread_id_t Node::get_next_backtrack() bool Node::is_enabled(Thread *t) { int thread_id=id_to_int(t->get_id()); - return thread_id < num_threads && enabled_array[thread_id]; + return thread_id < num_threads && (enabled_array[thread_id] != THREAD_DISABLED); } bool Node::is_enabled(thread_id_t tid) { int thread_id=id_to_int(tid); - return thread_id < num_threads && enabled_array[thread_id]; + return thread_id < num_threads && (enabled_array[thread_id] != THREAD_DISABLED); +} + +bool Node::has_priority(thread_id_t tid) +{ + return fairness[id_to_int(tid)].priority; } /** @@ -325,8 +333,11 @@ const ModelAction * Node::get_read_from() { bool Node::increment_read_from() { DBG(); promises.clear(); - read_from_index++; - return (read_from_index < may_read_from.size()); + if (read_from_index < may_read_from.size()) { + read_from_index++; + return read_from_index < may_read_from.size(); + } + return false; } /** @@ -336,8 +347,63 @@ bool Node::increment_read_from() { bool Node::increment_future_value() { DBG(); promises.clear(); - future_index++; - return (future_index < (int)future_values.size()); + if (future_index < ((int)future_values.size())) { + future_index++; + return (future_index < ((int)future_values.size())); + } + return false; +} + +/** + * Add a write ModelAction to the set of writes that may break the release + * sequence. This is used during replay exploration of pending release + * sequences. This Node must correspond to a release sequence fixup action. + * + * @param write The write that may break the release sequence. NULL means we + * allow the release sequence to synchronize. + */ +void Node::add_relseq_break(const ModelAction *write) +{ + relseq_break_writes.push_back(write); +} + +/** + * Get the write that may break the current pending release sequence, + * according to the replay / divergence pattern. + * + * @return A write that may break the release sequence. If NULL, that means + * the release sequence should not be broken. + */ +const ModelAction * Node::get_relseq_break() +{ + if (relseq_break_index < (int)relseq_break_writes.size()) + return relseq_break_writes[relseq_break_index]; + else + return NULL; +} + +/** + * Increments the index into the relseq_break_writes set to explore the next + * item. + * @return Returns false if we have explored all values. + */ +bool Node::increment_relseq_break() +{ + DBG(); + promises.clear(); + if (relseq_break_index < ((int)relseq_break_writes.size())) { + relseq_break_index++; + return (relseq_break_index < ((int)relseq_break_writes.size())); + } + return false; +} + +/** + * @return True if all writes that may break the release sequence have been + * explored + */ +bool Node::relseq_break_empty() { + return ((relseq_break_index + 1) >= ((int)relseq_break_writes.size())); } void Node::explore(thread_id_t tid) @@ -350,16 +416,18 @@ void Node::explore(thread_id_t tid) explored_children[i] = true; } -NodeStack::NodeStack() - : total_nodes(0) +NodeStack::NodeStack() : + node_list(1, new Node()), + iter(0), + total_nodes(0) { - node_list.push_back(new Node()); total_nodes++; - iter = 0; } NodeStack::~NodeStack() { + for (unsigned int i = 0; i < node_list.size(); i++) + delete node_list[i]; } void NodeStack::print() @@ -377,7 +445,7 @@ void NodeStack::print() /** Note: The is_enabled set contains what actions were enabled when * act was chosen. */ -ModelAction * NodeStack::explore_action(ModelAction *act, bool * is_enabled) +ModelAction * NodeStack::explore_action(ModelAction *act, enabled_type_t * is_enabled) { DBG(); @@ -412,6 +480,8 @@ void NodeStack::pop_restofstack(int numAhead) { /* Diverging from previous execution; clear out remainder of list */ unsigned int it=iter+numAhead; + for(unsigned int i=it;i