forked from OSchip/llvm-project
[sanitizer] when recycling deadlock graph nodes, properly recycle edges
llvm-svn: 204233
This commit is contained in:
parent
cc579aeba6
commit
2483acce21
|
@ -153,6 +153,14 @@ class DeadlockDetector {
|
|||
if (!available_nodes_.empty())
|
||||
return getAvailableNode(data);
|
||||
if (!recycled_nodes_.empty()) {
|
||||
// Printf("recycling: n_edges_ %zd\n", n_edges_);
|
||||
for (sptr i = n_edges_ - 1; i >= 0; i--) {
|
||||
if (recycled_nodes_.getBit(edges_[i].from) ||
|
||||
recycled_nodes_.getBit(edges_[i].to)) {
|
||||
Swap(edges_[i], edges_[n_edges_ - 1]);
|
||||
n_edges_--;
|
||||
}
|
||||
}
|
||||
CHECK(available_nodes_.empty());
|
||||
// removeEdgesFrom was called in removeNode.
|
||||
g_.removeEdgesTo(recycled_nodes_);
|
||||
|
@ -233,7 +241,7 @@ class DeadlockDetector {
|
|||
if (n_edges_ < ARRAY_SIZE(edges_))
|
||||
edges_[n_edges_++] = Edge((u16)added_edges[i], (u16)cur_idx,
|
||||
dtls->findLockContext(added_edges[i]), stk);
|
||||
// Printf("Edge [%zd]: %u %zd=>%zd\n", i, stk, added_edges[i], cur_idx);
|
||||
// Printf("E%zd: %u %zd=>%zd\n", n_edges_, stk, added_edges[i], cur_idx);
|
||||
}
|
||||
return n_added_edges;
|
||||
}
|
||||
|
@ -256,7 +264,7 @@ class DeadlockDetector {
|
|||
bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
|
||||
ensureCurrentEpoch(dtls);
|
||||
bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
|
||||
addEdges(dtls, cur_node, 0);
|
||||
addEdges(dtls, cur_node, stk);
|
||||
onLockAfter(dtls, cur_node, stk);
|
||||
return is_reachable;
|
||||
}
|
||||
|
|
|
@ -444,3 +444,44 @@ void RunLockContextTest() {
|
|||
TEST(DeadlockDetector, LockContextTest) {
|
||||
RunLockContextTest<BV2>();
|
||||
}
|
||||
|
||||
template <class BV>
|
||||
void RunRemoveEdgesTest() {
|
||||
ScopedDD<BV> sdd;
|
||||
DeadlockDetector<BV> &d = *sdd.dp;
|
||||
DeadlockDetectorTLS<BV> &dtls = sdd.dtls;
|
||||
vector<uptr> node(BV::kSize);
|
||||
u32 stk_from = 0, stk_to = 0;
|
||||
for (size_t i = 0; i < BV::kSize; i++)
|
||||
node[i] = d.newNode(0);
|
||||
|
||||
for (size_t i = 0; i < BV::kSize; i++)
|
||||
EXPECT_FALSE(d.onLock(&dtls, node[i], i + 1));
|
||||
for (size_t i = 0; i < BV::kSize; i++) {
|
||||
for (uptr j = i + 1; j < BV::kSize; j++) {
|
||||
EXPECT_TRUE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
|
||||
EXPECT_EQ(stk_from, i + 1);
|
||||
EXPECT_EQ(stk_to, j + 1);
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(d.testOnlyGetEpoch(), d.size());
|
||||
// Remove and re-create half of the nodes.
|
||||
for (uptr i = 1; i < BV::kSize; i += 2)
|
||||
d.removeNode(node[i]);
|
||||
for (uptr i = 1; i < BV::kSize; i += 2)
|
||||
node[i] = d.newNode(0);
|
||||
EXPECT_EQ(d.testOnlyGetEpoch(), d.size());
|
||||
// The edges from or to the removed nodes should be gone.
|
||||
for (size_t i = 0; i < BV::kSize; i++) {
|
||||
for (uptr j = i + 1; j < BV::kSize; j++) {
|
||||
if ((i % 2) || (j % 2))
|
||||
EXPECT_FALSE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
|
||||
else
|
||||
EXPECT_TRUE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DeadlockDetector, RemoveEdgesTest) {
|
||||
RunRemoveEdgesTest<BV1>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue