diff options
3 files changed, 18 insertions, 14 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h index 30d503def36..318288e66ba 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h +++ b/compiler-rt/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; diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc index 49b3bf1a350..3852b33dadf 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc @@ -269,9 +269,8 @@ void RunMultipleEpochsTest() { EXPECT_EQ(d.testOnlyGetEpoch(), 4 * d.size()); // Can not handle the locks from the previous epoch. - // The user should update the lock id. + // The caller should update the lock id. EXPECT_DEATH(d.onLock(&dtls, l0), "CHECK failed.*current_epoch_"); - EXPECT_DEATH(d.onUnlock(&dtls, l1), "CHECK failed.*current_epoch_"); } TEST(DeadlockDetector, MultipleEpochsTest) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index d2addd17c6a..c3332812698 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -32,8 +32,6 @@ static void EnsureDeadlockDetectorID(Context *ctx, ThreadState *thr, static void DDUnlock(Context *ctx, ThreadState *thr, SyncVar *s) { if (!common_flags()->detect_deadlocks) return; if (s->recursion != 0) return; - Lock lk(&ctx->dd_mtx); - EnsureDeadlockDetectorID(ctx, thr, s); // Printf("T%d MutexUnlock: %zx; recursion %d\n", thr->tid, // s->deadlock_detector_id, s->recursion); ctx->dd.onUnlock(&thr->deadlock_detector_tls, s->deadlock_detector_id); |