From: bdemsky Date: Wed, 12 Jun 2019 22:30:30 +0000 (-0700) Subject: partial edits X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=commitdiff_plain;h=15162a2ac08b0a6b06e5319a7424055f4d12e01c partial edits --- diff --git a/clockvector.cc b/clockvector.cc index 54e8c4a1..c86995bc 100644 --- a/clockvector.cc +++ b/clockvector.cc @@ -16,7 +16,7 @@ * same thread or the parent that created this thread) * @param act is an action with which to update the ClockVector */ -ClockVector::ClockVector(ClockVector *parent, ModelAction *act) +ClockVector::ClockVector(ClockVector *parent, const ModelAction *act) { ASSERT(act); num_threads = int_to_id(act->get_tid()) + 1; diff --git a/clockvector.h b/clockvector.h index 430dc177..962e9ec4 100644 --- a/clockvector.h +++ b/clockvector.h @@ -11,7 +11,7 @@ class ClockVector { public: - ClockVector(ClockVector *parent = NULL, ModelAction *act = NULL); + ClockVector(ClockVector *parent = NULL, const ModelAction *act = NULL); ~ClockVector(); bool merge(const ClockVector *cv); bool synchronized_since(const ModelAction *act) const; diff --git a/cyclegraph.cc b/cyclegraph.cc index 36f64a43..a3e86cf0 100644 --- a/cyclegraph.cc +++ b/cyclegraph.cc @@ -2,13 +2,11 @@ #include "action.h" #include "common.h" #include "threads-model.h" +#include "clockvector.h" /** Initializes a CycleGraph object. */ CycleGraph::CycleGraph() : - discovered(new HashTable(16)), - queue(new ModelVector()), - hasCycles(false), - oldCycles(false) + queue(new SnapVector()) { } @@ -16,7 +14,6 @@ CycleGraph::CycleGraph() : CycleGraph::~CycleGraph() { delete queue; - delete discovered; } /** @@ -62,51 +59,55 @@ CycleNode * CycleGraph::getNode(const ModelAction *action) * @param tonode The edge points to this CycleNode * @return True, if new edge(s) are added; otherwise false */ -bool CycleGraph::addNodeEdge(CycleNode *fromnode, CycleNode *tonode) +void CycleGraph::addNodeEdge(CycleNode *fromnode, CycleNode *tonode) { - if (fromnode->addEdge(tonode)) { - rollbackvector.push_back(fromnode); - if (!hasCycles) - hasCycles = checkReachable(tonode, fromnode); - } else - return false;/* No new edge */ + //quick check whether edge is redundant + if (checkReachable(fromnode, tonode)) + return; + + CycleNode *edgeSrcNode = fromnode; /* - * If the fromnode has a rmwnode that is not the tonode, we should - * follow its RMW chain to add an edge at the end, unless we encounter - * tonode along the way + * If the fromnode has a rmwnode, we should + * follow its RMW chain to add an edge at the end. */ CycleNode *rmwnode = fromnode->getRMW(); if (rmwnode) { - while (rmwnode != tonode && rmwnode->getRMW()) + while (rmwnode->getRMW()) rmwnode = rmwnode->getRMW(); + edgeSrcNode = rmwnode; + } - if (rmwnode != tonode) { - if (rmwnode->addEdge(tonode)) { - if (!hasCycles) - hasCycles = checkReachable(tonode, rmwnode); - - rollbackvector.push_back(rmwnode); + edgeSrcNode->addEdge(tonode); //Add edge to edgeSrcNode + + /* Propagate clock vector changes */ + if (tonode->cv->merge(edgeSrcNode->cv)) { + queue->push_back(edgeSrcNode); + while(!queue->empty()) { + const CycleNode *node = queue->back(); + unsigned int numedges = node->getNumEdges(); + for(unsigned int i = 0;i < numedges;i++) { + CycleNode * enode = node->getEdge(i); + if (enode->cv->merge(node->cv)) + queue->push_back(enode); } } } - return true; } /** * @brief Add an edge between a write and the RMW which reads from it * * Handles special case of a RMW action, where the ModelAction rmw reads from - * the ModelAction/Promise from. The key differences are: + * the ModelAction from. The key differences are: * -# No write can occur in between the @a rmw and @a from actions. * -# Only one RMW action can read from a given write. * - * @param from The edge comes from this ModelAction/Promise + * @param from The edge comes from this ModelAction * @param rmw The edge points to this ModelAction; this action must read from - * the ModelAction/Promise from + * the ModelAction from */ -template -void CycleGraph::addRMWEdge(const T *from, const ModelAction *rmw) +void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction *rmw) { ASSERT(from); ASSERT(rmw); @@ -117,11 +118,7 @@ void CycleGraph::addRMWEdge(const T *from, const ModelAction *rmw) /* We assume that this RMW has no RMW reading from it yet */ ASSERT(!rmwnode->getRMW()); - /* Two RMW actions cannot read from the same write. */ - if (fromnode->setRMW(rmwnode)) - hasCycles = true; - else - rmwrollbackvector.push_back(fromnode); + fromnode->setRMW(rmwnode); /* Transfer all outgoing edges from the from node to the rmw node */ /* This process should not add a cycle because either: @@ -133,15 +130,12 @@ void CycleGraph::addRMWEdge(const T *from, const ModelAction *rmw) for (unsigned int i = 0;i < fromnode->getNumEdges();i++) { CycleNode *tonode = fromnode->getEdge(i); if (tonode != rmwnode) { - if (rmwnode->addEdge(tonode)) - rollbackvector.push_back(rmwnode); + rmwnode->addEdge(tonode); } } addNodeEdge(fromnode, rmwnode); } -/* Instantiate two forms of CycleGraph::addRMWEdge */ -template void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction *rmw); /** * @brief Adds an edge between objects @@ -156,8 +150,8 @@ template void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction * @param from The edge comes from this object, of type U * @return True, if new edge(s) are added; otherwise false */ -template -bool CycleGraph::addEdge(const T *from, const U *to) + +void CycleGraph::addEdge(const ModelAction *from, const ModelAction *to) { ASSERT(from); ASSERT(to); @@ -165,10 +159,8 @@ bool CycleGraph::addEdge(const T *from, const U *to) CycleNode *fromnode = getNode(from); CycleNode *tonode = getNode(to); - return addNodeEdge(fromnode, tonode); + addNodeEdge(fromnode, tonode); } -/* Instantiate four forms of CycleGraph::addEdge */ -template bool CycleGraph::addEdge(const ModelAction *from, const ModelAction *to); #if SUPPORT_MOD_ORDER_DUMP @@ -196,16 +188,13 @@ void CycleGraph::dot_print_node(FILE *file, const ModelAction *act) print_node(file, getNode(act), 1); } -template -void CycleGraph::dot_print_edge(FILE *file, const T *from, const U *to, const char *prop) +void CycleGraph::dot_print_edge(FILE *file, const ModelAction *from, const ModelAction *to, const char *prop) { CycleNode *fromnode = getNode(from); CycleNode *tonode = getNode(to); print_edge(file, fromnode, tonode, prop); } -/* Instantiate two forms of CycleGraph::dot_print_edge */ -template void CycleGraph::dot_print_edge(FILE *file, const ModelAction *from, const ModelAction *to, const char *prop); void CycleGraph::dumpNodes(FILE *file) const { @@ -240,34 +229,16 @@ void CycleGraph::dumpGraphToFile(const char *filename) const */ bool CycleGraph::checkReachable(const CycleNode *from, const CycleNode *to) const { - discovered->reset(); - queue->clear(); - queue->push_back(from); - discovered->put(from, from); - while (!queue->empty()) { - const CycleNode *node = queue->back(); - queue->pop_back(); - if (node == to) - return true; - for (unsigned int i = 0;i < node->getNumEdges();i++) { - CycleNode *next = node->getEdge(i); - if (!discovered->contains(next)) { - discovered->put(next, next); - queue->push_back(next); - } - } - } - return false; + return to->cv->synchronized_since(from->action); } /** - * Checks whether one ModelAction/Promise can reach another ModelAction/Promise - * @param from The ModelAction or Promise from which to begin exploration - * @param to The ModelAction or Promise to reach + * Checks whether one ModelAction can reach another ModelAction + * @param from The ModelAction from which to begin exploration + * @param to The ModelAction to reach * @return True, @a from can reach @a to; otherwise, false */ -template -bool CycleGraph::checkReachable(const T *from, const U *to) const +bool CycleGraph::checkReachable(const ModelAction *from, const ModelAction *to) const { CycleNode *fromnode = getNode_noCreate(from); CycleNode *tonode = getNode_noCreate(to); @@ -277,45 +248,6 @@ bool CycleGraph::checkReachable(const T *from, const U *to) const return checkReachable(fromnode, tonode); } -/* Instantiate four forms of CycleGraph::checkReachable */ -template bool CycleGraph::checkReachable(const ModelAction *from, - const ModelAction *to) const; - -/** @brief Begin a new sequence of graph additions which can be rolled back */ -void CycleGraph::startChanges() -{ - ASSERT(rollbackvector.empty()); - ASSERT(rmwrollbackvector.empty()); - ASSERT(oldCycles == hasCycles); -} - -/** Commit changes to the cyclegraph. */ -void CycleGraph::commitChanges() -{ - rollbackvector.clear(); - rmwrollbackvector.clear(); - oldCycles = hasCycles; -} - -/** Rollback changes to the previous commit. */ -void CycleGraph::rollbackChanges() -{ - for (unsigned int i = 0;i < rollbackvector.size();i++) - rollbackvector[i]->removeEdge(); - - for (unsigned int i = 0;i < rmwrollbackvector.size();i++) - rmwrollbackvector[i]->clearRMW(); - - hasCycles = oldCycles; - rollbackvector.clear(); - rmwrollbackvector.clear(); -} - -/** @returns whether a CycleGraph contains cycles. */ -bool CycleGraph::checkForCycles() const -{ - return hasCycles; -} /** * @brief Constructor for a CycleNode @@ -323,7 +255,8 @@ bool CycleGraph::checkForCycles() const */ CycleNode::CycleNode(const ModelAction *act) : action(act), - hasRMW(NULL) + hasRMW(NULL), + cv(new ClockVector(NULL, act)) { } @@ -342,24 +275,6 @@ unsigned int CycleNode::getNumEdges() const return edges.size(); } -/** - * @brief Remove an element from a vector - * @param v The vector - * @param n The element to remove - * @return True if the element was found; false otherwise - */ -template -static bool vector_remove_node(SnapVector& v, const T n) -{ - for (unsigned int i = 0;i < v.size();i++) { - if (v[i] == n) { - v.erase(v.begin() + i); - return true; - } - } - return false; -} - /** * @brief Remove a (forward) edge from this CycleNode * @return The CycleNode which was popped, if one exists; otherwise NULL @@ -379,13 +294,12 @@ CycleNode * CycleNode::removeEdge() * @param node The node to which we add a directed edge * @return True if this edge is a new edge; false otherwise */ -bool CycleNode::addEdge(CycleNode *node) +void CycleNode::addEdge(CycleNode *node) { for (unsigned int i = 0;i < edges.size();i++) if (edges[i] == node) - return false; + return; edges.push_back(node); - return true; } /** @returns the RMW CycleNode that reads from the current CycleNode */ diff --git a/cyclegraph.h b/cyclegraph.h index fefe3440..624ce885 100644 --- a/cyclegraph.h +++ b/cyclegraph.h @@ -23,58 +23,33 @@ class CycleGraph { public: CycleGraph(); ~CycleGraph(); + void addEdge(const ModelAction *from, const ModelAction *to); + void addRMWEdge(const ModelAction *from, const ModelAction *rmw); + bool checkReachable(const ModelAction *from, const ModelAction *to) const; - template - bool addEdge(const T *from, const U *to); - - template - void addRMWEdge(const T *from, const ModelAction *rmw); - - bool checkForCycles() const; - - template - bool checkReachable(const T *from, const U *to) const; - - void startChanges(); - void commitChanges(); - void rollbackChanges(); #if SUPPORT_MOD_ORDER_DUMP void dumpNodes(FILE *file) const; void dumpGraphToFile(const char *filename) const; - void dot_print_node(FILE *file, const ModelAction *act); - template - void dot_print_edge(FILE *file, const T *from, const U *to, const char *prop); + void dot_print_edge(FILE *file, const ModelAction *from, const ModelAction *to, const char *prop); #endif - CycleNode * getNode_noCreate(const ModelAction *act) const; + CycleNode * getNode_noCreate(const ModelAction *act) const; SNAPSHOTALLOC private: - bool addNodeEdge(CycleNode *fromnode, CycleNode *tonode); + void addNodeEdge(CycleNode *fromnode, CycleNode *tonode); void putNode(const ModelAction *act, CycleNode *node); CycleNode * getNode(const ModelAction *act); - bool mergeNodes(CycleNode *node1, CycleNode *node2); - - HashTable *discovered; - ModelVector * queue; - /** @brief A table for mapping ModelActions to CycleNodes */ HashTable actionToNode; + SnapVector * queue; #if SUPPORT_MOD_ORDER_DUMP SnapVector nodeList; #endif bool checkReachable(const CycleNode *from, const CycleNode *to) const; - - /** @brief A flag: true if this graph contains cycles */ - bool hasCycles; - /** @brief The previous value of CycleGraph::hasCycles, for rollback */ - bool oldCycles; - - SnapVector rollbackvector; - SnapVector rmwrollbackvector; }; /** @@ -83,11 +58,10 @@ private: class CycleNode { public: CycleNode(const ModelAction *act); - bool addEdge(CycleNode *node); + void addEdge(CycleNode *node); CycleNode * getEdge(unsigned int i) const; unsigned int getNumEdges() const; CycleNode * removeEdge(); - bool setRMW(CycleNode *); CycleNode * getRMW() const; void clearRMW() { hasRMW = NULL; } @@ -104,6 +78,10 @@ private: /** Pointer to a RMW node that reads from this node, or NULL, if none * exists */ CycleNode *hasRMW; + + /** ClockVector for this Node. */ + ClockVector *cv; + friend class CycleGraph; }; #endif /* __CYCLEGRAPH_H__ */ diff --git a/execution.cc b/execution.cc index e253ab0f..b62f6944 100644 --- a/execution.cc +++ b/execution.cc @@ -28,7 +28,6 @@ struct model_snapshot_members { used_sequence_numbers(0), bugs(), bad_synchronization(false), - bad_sc_read(false), asserted(false) { } @@ -43,16 +42,13 @@ struct model_snapshot_members { SnapVector bugs; /** @brief Incorrectly-ordered synchronization was made */ bool bad_synchronization; - bool bad_sc_read; bool asserted; SNAPSHOTALLOC }; /** @brief Constructor */ -ModelExecution::ModelExecution(ModelChecker *m, - Scheduler *scheduler, - NodeStack *node_stack) : +ModelExecution::ModelExecution(ModelChecker *m, Scheduler *scheduler, NodeStack *node_stack) : model(m), params(NULL), scheduler(scheduler), @@ -190,13 +186,6 @@ void ModelExecution::set_bad_synchronization() priv->bad_synchronization = true; } -/** @brief Alert the model-checker that an incorrectly-ordered - * synchronization was made */ -void ModelExecution::set_bad_sc_read() -{ - priv->bad_sc_read = true; -} - bool ModelExecution::assert_bug(const char *msg) { priv->bugs.push_back(new bug_message(msg)); @@ -283,7 +272,7 @@ bool ModelExecution::is_complete_execution() const * @param rf_set is the set of model actions we can possibly read from * @return True if processing this read updates the mo_graph. */ -bool ModelExecution::process_read(ModelAction *curr, ModelVector * rf_set) +bool ModelExecution::process_read(ModelAction *curr, SnapVector * rf_set) { while(true) { @@ -294,7 +283,7 @@ bool ModelExecution::process_read(ModelAction *curr, ModelVector ASSERT(rf); mo_graph->startChanges(); - bool updated = r_modification_order(curr, rf); + r_modification_order(curr, rf); if (!is_infeasible()) { read_from(curr, rf); mo_graph->commitChanges(); @@ -696,7 +685,7 @@ ModelAction * ModelExecution::check_current_action(ModelAction *curr) if (!second_part_of_rmw) add_action_to_lists(curr); - ModelVector * rf_set = NULL; + SnapVector * rf_set = NULL; /* Build may_read_from set for newly-created actions */ if (newly_explored && curr->is_read()) rf_set = build_may_read_from(curr); @@ -745,8 +734,6 @@ void ModelExecution::print_infeasibility(const char *prefix) const ptr += sprintf(ptr, "[mo cycle]"); if (priv->bad_synchronization) ptr += sprintf(ptr, "[bad sw ordering]"); - if (priv->bad_sc_read) - ptr += sprintf(ptr, "[bad sc read]"); if (ptr != buf) model_print("%s: %s", prefix ? prefix : "Infeasible", buf); } @@ -760,8 +747,7 @@ void ModelExecution::print_infeasibility(const char *prefix) const bool ModelExecution::is_infeasible() const { return mo_graph->checkForCycles() || - priv->bad_synchronization || - priv->bad_sc_read; + priv->bad_synchronization; } /** Close out a RMWR by converting previous RMWR into a RMW or READ. */ @@ -791,12 +777,11 @@ ModelAction * ModelExecution::process_rmw(ModelAction *act) { * @param rf The ModelAction or Promise that curr reads from. Must be a write. * @return True if modification order edges were added; false otherwise */ -template -bool ModelExecution::r_modification_order(ModelAction *curr, const rf_type *rf) + +bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf, SnapVector * priorset) { SnapVector *thrd_lists = obj_thrd_map.get(curr->get_location()); unsigned int i; - bool added = false; ASSERT(curr->is_read()); /* Last SC fence in the current thread */ @@ -838,20 +823,26 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const rf_type *rf) /* C++, Section 29.3 statement 5 */ if (curr->is_seqcst() && last_sc_fence_thread_local && *act < *last_sc_fence_thread_local) { - added = mo_graph->addEdge(act, rf) || added; + if (mo_graph->checkReachable(rf, act)) + return false; + priorset->add(act); break; } /* C++, Section 29.3 statement 4 */ else if (act->is_seqcst() && last_sc_fence_local && *act < *last_sc_fence_local) { - added = mo_graph->addEdge(act, rf) || added; - break; + if (mo_graph->checkReachable(rf, act)) + return false; + priorset->add(act); + break; } /* C++, Section 29.3 statement 6 */ else if (last_sc_fence_thread_before && *act < *last_sc_fence_thread_before) { - added = mo_graph->addEdge(act, rf) || added; - break; + if (mo_graph->checkReachable(rf, act)) + return false; + priorset->add(act); + break; } } @@ -861,18 +852,22 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const rf_type *rf) */ if (act->happens_before(curr)) { if (act->is_write()) { - added = mo_graph->addEdge(act, rf) || added; + if (mo_graph->checkReachable(rf, act)) + return false; + priorset->add(act); } else { const ModelAction *prevrf = act->get_reads_from(); - if (!prevrf->equals(rf)) - added = mo_graph->addEdge(prevrf, rf) || added; + if (!prevrf->equals(rf)) { + if (mo_graph->checkReachable(rf, prevrf)) + return false; + priorset->add(prevrf); + } } break; } } } - - return added; + return true; } /** @@ -899,11 +894,10 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const rf_type *rf) * value. If NULL, then don't record any future values. * @return True if modification order edges were added; false otherwise */ -bool ModelExecution::w_modification_order(ModelAction *curr) +void ModelExecution::w_modification_order(ModelAction *curr) { SnapVector *thrd_lists = obj_thrd_map.get(curr->get_location()); unsigned int i; - bool added = false; ASSERT(curr->is_write()); if (curr->is_seqcst()) { @@ -911,7 +905,7 @@ bool ModelExecution::w_modification_order(ModelAction *curr) so we are initialized. */ ModelAction *last_seq_cst = get_last_seq_cst_write(curr); if (last_seq_cst != NULL) { - added = mo_graph->addEdge(last_seq_cst, curr) || added; + mo_graph->addEdge(last_seq_cst, curr); } } @@ -954,7 +948,7 @@ bool ModelExecution::w_modification_order(ModelAction *curr) /* C++, Section 29.3 statement 7 */ if (last_sc_fence_thread_before && act->is_write() && *act < *last_sc_fence_thread_before) { - added = mo_graph->addEdge(act, curr) || added; + mo_graph->addEdge(act, curr); break; } @@ -970,10 +964,10 @@ bool ModelExecution::w_modification_order(ModelAction *curr) * readfrom(act) --mo--> act */ if (act->is_write()) - added = mo_graph->addEdge(act, curr) || added; + mo_graph->addEdge(act, curr); else if (act->is_read()) { //if previous read accessed a null, just keep going - added = mo_graph->addEdge(act->get_reads_from(), curr) || added; + mo_graph->addEdge(act->get_reads_from(), curr); } break; } else if (act->is_read() && !act->could_synchronize_with(curr) && @@ -994,8 +988,6 @@ bool ModelExecution::w_modification_order(ModelAction *curr) } } } - - return added; } /** @@ -1327,7 +1319,7 @@ bool valequals(uint64_t val1, uint64_t val2, int size) { * @param curr is the current ModelAction that we are exploring; it must be a * 'read' operation. */ -ModelVector * ModelExecution::build_may_read_from(ModelAction *curr) +SnapVector * ModelExecution::build_may_read_from(ModelAction *curr) { SnapVector *thrd_lists = obj_thrd_map.get(curr->get_location()); unsigned int i; @@ -1338,7 +1330,8 @@ ModelVector * ModelExecution::build_may_read_from(ModelAction *c if (curr->is_seqcst()) last_sc_write = get_last_seq_cst_write(curr); - ModelVector * rf_set = new ModelVector(); + SnapVector * rf_set = new SnapVector(); + SnapVector * priorset = new SnapVector(); /* Iterate over all threads */ for (i = 0;i < thrd_lists->size();i++) { diff --git a/execution.h b/execution.h index 950d6335..40cd3ac0 100644 --- a/execution.h +++ b/execution.h @@ -120,7 +120,6 @@ private: bool mo_may_allow(const ModelAction *writer, const ModelAction *reader); void set_bad_synchronization(); - void set_bad_sc_read(); bool should_wake_up(const ModelAction *curr, const Thread *thread) const; void wake_up_sleeping_actions(ModelAction *curr); modelclock_t get_next_seq_num(); @@ -128,7 +127,7 @@ private: bool next_execution(); ModelAction * check_current_action(ModelAction *curr); bool initialize_curr_action(ModelAction **curr); - bool process_read(ModelAction *curr, ModelVector * rf_set); + bool process_read(ModelAction *curr, SnapVector * rf_set); bool process_write(ModelAction *curr); bool process_fence(ModelAction *curr); bool process_mutex(ModelAction *curr); @@ -142,13 +141,11 @@ private: ModelAction * get_last_seq_cst_write(ModelAction *curr) const; ModelAction * get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const; ModelAction * get_last_unlock(ModelAction *curr) const; - ModelVector * build_may_read_from(ModelAction *curr); + SnapVector * build_may_read_from(ModelAction *curr); ModelAction * process_rmw(ModelAction *curr); - template - bool r_modification_order(ModelAction *curr, const rf_type *rf); - - bool w_modification_order(ModelAction *curr); + bool r_modification_order(ModelAction *curr, const ModelAction *rf, SnapVector *priorset); + void w_modification_order(ModelAction *curr); void get_release_seq_heads(ModelAction *acquire, ModelAction *read, rel_heads_list_t *release_heads); bool release_seq_heads(const ModelAction *rf, rel_heads_list_t *release_heads) const; ModelAction * get_uninitialized_action(const ModelAction *curr) const; diff --git a/fuzzer.cc b/fuzzer.cc index d3d9d2c5..9ad61c3c 100644 --- a/fuzzer.cc +++ b/fuzzer.cc @@ -3,7 +3,7 @@ #include "threads-model.h" #include "model.h" -int Fuzzer::selectWrite(ModelAction *read, ModelVector * rf_set) { +int Fuzzer::selectWrite(ModelAction *read, SnapVector * rf_set) { int random_index = random() % rf_set->size(); return random_index; } diff --git a/fuzzer.h b/fuzzer.h index 3a843510..6cf1efba 100644 --- a/fuzzer.h +++ b/fuzzer.h @@ -7,7 +7,7 @@ class Fuzzer { public: Fuzzer() {} - int selectWrite(ModelAction *read, ModelVector* rf_set); + int selectWrite(ModelAction *read, SnapVector* rf_set); Thread * selectThread(Node *n, int * threadlist, int numthreads); Thread * selectNotify(action_list_t * waiters); MEMALLOC