[compiler-rt] r203902 - [sanitizer] in bitset-based deadlock detector collect edge's stack trace when an edge is added to the graph (in following CLs these stack traces will be added to the report)

Kostya Serebryany kcc at google.com
Fri Mar 14 00:09:01 PDT 2014


Author: kcc
Date: Fri Mar 14 02:09:01 2014
New Revision: 203902

URL: http://llvm.org/viewvc/llvm-project?rev=203902&view=rev
Log:
[sanitizer] in bitset-based deadlock detector collect edge's stack trace when an edge is added to the graph (in following CLs these stack traces will be added to the report)

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_bvgraph.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_bvgraph.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_bvgraph.h?rev=203902&r1=203901&r2=203902&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_bvgraph.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_bvgraph.h Fri Mar 14 02:09:01 2014
@@ -47,12 +47,16 @@ class BVGraph {
   }
 
   // Returns true if at least one new edge was added.
-  bool addEdges(const BV &from, uptr to) {
-    bool res = false;
+  uptr addEdges(const BV &from, uptr to, uptr added_edges[],
+                uptr max_added_edges) {
+    uptr res = 0;
     t1.copyFrom(from);
-    while (!t1.empty())
-      if (v[t1.getAndClearFirstOne()].setBit(to))
-        res = true;
+    while (!t1.empty()) {
+      uptr node = t1.getAndClearFirstOne();
+      if (v[node].setBit(to))
+        if (res < max_added_edges)
+          added_edges[res++] = node;
+    }
     return res;
   }
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h?rev=203902&r1=203901&r2=203902&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h Fri Mar 14 02:09:01 2014
@@ -112,6 +112,7 @@ class DeadlockDetector {
     available_nodes_.clear();
     recycled_nodes_.clear();
     g_.clear();
+    n_edges_ = 0;
   }
 
   // Allocate new deadlock detector node.
@@ -164,21 +165,49 @@ class DeadlockDetector {
     return g_.isReachable(cur_idx, dtls->getLocks(current_epoch_));
   }
 
-  // Returns true if a new edge has been added to the graph.
-  // Should be called before after the lock is acquired.
-  bool onLockAfter(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
+  // Add cur_node to the set of locks held currently by dtls.
+  void onLockAfter(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
     ensureCurrentEpoch(dtls);
     uptr cur_idx = nodeToIndex(cur_node);
-    g_.addEdges(dtls->getLocks(current_epoch_), cur_idx);
-    return dtls->addLock(cur_idx, current_epoch_);
+    dtls->addLock(cur_idx, current_epoch_);
+  }
+
+  // Adds edges from currently held locks to cur_node,
+  // returns the number of added edges, and puts the sources of added edges
+  // into added_edges[].
+  // Should be called before onLockAfter.
+  uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk) {
+    ensureCurrentEpoch(dtls);
+    uptr cur_idx = nodeToIndex(cur_node);
+    uptr added_edges[40];
+    uptr n_added_edges = g_.addEdges(dtls->getLocks(current_epoch_), cur_idx,
+                                     added_edges, ARRAY_SIZE(added_edges));
+    for (uptr i = 0; i < n_added_edges; i++) {
+      if (n_edges_ < ARRAY_SIZE(edges_))
+        edges_[n_edges_++] = Edge((u16)added_edges[i], (u16)cur_idx, stk);
+      // Printf("Edge [%zd]: %u %zd=>%zd\n", i, stk, added_edges[i], cur_idx);
+    }
+    return n_added_edges;
+  }
+
+  u32 findEdge(uptr from_node, uptr to_node) {
+    uptr from_idx = nodeToIndex(from_node);
+    uptr to_idx = nodeToIndex(to_node);
+    for (uptr i = 0; i < n_edges_; i++) {
+      if (edges_[i].from == from_idx && edges_[i].to == to_idx)
+        return edges_[i].stk;
+    }
+    return 0;
   }
 
   // Test-only function. Handles the before/after lock events,
   // returns true if there is a cycle.
   bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
     ensureCurrentEpoch(dtls);
-    bool is_reachable = onLockBefore(dtls, cur_node);
-    return onLockAfter(dtls, cur_node) && is_reachable;
+    bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
+    addEdges(dtls, cur_node, 0);
+    onLockAfter(dtls, cur_node);
+    return is_reachable;
   }
 
   // Handles the try_lock event, returns false.
