Implement most of VMStack and some of Zygote.

Change-Id: I07e18259a0452a2a9b077148f4f1ca67d3f63427
diff --git a/src/thread_list.cc b/src/thread_list.cc
index f17414c..8c6185d 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -122,6 +122,29 @@
   //LOG(INFO) << *self << " SuspendAll complete";
 }
 
+void ThreadList::Suspend(Thread* thread) {
+  DCHECK(thread != Thread::Current());
+
+  // TODO: add another thread_suspend_lock_ to avoid GC/debugger races.
+
+  //LOG(INFO) << "Suspend(" << *thread << ") starting...";
+
+  MutexLock mu(thread_list_lock_);
+  if (!Contains(thread)) {
+    return;
+  }
+
+  {
+    MutexLock mu(thread_suspend_count_lock_);
+    ++thread->suspend_count_;
+  }
+
+  thread->WaitUntilSuspended();
+
+  //LOG(INFO) << "Suspend(" << *thread << ") complete";
+}
+
+
 void ThreadList::ResumeAll() {
   Thread* self = Thread::Current();
 
@@ -156,6 +179,45 @@
   //LOG(INFO) << *self << " ResumeAll complete";
 }
 
+void ThreadList::Resume(Thread* thread) {
+  DCHECK(thread != Thread::Current());
+
+  //LOG(INFO) << "Resume(" << *thread << ") starting...";
+
+  {
+    MutexLock mu1(thread_list_lock_);
+    MutexLock mu2(thread_suspend_count_lock_);
+    if (!Contains(thread)) {
+      return;
+    }
+    if (thread->suspend_count_ > 0) {
+      --thread->suspend_count_;
+    } else {
+      LOG(WARNING) << *thread << " suspend count already zero";
+    }
+  }
+
+  {
+    //LOG(INFO) << "Resume(" << *thread << ") waking others";
+    MutexLock mu(thread_suspend_count_lock_);
+    thread_suspend_count_cond_.Broadcast();
+  }
+
+  //LOG(INFO) << "Resume(" << *thread << ") complete";
+}
+
+void ThreadList::RunWhileSuspended(Thread* thread, void (*callback)(void*), void* arg) {
+  DCHECK(thread != NULL);
+  Thread* self = Thread::Current();
+  if (thread != self) {
+    Suspend(thread);
+  }
+  callback(arg);
+  if (thread != self) {
+    Resume(thread);
+  }
+}
+
 void ThreadList::Register(Thread* thread) {
   //LOG(INFO) << "ThreadList::Register() " << *thread;
   MutexLock mu(thread_list_lock_);