summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_deadlock_detector.h
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-02-27 14:38:42 +0000
committerKostya Serebryany <kcc@google.com>2014-02-27 14:38:42 +0000
commite68e8f87a47b7cacac6af0f8bd486e36a74a7cac (patch)
tree6911032acb04753dee19957c5ded38d16acadc36 /lib/sanitizer_common/sanitizer_deadlock_detector.h
parentccf6a360fb5c80e3f1586f093eb44757d3592745 (diff)
[sanitizer] do not acquire a global mutex in deadlock detector when dealing with Unlock (it is essentially a thread-local operation)
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@202401 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_deadlock_detector.h')
-rw-r--r--lib/sanitizer_common/sanitizer_deadlock_detector.h27
1 files changed, 17 insertions, 10 deletions
diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector.h b/lib/sanitizer_common/sanitizer_deadlock_detector.h
index 30d503def..318288e66 100644
--- a/lib/sanitizer_common/sanitizer_deadlock_detector.h
+++ b/lib/sanitizer_common/sanitizer_deadlock_detector.h
@@ -48,16 +48,17 @@ class DeadlockDetectorTLS {
epoch_ = current_epoch;
}
+ uptr getEpoch() const { return epoch_; }
+
void addLock(uptr lock_id, uptr current_epoch) {
// Printf("addLock: %zx %zx\n", lock_id, current_epoch);
CHECK_EQ(epoch_, current_epoch);
CHECK(bv_.setBit(lock_id));
}
- void removeLock(uptr lock_id, uptr current_epoch) {
+ void removeLock(uptr lock_id) {
// Printf("remLock: %zx %zx\n", lock_id, current_epoch);
- CHECK_EQ(epoch_, current_epoch);
- bv_.clearBit(lock_id); // May already be cleared due to epoch update.
+ CHECK(bv_.clearBit(lock_id));
}
const BV &getLocks(uptr current_epoch) const {
@@ -75,7 +76,8 @@ class DeadlockDetectorTLS {
// and one DeadlockDetectorTLS object per evey thread.
// This class is not thread safe, all concurrent accesses should be guarded
// by an external lock.
-// Not thread-safe, all accesses should be protected by an external lock.
+// Most of the methods of this class are not thread-safe (i.e. should
+// be protected by an external lock) unless explicitly told otherwise.
template <class BV>
class DeadlockDetector {
public:
@@ -133,7 +135,7 @@ class DeadlockDetector {
}
// Handles the lock event, returns true if there is a cycle.
- // FIXME: handle RW locks, recusive locks, etc.
+ // FIXME: handle RW locks, recursive locks, etc.
bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
ensureCurrentEpoch(dtls);
uptr cur_idx = nodeToIndex(cur_node);
@@ -171,10 +173,11 @@ class DeadlockDetector {
return res;
}
- // Handle the unlock event.
+ // Handle the unlock event. This operation is thread-safe
+ // as it only touches the dtls.
void onUnlock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
- ensureCurrentEpoch(dtls);
- dtls->removeLock(nodeToIndex(node), current_epoch_);
+ if (dtls->getEpoch() == nodeToEpoch(node))
+ dtls->removeLock(nodeToIndexUnchecked(node));
}
bool isHeld(DeadlockDetectorTLS<BV> *dtls, uptr node) const {
@@ -202,7 +205,7 @@ class DeadlockDetector {
void check_node(uptr node) const {
CHECK_GE(node, size());
- CHECK_EQ(current_epoch_, node / size() * size());
+ CHECK_EQ(current_epoch_, nodeToEpoch(node));
}
uptr indexToNode(uptr idx) const {
@@ -210,11 +213,15 @@ class DeadlockDetector {
return idx + current_epoch_;
}
+ uptr nodeToIndexUnchecked(uptr node) const { return node % size(); }
+
uptr nodeToIndex(uptr node) const {
check_node(node);
- return node % size();
+ return nodeToIndexUnchecked(node);
}
+ uptr nodeToEpoch(uptr node) const { return node / size() * size(); }
+
uptr getAvailableNode(uptr data) {
uptr idx = available_nodes_.getAndClearFirstOne();
data_[idx] = data;