@@ -276,12 +305,23 @@ class DeadlockDetector {
     return indexToNode(idx);
   }
 
+  struct Edge {
+    u16 from;
+    u16 to;
+    u32 stk;
+    // FIXME: replace with initializer list once the tests are built as c++11.
+    Edge(u16 f, u16 t, u32 s) : from(f), to(t), stk(s) {}
+    Edge() {}
+  };
+
   uptr current_epoch_;
   BV available_nodes_;
   BV recycled_nodes_;
   BV tmp_bv_;
   BVGraph<BV> g_;
   uptr data_[BV::kSize];
+  Edge edges_[BV::kSize * 32];
+  uptr n_edges_;
 };
 
 } // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc?rev=203902&r1=203901&r2=203902&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc Fri Mar 14 02:09:01 2014
@@ -112,8 +112,12 @@ void DD::MutexBeforeLock(DDCallback *cb,
     DDReport *rep = &lt->rep;
     rep->n = len;
     for (uptr i = 0; i < len; i++) {
-      DDMutex *m0 = (DDMutex*)dd.getData(path[i]);
-      DDMutex *m1 = (DDMutex*)dd.getData(path[i < len - 1 ? i + 1 : 0]);
+      uptr from = path[i];
+      uptr to = path[(i + 1) % len];
+      DDMutex *m0 = (DDMutex*)dd.getData(from);
+      DDMutex *m1 = (DDMutex*)dd.getData(to);
+
+      Printf("Edge: %zd=>%zd: %u\n", from, to, dd.findEdge(from, to));
       rep->loop[i].thr_ctx = 0;  // don't know
       rep->loop[i].mtx_ctx0 = m0->ctx;
       rep->loop[i].mtx_ctx1 = m1->ctx;
@@ -131,11 +135,9 @@ void DD::MutexAfterLock(DDCallback *cb,
   MutexEnsureID(lt, m);
   if (wlock)  // Only a recursive rlock may be held.
     CHECK(!dd.isHeld(&lt->dd, m->id));
-  bool edge_added =
-      trylock ? dd.onTryLock(&lt->dd, m->id) : dd.onLockAfter(&lt->dd, m->id);
-  if (edge_added) {
-    // Printf("Edge added\n");
-  }
+  if (!trylock)
+    dd.addEdges(&lt->dd, m->id, cb->Unwind());
+  dd.onLockAfter(&lt->dd, m->id);
 }
 
 void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc?rev=203902&r1=203901&r2=203902&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc Fri Mar 14 02:09:01 2014
@@ -301,3 +301,33 @@ TEST(BVGraph, ShortestPath) {
   ShortestPath<BV3>();
   ShortestPath<BV4>();
 }
+
+template <class BV>
+void RunAddEdgesTest() {
+  BVGraph<BV> g;
+  BV from;
+  const int kMaxEdges = 10;
+  uptr added_edges[kMaxEdges];
+  g.clear();
+  from.clear();
+  EXPECT_EQ(0U, g.addEdges(from, 0, added_edges, kMaxEdges));
+  EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges));
+  from.setBit(0);
+  EXPECT_EQ(1U, g.addEdges(from, 1, added_edges, kMaxEdges));
+  EXPECT_EQ(0U, added_edges[0]);
+  EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges));
+
+  from.clear();
+  from.setBit(1);
+  EXPECT_EQ(1U, g.addEdges(from, 4, added_edges, kMaxEdges));
+  EXPECT_EQ(1U, added_edges[0]);
+  from.setBit(2);
+  from.setBit(3);
+  EXPECT_EQ(2U, g.addEdges(from, 4, added_edges, kMaxEdges));
+  EXPECT_EQ(2U, added_edges[0]);
+  EXPECT_EQ(3U, added_edges[1]);
+}
+
+TEST(BVGraph, AddEdgesTest) {
+  RunAddEdgesTest<BV2>();
+}





More information about the llvm-commits mailing list