cyclegraph: propagate RMW atomicity edges down the chain
[model-checker.git] / cyclegraph.cc
index e96549ff1fddcace369f57102572edf2c6bf9c32..26ea215d434921f2b27fd69e07ef18d1e6029f54 100644 (file)
@@ -8,7 +8,7 @@
 /** Initializes a CycleGraph object. */
 CycleGraph::CycleGraph() :
        discovered(new HashTable<const CycleNode *, const CycleNode *, uintptr_t, 4, model_malloc, model_calloc, model_free>(16)),
-       queue(new std::vector< const CycleNode *, ModelAlloc<const CycleNode *> >()),
+       queue(new ModelVector<const CycleNode *>()),
        hasCycles(false),
        oldCycles(false)
 {
@@ -198,29 +198,33 @@ bool CycleGraph::mergeNodes(CycleNode *w_node, CycleNode *p_node)
  */
 bool CycleGraph::addNodeEdge(CycleNode *fromnode, CycleNode *tonode)
 {
-       bool added;
-
-       if ((added = fromnode->addEdge(tonode))) {
+       if (fromnode->addEdge(tonode)) {
                rollbackvector.push_back(fromnode);
                if (!hasCycles)
                        hasCycles = checkReachable(tonode, fromnode);
-       }
+       } else
+               return false; /* No new edge */
 
        /*
-        * If the fromnode has a rmwnode that is not the tonode, we should add
-        * an edge between its rmwnode and the tonode
+        * 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
         */
        CycleNode *rmwnode = fromnode->getRMW();
-       if (rmwnode && rmwnode != tonode) {
-               if (rmwnode->addEdge(tonode)) {
-                       if (!hasCycles)
-                               hasCycles = checkReachable(tonode, rmwnode);
+       if (rmwnode) {
+               while (rmwnode != tonode && rmwnode->getRMW())
+                       rmwnode = rmwnode->getRMW();
 
-                       rollbackvector.push_back(rmwnode);
-                       added = true;
+               if (rmwnode != tonode) {
+                       if (rmwnode->addEdge(tonode)) {
+                               if (!hasCycles)
+                                       hasCycles = checkReachable(tonode, rmwnode);
+
+                               rollbackvector.push_back(rmwnode);
+                       }
                }
        }
-       return added;
+       return true;
 }
 
 /**
@@ -244,6 +248,9 @@ void CycleGraph::addRMWEdge(const T *from, const ModelAction *rmw)
        CycleNode *fromnode = getNode(from);
        CycleNode *rmwnode = getNode(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;
@@ -554,7 +561,7 @@ unsigned int CycleNode::getNumBackEdges() const
  * @return True if the element was found; false otherwise
  */
 template <typename T>
-static bool vector_remove_node(std::vector<T, SnapshotAlloc<T> >& v, const T n)
+static bool vector_remove_node(SnapVector<T>& v, const T n)
 {
        for (unsigned int i = 0; i < v.size(); i++) {
                if (v[i] == n) {