Address two ThreadList deadlocks
Change-Id: Ibd40ef6dda75a2bebc8a17a3e03053dc42662041
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 84edf46..29a0195 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -94,7 +94,13 @@
LOG(INFO) << *self << " SuspendAll starting...";
}
- MutexLock mu(thread_list_lock_);
+ // Avoid deadlock between two threads trying to SuspendAll
+ // simultaneously by going to kVmWait if the lock cannot be
+ // immediately acquired.
+ if (!thread_list_lock_.TryLock()) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
+ thread_list_lock_.Lock();
+ }
{
// Increment everybody's suspend count (except our own).
@@ -134,6 +140,8 @@
}
}
+ thread_list_lock_.Unlock();
+
if (verbose_) {
LOG(INFO) << *self << " SuspendAll complete";
}
@@ -338,16 +346,18 @@
Thread* self = Thread::Current();
DCHECK(Contains(self));
- MutexLock mu(thread_list_lock_);
+ {
+ MutexLock mu(thread_list_lock_);
- // Tell our parent that we're in the thread list.
- self->SetState(Thread::kStarting);
- thread_start_cond_.Broadcast();
+ // Tell our parent that we're in the thread list.
+ self->SetState(Thread::kStarting);
+ thread_start_cond_.Broadcast();
- // Wait until our parent tells us there's no suspend still pending
- // from before we were on the thread list.
- while (self->GetState() != Thread::kVmWait) {
- thread_start_cond_.Wait(thread_list_lock_);
+ // Wait until our parent tells us there's no suspend still pending
+ // from before we were on the thread list.
+ while (self->GetState() != Thread::kVmWait) {
+ thread_start_cond_.Wait(thread_list_lock_);
+ }
}
// Enter the runnable state. We know that any pending suspend will affect us now.