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 }