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.