Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp
38921 views
/*1* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 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 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/systemDictionary.hpp"26#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp"27#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"28#include "memory/genCollectedHeap.hpp"29#include "oops/instanceRefKlass.hpp"30#include "oops/oop.inline.hpp"31#include "runtime/init.hpp"32#include "runtime/interfaceSupport.hpp"33#include "runtime/java.hpp"34#include "runtime/javaCalls.hpp"35#include "runtime/mutexLocker.hpp"36#include "runtime/os.hpp"37#include "runtime/vmThread.hpp"3839// ======= Concurrent Mark Sweep Thread ========4041// The CMS thread is created when Concurrent Mark Sweep is used in the42// older of two generations in a generational memory system.4344ConcurrentMarkSweepThread*45ConcurrentMarkSweepThread::_cmst = NULL;46CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;47bool ConcurrentMarkSweepThread::_should_terminate = false;48int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;4950volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;51volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0;5253volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0;54volatile bool ConcurrentMarkSweepThread::_should_run = false;55// When icms is enabled, the icms thread is stopped until explicitly56// started.57volatile bool ConcurrentMarkSweepThread::_should_stop = true;5859SurrogateLockerThread*60ConcurrentMarkSweepThread::_slt = NULL;61SurrogateLockerThread::SLT_msg_type62ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;63Monitor*64ConcurrentMarkSweepThread::_sltMonitor = NULL;6566ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)67: ConcurrentGCThread() {68assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");69assert(_cmst == NULL, "CMS thread already created");70_cmst = this;71assert(_collector == NULL, "Collector already set");72_collector = collector;7374set_name("Concurrent Mark-Sweep GC Thread");7576if (os::create_thread(this, os::cgc_thread)) {77// An old comment here said: "Priority should be just less78// than that of VMThread". Since the VMThread runs at79// NearMaxPriority, the old comment was inaccurate, but80// changing the default priority to NearMaxPriority-181// could change current behavior, so the default of82// NearMaxPriority stays in place.83//84// Note that there's a possibility of the VMThread85// starving if UseCriticalCMSThreadPriority is on.86// That won't happen on Solaris for various reasons,87// but may well happen on non-Solaris platforms.88int native_prio;89if (UseCriticalCMSThreadPriority) {90native_prio = os::java_to_os_priority[CriticalPriority];91} else {92native_prio = os::java_to_os_priority[NearMaxPriority];93}94os::set_native_priority(this, native_prio);9596if (!DisableStartThread) {97os::start_thread(this);98}99}100_sltMonitor = SLT_lock;101assert(!CMSIncrementalMode || icms_is_enabled(), "Error");102}103104void ConcurrentMarkSweepThread::run() {105assert(this == cmst(), "just checking");106107this->record_stack_base_and_size();108this->initialize_thread_local_storage();109this->set_active_handles(JNIHandleBlock::allocate_block());110// From this time Thread::current() should be working.111assert(this == Thread::current(), "just checking");112if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) {113warning("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread);114}115// Wait until Universe::is_fully_initialized()116{117CMSLoopCountWarn loopX("CMS::run", "waiting for "118"Universe::is_fully_initialized()", 2);119MutexLockerEx x(CGC_lock, true);120set_CMS_flag(CMS_cms_wants_token);121// Wait until Universe is initialized and all initialization is completed.122while (!is_init_completed() && !Universe::is_fully_initialized() &&123!_should_terminate) {124CGC_lock->wait(true, 200);125loopX.tick();126}127// Wait until the surrogate locker thread that will do128// pending list locking on our behalf has been created.129// We cannot start the SLT thread ourselves since we need130// to be a JavaThread to do so.131CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);132while (_slt == NULL && !_should_terminate) {133CGC_lock->wait(true, 200);134loopY.tick();135}136clear_CMS_flag(CMS_cms_wants_token);137}138139while (!_should_terminate) {140sleepBeforeNextCycle();141if (_should_terminate) break;142GCCause::Cause cause = _collector->_full_gc_requested ?143_collector->_full_gc_cause : GCCause::_cms_concurrent_mark;144_collector->collect_in_background(false, cause);145}146assert(_should_terminate, "just checking");147// Check that the state of any protocol for synchronization148// between background (CMS) and foreground collector is "clean"149// (i.e. will not potentially block the foreground collector,150// requiring action by us).151verify_ok_to_terminate();152// Signal that it is terminated153{154MutexLockerEx mu(Terminator_lock,155Mutex::_no_safepoint_check_flag);156assert(_cmst == this, "Weird!");157_cmst = NULL;158Terminator_lock->notify();159}160161// Thread destructor usually does this..162ThreadLocalStorage::set_thread(NULL);163}164165#ifndef PRODUCT166void ConcurrentMarkSweepThread::verify_ok_to_terminate() const {167assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() ||168cms_thread_wants_cms_token()),169"Must renounce all worldly possessions and desires for nirvana");170_collector->verify_ok_to_terminate();171}172#endif173174// create and start a new ConcurrentMarkSweep Thread for given CMS generation175ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) {176if (!_should_terminate) {177assert(cmst() == NULL, "start() called twice?");178ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector);179assert(cmst() == th, "Where did the just-created CMS thread go?");180return th;181}182return NULL;183}184185void ConcurrentMarkSweepThread::stop() {186if (CMSIncrementalMode) {187// Disable incremental mode and wake up the thread so it notices the change.188disable_icms();189start_icms();190}191// it is ok to take late safepoints here, if needed192{193MutexLockerEx x(Terminator_lock);194_should_terminate = true;195}196{ // Now post a notify on CGC_lock so as to nudge197// CMS thread(s) that might be slumbering in198// sleepBeforeNextCycle.199MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);200CGC_lock->notify_all();201}202{ // Now wait until (all) CMS thread(s) have exited203MutexLockerEx x(Terminator_lock);204while(cmst() != NULL) {205Terminator_lock->wait();206}207}208}209210void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) {211assert(tc != NULL, "Null ThreadClosure");212if (_cmst != NULL) {213tc->do_thread(_cmst);214}215assert(Universe::is_fully_initialized(),216"Called too early, make sure heap is fully initialized");217if (_collector != NULL) {218AbstractWorkGang* gang = _collector->conc_workers();219if (gang != NULL) {220gang->threads_do(tc);221}222}223}224225void ConcurrentMarkSweepThread::print_on(outputStream* st) const {226st->print("\"%s\" ", name());227Thread::print_on(st);228st->cr();229}230231void ConcurrentMarkSweepThread::print_all_on(outputStream* st) {232if (_cmst != NULL) {233_cmst->print_on(st);234st->cr();235}236if (_collector != NULL) {237AbstractWorkGang* gang = _collector->conc_workers();238if (gang != NULL) {239gang->print_worker_threads_on(st);240}241}242}243244void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) {245assert(UseConcMarkSweepGC, "just checking");246247MutexLockerEx x(CGC_lock,248Mutex::_no_safepoint_check_flag);249if (!is_cms_thread) {250assert(Thread::current()->is_VM_thread(), "Not a VM thread");251CMSSynchronousYieldRequest yr;252while (CMS_flag_is_set(CMS_cms_has_token)) {253// indicate that we want to get the token254set_CMS_flag(CMS_vm_wants_token);255CGC_lock->wait(true);256}257// claim the token and proceed258clear_CMS_flag(CMS_vm_wants_token);259set_CMS_flag(CMS_vm_has_token);260} else {261assert(Thread::current()->is_ConcurrentGC_thread(),262"Not a CMS thread");263// The following barrier assumes there's only one CMS thread.264// This will need to be modified is there are more CMS threads than one.265while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) {266set_CMS_flag(CMS_cms_wants_token);267CGC_lock->wait(true);268}269// claim the token270clear_CMS_flag(CMS_cms_wants_token);271set_CMS_flag(CMS_cms_has_token);272}273}274275void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {276assert(UseConcMarkSweepGC, "just checking");277278MutexLockerEx x(CGC_lock,279Mutex::_no_safepoint_check_flag);280if (!is_cms_thread) {281assert(Thread::current()->is_VM_thread(), "Not a VM thread");282assert(CMS_flag_is_set(CMS_vm_has_token), "just checking");283clear_CMS_flag(CMS_vm_has_token);284if (CMS_flag_is_set(CMS_cms_wants_token)) {285// wake-up a waiting CMS thread286CGC_lock->notify();287}288assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token),289"Should have been cleared");290} else {291assert(Thread::current()->is_ConcurrentGC_thread(),292"Not a CMS thread");293assert(CMS_flag_is_set(CMS_cms_has_token), "just checking");294clear_CMS_flag(CMS_cms_has_token);295if (CMS_flag_is_set(CMS_vm_wants_token)) {296// wake-up a waiting VM thread297CGC_lock->notify();298}299assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),300"Should have been cleared");301}302}303304// Wait until any cms_lock event305void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {306MutexLockerEx x(CGC_lock,307Mutex::_no_safepoint_check_flag);308if (_should_terminate || _collector->_full_gc_requested) {309return;310}311set_CMS_flag(CMS_cms_wants_token); // to provoke notifies312CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis);313clear_CMS_flag(CMS_cms_wants_token);314assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),315"Should not be set");316}317318// Wait until the next synchronous GC, a concurrent full gc request,319// or a timeout, whichever is earlier.320void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {321// Wait time in millis or 0 value representing infinite wait for a scavenge322assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive");323324GenCollectedHeap* gch = GenCollectedHeap::heap();325double start_time_secs = os::elapsedTime();326double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS));327328// Total collections count before waiting loop329unsigned int before_count;330{331MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);332before_count = gch->total_collections();333}334335unsigned int loop_count = 0;336337while(!_should_terminate) {338double now_time = os::elapsedTime();339long wait_time_millis;340341if(t_millis != 0) {342// New wait limit343wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS);344if(wait_time_millis <= 0) {345// Wait time is over346break;347}348} else {349// No wait limit, wait if necessary forever350wait_time_millis = 0;351}352353// Wait until the next event or the remaining timeout354{355MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);356357if (_should_terminate || _collector->_full_gc_requested) {358return;359}360set_CMS_flag(CMS_cms_wants_token); // to provoke notifies361assert(t_millis == 0 || wait_time_millis > 0, "Sanity");362CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis);363clear_CMS_flag(CMS_cms_wants_token);364assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),365"Should not be set");366}367368// Extra wait time check before entering the heap lock to get the collection count369if(t_millis != 0 && os::elapsedTime() >= end_time_secs) {370// Wait time is over371break;372}373374// Total collections count after the event375unsigned int after_count;376{377MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);378after_count = gch->total_collections();379}380381if(before_count != after_count) {382// There was a collection - success383break;384}385386// Too many loops warning387if(++loop_count == 0) {388warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1);389}390}391}392393void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {394while (!_should_terminate) {395if (CMSIncrementalMode) {396icms_wait();397if(CMSWaitDuration >= 0) {398// Wait until the next synchronous GC, a concurrent full gc399// request or a timeout, whichever is earlier.400wait_on_cms_lock_for_scavenge(CMSWaitDuration);401}402return;403} else {404if(CMSWaitDuration >= 0) {405// Wait until the next synchronous GC, a concurrent full gc406// request or a timeout, whichever is earlier.407wait_on_cms_lock_for_scavenge(CMSWaitDuration);408} else {409// Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently410wait_on_cms_lock(CMSCheckInterval);411}412}413// Check if we should start a CMS collection cycle414if (_collector->shouldConcurrentCollect()) {415return;416}417// .. collection criterion not yet met, let's go back418// and wait some more419}420}421422// Incremental CMS423void ConcurrentMarkSweepThread::start_icms() {424assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");425MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);426trace_state("start_icms");427_should_run = true;428iCMS_lock->notify_all();429}430431void ConcurrentMarkSweepThread::stop_icms() {432assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");433MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);434if (!_should_stop) {435trace_state("stop_icms");436_should_stop = true;437_should_run = false;438asynchronous_yield_request();439iCMS_lock->notify_all();440}441}442443void ConcurrentMarkSweepThread::icms_wait() {444assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");445if (_should_stop && icms_is_enabled()) {446MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);447trace_state("pause_icms");448_collector->stats().stop_cms_timer();449while(!_should_run && icms_is_enabled()) {450iCMS_lock->wait(Mutex::_no_safepoint_check_flag);451}452_collector->stats().start_cms_timer();453_should_stop = false;454trace_state("pause_icms end");455}456}457458// Note: this method, although exported by the ConcurrentMarkSweepThread,459// which is a non-JavaThread, can only be called by a JavaThread.460// Currently this is done at vm creation time (post-vm-init) by the461// main/Primordial (Java)Thread.462// XXX Consider changing this in the future to allow the CMS thread463// itself to create this thread?464void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) {465assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC");466assert(_slt == NULL, "SLT already created");467_slt = SurrogateLockerThread::make(THREAD);468}469470471