1 /*
   2  * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "gc/shared/gcTraceTime.inline.hpp"
  25 #include "gc/shenandoah/shenandoahConcurrentThread.hpp"
  26 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
  27 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  28 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
  29 #include "gc/shenandoah/vm_operations_shenandoah.hpp"
  30 #include "memory/iterator.hpp"
  31 #include "memory/universe.hpp"
  32 #include "runtime/vmThread.hpp"
  33 
  34 ShenandoahConcurrentThread::ShenandoahConcurrentThread() :
  35   ConcurrentGCThread(),
  36   _full_gc_lock(Mutex::leaf, "ShenandoahFullGC_lock", true, Monitor::_safepoint_check_always),
  37   _do_full_gc(false)
  38 {
  39   create_and_start();
  40 }
  41 
  42 ShenandoahConcurrentThread::~ShenandoahConcurrentThread() {
  43   // This is here so that super is called.
  44 }
  45 
  46 void ShenandoahConcurrentThread::run_service() {
  47 
  48   ShenandoahHeap* heap = ShenandoahHeap::heap();
  49 
  50   GCTimer* gc_timer = heap->gc_timer();
  51 
  52   while (! should_terminate()) {
  53     if (_do_full_gc) {
  54       {
  55         if (_full_gc_cause == GCCause::_allocation_failure) {
  56           heap->shenandoahPolicy()->record_allocation_failure_gc();
  57         } else {
  58           heap->shenandoahPolicy()->record_user_requested_gc();
  59         }
  60 
  61         TraceCollectorStats tcs(heap->monitoring_support()->full_collection_counters());
  62         TraceMemoryManagerStats tmms(true, _full_gc_cause);
  63         VM_ShenandoahFullGC full_gc(_full_gc_cause);
  64         VMThread::execute(&full_gc);
  65       }
  66       MonitorLockerEx ml(&_full_gc_lock);
  67       _do_full_gc = false;
  68       ml.notify_all();
  69     } else if (heap->shenandoahPolicy()->should_start_concurrent_mark(heap->used(),
  70                                                                heap->capacity()))
  71       {
  72 
  73         gc_timer->register_gc_start();
  74 
  75         heap->shenandoahPolicy()->increase_cycle_counter();
  76 
  77         TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
  78         TraceMemoryManagerStats tmms(false, GCCause::_no_cause_specified);
  79 
  80         {
  81           TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
  82           VM_ShenandoahInitMark initMark;
  83           heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::init_mark_gross);
  84           VMThread::execute(&initMark);
  85           heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::init_mark_gross);
  86         }
  87         {
  88           GCTraceTime(Info, gc) time("Concurrent marking", gc_timer, GCCause::_no_gc, true);
  89           TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
  90           ShenandoahHeap::heap()->concurrentMark()->mark_from_roots();
  91         }
  92 
  93         {
  94           TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
  95           VM_ShenandoahStartEvacuation finishMark;
  96           heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_mark_gross);
  97           VMThread::execute(&finishMark);
  98           heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_mark_gross);
  99         }
 100 
 101         if (! should_terminate()) {
 102           GCTraceTime(Info, gc) time("Concurrent evacuation ", gc_timer, GCCause::_no_gc, true);
 103           TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
 104           heap->do_evacuation();
 105         }
 106 
 107         if (heap->is_evacuation_in_progress()) {
 108           MutexLocker mu(Threads_lock);
 109           heap->set_evacuation_in_progress(false);
 110         }
 111         heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::reset_bitmaps);
 112         heap->reset_next_mark_bitmap(heap->conc_workers());
 113         heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::reset_bitmaps);
 114 
 115         gc_timer->register_gc_end();
 116       } else {
 117       Thread::current()->_ParkEvent->park(10) ;
 118       // yield();
 119     }
 120 
 121     // Make sure the _do_full_gc flag changes are seen.
 122     OrderAccess::storeload();
 123   }
 124 }
 125 
 126 void ShenandoahConcurrentThread::stop_service() {
 127   // Nothing to do here.
 128 }
 129 
 130 void ShenandoahConcurrentThread::do_full_gc(GCCause::Cause cause) {
 131 
 132   assert(Thread::current()->is_Java_thread(), "expect Java thread here");
 133 
 134   MonitorLockerEx ml(&_full_gc_lock);
 135   schedule_full_gc();
 136   _full_gc_cause = cause;
 137   while (_do_full_gc) {
 138     ml.wait();
 139     OrderAccess::storeload();
 140   }
 141   assert(!_do_full_gc, "expect full GC to have completed");
 142 }
 143 
 144 void ShenandoahConcurrentThread::schedule_full_gc() {
 145   _do_full_gc = true;
 146 }
 147 
 148 void ShenandoahConcurrentThread::print() const {
 149   print_on(tty);
 150 }
 151 
 152 void ShenandoahConcurrentThread::print_on(outputStream* st) const {
 153   st->print("Shenandoah Concurrent Thread");
 154   Thread::print_on(st);
 155   st->cr();
 156 }
 157 
 158 void ShenandoahConcurrentThread::sleepBeforeNextCycle() {
 159   assert(false, "Wake up in the GC thread that never sleeps :-)");
 160 }
 161 
 162 void ShenandoahConcurrentThread::start() {
 163   create_and_start();
 164 }