8140257: Add support for "gc service threads" to ConcurrentGCThread
Push up the common run() and stop() methods from subclasses to ConcurrentGCThread, as well as declaration iof run_service() stop_service(). Reviewed-by: kbarrett, pliden
This commit is contained in:
parent
8c894a92ef
commit
f6810526ab
@ -1412,7 +1412,7 @@ void CMSCollector::acquire_control_and_collect(bool full,
|
||||
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(
|
||||
@ -3648,7 +3648,7 @@ void CMSCollector::abortable_preclean() {
|
||||
// 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++;
|
||||
|
@ -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,88 +61,60 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
|
||||
|
||||
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)) {
|
||||
log_warning(gc)("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
|
||||
// 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;
|
||||
_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,24 @@ void ConcurrentMarkSweepThread::verify_ok_to_terminate() const {
|
||||
|
||||
// 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() {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
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 && !cmst()->has_terminated()) {
|
||||
tc->do_thread(cmst());
|
||||
}
|
||||
assert(Universe::is_fully_initialized(),
|
||||
"Called too early, make sure heap is fully initialized");
|
||||
@ -202,8 +158,8 @@ void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) {
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepThread::print_all_on(outputStream* st) {
|
||||
if (_cmst != NULL) {
|
||||
_cmst->print_on(st);
|
||||
if (cmst() != NULL && !cmst()->has_terminated()) {
|
||||
cmst()->print_on(st);
|
||||
st->cr();
|
||||
}
|
||||
if (_collector != NULL) {
|
||||
@ -278,7 +234,7 @@ void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
|
||||
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
|
||||
@ -307,7 +263,7 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {
|
||||
|
||||
unsigned int loop_count = 0;
|
||||
|
||||
while(!_should_terminate) {
|
||||
while(!should_terminate()) {
|
||||
double now_time = os::elapsedTime();
|
||||
long wait_time_millis;
|
||||
|
||||
@ -327,7 +283,7 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(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
|
||||
@ -364,7 +320,7 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -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
|
||||
@ -37,8 +37,6 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
|
||||
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 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
|
||||
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 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
|
||||
// debugging
|
||||
void verify_ok_to_terminate() const PRODUCT_RETURN;
|
||||
|
||||
void run_service();
|
||||
void stop_service();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
ConcurrentMarkSweepThread(CMSCollector* collector);
|
||||
@ -91,8 +90,6 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
|
||||
|
||||
// Create and start the CMS Thread, or stop it on shutdown
|
||||
static ConcurrentMarkSweepThread* start(CMSCollector* collector);
|
||||
static void stop();
|
||||
static bool should_terminate() { return _should_terminate; }
|
||||
|
||||
// Synchronization using CMS token
|
||||
static void synchronize(bool is_cms_thread);
|
||||
|
@ -78,7 +78,7 @@ void ConcurrentG1RefineThread::initialize() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -109,22 +109,13 @@ void ConcurrentG1RefineThread::deactivate() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentG1RefineThread::run() {
|
||||
initialize_in_thread();
|
||||
wait_for_universe_init();
|
||||
|
||||
run_service();
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -168,23 +159,6 @@ void ConcurrentG1RefineThread::run_service() {
|
||||
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();
|
||||
|
@ -72,7 +72,6 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
|
||||
void stop_service();
|
||||
|
||||
public:
|
||||
virtual void run();
|
||||
// Constructor
|
||||
ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
|
||||
CardTableEntryClosure* refine_closure,
|
||||
@ -84,9 +83,6 @@ public:
|
||||
double vtime_accum() { return _vtime_accum; }
|
||||
|
||||
ConcurrentG1Refine* cg1r() { return _cg1r; }
|
||||
|
||||
// shutdown
|
||||
void stop();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP
|
||||
|
@ -105,25 +105,16 @@ class GCConcPhaseTimer : StackObj {
|
||||
}
|
||||
};
|
||||
|
||||
void ConcurrentMarkThread::run() {
|
||||
initialize_in_thread();
|
||||
wait_for_universe_init();
|
||||
|
||||
run_service();
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
void ConcurrentMarkThread::run_service() {
|
||||
_vtime_start = os::elapsedVTime();
|
||||
|
||||
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;
|
||||
}
|
||||
@ -293,22 +284,6 @@ void ConcurrentMarkThread::run_service() {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
@ -320,7 +295,7 @@ void ConcurrentMarkThread::sleepBeforeNextCycle() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -38,13 +38,8 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
|
||||
|
||||
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 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
|
||||
// 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
|
||||
|
@ -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::initialize() {
|
||||
|
||||
void G1StringDedup::stop() {
|
||||
assert(is_enabled(), "String deduplication not enabled");
|
||||
G1StringDedupThread::stop();
|
||||
G1StringDedupThread::thread()->stop();
|
||||
}
|
||||
|
||||
bool G1StringDedup::is_candidate_from_mark(oop obj) {
|
||||
|
@ -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 @@ void G1StringDedupThread::deduplicate_shared_strings(G1StringDedupStat& stat) {
|
||||
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
|
||||
@ -96,7 +94,7 @@ void G1StringDedupThread::run() {
|
||||
|
||||
// Wait for the queue to become non-empty
|
||||
G1StringDedupQueue::wait();
|
||||
if (_should_terminate) {
|
||||
if (should_terminate()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -133,23 +131,10 @@ void G1StringDedupThread::run() {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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 @@ private:
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
@ -70,7 +44,7 @@ G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() :
|
||||
|
||||
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);
|
||||
}
|
||||
@ -79,7 +53,7 @@ void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
|
||||
void G1YoungRemSetSamplingThread::run_service() {
|
||||
double vtime_start = os::elapsedVTime();
|
||||
|
||||
while (!_should_terminate) {
|
||||
while (!should_terminate()) {
|
||||
sample_young_list_rs_lengths();
|
||||
|
||||
if (os::supports_vtime()) {
|
||||
|
@ -55,9 +55,6 @@ private:
|
||||
public:
|
||||
G1YoungRemSetSamplingThread();
|
||||
double vtime_accum() { return _vtime_accum; }
|
||||
|
||||
virtual void run();
|
||||
void stop();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP
|
||||
|
@ -37,12 +37,12 @@ ConcurrentGCThread::ConcurrentGCThread() :
|
||||
_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);
|
||||
}
|
||||
@ -75,6 +75,34 @@ void ConcurrentGCThread::terminate() {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
assert(!_has_terminated, "stop should only be called once");
|
||||
assert(!_should_terminate, "stop should only be called once");
|
||||
_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();
|
||||
|
@ -31,13 +31,9 @@
|
||||
class ConcurrentGCThread: public NamedThread {
|
||||
friend class VMStructs;
|
||||
|
||||
protected:
|
||||
bool volatile _should_terminate;
|
||||
bool _has_terminated;
|
||||
|
||||
// Create and start the thread (setting it's priority high.)
|
||||
void create_and_start();
|
||||
|
||||
// Do initialization steps in the thread: record stack base and size,
|
||||
// init thread local storage, set JNI handle block.
|
||||
void initialize_in_thread();
|
||||
@ -49,11 +45,29 @@ protected:
|
||||
// concurrent work.
|
||||
void terminate();
|
||||
|
||||
protected:
|
||||
// Create and start the thread (setting it's priority.)
|
||||
void create_and_start(ThreadPriority prio = NearMaxPriority);
|
||||
|
||||
// Do the specific GC work. Called by run() after initialization complete.
|
||||
virtual void run_service() = 0;
|
||||
|
||||
// Shut down the specific GC work. Called by stop() as part of termination protocol.
|
||||
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();
|
||||
|
||||
bool should_terminate() { return _should_terminate; }
|
||||
bool has_terminated() { return _has_terminated; }
|
||||
};
|
||||
|
||||
// The SurrogateLockerThread is used by concurrent GC threads for
|
||||
|
@ -1281,7 +1281,7 @@ jlong GenCollectedHeap::millis_since_last_gc() {
|
||||
void GenCollectedHeap::stop() {
|
||||
#if INCLUDE_ALL_GCS
|
||||
if (UseConcMarkSweepGC) {
|
||||
ConcurrentMarkSweepThread::stop();
|
||||
ConcurrentMarkSweepThread::cmst()->stop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user