# HG changeset patch # User drwhite # Date 1457542731 18000 # Wed Mar 09 11:58:51 2016 -0500 # Node ID a74fa34dc5908d6061e503517acdd3a6bd013f88 # Parent f81ea6b38171dac0bfa938b1adb9c6c610f71fd8 imported patch webrev.01 diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -166,7 +166,7 @@ return NULL; } -void ConcurrentMarkSweepThread::stop() { +void ConcurrentMarkSweepThread::stop_all() { // it is ok to take late safepoints here, if needed { MutexLockerEx x(Terminator_lock); diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,10 @@ // Create and start the CMS Thread, or stop it on shutdown static ConcurrentMarkSweepThread* start(CMSCollector* collector); - static void stop(); + static void stop_all(); static bool should_terminate() { return _should_terminate; } + // ConcurrentMarkSweepThread uses it's own termination protocol, not ConcurrentGCThread's: + virtual void stop() { ShouldNotReachHere(); } // Synchronization using CMS token static void synchronize(bool is_cms_thread); diff --git a/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/src/share/vm/gc/g1/concurrentG1RefineThread.cpp --- a/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -109,15 +109,6 @@ } } -void ConcurrentG1RefineThread::run() { - initialize_in_thread(); - wait_for_universe_init(); - - run_service(); - - terminate(); -} - void ConcurrentG1RefineThread::run_service() { _vtime_start = os::elapsedVTime(); @@ -168,23 +159,6 @@ log_debug(gc, refine)("Stopping %d", _worker_id); } -void ConcurrentG1RefineThread::stop() { - // it is ok to take late safepoints here, if needed - { - MutexLockerEx mu(Terminator_lock); - _should_terminate = true; - } - - stop_service(); - - { - MutexLockerEx mu(Terminator_lock); - while (!_has_terminated) { - Terminator_lock->wait(); - } - } -} - void ConcurrentG1RefineThread::stop_service() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); _monitor->notify(); diff --git a/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/src/share/vm/gc/g1/concurrentG1RefineThread.hpp --- a/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -72,7 +72,6 @@ void stop_service(); public: - virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, CardTableEntryClosure* refine_closure, @@ -84,9 +83,6 @@ double vtime_accum() { return _vtime_accum; } ConcurrentG1Refine* cg1r() { return _cg1r; } - - // shutdown - void stop(); }; #endif // SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP diff --git a/src/share/vm/gc/g1/concurrentMarkThread.cpp b/src/share/vm/gc/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -105,15 +105,6 @@ } }; -void ConcurrentMarkThread::run() { - initialize_in_thread(); - wait_for_universe_init(); - - run_service(); - - terminate(); -} - void ConcurrentMarkThread::run_service() { _vtime_start = os::elapsedVTime(); @@ -293,22 +284,6 @@ } } -void ConcurrentMarkThread::stop() { - { - MutexLockerEx ml(Terminator_lock); - _should_terminate = true; - } - - stop_service(); - - { - MutexLockerEx ml(Terminator_lock); - while (!_has_terminated) { - Terminator_lock->wait(); - } - } -} - void ConcurrentMarkThread::stop_service() { MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag); CGC_lock->notify_all(); diff --git a/src/share/vm/gc/g1/concurrentMarkThread.hpp b/src/share/vm/gc/g1/concurrentMarkThread.hpp --- a/src/share/vm/gc/g1/concurrentMarkThread.hpp +++ b/src/share/vm/gc/g1/concurrentMarkThread.hpp @@ -38,13 +38,8 @@ double _vtime_start; // Initial virtual time. double _vtime_accum; // Accumulated virtual time. - double _vtime_mark_accum; - public: - virtual void run(); - - private: G1ConcurrentMark* _cm; enum State { @@ -93,9 +88,6 @@ // as the CM thread might take some time to wake up before noticing // that started() is set and set in_progress(). bool during_cycle() { return !idle(); } - - // shutdown - void stop(); }; #endif // SHARE_VM_GC_G1_CONCURRENTMARKTHREAD_HPP diff --git a/src/share/vm/gc/g1/g1StringDedup.cpp b/src/share/vm/gc/g1/g1StringDedup.cpp --- a/src/share/vm/gc/g1/g1StringDedup.cpp +++ b/src/share/vm/gc/g1/g1StringDedup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ void G1StringDedup::stop() { assert(is_enabled(), "String deduplication not enabled"); - G1StringDedupThread::stop(); + G1StringDedupThread::thread()->stop(); } bool G1StringDedup::is_candidate_from_mark(oop obj) { diff --git a/src/share/vm/gc/g1/g1StringDedupThread.cpp b/src/share/vm/gc/g1/g1StringDedupThread.cpp --- a/src/share/vm/gc/g1/g1StringDedupThread.cpp +++ b/src/share/vm/gc/g1/g1StringDedupThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,11 +81,9 @@ StringTable::shared_oops_do(&sharedStringDedup); } -void G1StringDedupThread::run() { +void G1StringDedupThread::run_service() { G1StringDedupStat total_stat; - initialize_in_thread(); - wait_for_universe_init(); deduplicate_shared_strings(total_stat); // Main loop @@ -133,23 +131,10 @@ } } - terminate(); } -void G1StringDedupThread::stop() { - { - MonitorLockerEx ml(Terminator_lock); - _thread->_should_terminate = true; - } - +void G1StringDedupThread::stop_service() { G1StringDedupQueue::cancel_wait(); - - { - MonitorLockerEx ml(Terminator_lock); - while (!_thread->_has_terminated) { - ml.wait(); - } - } } void G1StringDedupThread::print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) { diff --git a/src/share/vm/gc/g1/g1StringDedupThread.hpp b/src/share/vm/gc/g1/g1StringDedupThread.hpp --- a/src/share/vm/gc/g1/g1StringDedupThread.hpp +++ b/src/share/vm/gc/g1/g1StringDedupThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,14 +45,14 @@ void print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat); + void run_service(); + void stop_service(); + public: static void create(); - static void stop(); - + static G1StringDedupThread* thread(); - virtual void run(); - void deduplicate_shared_strings(G1StringDedupStat& stat); }; diff --git a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp --- a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -32,32 +32,6 @@ #include "gc/g1/suspendibleThreadSet.hpp" #include "runtime/mutexLocker.hpp" -void G1YoungRemSetSamplingThread::run() { - initialize_in_thread(); - wait_for_universe_init(); - - run_service(); - - terminate(); -} - -void G1YoungRemSetSamplingThread::stop() { - // it is ok to take late safepoints here, if needed - { - MutexLockerEx mu(Terminator_lock); - _should_terminate = true; - } - - stop_service(); - - { - MutexLockerEx mu(Terminator_lock); - while (!_has_terminated) { - Terminator_lock->wait(); - } - } -} - G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread(), _monitor(Mutex::nonleaf, diff --git a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp --- a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp +++ b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp @@ -55,9 +55,6 @@ public: G1YoungRemSetSamplingThread(); double vtime_accum() { return _vtime_accum; } - - virtual void run(); - void stop(); }; #endif // SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP diff --git a/src/share/vm/gc/shared/concurrentGCThread.cpp b/src/share/vm/gc/shared/concurrentGCThread.cpp --- a/src/share/vm/gc/shared/concurrentGCThread.cpp +++ b/src/share/vm/gc/shared/concurrentGCThread.cpp @@ -75,6 +75,32 @@ } } +void ConcurrentGCThread::run() { + initialize_in_thread(); + wait_for_universe_init(); + + run_service(); + + terminate(); +} + +void ConcurrentGCThread::stop() { + // it is ok to take late safepoints here, if needed + { + MutexLockerEx mu(Terminator_lock); + _should_terminate = true; + } + + stop_service(); + + { + MutexLockerEx mu(Terminator_lock); + while (!_has_terminated) { + Terminator_lock->wait(); + } + } +} + static void _sltLoop(JavaThread* thread, TRAPS) { SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; slt->loop(); diff --git a/src/share/vm/gc/shared/concurrentGCThread.hpp b/src/share/vm/gc/shared/concurrentGCThread.hpp --- a/src/share/vm/gc/shared/concurrentGCThread.hpp +++ b/src/share/vm/gc/shared/concurrentGCThread.hpp @@ -48,12 +48,27 @@ // Record that the current thread is terminating, and will do more // concurrent work. void terminate(); + + // Most implementations of ConcurrentGCThread use ConcurrentGCThread's termination protocol, + // run(), and stop() methods, and provide specific implementations of run_service() and stop_service. + // Otherwise run_service() and stop_service should not be called.) + + // Do the specific GC work. Called by run() after initialization complete. + virtual void run_service() { ShouldNotReachHere(); } + + // Shut down the specific GC work. Called by stop() as part of termination protocol. + virtual void stop_service() { ShouldNotReachHere(); } public: ConcurrentGCThread(); // Tester bool is_ConcurrentGC_thread() const { return true; } + + virtual void run(); + + // shutdown following termination protocol + virtual void stop(); }; // The SurrogateLockerThread is used by concurrent GC threads for diff --git a/src/share/vm/gc/shared/genCollectedHeap.cpp b/src/share/vm/gc/shared/genCollectedHeap.cpp --- a/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -1281,7 +1281,7 @@ void GenCollectedHeap::stop() { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { - ConcurrentMarkSweepThread::stop(); + ConcurrentMarkSweepThread::stop_all(); } #endif } # HG changeset patch # User drwhite # Date 1457542731 18000 # Wed Mar 09 11:58:51 2016 -0500 # Node ID 323757004135716f1b6cd8fd8c0528ebd3ff7159 # Parent a74fa34dc5908d6061e503517acdd3a6bd013f88 imported patch webrev.02 diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp @@ -42,7 +42,6 @@ ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::_cmst = NULL; CMSCollector* ConcurrentMarkSweepThread::_collector = NULL; -bool ConcurrentMarkSweepThread::_should_terminate = false; int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; @@ -62,54 +61,34 @@ set_name("CMS Main Thread"); - if (os::create_thread(this, os::cgc_thread)) { - // An old comment here said: "Priority should be just less - // than that of VMThread". Since the VMThread runs at - // NearMaxPriority, the old comment was inaccurate, but - // changing the default priority to NearMaxPriority-1 - // could change current behavior, so the default of - // NearMaxPriority stays in place. - // - // Note that there's a possibility of the VMThread - // starving if UseCriticalCMSThreadPriority is on. - // That won't happen on Solaris for various reasons, - // but may well happen on non-Solaris platforms. - int native_prio; - if (UseCriticalCMSThreadPriority) { - native_prio = os::java_to_os_priority[CriticalPriority]; - } else { - native_prio = os::java_to_os_priority[NearMaxPriority]; - } - os::set_native_priority(this, native_prio); + // An old comment here said: "Priority should be just less + // than that of VMThread". Since the VMThread runs at + // NearMaxPriority, the old comment was inaccurate, but + // changing the default priority to NearMaxPriority-1 + // could change current behavior, so the default of + // NearMaxPriority stays in place. + // + // Note that there's a possibility of the VMThread + // starving if UseCriticalCMSThreadPriority is on. + // That won't happen on Solaris for various reasons, + // but may well happen on non-Solaris platforms. + create_and_start(UseCriticalCMSThreadPriority ? CriticalPriority : NearMaxPriority); - if (!DisableStartThread) { - os::start_thread(this); - } - } _sltMonitor = SLT_lock; } -void ConcurrentMarkSweepThread::run() { +void ConcurrentMarkSweepThread::run_service() { assert(this == cmst(), "just checking"); - initialize_in_thread(); - // From this time Thread::current() should be working. - assert(this == Thread::current(), "just checking"); if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { warning("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread); } - // Wait until Universe::is_fully_initialized() + { - CMSLoopCountWarn loopX("CMS::run", "waiting for " - "Universe::is_fully_initialized()", 2); MutexLockerEx x(CGC_lock, true); set_CMS_flag(CMS_cms_wants_token); - // Wait until Universe is initialized and all initialization is completed. - while (!is_init_completed() && !Universe::is_fully_initialized() && - !_should_terminate) { - CGC_lock->wait(true, 200); - loopX.tick(); - } + assert(is_init_completed() && Universe::is_fully_initialized(), "ConcurrentGCThread::run() should have waited for this."); + // Wait until the surrogate locker thread that will do // pending list locking on our behalf has been created. // We cannot start the SLT thread ourselves since we need @@ -130,20 +109,12 @@ _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; _collector->collect_in_background(cause); } - assert(_should_terminate, "just checking"); + // Check that the state of any protocol for synchronization // between background (CMS) and foreground collector is "clean" // (i.e. will not potentially block the foreground collector, // requiring action by us). verify_ok_to_terminate(); - // Signal that it is terminated - { - MutexLockerEx mu(Terminator_lock, - Mutex::_no_safepoint_check_flag); - assert(_cmst == this, "Weird!"); - _cmst = NULL; - Terminator_lock->notify(); - } } #ifndef PRODUCT @@ -157,39 +128,29 @@ // create and start a new ConcurrentMarkSweep Thread for given CMS generation ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) { - if (!_should_terminate) { - assert(cmst() == NULL, "start() called twice?"); - ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); - assert(cmst() == th, "Where did the just-created CMS thread go?"); - return th; - } - return NULL; + guarantee(_cmst == NULL, "start() called twice!"); + ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); + assert(_cmst == th, "Where did the just-created CMS thread go?"); + return th; } void ConcurrentMarkSweepThread::stop_all() { - // it is ok to take late safepoints here, if needed - { - MutexLockerEx x(Terminator_lock); - _should_terminate = true; - } - { // Now post a notify on CGC_lock so as to nudge - // CMS thread(s) that might be slumbering in - // sleepBeforeNextCycle. - MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - CGC_lock->notify_all(); - } - { // Now wait until (all) CMS thread(s) have exited - MutexLockerEx x(Terminator_lock); - while(cmst() != NULL) { - Terminator_lock->wait(); - } - } + assert(_cmst != NULL, "stop_all should be called after initialization"); + _cmst->stop(); +} + +void ConcurrentMarkSweepThread::stop_service() { + // Now post a notify on CGC_lock so as to nudge + // CMS thread(s) that might be slumbering in + // sleepBeforeNextCycle. + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); + CGC_lock->notify_all(); } void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { assert(tc != NULL, "Null ThreadClosure"); - if (_cmst != NULL) { - tc->do_thread(_cmst); + if (cmst() != NULL) { + tc->do_thread(cmst()); } assert(Universe::is_fully_initialized(), "Called too early, make sure heap is fully initialized"); @@ -202,8 +163,8 @@ } void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { - if (_cmst != NULL) { - _cmst->print_on(st); + if (cmst() != NULL) { + cmst()->print_on(st); st->cr(); } if (_collector != NULL) { diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp @@ -37,8 +37,6 @@ friend class VMStructs; friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship friend class CMSCollector; - public: - virtual void run(); private: static ConcurrentMarkSweepThread* _cmst; @@ -47,8 +45,6 @@ static SurrogateLockerThread::SLT_msg_type _sltBuffer; static Monitor* _sltMonitor; - static bool _should_terminate; - enum CMS_flag_type { CMS_nil = NoBits, CMS_cms_wants_token = nth_bit(0), @@ -72,6 +68,9 @@ // debugging void verify_ok_to_terminate() const PRODUCT_RETURN; + void run_service(); + void stop_service(); + public: // Constructor ConcurrentMarkSweepThread(CMSCollector* collector); @@ -86,15 +85,19 @@ static void print_all() { print_all_on(tty); } // Returns the CMS Thread - static ConcurrentMarkSweepThread* cmst() { return _cmst; } + inline static ConcurrentMarkSweepThread* cmst() { + if (_cmst != NULL && !_cmst->_has_terminated) { + return _cmst; + } + return NULL; + } + static CMSCollector* collector() { return _collector; } // Create and start the CMS Thread, or stop it on shutdown static ConcurrentMarkSweepThread* start(CMSCollector* collector); static void stop_all(); - static bool should_terminate() { return _should_terminate; } - // ConcurrentMarkSweepThread uses it's own termination protocol, not ConcurrentGCThread's: - virtual void stop() { ShouldNotReachHere(); } + static bool should_terminate() { return _cmst != NULL && _cmst->_should_terminate; } // Synchronization using CMS token static void synchronize(bool is_cms_thread); diff --git a/src/share/vm/gc/shared/concurrentGCThread.cpp b/src/share/vm/gc/shared/concurrentGCThread.cpp --- a/src/share/vm/gc/shared/concurrentGCThread.cpp +++ b/src/share/vm/gc/shared/concurrentGCThread.cpp @@ -37,12 +37,12 @@ _should_terminate(false), _has_terminated(false) { }; -void ConcurrentGCThread::create_and_start() { +void ConcurrentGCThread::create_and_start(ThreadPriority prio) { if (os::create_thread(this, os::cgc_thread)) { // XXX: need to set this to low priority // unless "aggressive mode" set; priority // should be just less than that of VMThread. - os::set_priority(this, NearMaxPriority); + os::set_priority(this, prio); if (!_should_terminate && !DisableStartThread) { os::start_thread(this); } @@ -88,6 +88,8 @@ // it is ok to take late safepoints here, if needed { MutexLockerEx mu(Terminator_lock); + assert(!_has_terminated, "stop should only be called once"); + assert(!_should_terminate, "stop should only be called once"); _should_terminate = true; } diff --git a/src/share/vm/gc/shared/concurrentGCThread.hpp b/src/share/vm/gc/shared/concurrentGCThread.hpp --- a/src/share/vm/gc/shared/concurrentGCThread.hpp +++ b/src/share/vm/gc/shared/concurrentGCThread.hpp @@ -35,8 +35,8 @@ bool volatile _should_terminate; bool _has_terminated; - // Create and start the thread (setting it's priority high.) - void create_and_start(); + // Create and start the thread (setting it's priority.) + void create_and_start(ThreadPriority prio = NearMaxPriority); // Do initialization steps in the thread: record stack base and size, // init thread local storage, set JNI handle block. @@ -48,25 +48,21 @@ // Record that the current thread is terminating, and will do more // concurrent work. void terminate(); - - // Most implementations of ConcurrentGCThread use ConcurrentGCThread's termination protocol, - // run(), and stop() methods, and provide specific implementations of run_service() and stop_service. - // Otherwise run_service() and stop_service should not be called.) - + // Do the specific GC work. Called by run() after initialization complete. - virtual void run_service() { ShouldNotReachHere(); } - + virtual void run_service() = 0; + // Shut down the specific GC work. Called by stop() as part of termination protocol. - virtual void stop_service() { ShouldNotReachHere(); } + virtual void stop_service() = 0; public: ConcurrentGCThread(); // Tester bool is_ConcurrentGC_thread() const { return true; } - + virtual void run(); - + // shutdown following termination protocol virtual void stop(); }; # HG changeset patch # User drwhite # Date 1457542784 18000 # Wed Mar 09 11:59:44 2016 -0500 # Node ID c6a5cbf5dd4fd0e2fbe501ab6c159c89eafb2659 # Parent 323757004135716f1b6cd8fd8c0528ebd3ff7159 [mq]: webrev.03 diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp @@ -94,16 +94,16 @@ // We cannot start the SLT thread ourselves since we need // to be a JavaThread to do so. CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); - while (_slt == NULL && !_should_terminate) { + while (_slt == NULL && !should_terminate()) { CGC_lock->wait(true, 200); loopY.tick(); } clear_CMS_flag(CMS_cms_wants_token); } - while (!_should_terminate) { + while (!should_terminate()) { sleepBeforeNextCycle(); - if (_should_terminate) break; + if (should_terminate()) break; GCIdMark gc_id_mark; GCCause::Cause cause = _collector->_full_gc_requested ? _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; @@ -239,7 +239,7 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - if (_should_terminate || _collector->_full_gc_requested) { + if (should_terminate() || _collector->_full_gc_requested) { return; } set_CMS_flag(CMS_cms_wants_token); // to provoke notifies @@ -268,7 +268,7 @@ unsigned int loop_count = 0; - while(!_should_terminate) { + while(!should_terminate()) { double now_time = os::elapsedTime(); long wait_time_millis; @@ -288,7 +288,7 @@ { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - if (_should_terminate || _collector->_full_gc_requested) { + if (should_terminate() || _collector->_full_gc_requested) { return; } set_CMS_flag(CMS_cms_wants_token); // to provoke notifies @@ -325,7 +325,7 @@ } void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { - while (!_should_terminate) { + while (!should_terminate()) { if(CMSWaitDuration >= 0) { // Wait until the next synchronous GC, a concurrent full gc // request or a timeout, whichever is earlier. diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp @@ -86,7 +86,7 @@ // Returns the CMS Thread inline static ConcurrentMarkSweepThread* cmst() { - if (_cmst != NULL && !_cmst->_has_terminated) { + if (_cmst != NULL && !_cmst->has_terminated()) { return _cmst; } return NULL; @@ -97,7 +97,7 @@ // Create and start the CMS Thread, or stop it on shutdown static ConcurrentMarkSweepThread* start(CMSCollector* collector); static void stop_all(); - static bool should_terminate() { return _cmst != NULL && _cmst->_should_terminate; } + static bool should_terminate() { return _cmst != NULL && _cmst->should_terminate(); } // Synchronization using CMS token static void synchronize(bool is_cms_thread); diff --git a/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/src/share/vm/gc/g1/concurrentG1RefineThread.cpp --- a/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -78,7 +78,7 @@ void ConcurrentG1RefineThread::wait_for_completed_buffers() { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - while (!_should_terminate && !is_active()) { + while (!should_terminate() && !is_active()) { _monitor->wait(Mutex::_no_safepoint_check_flag); } } @@ -112,10 +112,10 @@ void ConcurrentG1RefineThread::run_service() { _vtime_start = os::elapsedVTime(); - while (!_should_terminate) { + while (!should_terminate()) { // Wait for work wait_for_completed_buffers(); - if (_should_terminate) { + if (should_terminate()) { break; } diff --git a/src/share/vm/gc/g1/concurrentMarkThread.cpp b/src/share/vm/gc/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -111,10 +111,10 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1_policy = g1h->g1_policy(); - while (!_should_terminate) { + while (!should_terminate()) { // wait until started is set. sleepBeforeNextCycle(); - if (_should_terminate) { + if (should_terminate()) { _cm->root_regions()->cancel_scan(); break; } @@ -295,7 +295,7 @@ assert(!in_progress(), "should have been cleared"); MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); - while (!started() && !_should_terminate) { + while (!started() && !should_terminate()) { CGC_lock->wait(Mutex::_no_safepoint_check_flag); } diff --git a/src/share/vm/gc/g1/g1StringDedupThread.cpp b/src/share/vm/gc/g1/g1StringDedupThread.cpp --- a/src/share/vm/gc/g1/g1StringDedupThread.cpp +++ b/src/share/vm/gc/g1/g1StringDedupThread.cpp @@ -94,7 +94,7 @@ // Wait for the queue to become non-empty G1StringDedupQueue::wait(); - if (_should_terminate) { + if (should_terminate()) { break; } diff --git a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp --- a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -44,7 +44,7 @@ void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); - if (!_should_terminate) { + if (!should_terminate()) { uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); } @@ -53,7 +53,7 @@ void G1YoungRemSetSamplingThread::run_service() { double vtime_start = os::elapsedVTime(); - while (!_should_terminate) { + while (!should_terminate()) { sample_young_list_rs_lengths(); if (os::supports_vtime()) { diff --git a/src/share/vm/gc/shared/concurrentGCThread.hpp b/src/share/vm/gc/shared/concurrentGCThread.hpp --- a/src/share/vm/gc/shared/concurrentGCThread.hpp +++ b/src/share/vm/gc/shared/concurrentGCThread.hpp @@ -30,10 +30,13 @@ class ConcurrentGCThread: public NamedThread { friend class VMStructs; - -protected: + bool volatile _should_terminate; bool _has_terminated; + +protected: + bool should_terminate() { return _should_terminate; } + bool has_terminated() { return _has_terminated; } // Create and start the thread (setting it's priority.) void create_and_start(ThreadPriority prio = NearMaxPriority); # HG changeset patch # User drwhite # Date 1457542799 18000 # Wed Mar 09 11:59:59 2016 -0500 # Node ID 2e8f37d70f5c5aa33d7a6aa2073b1338720c805a # Parent c6a5cbf5dd4fd0e2fbe501ab6c159c89eafb2659 imported patch webrev.04 diff --git a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -1413,7 +1413,7 @@ if (_foregroundGCShouldWait) { // We are going to be waiting for action for the CMS thread; // it had better not be gone (for instance at shutdown)! - assert(ConcurrentMarkSweepThread::cmst() != NULL, + assert(ConcurrentMarkSweepThread::cmst() != NULL && !ConcurrentMarkSweepThread::cmst()->has_terminated(), "CMS thread must be running"); // Wait here until the background collector gives us the go-ahead ConcurrentMarkSweepThread::clear_CMS_flag( @@ -3650,7 +3650,7 @@ // XXX FIX ME!!! YSR size_t loops = 0, workdone = 0, cumworkdone = 0, waited = 0; while (!(should_abort_preclean() || - ConcurrentMarkSweepThread::should_terminate())) { + ConcurrentMarkSweepThread::cmst()->should_terminate())) { workdone = preclean_work(CMSPrecleanRefLists2, CMSPrecleanSurvivors2); cumworkdone += workdone; loops++; diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp @@ -149,7 +149,7 @@ void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { assert(tc != NULL, "Null ThreadClosure"); - if (cmst() != NULL) { + if (cmst() != NULL && !cmst()->has_terminated()) { tc->do_thread(cmst()); } assert(Universe::is_fully_initialized(), @@ -163,7 +163,7 @@ } void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { - if (cmst() != NULL) { + if (cmst() != NULL && !cmst()->has_terminated()) { cmst()->print_on(st); st->cr(); } diff --git a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp --- a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp @@ -85,19 +85,12 @@ static void print_all() { print_all_on(tty); } // Returns the CMS Thread - inline static ConcurrentMarkSweepThread* cmst() { - if (_cmst != NULL && !_cmst->has_terminated()) { - return _cmst; - } - return NULL; - } - + static ConcurrentMarkSweepThread* cmst() { return _cmst; } static CMSCollector* collector() { return _collector; } // Create and start the CMS Thread, or stop it on shutdown static ConcurrentMarkSweepThread* start(CMSCollector* collector); static void stop_all(); - static bool should_terminate() { return _cmst != NULL && _cmst->should_terminate(); } // Synchronization using CMS token static void synchronize(bool is_cms_thread); diff --git a/src/share/vm/gc/shared/concurrentGCThread.hpp b/src/share/vm/gc/shared/concurrentGCThread.hpp --- a/src/share/vm/gc/shared/concurrentGCThread.hpp +++ b/src/share/vm/gc/shared/concurrentGCThread.hpp @@ -35,9 +35,6 @@ bool _has_terminated; protected: - bool should_terminate() { return _should_terminate; } - bool has_terminated() { return _has_terminated; } - // Create and start the thread (setting it's priority.) void create_and_start(ThreadPriority prio = NearMaxPriority); @@ -68,6 +65,9 @@ // shutdown following termination protocol virtual void stop(); + + bool should_terminate() { return _should_terminate; } + bool has_terminated() { return _has_terminated; } }; // The SurrogateLockerThread is used by concurrent GC threads for