Check point root marking.

Added thread list checkpoint function, this goes through every thread and runs
the checkpoint on each thread. Threads that are runnable run the checkpoint
callback themselves in the next suspend check, while suspended threads are
left suspended but have the callback called on them.

Added a checkpoint visitor member to each thread, this visitor called when the
checkpoint request flag is set during transitions to suspended from runnable.

Using the checkpoint to mark the roots reduces the first pause of partial /
full gc to around 1 ms.

Change-Id: I97239cc72ee0e4a3397e9138a62ee559268dce0a
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 601a93f..4ad25ae 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -151,6 +151,79 @@
 }
 #endif
 
+size_t ThreadList::RunCheckpoint(Thread::CheckpointFunction* checkpoint_function) {
+  Thread* self = Thread::Current();
+  if (kIsDebugBuild) {
+    Locks::mutator_lock_->AssertNotHeld(self);
+    Locks::thread_list_lock_->AssertNotHeld(self);
+    Locks::thread_suspend_count_lock_->AssertNotHeld(self);
+    CHECK_NE(self->GetState(), kRunnable);
+  }
+
+  std::vector<Thread*> suspended_count_modified_threads;
+  size_t count = 0;
+  {
+    // Call a checkpoint function for each thread, threads which are suspend get their checkpoint
+    // manually called.
+    MutexLock mu(self, *Locks::thread_list_lock_);
+    // TODO: C++0x auto.
+    for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
+      Thread* thread = *it;
+      if (thread != self) {
+        for (;;) {
+          if (thread->RequestCheckpoint(checkpoint_function)) {
+            // This thread will run it's checkpoint some time in the near future.
+            count++;
+            break;
+          } else {
+            // We are probably suspended, try to make sure that we stay suspended.
+            MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+            // The thread switched back to runnable.
+            if (thread->GetState() == kRunnable) {
+              continue;
+            }
+            thread->ModifySuspendCount(self, +1, false);
+            suspended_count_modified_threads.push_back(thread);
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  // Run the checkpoint on ourself while we wait for threads to suspend.
+  checkpoint_function->Run(self);
+
+  // Run the checkpoint on the suspended threads.
+  for (size_t i = 0; i < suspended_count_modified_threads.size(); ++i) {
+    Thread* thread = suspended_count_modified_threads[i];
+    if (!thread->IsSuspended()) {
+      // Wait until the thread is suspended.
+      uint64_t start = NanoTime();
+      do {
+        // Sleep for 100us.
+        usleep(100);
+      } while (!thread->IsSuspended());
+      uint64_t end = NanoTime();
+      // Shouldn't need to wait for longer than 1 millisecond.
+      const uint64_t threshold = 1;
+      if (NsToMs(end - start) > threshold) {
+        LOG(INFO) << "Warning: waited longer than " << threshold << " ms for thrad suspend"
+                  << std::endl;
+      }
+    }
+    // We know for sure that the thread is suspended at this point.
+    thread->RunCheckpointFunction();
+    {
+      MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+      thread->ModifySuspendCount(self, -1, false);
+    }
+  }
+
+  // Add one for self.
+  return count + suspended_count_modified_threads.size() + 1;
+}
+
 void ThreadList::SuspendAll() {
   Thread* self = Thread::Current();