Move GC daemon locking logic into heap

Fixes deadlock caused by acquirng the mutator lock while
synchronizing on the daemon thread.

Bug: 18739541
Change-Id: I925b8f0f3b58178da6eff17b9c073f655c39597b
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 4e1a0ff..529af95 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -611,6 +611,9 @@
     return zygote_space_ != nullptr;
   }
 
+  void WaitForConcurrentGCRequest(Thread* self) LOCKS_EXCLUDED(gc_request_lock_);
+  void NotifyConcurrentGCRequest(Thread* self) LOCKS_EXCLUDED(gc_request_lock_);
+
  private:
   // Compact source space to target space.
   void Compact(space::ContinuousMemMapAllocSpace* target_space,
@@ -874,6 +877,11 @@
   Mutex* gc_complete_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   std::unique_ptr<ConditionVariable> gc_complete_cond_ GUARDED_BY(gc_complete_lock_);
 
+  // Guards concurrent GC requests.
+  Mutex* gc_request_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  std::unique_ptr<ConditionVariable> gc_request_cond_ GUARDED_BY(gc_request_lock_);
+  bool gc_request_pending_ GUARDED_BY(gc_request_lock_);
+
   // Reference processor;
   ReferenceProcessor reference_processor_;