src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp

Print this page
rev 4482 : 8013934: Garbage collection event for CMS has wrong cause for System.gc()

@@ -61,10 +61,11 @@
 #include "services/runtimeService.hpp"
 
 // statics
 CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
 bool          CMSCollector::_full_gc_requested          = false;
+GCCause::Cause CMSCollector::_full_gc_cause = GCCause::_no_gc;
 
 //////////////////////////////////////////////////////////////////
 // In support of CMS/VM thread synchronization
 //////////////////////////////////////////////////////////////////
 // We split use of the CGC_lock into 2 "levels".

@@ -1681,16 +1682,17 @@
   acquire_control_and_collect(full, clear_all_soft_refs);
   _full_gcs_since_conc_gc++;
 
 }
 
-void CMSCollector::request_full_gc(unsigned int full_gc_count) {
+void CMSCollector::request_full_gc(unsigned int full_gc_count, GCCause::Cause cause) {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   unsigned int gc_count = gch->total_full_collections();
   if (gc_count == full_gc_count) {
     MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
     _full_gc_requested = true;
+    _full_gc_cause = cause;
     CGC_lock->notify();   // nudge CMS thread
   } else {
     assert(gc_count > full_gc_count, "Error: causal loop");
   }
 }

@@ -2121,11 +2123,11 @@
       // In the foreground case don't do the precleaning since
       // it is not done concurrently and there is extra work
       // required.
       _collectorState = FinalMarking;
   }
-  collect_in_foreground(clear_all_soft_refs);
+  collect_in_foreground(clear_all_soft_refs, GenCollectedHeap::heap()->gc_cause());
 
   // For a mark-sweep, compute_new_size() will be called
   // in the heap's do_collection() method.
 }
 

@@ -2184,11 +2186,11 @@
 // the different locking requirements of the background collector and the
 // foreground collector.  There was originally an attempt to share
 // one "collect" method between the background collector and the foreground
 // collector but the if-then-else required made it cleaner to have
 // separate methods.
-void CMSCollector::collect_in_background(bool clear_all_soft_refs) {
+void CMSCollector::collect_in_background(bool clear_all_soft_refs, GCCause::Cause cause) {
   assert(Thread::current()->is_ConcurrentGC_thread(),
     "A CMS asynchronous collection is only allowed on a CMS thread.");
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   {

@@ -2203,19 +2205,20 @@
       assert(!_foregroundGCShouldWait, "Should be clear");
       return;
     } else {
       assert(_collectorState == Idling, "Should be idling before start.");
       _collectorState = InitialMarking;
-      register_gc_start(GCCause::_cms_concurrent_mark);
+      register_gc_start(cause);
       // Reset the expansion cause, now that we are about to begin
       // a new cycle.
       clear_expansion_cause();
     }
     // Decide if we want to enable class unloading as part of the
     // ensuing concurrent GC cycle.
     update_should_unload_classes();
     _full_gc_requested = false;           // acks all outstanding full gc requests
+    _full_gc_cause = GCCause::_no_gc;
     // Signal that we are about to start a collection
     gch->increment_total_full_collections();  // ... starting a collection cycle
     _collection_count_start = gch->total_full_collections();
   }
 

@@ -2458,11 +2461,11 @@
 
 void CMSCollector::report_heap_summary(GCWhen::Type when) {
   _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_perm_gen_summary);
 }
 
-void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
+void CMSCollector::collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause) {
   assert(_foregroundGCIsActive && !_foregroundGCShouldWait,
          "Foreground collector should be waiting, not executing");
   assert(Thread::current()->is_VM_thread(), "A foreground collection"
     "may only be done by the VM Thread with the world stopped");
   assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),

@@ -2491,11 +2494,11 @@
       gclog_or_tty->print_cr("Thread " INTPTR_FORMAT " in CMS state %d",
         Thread::current(), _collectorState);
     }
     switch (_collectorState) {
       case InitialMarking:
-        register_foreground_gc_start(GenCollectedHeap::heap()->gc_cause());
+        register_foreground_gc_start(cause);
         init_mark_was_synchronous = true;  // fact to be exploited in re-mark
         checkpointRootsInitial(false);
         assert(_collectorState == Marking, "Collector state should have changed"
           " within checkpointRootsInitial()");
         break;