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/shenandoahJNICritical.hpp" 29 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" 30 #include "gc/shenandoah/vm_operations_shenandoah.hpp" 31 #include "memory/iterator.hpp" 32 #include "memory/universe.hpp" 33 #include "runtime/vmThread.hpp" 34 35 ShenandoahConcurrentThread::ShenandoahConcurrentThread() : 36 ConcurrentGCThread(), 37 _full_gc_lock(Mutex::leaf, "ShenandoahFullGC_lock", true, Monitor::_safepoint_check_always), 38 _do_full_gc(false) 39 { 40 create_and_start(); 41 } 42 43 ShenandoahConcurrentThread::~ShenandoahConcurrentThread() { 44 // This is here so that super is called. 45 } 46 47 void ShenandoahConcurrentThread::run_service() { 48 49 while (! ReferencePendingListLocker::is_initialized()) { 50 os::naked_yield(); 51 } 52 53 ShenandoahHeap* heap = ShenandoahHeap::heap(); 54 55 GCTimer* gc_timer = heap->gc_timer(); 56 57 while (! should_terminate()) { 58 if (_do_full_gc) { 59 { 60 if (_full_gc_cause == GCCause::_allocation_failure) { 61 heap->shenandoahPolicy()->record_allocation_failure_gc(); 62 } else { 63 heap->shenandoahPolicy()->record_user_requested_gc(); 64 } 65 66 TraceCollectorStats tcs(heap->monitoring_support()->full_collection_counters()); 67 TraceMemoryManagerStats tmms(true, _full_gc_cause); 68 VM_ShenandoahFullGC full_gc(_full_gc_cause); 69 heap->jni_critical()->execute_in_vm_thread(&full_gc); 70 } 71 MonitorLockerEx ml(&_full_gc_lock); 72 _do_full_gc = false; 73 ml.notify_all(); 74 } else if (heap->shenandoahPolicy()->should_start_concurrent_mark(heap->used(), 75 heap->capacity())) 76 { 77 78 gc_timer->register_gc_start(); 79 80 heap->shenandoahPolicy()->increase_cycle_counter(); 81 82 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); 83 TraceMemoryManagerStats tmms(false, GCCause::_no_cause_specified); 84 if (ShenandoahGCVerbose) 85 tty->print("Capacity = "SIZE_FORMAT" Used = "SIZE_FORMAT" doing initMark\n", heap->capacity(), heap->used()); 86 87 if (ShenandoahGCVerbose) tty->print("Starting a mark"); 88 89 { 90 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters()); 91 VM_ShenandoahInitMark initMark; 92 heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::init_mark_gross); 93 VMThread::execute(&initMark); 94 heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::init_mark_gross); 95 } 96 { 97 GCTraceTime(Info, gc, phases) time("Concurrent marking", gc_timer, GCCause::_no_gc, true); 98 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); 99 ShenandoahHeap::heap()->concurrentMark()->mark_from_roots(); 100 } 101 102 { 103 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters()); 104 VM_ShenandoahStartEvacuation finishMark; 105 heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_mark_gross); 106 heap->jni_critical()->execute_in_vm_thread(&finishMark); 107 heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_mark_gross); 108 } 109 110 if (! should_terminate()) { 111 GCTraceTime(Info, gc, phases) time("Concurrent evacuation", gc_timer, GCCause::_no_gc, true); 112 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); 113 heap->do_evacuation(); 114 } 115 116 if (heap->is_evacuation_in_progress()) { 117 heap->set_evacuation_in_progress(false); 118 } 119 heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::reset_bitmaps); 120 heap->reset_mark_bitmap(); 121 heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::reset_bitmaps); 122 123 gc_timer->register_gc_end(); 124 } else { 125 Thread::current()->_ParkEvent->park(10) ; 126 // yield(); 127 } 128 129 // Make sure the _do_full_gc flag changes are seen. 130 OrderAccess::storeload(); 131 } 132 } 133 134 void ShenandoahConcurrentThread::stop_service() { 135 // Nothing to do here. 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(&_full_gc_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::start() { 171 create_and_start(); 172 }