Dump more debug info for b/33006388.

Bug: 33006388
Bug: 12687968
Test: test-art-host with CC.
Change-Id: Id9d67bc603c6ff7bc8e346e181e3e09ffbda43b3
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 19ee0fb..fbab73f 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -812,13 +812,13 @@
   false_gray_stack_.clear();
 }
 
-
 void ConcurrentCopying::IssueEmptyCheckpoint() {
   Thread* self = Thread::Current();
   ThreadList* thread_list = Runtime::Current()->GetThreadList();
   Barrier* barrier = thread_list->EmptyCheckpointBarrier();
   barrier->Init(self, 0);
-  size_t barrier_count = thread_list->RunEmptyCheckpoint();
+  std::vector<uint32_t> runnable_thread_ids;  // Used in debug build only
+  size_t barrier_count = thread_list->RunEmptyCheckpoint(runnable_thread_ids);
   // If there are no threads to wait which implys that all the checkpoint functions are finished,
   // then no need to release the mutator lock.
   if (barrier_count == 0) {
@@ -828,7 +828,27 @@
   Locks::mutator_lock_->SharedUnlock(self);
   {
     ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
-    barrier->Increment(self, barrier_count);
+    if (kIsDebugBuild) {
+      static constexpr uint64_t kEmptyCheckpointTimeoutMs = 600 * 1000;  // 10 minutes.
+      bool timed_out = barrier->Increment(self, barrier_count, kEmptyCheckpointTimeoutMs);
+      if (timed_out) {
+        Runtime* runtime = Runtime::Current();
+        std::ostringstream ss;
+        ss << "Empty checkpoint timeout\n";
+        ss << "Barrier count " << barrier->GetCount(self) << "\n";
+        ss << "Runnable thread IDs";
+        for (uint32_t tid : runnable_thread_ids) {
+          ss << " " << tid;
+        }
+        ss << "\n";
+        Locks::mutator_lock_->Dump(ss);
+        ss << "\n";
+        runtime->GetThreadList()->Dump(ss);
+        LOG(FATAL) << ss.str();
+      }
+    } else {
+      barrier->Increment(self, barrier_count);
+    }
   }
   Locks::mutator_lock_->SharedLock(self);
 }