Ensure that ConcurrentGC always increments GC num
ConcurrentGC could end up waiting for a GC type like TrimSpaces()
that does not actually end up incrementing completed_gcs_.
It would erroneously think it was done, leaving gcs_requested_
> gcs_completed_, with no task running to perform the requested
GCs, but further requests getting ignored until the next explicit
or heap-overflow GC.
Make ConcurrentGC() actually perform a GC unless the GC number
was incremented. Add a CHECK in ConcurrentGCTask::Run that can catch
this. (Confirmed because it did catch it before we added the fix.)
Have RequestConcurrentGC() return a bool to indicate whether it
did anything. This makes another CHECK possible, and should
eventually allow us to again sleep() until a GC starts.
Bug: 186592536
Bug: 189150802
Test: Build and boot AOSP
Change-Id: Ib11734a9c87b9f9e19c5a3557eac9024f84cadf3
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index bd899bc..047af16 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -836,8 +836,10 @@
// Request asynchronous GC. Observed_gc_num is the value of GetCurrentGcNum() when we started to
// evaluate the GC triggering condition. If a GC has been completed since then, we consider our
- // job done. Ensures that gcs_completed_ will eventually be incremented beyond observed_gc_num.
- void RequestConcurrentGC(Thread* self, GcCause cause, bool force_full, uint32_t observed_gc_num)
+ // job done. If we return true, then we ensured that gcs_completed_ will eventually be
+ // incremented beyond observed_gc_num. We return false only in corner cases in which we cannot
+ // ensure that.
+ bool RequestConcurrentGC(Thread* self, GcCause cause, bool force_full, uint32_t observed_gc_num)
REQUIRES(!*pending_task_lock_);
// Whether or not we may use a garbage collector, used so that we only create collectors we need.
@@ -1587,9 +1589,10 @@
// Increment is guarded by gc_complete_lock_.
Atomic<uint32_t> gcs_completed_;
- // The number of garbage collections we've scheduled. Normally either gcs_complete_ or
- // gcs_complete + 1.
- Atomic<uint32_t> gcs_requested_;
+ // The number of the last garbage collection that has been requested. A value of gcs_completed
+ // + 1 indicates that another collection is needed or in progress. A value of gcs_completed_ or
+ // (logically) less means that no new GC has been requested.
+ Atomic<uint32_t> max_gc_requested_;
// Active tasks which we can modify (change target time, desired collector type, etc..).
CollectorTransitionTask* pending_collector_transition_ GUARDED_BY(pending_task_lock_);