summaryrefslogtreecommitdiff
path: root/runtime/base/mutex-inl.h
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2017-11-21 00:00:48 +0000
committer Alex Light <allight@google.com> 2017-11-20 16:58:05 -0800
commitb284f8d775ac32d8109744d94b99da451570beef (patch)
treec720648f1c018d224410314b30a891f2752bc781 /runtime/base/mutex-inl.h
parente6779fde5a3c0a8bb484a61398da439a37d25b92 (diff)
Revert "Revert "Make JVMTI DisposeEnvironment and GetEnv thread safe.""
This reverts commit af9341087aab0146b8323ece156bde8130948465. We needed to allow TopLockLevel locks to be acquired when the mutator_lock_ is exclusive held. This is required for spec conformance. To ensure there are no deadlocks the mutator_lock_ is the only lock level with this exception and one cannot acquire the mutator_lock_ when one holds any kTopLockLevel locks. Reason for revert: Fixed issue causing test 913 failure in art-gc-gss-tlab Test: ART_DEFAULT_GC_TYPE=GSS \ ART_USE_TLAB=true \ ART_USE_READ_BARRIER=false ./test.py --host -j50 Bug: 69465262 Change-Id: Ic1a4d9bb3ff64382ba7ae22ba27a4f44628ed095
Diffstat (limited to 'runtime/base/mutex-inl.h')
-rw-r--r--runtime/base/mutex-inl.h30
1 files changed, 28 insertions, 2 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index c9d48ff7f7..587b092ab7 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -80,7 +80,9 @@ static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALY
// (see Thread::TransitionFromSuspendedToRunnable).
level == kThreadSuspendCountLock ||
// Avoid recursive death.
- level == kAbortLock) << level;
+ level == kAbortLock ||
+ // Locks at the absolute top of the stack can be locked at any time.
+ level == kTopLockLevel) << level;
}
}
@@ -92,10 +94,34 @@ inline void BaseMutex::RegisterAsLocked(Thread* self) {
if (kDebugLocking) {
// Check if a bad Mutex of this level or lower is held.
bool bad_mutexes_held = false;
+ // Specifically allow a kTopLockLevel lock to be gained when the current thread holds the
+ // mutator_lock_ exclusive. This is because we suspending when holding locks at this level is
+ // not allowed and if we hold the mutator_lock_ exclusive we must unsuspend stuff eventually
+ // so there are no deadlocks.
+ if (level_ == kTopLockLevel &&
+ Locks::mutator_lock_->IsSharedHeld(self) &&
+ !Locks::mutator_lock_->IsExclusiveHeld(self)) {
+ LOG(ERROR) << "Lock level violation: holding \"" << Locks::mutator_lock_->name_ << "\" "
+ << "(level " << kMutatorLock << " - " << static_cast<int>(kMutatorLock)
+ << ") non-exclusive while locking \"" << name_ << "\" "
+ << "(level " << level_ << " - " << static_cast<int>(level_) << ") a top level"
+ << "mutex. This is not allowed.";
+ bad_mutexes_held = true;
+ } else if (this == Locks::mutator_lock_ && self->GetHeldMutex(kTopLockLevel) != nullptr) {
+ LOG(ERROR) << "Lock level violation. Locking mutator_lock_ while already having a "
+ << "kTopLevelLock (" << self->GetHeldMutex(kTopLockLevel)->name_ << "held is "
+ << "not allowed.";
+ bad_mutexes_held = true;
+ }
for (int i = level_; i >= 0; --i) {
LockLevel lock_level_i = static_cast<LockLevel>(i);
BaseMutex* held_mutex = self->GetHeldMutex(lock_level_i);
- if (UNLIKELY(held_mutex != nullptr) && lock_level_i != kAbortLock) {
+ if (level_ == kTopLockLevel &&
+ lock_level_i == kMutatorLock &&
+ Locks::mutator_lock_->IsExclusiveHeld(self)) {
+ // This is checked above.
+ continue;
+ } else if (UNLIKELY(held_mutex != nullptr) && lock_level_i != kAbortLock) {
LOG(ERROR) << "Lock level violation: holding \"" << held_mutex->name_ << "\" "
<< "(level " << lock_level_i << " - " << i
<< ") while locking \"" << name_ << "\" "