diff options
author | 2023-08-15 17:56:07 +0000 | |
---|---|---|
committer | 2023-08-23 22:06:46 +0000 | |
commit | 996cbb566a5521ca3b0653007e7921469f58981a (patch) | |
tree | c515682fbe53afe605b39e3d0ab2aa09e3d59ad8 /runtime/base/mutex-inl.h | |
parent | 9e5a197ee85b35e0e95fa48316f1a87e1d9232e5 (diff) |
Revert^12 "Thread suspension cleanup and deadlock fix"
This reverts commit b6f3b439d4f12e89393ba8101eea8671c94ba237.
PS1: Identical to aosp/2652371 .
PS2: Introduce kSuspensionImmune to disable suspension of a thread
that is being relied upon to execute ResumeAll(). This replaces
the test in SuspendAll() to check whether the caller was being asked
to suspend itself. That test was deadlock-prone, since a SuspendAll
request from e.g. the GC to block, and GC progress might be required
to resume the thread running the GC.
Since SuspendAll() now only loops for a single reason, we no longer
need to track why we looped.
Reduce the number of iterations in each 129-ThreadGetId thread
drammatically.
PS3: Address reviewer comments, including fixing a newly introduced
bug in CheckSuspend(). Fix 129-GetThreadId by drammatically reducing
the iteration count when we appear to be running slowly, which is
normally the case for gcstress. Earlier versions of this CL were
apparently also failing on this test, but the failure was hidden by
other failures. This mostly undoes the PS2 change to this test, now
that the failure is better understood.
PS4: Rebase.
PS5: Fix 129-GetThreadId code formatting.
PS6: Address more reviewer comments related to 129-GetThreadId.
PS7: Remove DCHECK in EnsureFlipFunctionStarted. It was unsafe,
since the thread may no longer be around.
Test: Treehugger.
Bug: 240742796
Bug: 203363895
Bug: 238032384
Bug: 253671779
Bug: 276660630
Bug: 295880862
Bug: 294334417
(and more)
Change-Id: I99260fdc4feb9bcdc8b8b566e40912532f1a4937
Diffstat (limited to 'runtime/base/mutex-inl.h')
-rw-r--r-- | runtime/base/mutex-inl.h | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h index dba1e1299b..712b61d4ac 100644 --- a/runtime/base/mutex-inl.h +++ b/runtime/base/mutex-inl.h @@ -60,43 +60,44 @@ static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALY // The check below enumerates the cases where we expect not to be able to check the validity of // locks on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock. // TODO: tighten this check. - if (kDebugLocking) { - CHECK(!Locks::IsSafeToCallAbortRacy() || - // Used during thread creation to avoid races with runtime shutdown. Thread::Current not - // yet established. - level == kRuntimeShutdownLock || - // Thread Ids are allocated/released before threads are established. - level == kAllocatedThreadIdsLock || - // Thread LDT's are initialized without Thread::Current established. - level == kModifyLdtLock || - // Threads are unregistered while holding the thread list lock, during this process they - // no longer exist and so we expect an unlock with no self. - level == kThreadListLock || - // Ignore logging which may or may not have set up thread data structures. - level == kLoggingLock || - // When transitioning from suspended to runnable, a daemon thread might be in - // a situation where the runtime is shutting down. To not crash our debug locking - // mechanism we just pass null Thread* to the MutexLock during that transition - // (see Thread::TransitionFromSuspendedToRunnable). - level == kThreadSuspendCountLock || - // Avoid recursive death. - level == kAbortLock || - // Locks at the absolute top of the stack can be locked at any time. - level == kTopLockLevel || - // The unexpected signal handler may be catching signals from any thread. - level == kUnexpectedSignalLock) << level; - } + CHECK(!Locks::IsSafeToCallAbortRacy() || + // Used during thread creation to avoid races with runtime shutdown. Thread::Current not + // yet established. + level == kRuntimeShutdownLock || + // Thread Ids are allocated/released before threads are established. + level == kAllocatedThreadIdsLock || + // Thread LDT's are initialized without Thread::Current established. + level == kModifyLdtLock || + // Threads are unregistered while holding the thread list lock, during this process they + // no longer exist and so we expect an unlock with no self. + level == kThreadListLock || + // Ignore logging which may or may not have set up thread data structures. + level == kLoggingLock || + // When transitioning from suspended to runnable, a daemon thread might be in + // a situation where the runtime is shutting down. To not crash our debug locking + // mechanism we just pass null Thread* to the MutexLock during that transition + // (see Thread::TransitionFromSuspendedToRunnable). + level == kThreadSuspendCountLock || + // Avoid recursive death. + level == kAbortLock || + // Locks at the absolute top of the stack can be locked at any time. + level == kTopLockLevel || + // The unexpected signal handler may be catching signals from any thread. + level == kUnexpectedSignalLock) + << level; } -inline void BaseMutex::RegisterAsLocked(Thread* self) { +inline void BaseMutex::RegisterAsLocked(Thread* self, bool check) { if (UNLIKELY(self == nullptr)) { - CheckUnattachedThread(level_); - return; + if (check) { + CheckUnattachedThread(level_); + } + } else { + RegisterAsLockedImpl(self, level_, check); } - RegisterAsLockedImpl(self, level_); } -inline void BaseMutex::RegisterAsLockedImpl(Thread* self, LockLevel level) { +inline void BaseMutex::RegisterAsLockedImpl(Thread* self, LockLevel level, bool check) { DCHECK(self != nullptr); DCHECK_EQ(level_, level); // It would be nice to avoid this condition checking in the non-debug case, @@ -107,7 +108,7 @@ inline void BaseMutex::RegisterAsLockedImpl(Thread* self, LockLevel level) { if (UNLIKELY(level == kThreadWaitLock) && self->GetHeldMutex(kThreadWaitLock) != nullptr) { level = kThreadWaitWakeLock; } - if (kDebugLocking) { + if (check) { // 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 @@ -161,10 +162,12 @@ inline void BaseMutex::RegisterAsLockedImpl(Thread* self, LockLevel level) { inline void BaseMutex::RegisterAsUnlocked(Thread* self) { if (UNLIKELY(self == nullptr)) { - CheckUnattachedThread(level_); - return; + if (kDebugLocking) { + CheckUnattachedThread(level_); + } + } else { + RegisterAsUnlockedImpl(self, level_); } - RegisterAsUnlockedImpl(self , level_); } inline void BaseMutex::RegisterAsUnlockedImpl(Thread* self, LockLevel level) { @@ -306,7 +309,7 @@ inline void MutatorMutex::TransitionFromRunnableToSuspended(Thread* self) { } inline void MutatorMutex::TransitionFromSuspendedToRunnable(Thread* self) { - RegisterAsLockedImpl(self, kMutatorLock); + RegisterAsLockedImpl(self, kMutatorLock, kDebugLocking); AssertSharedHeld(self); } |