Fix a deadlock caused by my big threading change yesterday.

Also add even more locking diagnostics that catch this class of error and
explain what you've done in clear terms. In this case:

03-02 16:42:46.040 20768 20785 E art     : holding ThreadListLock while doing condition variable wait on ThreadSuspendCountLock
...
03-02 16:42:46.493 23421 23421 I DEBUG   :     #01  pc 00149e5f  /system/lib/libartd.so (art::Runtime::Abort(char const*, int)+338)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #02  pc 00113c0b  /system/lib/libartd.so (art::LogMessage::~LogMessage()+1026)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #03  pc 0015a723  /system/lib/libartd.so (art::Thread::CheckSafeToWait(art::MutexRank)+290)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #04  pc 0012481f  /system/lib/libartd.so (art::ConditionVariable::Wait(art::Mutex&)+26)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #05  pc 001631fb  /system/lib/libartd.so (art::ThreadList::FullSuspendCheck(art::Thread*)+154)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #06  pc 00159ffd  /system/lib/libartd.so (art::Thread::SetState(art::Thread::State)+128)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #07  pc 00161bb5  /system/lib/libartd.so (art::ScopedThreadListLock::ScopedThreadListLock()+64)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #08  pc 00164a31  /system/lib/libartd.so (art::ThreadList::Unregister()+92)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #09  pc 0015e537  /system/lib/libartd.so (art::Thread::CreateCallback(void*)+230)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #10  pc 00013b08  /system/lib/libc.so (__thread_entry+48)
03-02 16:42:46.493 23421 23421 I DEBUG   :     #11  pc 0001363c  /system/lib/libc.so (pthread_create+180)

Change-Id: I9cdb770e766f63359ab7d11ee1993dd7a6fc1c90
diff --git a/src/thread.cc b/src/thread.cc
index 1c521c1..dcaf01f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -599,6 +599,12 @@
   WalkStack(&dumper);
 }
 
+void Thread::SetStateWithoutSuspendCheck(Thread::State new_state) {
+  volatile void* raw = reinterpret_cast<volatile void*>(&state_);
+  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw);
+  android_atomic_release_store(new_state, addr);
+}
+
 Thread::State Thread::SetState(Thread::State new_state) {
   Thread::State old_state = state_;
   if (old_state == new_state) {
@@ -1674,7 +1680,7 @@
   return os;
 }
 
-void Thread::CheckRank(MutexRank rank, bool is_locking) {
+void Thread::CheckSafeToLockOrUnlock(MutexRank rank, bool is_locking) {
   if (is_locking) {
     if (held_mutexes_[rank] == 0) {
       bool bad_mutexes_held = false;
@@ -1693,4 +1699,19 @@
   }
 }
 
+void Thread::CheckSafeToWait(MutexRank rank) {
+  bool bad_mutexes_held = false;
+  for (int i = kMaxMutexRank; i >= 0; --i) {
+    if (i != rank && held_mutexes_[i] != 0) {
+      LOG(ERROR) << "holding " << static_cast<MutexRank>(i) << " while doing condition variable wait on " << rank;
+      bad_mutexes_held = true;
+    }
+  }
+  if (held_mutexes_[rank] == 0) {
+    LOG(ERROR) << "*not* holding " << rank << " while doing condition variable wait on it";
+    bad_mutexes_held = true;
+  }
+  CHECK(!bad_mutexes_held);
+}
+
 }  // namespace art