X-Git-Url: http://plrg.eecs.uci.edu/git/?p=model-checker.git;a=blobdiff_plain;f=nodestack.cc;h=06259b91c54964ba4c094af50347c11a23d9cb41;hp=a73765320dac47e97428390fe37bc3b06ba10483;hb=fe7b400edb33255770fb47ad520afbd05d13a231;hpb=f4d77c40b4029cdc18f4aaa5a4e01dfbcfca5f7b diff --git a/nodestack.cc b/nodestack.cc index a737653..06259b9 100644 --- a/nodestack.cc +++ b/nodestack.cc @@ -4,7 +4,7 @@ #include "action.h" #include "common.h" #include "model.h" -#include "threads.h" +#include "threads-model.h" /** * @brief Node constructor @@ -32,7 +32,11 @@ 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), + misc_index(0), + misc_max(0) { if (act) { act->set_node(this); @@ -47,7 +51,7 @@ Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) if (prevfi) { *fi=*prevfi; } - if (parent->enabled_array[i]) { + if (parent->is_enabled(int_to_id(i))) { fi->enabled_count++; } if (i==currtid) { @@ -56,7 +60,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->is_enabled(int_to_id(i))) fi->enabled_count--; if (i==prevtid) { fi->turns--; @@ -149,6 +153,24 @@ bool Node::promise_empty() { return true; } + +void Node::set_misc_max(int i) { + misc_max=i; +} + +int Node::get_misc() { + return misc_index; +} + +bool Node::increment_misc() { + return (misc_index=misc_max; +} + + /** * Adds a value from a weakly ordered future write to backtrack to. * @param value is the value to backtrack to. @@ -216,15 +238,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()); @@ -265,13 +287,13 @@ 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) @@ -294,12 +316,12 @@ void Node::add_read_from(const ModelAction *act) * @return The first element in future_values */ uint64_t Node::get_future_value() { - ASSERT(future_index<((int)future_values.size())); + ASSERT(future_index >= 0 && future_index<((int)future_values.size())); return future_values[future_index].value; } modelclock_t Node::get_future_value_expiration() { - ASSERT(future_index<((int)future_values.size())); + ASSERT(future_index >= 0 && future_index<((int)future_values.size())); return future_values[future_index].expiration; } @@ -352,6 +374,58 @@ bool Node::increment_future_value() { 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) { int i = id_to_int(tid); @@ -362,16 +436,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() @@ -389,7 +465,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();