8079579: Add SuspendibleThreadSetLeaver and make SuspendibleThreadSet::joint()/leave() private

Reviewed-by: brutisso, david
This commit is contained in:
Per Lidén 2015-05-11 13:57:30 +02:00
parent 5b29324b68
commit 95da544d68
5 changed files with 90 additions and 65 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -77,7 +77,7 @@ void ConcurrentG1RefineThread::initialize() {
} }
void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1CollectorPolicy* g1p = g1h->g1_policy(); G1CollectorPolicy* g1p = g1h->g1_policy();
if (g1p->adaptive_young_list_length()) { if (g1p->adaptive_young_list_length()) {
@ -89,8 +89,8 @@ void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
// we try to yield every time we visit 10 regions // we try to yield every time we visit 10 regions
if (regions_visited == 10) { if (regions_visited == 10) {
if (sts.should_yield()) { if (sts_join.should_yield()) {
sts.yield(); sts_join.yield();
// we just abandon the iteration // we just abandon the iteration
break; break;
} }
@ -188,7 +188,7 @@ void ConcurrentG1RefineThread::run() {
} }
{ {
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
do { do {
int curr_buffer_num = (int)dcqs.completed_buffers_num(); int curr_buffer_num = (int)dcqs.completed_buffers_num();

View File

@ -193,13 +193,8 @@ public:
_cl(cl), _suspendible(suspendible), AbstractGangTask("Parallel Clear Bitmap Task"), _hrclaimer(n_workers) {} _cl(cl), _suspendible(suspendible), AbstractGangTask("Parallel Clear Bitmap Task"), _hrclaimer(n_workers) {}
void work(uint worker_id) { void work(uint worker_id) {
if (_suspendible) { SuspendibleThreadSetJoiner sts_join(_suspendible);
SuspendibleThreadSet::join();
}
G1CollectedHeap::heap()->heap_region_par_iterate(_cl, worker_id, &_hrclaimer, true); G1CollectedHeap::heap()->heap_region_par_iterate(_cl, worker_id, &_hrclaimer, true);
if (_suspendible) {
SuspendibleThreadSet::leave();
}
} }
}; };
@ -956,19 +951,17 @@ void ConcurrentMark::checkpointRootsInitialPost() {
*/ */
void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
bool barrier_aborted;
if (verbose_low()) { if (verbose_low()) {
gclog_or_tty->print_cr("[%u] entering first barrier", worker_id); gclog_or_tty->print_cr("[%u] entering first barrier", worker_id);
} }
if (concurrent()) { {
SuspendibleThreadSet::leave(); SuspendibleThreadSetLeaver sts_leave(concurrent());
barrier_aborted = !_first_overflow_barrier_sync.enter();
} }
bool barrier_aborted = !_first_overflow_barrier_sync.enter();
if (concurrent()) {
SuspendibleThreadSet::join();
}
// at this point everyone should have synced up and not be doing any // at this point everyone should have synced up and not be doing any
// more work // more work
@ -1015,19 +1008,17 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
} }
void ConcurrentMark::enter_second_sync_barrier(uint worker_id) { void ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
bool barrier_aborted;
if (verbose_low()) { if (verbose_low()) {
gclog_or_tty->print_cr("[%u] entering second barrier", worker_id); gclog_or_tty->print_cr("[%u] entering second barrier", worker_id);
} }
if (concurrent()) { {
SuspendibleThreadSet::leave(); SuspendibleThreadSetLeaver sts_leave(concurrent());
barrier_aborted = !_second_overflow_barrier_sync.enter();
} }
bool barrier_aborted = !_second_overflow_barrier_sync.enter();
if (concurrent()) {
SuspendibleThreadSet::join();
}
// at this point everything should be re-initialized and ready to go // at this point everything should be re-initialized and ready to go
if (verbose_low()) { if (verbose_low()) {
@ -1078,40 +1069,41 @@ public:
double start_vtime = os::elapsedVTime(); double start_vtime = os::elapsedVTime();
SuspendibleThreadSet::join(); {
SuspendibleThreadSetJoiner sts_join;
assert(worker_id < _cm->active_tasks(), "invariant"); assert(worker_id < _cm->active_tasks(), "invariant");
CMTask* the_task = _cm->task(worker_id); CMTask* the_task = _cm->task(worker_id);
the_task->record_start_time(); the_task->record_start_time();
if (!_cm->has_aborted()) { if (!_cm->has_aborted()) {
do { do {
double start_vtime_sec = os::elapsedVTime(); double start_vtime_sec = os::elapsedVTime();
double mark_step_duration_ms = G1ConcMarkStepDurationMillis; double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
the_task->do_marking_step(mark_step_duration_ms, the_task->do_marking_step(mark_step_duration_ms,
true /* do_termination */, true /* do_termination */,
false /* is_serial*/); false /* is_serial*/);
double end_vtime_sec = os::elapsedVTime(); double end_vtime_sec = os::elapsedVTime();
double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
_cm->clear_has_overflown(); _cm->clear_has_overflown();
_cm->do_yield_check(worker_id); _cm->do_yield_check(worker_id);
jlong sleep_time_ms; jlong sleep_time_ms;
if (!_cm->has_aborted() && the_task->has_aborted()) { if (!_cm->has_aborted() && the_task->has_aborted()) {
sleep_time_ms = sleep_time_ms =
(jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0); (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
SuspendibleThreadSet::leave(); {
os::sleep(Thread::current(), sleep_time_ms, false); SuspendibleThreadSetLeaver sts_leave;
SuspendibleThreadSet::join(); os::sleep(Thread::current(), sleep_time_ms, false);
} }
} while (!_cm->has_aborted() && the_task->has_aborted()); }
} while (!_cm->has_aborted() && the_task->has_aborted());
}
the_task->record_end_time();
guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
} }
the_task->record_end_time();
guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
SuspendibleThreadSet::leave();
double end_vtime = os::elapsedVTime(); double end_vtime = os::elapsedVTime();
_cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime); _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime);

View File

@ -192,7 +192,7 @@ void ConcurrentMarkThread::run() {
} else { } else {
// We don't want to update the marking status if a GC pause // We don't want to update the marking status if a GC pause
// is already underway. // is already underway.
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
g1h->set_marking_complete(); g1h->set_marking_complete();
} }
@ -262,7 +262,7 @@ void ConcurrentMarkThread::run() {
// not needed any more as the concurrent mark state has been // not needed any more as the concurrent mark state has been
// already reset). // already reset).
{ {
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
if (!cm()->has_aborted()) { if (!cm()->has_aborted()) {
g1_policy->record_concurrent_mark_cleanup_completed(); g1_policy->record_concurrent_mark_cleanup_completed();
} }
@ -291,7 +291,7 @@ void ConcurrentMarkThread::run() {
// Java thread is waiting for a full GC to happen (e.g., it // Java thread is waiting for a full GC to happen (e.g., it
// called System.gc() with +ExplicitGCInvokesConcurrent). // called System.gc() with +ExplicitGCInvokesConcurrent).
{ {
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
g1h->increment_old_marking_cycles_completed(true /* concurrent */); g1h->increment_old_marking_cycles_completed(true /* concurrent */);
g1h->register_concurrent_cycle_end(); g1h->register_concurrent_cycle_end();
} }

View File

@ -74,7 +74,7 @@ void G1StringDedupThread::run() {
{ {
// Include thread in safepoints // Include thread in safepoints
SuspendibleThreadSetJoiner sts; SuspendibleThreadSetJoiner sts_join;
stat.mark_exec(); stat.mark_exec();
@ -88,9 +88,9 @@ void G1StringDedupThread::run() {
G1StringDedupTable::deduplicate(java_string, stat); G1StringDedupTable::deduplicate(java_string, stat);
// Safepoint this thread if needed // Safepoint this thread if needed
if (sts.should_yield()) { if (sts_join.should_yield()) {
stat.mark_block(); stat.mark_block();
sts.yield(); sts_join.yield();
stat.mark_unblock(); stat.mark_unblock();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,19 +36,22 @@
// suspending thread later calls desynchronize(), allowing the suspended // suspending thread later calls desynchronize(), allowing the suspended
// threads to continue. // threads to continue.
class SuspendibleThreadSet : public AllStatic { class SuspendibleThreadSet : public AllStatic {
friend class SuspendibleThreadSetJoiner;
friend class SuspendibleThreadSetLeaver;
private: private:
static uint _nthreads; static uint _nthreads;
static uint _nthreads_stopped; static uint _nthreads_stopped;
static bool _suspend_all; static bool _suspend_all;
static double _suspend_all_start; static double _suspend_all_start;
public:
// Add the current thread to the set. May block if a suspension is in progress. // Add the current thread to the set. May block if a suspension is in progress.
static void join(); static void join();
// Removes the current thread from the set. // Removes the current thread from the set.
static void leave(); static void leave();
public:
// Returns true if an suspension is in progress. // Returns true if an suspension is in progress.
static bool should_yield() { return _suspend_all; } static bool should_yield() { return _suspend_all; }
@ -63,22 +66,52 @@ public:
}; };
class SuspendibleThreadSetJoiner : public StackObj { class SuspendibleThreadSetJoiner : public StackObj {
private:
bool _active;
public: public:
SuspendibleThreadSetJoiner() { SuspendibleThreadSetJoiner(bool active = true) : _active(active) {
SuspendibleThreadSet::join(); if (_active) {
SuspendibleThreadSet::join();
}
} }
~SuspendibleThreadSetJoiner() { ~SuspendibleThreadSetJoiner() {
SuspendibleThreadSet::leave(); if (_active) {
SuspendibleThreadSet::leave();
}
} }
bool should_yield() { bool should_yield() {
return SuspendibleThreadSet::should_yield(); if (_active) {
return SuspendibleThreadSet::should_yield();
} else {
return false;
}
} }
void yield() { void yield() {
assert(_active, "Thread has not joined the suspendible thread set");
SuspendibleThreadSet::yield(); SuspendibleThreadSet::yield();
} }
}; };
class SuspendibleThreadSetLeaver : public StackObj {
private:
bool _active;
public:
SuspendibleThreadSetLeaver(bool active = true) : _active(active) {
if (_active) {
SuspendibleThreadSet::leave();
}
}
~SuspendibleThreadSetLeaver() {
if (_active) {
SuspendibleThreadSet::join();
}
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP