ART: Fix issues in RequestSynchronousCheckpoint

Do not run the checkpoint for another thread while being suspended.
Only suspend while waiting for that thread to become suspended.

After decreasing the suspend count, broadcast on the resume condition,
to tell the thread that it may progress.

Bug: 62353392
Test: m test-art-host
Change-Id: I63082b1fac5ec1db6ac31199548b9ae3cb30ea47
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 9f8c90a..be1614b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1467,11 +1467,13 @@
 
     {
       ScopedThreadListLockUnlock stllu(self);
-      ScopedThreadSuspension sts(self, ThreadState::kWaiting);
-      while (GetState() == ThreadState::kRunnable) {
-        // We became runnable again. Wait till the suspend triggered in ModifySuspendCount
-        // moves us to suspended.
-        sched_yield();
+      {
+        ScopedThreadSuspension sts(self, ThreadState::kWaiting);
+        while (GetState() == ThreadState::kRunnable) {
+          // We became runnable again. Wait till the suspend triggered in ModifySuspendCount
+          // moves us to suspended.
+          sched_yield();
+        }
       }
 
       function->Run(this);
@@ -1485,6 +1487,13 @@
       DCHECK(updated);
     }
 
+    {
+      // Imitate ResumeAll, the thread may be waiting on Thread::resume_cond_ since we raised its
+      // suspend count. Now the suspend_count_ is lowered so we must do the broadcast.
+      MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+      Thread::resume_cond_->Broadcast(self);
+    }
+
     return true;  // We're done, break out of the loop.
   }
 }