提交 72ae63a4 编写于 作者: P pliden

8039147: Cleanup SuspendibleThreadSet

Reviewed-by: brutisso, tschatzl, mgerdin
上级 49dad6d9
...@@ -71,6 +71,7 @@ void ConcurrentG1RefineThread::initialize() { ...@@ -71,6 +71,7 @@ void ConcurrentG1RefineThread::initialize() {
} }
void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
SuspendibleThreadSetJoiner sts;
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()) {
...@@ -82,8 +83,8 @@ void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { ...@@ -82,8 +83,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.should_yield()) {
_sts.yield("G1 refine"); sts.yield();
// we just abandon the iteration // we just abandon the iteration
break; break;
} }
...@@ -99,9 +100,7 @@ void ConcurrentG1RefineThread::run_young_rs_sampling() { ...@@ -99,9 +100,7 @@ void ConcurrentG1RefineThread::run_young_rs_sampling() {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
_vtime_start = os::elapsedVTime(); _vtime_start = os::elapsedVTime();
while(!_should_terminate) { while(!_should_terminate) {
_sts.join();
sample_young_list_rs_lengths(); sample_young_list_rs_lengths();
_sts.leave();
if (os::supports_vtime()) { if (os::supports_vtime()) {
_vtime_accum = (os::elapsedVTime() - _vtime_start); _vtime_accum = (os::elapsedVTime() - _vtime_start);
...@@ -182,37 +181,37 @@ void ConcurrentG1RefineThread::run() { ...@@ -182,37 +181,37 @@ void ConcurrentG1RefineThread::run() {
break; break;
} }
_sts.join(); {
SuspendibleThreadSetJoiner sts;
do { do {
int curr_buffer_num = (int)dcqs.completed_buffers_num(); int curr_buffer_num = (int)dcqs.completed_buffers_num();
// If the number of the buffers falls down into the yellow zone, // If the number of the buffers falls down into the yellow zone,
// that means that the transition period after the evacuation pause has ended. // that means that the transition period after the evacuation pause has ended.
if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
dcqs.set_completed_queue_padding(0); dcqs.set_completed_queue_padding(0);
} }
if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
// If the number of the buffer has fallen below our threshold // If the number of the buffer has fallen below our threshold
// we should deactivate. The predecessor will reactivate this // we should deactivate. The predecessor will reactivate this
// thread should the number of the buffers cross the threshold again. // thread should the number of the buffers cross the threshold again.
deactivate(); deactivate();
break; break;
} }
// Check if we need to activate the next thread. // Check if we need to activate the next thread.
if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
_next->activate(); _next->activate();
} }
} while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
// We can exit the loop above while being active if there was a yield request. // We can exit the loop above while being active if there was a yield request.
if (is_active()) { if (is_active()) {
deactivate(); deactivate();
}
} }
_sts.leave();
if (os::supports_vtime()) { if (os::supports_vtime()) {
_vtime_accum = (os::elapsedVTime() - _vtime_start); _vtime_accum = (os::elapsedVTime() - _vtime_start);
} else { } else {
...@@ -223,17 +222,6 @@ void ConcurrentG1RefineThread::run() { ...@@ -223,17 +222,6 @@ void ConcurrentG1RefineThread::run() {
terminate(); terminate();
} }
void ConcurrentG1RefineThread::yield() {
if (G1TraceConcRefinement) {
gclog_or_tty->print_cr("G1-Refine-yield");
}
_sts.yield("G1 refine");
if (G1TraceConcRefinement) {
gclog_or_tty->print_cr("G1-Refine-yield-end");
}
}
void ConcurrentG1RefineThread::stop() { void ConcurrentG1RefineThread::stop() {
// it is ok to take late safepoints here, if needed // it is ok to take late safepoints here, if needed
{ {
......
...@@ -64,9 +64,6 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { ...@@ -64,9 +64,6 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
void activate(); void activate();
void deactivate(); void deactivate();
// For use by G1CollectedHeap, which is a friend.
static SuspendibleThreadSet* sts() { return &_sts; }
public: public:
virtual void run(); virtual void run();
// Constructor // Constructor
...@@ -84,8 +81,6 @@ public: ...@@ -84,8 +81,6 @@ public:
ConcurrentG1Refine* cg1r() { return _cg1r; } ConcurrentG1Refine* cg1r() { return _cg1r; }
// Yield for GC
void yield();
// shutdown // shutdown
void stop(); void stop();
}; };
......
...@@ -976,11 +976,11 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { ...@@ -976,11 +976,11 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
} }
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsLeave(); SuspendibleThreadSet::leave();
} }
_first_overflow_barrier_sync.enter(); _first_overflow_barrier_sync.enter();
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsJoin(); 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
...@@ -1024,11 +1024,11 @@ void ConcurrentMark::enter_second_sync_barrier(uint worker_id) { ...@@ -1024,11 +1024,11 @@ void ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
} }
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsLeave(); SuspendibleThreadSet::leave();
} }
_second_overflow_barrier_sync.enter(); _second_overflow_barrier_sync.enter();
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsJoin(); 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
...@@ -1076,7 +1076,7 @@ public: ...@@ -1076,7 +1076,7 @@ public:
double start_vtime = os::elapsedVTime(); double start_vtime = os::elapsedVTime();
ConcurrentGCThread::stsJoin(); SuspendibleThreadSet::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);
...@@ -1103,9 +1103,9 @@ public: ...@@ -1103,9 +1103,9 @@ public:
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);
ConcurrentGCThread::stsLeave(); SuspendibleThreadSet::leave();
os::sleep(Thread::current(), sleep_time_ms, false); os::sleep(Thread::current(), sleep_time_ms, false);
ConcurrentGCThread::stsJoin(); SuspendibleThreadSet::join();
} }
double end_time2_sec = os::elapsedTime(); double end_time2_sec = os::elapsedTime();
double elapsed_time2_sec = end_time2_sec - start_time_sec; double elapsed_time2_sec = end_time2_sec - start_time_sec;
...@@ -1123,7 +1123,7 @@ public: ...@@ -1123,7 +1123,7 @@ public:
the_task->record_end_time(); the_task->record_end_time();
guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant"); guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
ConcurrentGCThread::stsLeave(); 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);
...@@ -3302,21 +3302,17 @@ void ConcurrentMark::print_on_error(outputStream* st) const { ...@@ -3302,21 +3302,17 @@ void ConcurrentMark::print_on_error(outputStream* st) const {
// We take a break if someone is trying to stop the world. // We take a break if someone is trying to stop the world.
bool ConcurrentMark::do_yield_check(uint worker_id) { bool ConcurrentMark::do_yield_check(uint worker_id) {
if (should_yield()) { if (SuspendibleThreadSet::should_yield()) {
if (worker_id == 0) { if (worker_id == 0) {
_g1h->g1_policy()->record_concurrent_pause(); _g1h->g1_policy()->record_concurrent_pause();
} }
cmThread()->yield(); SuspendibleThreadSet::yield();
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool ConcurrentMark::should_yield() {
return cmThread()->should_yield();
}
bool ConcurrentMark::containing_card_is_marked(void* p) { bool ConcurrentMark::containing_card_is_marked(void* p) {
size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1); size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1);
return _card_bm.at(offset >> CardTableModRefBS::card_shift); return _card_bm.at(offset >> CardTableModRefBS::card_shift);
...@@ -3605,7 +3601,7 @@ void CMTask::regular_clock_call() { ...@@ -3605,7 +3601,7 @@ void CMTask::regular_clock_call() {
#endif // _MARKING_STATS_ #endif // _MARKING_STATS_
// (4) We check whether we should yield. If we have to, then we abort. // (4) We check whether we should yield. If we have to, then we abort.
if (_cm->should_yield()) { if (SuspendibleThreadSet::should_yield()) {
// We should yield. To do this we abort the task. The caller is // We should yield. To do this we abort the task. The caller is
// responsible for yielding. // responsible for yielding.
set_has_aborted(); set_has_aborted();
......
...@@ -814,7 +814,6 @@ public: ...@@ -814,7 +814,6 @@ public:
} }
inline bool do_yield_check(uint worker_i = 0); inline bool do_yield_check(uint worker_i = 0);
inline bool should_yield();
// Called to abort the marking cycle after a Full GC takes place. // Called to abort the marking cycle after a Full GC takes place.
void abort(); void abort();
......
...@@ -194,9 +194,8 @@ void ConcurrentMarkThread::run() { ...@@ -194,9 +194,8 @@ 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.
_sts.join(); SuspendibleThreadSetJoiner sts;
g1h->set_marking_complete(); g1h->set_marking_complete();
_sts.leave();
} }
// Check if cleanup set the free_regions_coming flag. If it // Check if cleanup set the free_regions_coming flag. If it
...@@ -266,11 +265,12 @@ void ConcurrentMarkThread::run() { ...@@ -266,11 +265,12 @@ void ConcurrentMarkThread::run() {
// record_concurrent_mark_cleanup_completed() (and, in fact, it's // record_concurrent_mark_cleanup_completed() (and, in fact, it's
// 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).
_sts.join(); {
if (!cm()->has_aborted()) { SuspendibleThreadSetJoiner sts;
g1_policy->record_concurrent_mark_cleanup_completed(); if (!cm()->has_aborted()) {
g1_policy->record_concurrent_mark_cleanup_completed();
}
} }
_sts.leave();
if (cm()->has_aborted()) { if (cm()->has_aborted()) {
if (G1Log::fine()) { if (G1Log::fine()) {
...@@ -282,30 +282,27 @@ void ConcurrentMarkThread::run() { ...@@ -282,30 +282,27 @@ void ConcurrentMarkThread::run() {
// We now want to allow clearing of the marking bitmap to be // We now want to allow clearing of the marking bitmap to be
// suspended by a collection pause. // suspended by a collection pause.
_sts.join(); {
_cm->clearNextBitmap(); SuspendibleThreadSetJoiner sts;
_sts.leave(); _cm->clearNextBitmap();
}
} }
// Update the number of full collections that have been // Update the number of full collections that have been
// completed. This will also notify the FullGCCount_lock in case a // completed. This will also notify the FullGCCount_lock in case a
// 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).
_sts.join(); {
g1h->increment_old_marking_cycles_completed(true /* concurrent */); SuspendibleThreadSetJoiner sts;
g1h->register_concurrent_cycle_end(); g1h->increment_old_marking_cycles_completed(true /* concurrent */);
_sts.leave(); g1h->register_concurrent_cycle_end();
}
} }
assert(_should_terminate, "just checking"); assert(_should_terminate, "just checking");
terminate(); terminate();
} }
void ConcurrentMarkThread::yield() {
_sts.yield("Concurrent Mark");
}
void ConcurrentMarkThread::stop() { void ConcurrentMarkThread::stop() {
{ {
MutexLockerEx ml(Terminator_lock); MutexLockerEx ml(Terminator_lock);
......
...@@ -89,9 +89,6 @@ class ConcurrentMarkThread: public ConcurrentGCThread { ...@@ -89,9 +89,6 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
// that started() is set and set in_progress(). // that started() is set and set in_progress().
bool during_cycle() { return started() || in_progress(); } bool during_cycle() { return started() || in_progress(); }
// Yield for GC
void yield();
// shutdown // shutdown
void stop(); void stop();
}; };
......
...@@ -92,15 +92,13 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; ...@@ -92,15 +92,13 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
// Local to this file. // Local to this file.
class RefineCardTableEntryClosure: public CardTableEntryClosure { class RefineCardTableEntryClosure: public CardTableEntryClosure {
SuspendibleThreadSet* _sts;
G1RemSet* _g1rs; G1RemSet* _g1rs;
ConcurrentG1Refine* _cg1r; ConcurrentG1Refine* _cg1r;
bool _concurrent; bool _concurrent;
public: public:
RefineCardTableEntryClosure(SuspendibleThreadSet* sts, RefineCardTableEntryClosure(G1RemSet* g1rs,
G1RemSet* g1rs,
ConcurrentG1Refine* cg1r) : ConcurrentG1Refine* cg1r) :
_sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
{} {}
bool do_card_ptr(jbyte* card_ptr, uint worker_i) { bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false);
...@@ -109,7 +107,7 @@ public: ...@@ -109,7 +107,7 @@ public:
// that point into the collection set. // that point into the collection set.
assert(!oops_into_cset, "should be"); assert(!oops_into_cset, "should be");
if (_concurrent && _sts->should_yield()) { if (_concurrent && SuspendibleThreadSet::should_yield()) {
// Caller will actually yield. // Caller will actually yield.
return false; return false;
} }
...@@ -2117,8 +2115,7 @@ jint G1CollectedHeap::initialize() { ...@@ -2117,8 +2115,7 @@ jint G1CollectedHeap::initialize() {
g1_policy()->init(); g1_policy()->init();
_refine_cte_cl = _refine_cte_cl =
new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(), new RefineCardTableEntryClosure(g1_rem_set(),
g1_rem_set(),
concurrent_g1_refine()); concurrent_g1_refine());
JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
...@@ -4317,7 +4314,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { ...@@ -4317,7 +4314,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// this point does not assume that we are the only GC thread // this point does not assume that we are the only GC thread
// running. Note: of course, the actual marking work will // running. Note: of course, the actual marking work will
// not start until the safepoint itself is released in // not start until the safepoint itself is released in
// ConcurrentGCThread::safepoint_desynchronize(). // SuspendibleThreadSet::desynchronize().
doConcurrentMark(); doConcurrentMark();
} }
......
...@@ -77,38 +77,37 @@ void G1StringDedupThread::run() { ...@@ -77,38 +77,37 @@ void G1StringDedupThread::run() {
break; break;
} }
// Include this thread in safepoints {
stsJoin(); // Include thread in safepoints
SuspendibleThreadSetJoiner sts;
stat.mark_exec();
stat.mark_exec();
// Process the queue
for (;;) { // Process the queue
oop java_string = G1StringDedupQueue::pop(); for (;;) {
if (java_string == NULL) { oop java_string = G1StringDedupQueue::pop();
break; if (java_string == NULL) {
} break;
}
G1StringDedupTable::deduplicate(java_string, stat);
G1StringDedupTable::deduplicate(java_string, stat);
// Safepoint this thread if needed
if (stsShouldYield()) { // Safepoint this thread if needed
stat.mark_block(); if (sts.should_yield()) {
stsYield(NULL); stat.mark_block();
stat.mark_unblock(); sts.yield();
stat.mark_unblock();
}
} }
}
G1StringDedupTable::trim_entry_cache(); G1StringDedupTable::trim_entry_cache();
stat.mark_done(); stat.mark_done();
// Print statistics // Print statistics
total_stat.add(stat); total_stat.add(stat);
print(gclog_or_tty, stat, total_stat); print(gclog_or_tty, stat, total_stat);
}
// Exclude this thread from safepoints
stsLeave();
} }
terminate(); terminate();
......
...@@ -37,21 +37,10 @@ ...@@ -37,21 +37,10 @@
int ConcurrentGCThread::_CGC_flag = CGC_nil; int ConcurrentGCThread::_CGC_flag = CGC_nil;
SuspendibleThreadSet ConcurrentGCThread::_sts;
ConcurrentGCThread::ConcurrentGCThread() : ConcurrentGCThread::ConcurrentGCThread() :
_should_terminate(false), _has_terminated(false) { _should_terminate(false), _has_terminated(false) {
_sts.initialize();
}; };
void ConcurrentGCThread::safepoint_synchronize() {
_sts.suspend_all();
}
void ConcurrentGCThread::safepoint_desynchronize() {
_sts.resume_all();
}
void ConcurrentGCThread::create_and_start() { void ConcurrentGCThread::create_and_start() {
if (os::create_thread(this, os::cgc_thread)) { if (os::create_thread(this, os::cgc_thread)) {
// XXX: need to set this to low priority // XXX: need to set this to low priority
...@@ -92,78 +81,6 @@ void ConcurrentGCThread::terminate() { ...@@ -92,78 +81,6 @@ void ConcurrentGCThread::terminate() {
ThreadLocalStorage::set_thread(NULL); ThreadLocalStorage::set_thread(NULL);
} }
void SuspendibleThreadSet::initialize_work() {
MutexLocker x(STS_init_lock);
if (!_initialized) {
_m = new Monitor(Mutex::leaf,
"SuspendibleThreadSetLock", true);
_async = 0;
_async_stop = false;
_async_stopped = 0;
_initialized = true;
}
}
void SuspendibleThreadSet::join() {
initialize();
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
_async++;
assert(_async > 0, "Huh.");
}
void SuspendibleThreadSet::leave() {
assert(_initialized, "Must be initialized.");
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
_async--;
assert(_async >= 0, "Huh.");
if (_async_stop) _m->notify_all();
}
void SuspendibleThreadSet::yield(const char* id) {
assert(_initialized, "Must be initialized.");
if (_async_stop) {
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
if (_async_stop) {
_async_stopped++;
assert(_async_stopped > 0, "Huh.");
if (_async_stopped == _async) {
if (ConcGCYieldTimeout > 0) {
double now = os::elapsedTime();
guarantee((now - _suspend_all_start) * 1000.0 <
(double)ConcGCYieldTimeout,
"Long delay; whodunit?");
}
}
_m->notify_all();
while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
_async_stopped--;
assert(_async >= 0, "Huh");
_m->notify_all();
}
}
}
void SuspendibleThreadSet::suspend_all() {
initialize(); // If necessary.
if (ConcGCYieldTimeout > 0) {
_suspend_all_start = os::elapsedTime();
}
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
assert(!_async_stop, "Only one at a time.");
_async_stop = true;
while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
}
void SuspendibleThreadSet::resume_all() {
assert(_initialized, "Must be initialized.");
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
assert(_async_stopped == _async, "Huh.");
_async_stop = false;
_m->notify_all();
}
static void _sltLoop(JavaThread* thread, TRAPS) { static void _sltLoop(JavaThread* thread, TRAPS) {
SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
slt->loop(); slt->loop();
...@@ -283,30 +200,3 @@ void SurrogateLockerThread::loop() { ...@@ -283,30 +200,3 @@ void SurrogateLockerThread::loop() {
} }
assert(!_monitor.owned_by_self(), "Should unlock before exit."); assert(!_monitor.owned_by_self(), "Should unlock before exit.");
} }
// ===== STS Access From Outside CGCT =====
void ConcurrentGCThread::stsYield(const char* id) {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.yield(id);
}
bool ConcurrentGCThread::stsShouldYield() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
return _sts.should_yield();
}
void ConcurrentGCThread::stsJoin() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.join();
}
void ConcurrentGCThread::stsLeave() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.leave();
}
...@@ -26,55 +26,8 @@ ...@@ -26,55 +26,8 @@
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS #include "gc_implementation/shared/suspendibleThreadSet.hpp"
#include "runtime/thread.hpp" #include "runtime/thread.hpp"
#endif // INCLUDE_ALL_GCS
class VoidClosure;
// A SuspendibleThreadSet is (obviously) a set of threads that can be
// suspended. A thread can join and later leave the set, and periodically
// yield. If some thread (not in the set) requests, via suspend_all, that
// the threads be suspended, then the requesting thread is blocked until
// all the threads in the set have yielded or left the set. (Threads may
// not enter the set when an attempted suspension is in progress.) The
// suspending thread later calls resume_all, allowing the suspended threads
// to continue.
class SuspendibleThreadSet {
Monitor* _m;
int _async;
bool _async_stop;
int _async_stopped;
bool _initialized;
double _suspend_all_start;
void initialize_work();
public:
SuspendibleThreadSet() : _initialized(false) {}
// Add the current thread to the set. May block if a suspension
// is in progress.
void join();
// Removes the current thread from the set.
void leave();
// Returns "true" iff an suspension is in progress.
bool should_yield() { return _async_stop; }
// Suspends the current thread if a suspension is in progress (for
// the duration of the suspension.)
void yield(const char* id);
// Return when all threads in the set are suspended.
void suspend_all();
// Allow suspended threads to resume.
void resume_all();
// Redundant initializations okay.
void initialize() {
// Double-check dirty read idiom.
if (!_initialized) initialize_work();
}
};
class ConcurrentGCThread: public NamedThread { class ConcurrentGCThread: public NamedThread {
friend class VMStructs; friend class VMStructs;
...@@ -96,9 +49,6 @@ protected: ...@@ -96,9 +49,6 @@ protected:
static int set_CGC_flag(int b) { return _CGC_flag |= b; } static int set_CGC_flag(int b) { return _CGC_flag |= b; }
static int reset_CGC_flag(int b) { return _CGC_flag &= ~b; } static int reset_CGC_flag(int b) { return _CGC_flag &= ~b; }
// All instances share this one set.
static SuspendibleThreadSet _sts;
// Create and start the thread (setting it's priority high.) // Create and start the thread (setting it's priority high.)
void create_and_start(); void create_and_start();
...@@ -121,25 +71,6 @@ public: ...@@ -121,25 +71,6 @@ public:
// Tester // Tester
bool is_ConcurrentGC_thread() const { return true; } bool is_ConcurrentGC_thread() const { return true; }
static void safepoint_synchronize();
static void safepoint_desynchronize();
// All overridings should probably do _sts::yield, but we allow
// overriding for distinguished debugging messages. Default is to do
// nothing.
virtual void yield() {}
bool should_yield() { return _sts.should_yield(); }
// they are prefixed by sts since there are already yield() and
// should_yield() (non-static) methods in this class and it was an
// easy way to differentiate them.
static void stsYield(const char* id);
static bool stsShouldYield();
static void stsJoin();
static void stsLeave();
}; };
// The SurrogateLockerThread is used by concurrent GC threads for // The SurrogateLockerThread is used by concurrent GC threads for
......
/*
* Copyright (c) 2014, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/shared/suspendibleThreadSet.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
uint SuspendibleThreadSet::_nthreads = 0;
uint SuspendibleThreadSet::_nthreads_stopped = 0;
bool SuspendibleThreadSet::_suspend_all = false;
double SuspendibleThreadSet::_suspend_all_start = 0.0;
void SuspendibleThreadSet::join() {
MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
while (_suspend_all) {
ml.wait(Mutex::_no_safepoint_check_flag);
}
_nthreads++;
}
void SuspendibleThreadSet::leave() {
MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
assert(_nthreads > 0, "Invalid");
_nthreads--;
if (_suspend_all) {
ml.notify_all();
}
}
void SuspendibleThreadSet::yield() {
if (_suspend_all) {
MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
if (_suspend_all) {
_nthreads_stopped++;
if (_nthreads_stopped == _nthreads) {
if (ConcGCYieldTimeout > 0) {
double now = os::elapsedTime();
guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay");
}
}
ml.notify_all();
while (_suspend_all) {
ml.wait(Mutex::_no_safepoint_check_flag);
}
assert(_nthreads_stopped > 0, "Invalid");
_nthreads_stopped--;
ml.notify_all();
}
}
}
void SuspendibleThreadSet::synchronize() {
assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
if (ConcGCYieldTimeout > 0) {
_suspend_all_start = os::elapsedTime();
}
MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
assert(!_suspend_all, "Only one at a time");
_suspend_all = true;
while (_nthreads_stopped < _nthreads) {
ml.wait(Mutex::_no_safepoint_check_flag);
}
}
void SuspendibleThreadSet::desynchronize() {
assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
assert(_nthreads_stopped == _nthreads, "Invalid");
_suspend_all = false;
ml.notify_all();
}
/*
* Copyright (c) 2014, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
#include "memory/allocation.hpp"
// A SuspendibleThreadSet is a set of threads that can be suspended.
// A thread can join and later leave the set, and periodically yield.
// If some thread (not in the set) requests, via synchronize(), that
// the threads be suspended, then the requesting thread is blocked
// until all the threads in the set have yielded or left the set. Threads
// may not enter the set when an attempted suspension is in progress. The
// suspending thread later calls desynchronize(), allowing the suspended
// threads to continue.
class SuspendibleThreadSet : public AllStatic {
private:
static uint _nthreads;
static uint _nthreads_stopped;
static bool _suspend_all;
static double _suspend_all_start;
public:
// Add the current thread to the set. May block if a suspension is in progress.
static void join();
// Removes the current thread from the set.
static void leave();
// Returns true if an suspension is in progress.
static bool should_yield() { return _suspend_all; }
// Suspends the current thread if a suspension is in progress.
static void yield();
// Returns when all threads in the set are suspended.
static void synchronize();
// Resumes all suspended threads in the set.
static void desynchronize();
};
class SuspendibleThreadSetJoiner : public StackObj {
public:
SuspendibleThreadSetJoiner() {
SuspendibleThreadSet::join();
}
~SuspendibleThreadSetJoiner() {
SuspendibleThreadSet::leave();
}
bool should_yield() {
return SuspendibleThreadSet::should_yield();
}
void yield() {
SuspendibleThreadSet::yield();
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
...@@ -69,7 +69,7 @@ Monitor* Safepoint_lock = NULL; ...@@ -69,7 +69,7 @@ Monitor* Safepoint_lock = NULL;
Monitor* SerializePage_lock = NULL; Monitor* SerializePage_lock = NULL;
Monitor* Threads_lock = NULL; Monitor* Threads_lock = NULL;
Monitor* CGC_lock = NULL; Monitor* CGC_lock = NULL;
Mutex* STS_init_lock = NULL; Monitor* STS_lock = NULL;
Monitor* SLT_lock = NULL; Monitor* SLT_lock = NULL;
Monitor* iCMS_lock = NULL; Monitor* iCMS_lock = NULL;
Monitor* FullGCCount_lock = NULL; Monitor* FullGCCount_lock = NULL;
...@@ -173,7 +173,7 @@ void mutex_init() { ...@@ -173,7 +173,7 @@ void mutex_init() {
def(tty_lock , Mutex , event, true ); // allow to lock in VM def(tty_lock , Mutex , event, true ); // allow to lock in VM
def(CGC_lock , Monitor, special, true ); // coordinate between fore- and background GC def(CGC_lock , Monitor, special, true ); // coordinate between fore- and background GC
def(STS_init_lock , Mutex, leaf, true ); def(STS_lock , Monitor, leaf, true );
if (UseConcMarkSweepGC) { if (UseConcMarkSweepGC) {
def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification
} }
......
...@@ -79,7 +79,7 @@ extern Monitor* Threads_lock; // a lock on the Threads table ...@@ -79,7 +79,7 @@ extern Monitor* Threads_lock; // a lock on the Threads table
// (also used by Safepoints too to block threads creation/destruction) // (also used by Safepoints too to block threads creation/destruction)
extern Monitor* CGC_lock; // used for coordination between extern Monitor* CGC_lock; // used for coordination between
// fore- & background GC threads. // fore- & background GC threads.
extern Mutex* STS_init_lock; // coordinate initialization of SuspendibleThreadSets. extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet.
extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL
extern Monitor* iCMS_lock; // CMS incremental mode start/stop notification extern Monitor* iCMS_lock; // CMS incremental mode start/stop notification
extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
#endif #endif
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
#include "gc_implementation/shared/concurrentGCThread.hpp" #include "gc_implementation/shared/suspendibleThreadSet.hpp"
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
#ifdef COMPILER1 #ifdef COMPILER1
#include "c1/c1_globals.hpp" #include "c1/c1_globals.hpp"
...@@ -110,7 +110,7 @@ void SafepointSynchronize::begin() { ...@@ -110,7 +110,7 @@ void SafepointSynchronize::begin() {
// more-general mechanism below. DLD (01/05). // more-general mechanism below. DLD (01/05).
ConcurrentMarkSweepThread::synchronize(false); ConcurrentMarkSweepThread::synchronize(false);
} else if (UseG1GC) { } else if (UseG1GC) {
ConcurrentGCThread::safepoint_synchronize(); SuspendibleThreadSet::synchronize();
} }
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
...@@ -486,7 +486,7 @@ void SafepointSynchronize::end() { ...@@ -486,7 +486,7 @@ void SafepointSynchronize::end() {
if (UseConcMarkSweepGC) { if (UseConcMarkSweepGC) {
ConcurrentMarkSweepThread::desynchronize(false); ConcurrentMarkSweepThread::desynchronize(false);
} else if (UseG1GC) { } else if (UseG1GC) {
ConcurrentGCThread::safepoint_desynchronize(); SuspendibleThreadSet::desynchronize();
} }
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
// record this time so VMThread can keep track how much time has elapsed // record this time so VMThread can keep track how much time has elapsed
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册