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/shenandoah/shenandoahConcurrentThread.hpp"
  25 #include "gc/shenandoah/shenandoahHeap.hpp"
  26 #include "gc/shenandoah/shenandoahJNICritical.hpp"
  27 #include "gc/shenandoah/vm_operations_shenandoah.hpp"
  28 #include "memory/iterator.hpp"
  29 #include "memory/universe.hpp"
  30 #include "runtime/vmThread.hpp"
  31 
  32 SurrogateLockerThread* ShenandoahConcurrentThread::_slt = NULL;
  33 
  34 ShenandoahConcurrentThread::ShenandoahConcurrentThread() :
  35   ConcurrentGCThread(),
  36   _epoch(0),
  37   _concurrent_mark_started(false),
  38   _concurrent_mark_in_progress(false),
  39   _do_full_gc(false),
  40   _concurrent_mark_aborted(false)
  41 {
  42   create_and_start();
  43 }
  44 
  45 ShenandoahConcurrentThread::~ShenandoahConcurrentThread() {
  46   // This is here so that super is called.
  47 }
  48 
  49 void ShenandoahConcurrentThread::run() {
  50   initialize_in_thread();
  51 
  52   wait_for_universe_init();
  53 
  54   // Wait until we have the surrogate locker thread in place.
  55   {
  56     MutexLockerEx x(CGC_lock, true);
  57     while(_slt == NULL && !_should_terminate) {
  58       CGC_lock->wait(true, 200);
  59     }
  60   }
  61 
  62   ShenandoahHeap* heap = ShenandoahHeap::heap();
  63 
  64   while (!_should_terminate) {
  65     if (_do_full_gc) {
  66       {
  67         if (_full_gc_cause == GCCause::_allocation_failure) {
  68           heap->shenandoahPolicy()->record_allocation_failure_gc();
  69         } else {
  70           heap->shenandoahPolicy()->record_user_requested_gc();
  71         }
  72 
  73         VM_ShenandoahFullGC full_gc;
  74         heap->jni_critical()->execute_in_vm_thread(&full_gc);
  75       }
  76       MonitorLockerEx ml(ShenandoahFullGC_lock);
  77       _do_full_gc = false;
  78       ml.notify_all();
  79     } else if (heap->shenandoahPolicy()->should_start_concurrent_mark(heap->used(),
  80                                                                heap->capacity()))
  81       {
  82 
  83         if (ShenandoahGCVerbose)
  84           tty->print("Capacity = "SIZE_FORMAT" Used = "SIZE_FORMAT"  doing initMark\n", heap->capacity(), heap->used());
  85 
  86         if (ShenandoahGCVerbose) tty->print("Starting a mark");
  87 
  88         VM_ShenandoahInitMark initMark;
  89         VMThread::execute(&initMark);
  90 
  91         if (ShenandoahConcurrentMarking) {
  92           ShenandoahHeap::heap()->concurrentMark()->mark_from_roots();
  93 
  94           VM_ShenandoahStartEvacuation finishMark;
  95           heap->jni_critical()->execute_in_vm_thread(&finishMark);
  96         }
  97 
  98         if (cm_has_aborted()) {
  99           clear_cm_aborted();
 100           assert(heap->is_bitmap_clear(), "need to continue with clear mark bitmap");
 101           assert(! heap->concurrent_mark_in_progress(), "concurrent mark must have terminated");
 102           continue;
 103         }
 104         if (! _should_terminate) {
 105           // If we're not concurrently evacuating, evacuation is done
 106           // from VM_ShenandoahFinishMark within the VMThread above.
 107           if (ShenandoahConcurrentEvacuation) {
 108             VM_ShenandoahEvacuation evacuation;
 109             evacuation.doit();
 110           }
 111         }
 112 
 113         if (heap->shenandoahPolicy()->update_refs_early() && ! _should_terminate && ! heap->cancelled_concgc()) {
 114           if (ShenandoahConcurrentUpdateRefs) {
 115             VM_ShenandoahUpdateRefs update_refs;
 116             VMThread::execute(&update_refs);
 117             heap->update_references();
 118           }
 119         } else {
 120           if (heap->is_evacuation_in_progress()) {
 121             heap->set_evacuation_in_progress(false);
 122           }
 123           heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::reset_bitmaps);
 124           heap->reset_mark_bitmap();
 125           heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::reset_bitmaps);
 126         }
 127 
 128       } else {
 129       Thread::current()->_ParkEvent->park(10) ;
 130       // yield();
 131     }
 132     heap->clear_cancelled_concgc();
 133     // Make sure the _do_full_gc flag changes are seen.
 134     OrderAccess::storeload();
 135   }
 136 }
 137 
 138 void ShenandoahConcurrentThread::do_full_gc(GCCause::Cause cause) {
 139 
 140   assert(Thread::current()->is_Java_thread(), "expect Java thread here");
 141 
 142   MonitorLockerEx ml(ShenandoahFullGC_lock);
 143   schedule_full_gc();
 144   _full_gc_cause = cause;
 145   while (_do_full_gc) {
 146     ml.wait();
 147     OrderAccess::storeload();
 148   }
 149   assert(_do_full_gc == false, "expect full GC to have completed");
 150 }
 151 
 152 void ShenandoahConcurrentThread::schedule_full_gc() {
 153   _do_full_gc = true;
 154 }
 155 
 156 void ShenandoahConcurrentThread::print() const {
 157   print_on(tty);
 158 }
 159 
 160 void ShenandoahConcurrentThread::print_on(outputStream* st) const {
 161   st->print("Shenandoah Concurrent Thread");
 162   Thread::print_on(st);
 163   st->cr();
 164 }
 165 
 166 void ShenandoahConcurrentThread::sleepBeforeNextCycle() {
 167   assert(false, "Wake up in the GC thread that never sleeps :-)");
 168 }
 169 
 170 void ShenandoahConcurrentThread::set_cm_started() {
 171     assert(!_concurrent_mark_in_progress, "cycle in progress");
 172     _concurrent_mark_started = true;
 173 }
 174 
 175 void ShenandoahConcurrentThread::clear_cm_started() {
 176     assert(_concurrent_mark_in_progress, "must be starting a cycle");
 177     _concurrent_mark_started = false;
 178 }
 179 
 180 bool ShenandoahConcurrentThread::cm_started() {
 181   return _concurrent_mark_started;
 182 }
 183 
 184 void ShenandoahConcurrentThread::set_cm_in_progress() {
 185   assert(_concurrent_mark_started, "must be starting a cycle");
 186   _concurrent_mark_in_progress = true;
 187 }
 188 
 189 void ShenandoahConcurrentThread::clear_cm_in_progress() {
 190   assert(!_concurrent_mark_started, "must not be starting a new cycle");
 191   _concurrent_mark_in_progress = false;
 192 }
 193 
 194 bool ShenandoahConcurrentThread::cm_in_progress() {
 195   return _concurrent_mark_in_progress;
 196 }
 197 
 198 void ShenandoahConcurrentThread::start() {
 199   create_and_start();
 200 }
 201 
 202 void ShenandoahConcurrentThread::yield() {
 203   _sts.yield();
 204 }
 205 
 206 void ShenandoahConcurrentThread::safepoint_synchronize() {
 207   assert(UseShenandoahGC, "just checking");
 208   _sts.synchronize();
 209 }
 210 
 211 void ShenandoahConcurrentThread::safepoint_desynchronize() {
 212   assert(UseShenandoahGC, "just checking");
 213   _sts.desynchronize();
 214 }
 215 
 216 void ShenandoahConcurrentThread::makeSurrogateLockerThread(TRAPS) {
 217   assert(UseShenandoahGC, "SLT thread needed only for concurrent GC");
 218   assert(THREAD->is_Java_thread(), "must be a Java thread");
 219   assert(_slt == NULL, "SLT already created");
 220   _slt = SurrogateLockerThread::make(THREAD);
 221 }
 222 
 223 void ShenandoahConcurrentThread::shutdown() {
 224   _should_terminate = true;
 225 }