diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h index 6d4cec86c4ea3209686154759ff2d98564f097d1..dfaacb3d22d89aee801ed915c3b2bc0ca0efaad0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h @@ -175,9 +175,12 @@ class DeadlockDetector { // Experimental *racy* fast path function. // Returns true if all edges from the currently held locks to cur_node exist. bool hasAllEdges(DeadlockDetectorTLS *dtls, uptr cur_node) { - if (dtls->getEpoch() == nodeToEpoch(cur_node)) { + uptr local_epoch = dtls->getEpoch(); + // Read from current_epoch_ is racy. + if (cur_node && local_epoch == current_epoch_ && + local_epoch == nodeToEpoch(cur_node)) { uptr cur_idx = nodeToIndexUnchecked(cur_node); - return g_.hasAllEdges(dtls->getLocks(current_epoch_), cur_idx); + return g_.hasAllEdges(dtls->getLocks(local_epoch), cur_idx); } return false; } @@ -267,6 +270,18 @@ class DeadlockDetector { dtls->removeLock(nodeToIndexUnchecked(node)); } + // Tries to handle the lock event w/o writing to global state. + // Returns true on success. + // This operation is thread-safe as it only touches the dtls + // (modulo racy nature of hasAllEdges). + bool onLockFast(DeadlockDetectorTLS *dtls, uptr node) { + if (hasAllEdges(dtls, node)) { + dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node)); + return true; + } + return false; + } + bool isHeld(DeadlockDetectorTLS *dtls, uptr node) const { return dtls->getLocks(current_epoch_).getBit(nodeToIndex(node)); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc index 3f02b3417a220654f884bc784bd1317c15bef223..201ad149d116162a5e85d896ff99eed6ba7a658f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cc @@ -132,7 +132,9 @@ void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) { // Printf("T%p MutexLock: %zx\n", lt, m->id); if (dd.onFirstLock(<->dd, m->id)) return; - // if (dd.hasAllEdges(<->dd, m->id)) return; + if (dd.onLockFast(<->dd, m->id)) + return; + SpinMutexLock lk(&mtx); MutexEnsureID(lt, m); if (wlock) // Only a recursive rlock may be held.