forked from OSchip/llvm-project
[sanitizer] findPath for deadlock detector
llvm-svn: 201306
This commit is contained in:
parent
5bbb72f37e
commit
f6cb35abb4
|
@ -56,6 +56,8 @@ class BasicBitVector {
|
|||
return bits_ != old;
|
||||
}
|
||||
|
||||
void copyFrom(const BasicBitVector &v) { bits_ = v.bits_; }
|
||||
|
||||
// Returns true if 'this' intersects with 'v'.
|
||||
bool intersectsWith(const BasicBitVector &v) const { return bits_ & v.bits_; }
|
||||
|
||||
|
@ -165,6 +167,11 @@ class TwoLevelBitVector {
|
|||
return res;
|
||||
}
|
||||
|
||||
void copyFrom(const TwoLevelBitVector &v) {
|
||||
clear();
|
||||
setUnion(v);
|
||||
}
|
||||
|
||||
// Returns true if 'this' intersects with 'v'.
|
||||
bool intersectsWith(const TwoLevelBitVector &v) const {
|
||||
for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
|
||||
|
|
|
@ -47,8 +47,7 @@ class BVGraph {
|
|||
// to any of the nodes in 'targets'.
|
||||
bool isReachable(uptr from, const BV &targets) {
|
||||
BV to_visit, visited;
|
||||
to_visit.clear();
|
||||
to_visit.setUnion(v[from]);
|
||||
to_visit.copyFrom(v[from]);
|
||||
visited.clear();
|
||||
visited.setBit(from);
|
||||
while (!to_visit.empty()) {
|
||||
|
@ -59,6 +58,25 @@ class BVGraph {
|
|||
return targets.intersectsWith(visited);
|
||||
}
|
||||
|
||||
// Finds a path from 'from' to one of the nodes in 'target',
|
||||
// stores up to 'path_size' items of the path into 'path',
|
||||
// returns the path length, or 0 if there is no path of size 'path_size'.
|
||||
uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
|
||||
if (path_size == 0)
|
||||
return 0;
|
||||
path[0] = from;
|
||||
if (targets.getBit(from))
|
||||
return 1;
|
||||
BV t;
|
||||
t.copyFrom(v[from]);
|
||||
while (!t.empty()) {
|
||||
uptr idx = t.getAndClearFirstOne();
|
||||
if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
|
||||
return res + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void check(uptr idx) const { CHECK_LE(idx, size()); }
|
||||
BV v[kSize];
|
||||
|
|
|
@ -59,6 +59,8 @@ class DeadlockDetectorTLS {
|
|||
// DeadlockDetector.
|
||||
// For deadlock detection to work we need one global DeadlockDetector object
|
||||
// and one DeadlockDetectorTLS object per evey thread.
|
||||
// This class is not thread safe, all concurrent accesses should be guarded
|
||||
// by an external lock.
|
||||
template <class BV>
|
||||
class DeadlockDetector {
|
||||
public:
|
||||
|
|
|
@ -61,7 +61,16 @@ TEST(SanitizerCommon, BVGraph) {
|
|||
from = my_rand() % g.size();
|
||||
bool is_reachable = g.isReachable(from, target);
|
||||
if (is_reachable) {
|
||||
// printf("reachable: %d %zd\n", it, from);
|
||||
uptr path[BV::kSize];
|
||||
uptr len;
|
||||
for (len = 1; len < BV::kSize; len++) {
|
||||
if (g.findPath(from, target, path, len) == len)
|
||||
break;
|
||||
}
|
||||
EXPECT_LT(len, BV::kSize);
|
||||
EXPECT_TRUE(target.getBit(path[len - 1]));
|
||||
// fprintf(stderr, "reachable: %zd; path %zd {%zd %zd %zd}\n",
|
||||
// from, len, path[0], path[1], path[2]);
|
||||
num_reachable++;
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +80,7 @@ TEST(SanitizerCommon, BVGraph) {
|
|||
|
||||
TEST(SanitizerCommon, BVGraph_isReachable) {
|
||||
typedef TwoLevelBitVector<> BV;
|
||||
uptr path[5];
|
||||
BVGraph<BV> g;
|
||||
g.clear();
|
||||
BV target;
|
||||
|
@ -103,6 +113,13 @@ TEST(SanitizerCommon, BVGraph_isReachable) {
|
|||
EXPECT_TRUE(g.isReachable(f1, target));
|
||||
EXPECT_FALSE(g.isReachable(f2, target));
|
||||
EXPECT_FALSE(g.isReachable(f3, target));
|
||||
EXPECT_EQ(g.findPath(f0, target, path, ARRAY_SIZE(path)), 3U);
|
||||
EXPECT_EQ(path[0], f0);
|
||||
EXPECT_EQ(path[1], f1);
|
||||
EXPECT_EQ(path[2], t0);
|
||||
EXPECT_EQ(g.findPath(f1, target, path, ARRAY_SIZE(path)), 2U);
|
||||
EXPECT_EQ(path[0], f1);
|
||||
EXPECT_EQ(path[1], t0);
|
||||
|
||||
g.addEdge(f3, t1);
|
||||
EXPECT_TRUE(g.isReachable(f0, target));
|
||||
|
|
Loading…
Reference in New Issue