summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2016-06-29 14:39:59 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2016-06-29 17:28:27 +0100
commit9f5f8ac136d88de546f70f0ac2438610150ff401 (patch)
tree2d681b45f4e9652877833f160c9a674c78ba636d
parent05f0167cdd207edecaebf2cac7eea879678147c5 (diff)
Special case the suspend to runnable transition when locking.
The runtime may be shutting down in parallel, and for daemons that could lead to failed locking assertions. bug:27378067 Change-Id: I53785cad537a3d4846661a7b0780543226ea3928
-rw-r--r--runtime/base/mutex-inl.h5
-rw-r--r--runtime/thread-inl.h14
2 files changed, 17 insertions, 2 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index bd8de877e0..1c320243dc 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -73,6 +73,11 @@ static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALY
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) << level;
}
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index d98f82a541..3fd66a7bcb 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -201,12 +201,22 @@ inline ThreadState Thread::TransitionFromSuspendedToRunnable() {
<< " state=" << old_state_and_flags.as_struct.state;
} else if ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) {
// Wait while our suspend count is non-zero.
- MutexLock mu(this, *Locks::thread_suspend_count_lock_);
+
+ // We pass null to the MutexLock as we may be in a situation where the
+ // runtime is shutting down. Guarding ourselves from that situation
+ // requires to take the shutdown lock, which is undesirable here.
+ Thread* thread_to_pass = nullptr;
+ if (kIsDebugBuild && !IsDaemon()) {
+ // We know we can make our debug locking checks on non-daemon threads,
+ // so re-enable them on debug builds.
+ thread_to_pass = this;
+ }
+ MutexLock mu(thread_to_pass, *Locks::thread_suspend_count_lock_);
old_state_and_flags.as_int = tls32_.state_and_flags.as_int;
DCHECK_EQ(old_state_and_flags.as_struct.state, old_state);
while ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) {
// Re-check when Thread::resume_cond_ is notified.
- Thread::resume_cond_->Wait(this);
+ Thread::resume_cond_->Wait(thread_to_pass);
old_state_and_flags.as_int = tls32_.state_and_flags.as_int;
DCHECK_EQ(old_state_and_flags.as_struct.state, old_state);
}