提交 da32f40e 编写于 作者: P pliden

8040803: G1: Concurrent mark hangs when mark stack overflows

Reviewed-by: brutisso, ehelin
上级 0fff0369
...@@ -978,7 +978,9 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { ...@@ -978,7 +978,9 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsLeave(); ConcurrentGCThread::stsLeave();
} }
_first_overflow_barrier_sync.enter();
bool barrier_aborted = !_first_overflow_barrier_sync.enter();
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsJoin(); ConcurrentGCThread::stsJoin();
} }
...@@ -986,7 +988,17 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { ...@@ -986,7 +988,17 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
// more work // more work
if (verbose_low()) { if (verbose_low()) {
gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id); if (barrier_aborted) {
gclog_or_tty->print_cr("[%u] aborted first barrier", worker_id);
} else {
gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id);
}
}
if (barrier_aborted) {
// If the barrier aborted we ignore the overflow condition and
// just abort the whole marking phase as quickly as possible.
return;
} }
// If we're executing the concurrent phase of marking, reset the marking // If we're executing the concurrent phase of marking, reset the marking
...@@ -1026,14 +1038,20 @@ void ConcurrentMark::enter_second_sync_barrier(uint worker_id) { ...@@ -1026,14 +1038,20 @@ void ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsLeave(); ConcurrentGCThread::stsLeave();
} }
_second_overflow_barrier_sync.enter();
bool barrier_aborted = !_second_overflow_barrier_sync.enter();
if (concurrent()) { if (concurrent()) {
ConcurrentGCThread::stsJoin(); ConcurrentGCThread::stsJoin();
} }
// 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()) {
gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id); if (barrier_aborted) {
gclog_or_tty->print_cr("[%u] aborted second barrier", worker_id);
} else {
gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id);
}
} }
} }
...@@ -3232,6 +3250,8 @@ void ConcurrentMark::abort() { ...@@ -3232,6 +3250,8 @@ void ConcurrentMark::abort() {
for (uint i = 0; i < _max_worker_id; ++i) { for (uint i = 0; i < _max_worker_id; ++i) {
_tasks[i]->clear_region_fields(); _tasks[i]->clear_region_fields();
} }
_first_overflow_barrier_sync.abort();
_second_overflow_barrier_sync.abort();
_has_aborted = true; _has_aborted = true;
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
......
...@@ -378,21 +378,22 @@ const char* AbstractGangTask::name() const { ...@@ -378,21 +378,22 @@ const char* AbstractGangTask::name() const {
WorkGangBarrierSync::WorkGangBarrierSync() WorkGangBarrierSync::WorkGangBarrierSync()
: _monitor(Mutex::safepoint, "work gang barrier sync", true), : _monitor(Mutex::safepoint, "work gang barrier sync", true),
_n_workers(0), _n_completed(0), _should_reset(false) { _n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) {
} }
WorkGangBarrierSync::WorkGangBarrierSync(uint n_workers, const char* name) WorkGangBarrierSync::WorkGangBarrierSync(uint n_workers, const char* name)
: _monitor(Mutex::safepoint, name, true), : _monitor(Mutex::safepoint, name, true),
_n_workers(n_workers), _n_completed(0), _should_reset(false) { _n_workers(n_workers), _n_completed(0), _should_reset(false), _aborted(false) {
} }
void WorkGangBarrierSync::set_n_workers(uint n_workers) { void WorkGangBarrierSync::set_n_workers(uint n_workers) {
_n_workers = n_workers; _n_workers = n_workers;
_n_completed = 0; _n_completed = 0;
_should_reset = false; _should_reset = false;
_aborted = false;
} }
void WorkGangBarrierSync::enter() { bool WorkGangBarrierSync::enter() {
MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag); MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
if (should_reset()) { if (should_reset()) {
// The should_reset() was set and we are the first worker to enter // The should_reset() was set and we are the first worker to enter
...@@ -415,10 +416,17 @@ void WorkGangBarrierSync::enter() { ...@@ -415,10 +416,17 @@ void WorkGangBarrierSync::enter() {
set_should_reset(true); set_should_reset(true);
monitor()->notify_all(); monitor()->notify_all();
} else { } else {
while (n_completed() != n_workers()) { while (n_completed() != n_workers() && !aborted()) {
monitor()->wait(/* no_safepoint_check */ true); monitor()->wait(/* no_safepoint_check */ true);
} }
} }
return !aborted();
}
void WorkGangBarrierSync::abort() {
MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
set_aborted();
monitor()->notify_all();
} }
// SubTasksDone functions. // SubTasksDone functions.
......
...@@ -359,18 +359,20 @@ class FlexibleWorkGang: public WorkGang { ...@@ -359,18 +359,20 @@ class FlexibleWorkGang: public WorkGang {
class WorkGangBarrierSync : public StackObj { class WorkGangBarrierSync : public StackObj {
protected: protected:
Monitor _monitor; Monitor _monitor;
uint _n_workers; uint _n_workers;
uint _n_completed; uint _n_completed;
bool _should_reset; bool _should_reset;
bool _aborted;
Monitor* monitor() { return &_monitor; } Monitor* monitor() { return &_monitor; }
uint n_workers() { return _n_workers; } uint n_workers() { return _n_workers; }
uint n_completed() { return _n_completed; } uint n_completed() { return _n_completed; }
bool should_reset() { return _should_reset; } bool should_reset() { return _should_reset; }
bool aborted() { return _aborted; }
void zero_completed() { _n_completed = 0; } void zero_completed() { _n_completed = 0; }
void inc_completed() { _n_completed++; } void inc_completed() { _n_completed++; }
void set_aborted() { _aborted = true; }
void set_should_reset(bool v) { _should_reset = v; } void set_should_reset(bool v) { _should_reset = v; }
public: public:
...@@ -383,8 +385,14 @@ public: ...@@ -383,8 +385,14 @@ public:
// Enter the barrier. A worker that enters the barrier will // Enter the barrier. A worker that enters the barrier will
// not be allowed to leave until all other threads have // not be allowed to leave until all other threads have
// also entered the barrier. // also entered the barrier or the barrier is aborted.
void enter(); // Returns false if the barrier was aborted.
bool enter();
// Aborts the barrier and wakes up any threads waiting for
// the barrier to complete. The barrier will remain in the
// aborted state until the next call to set_n_workers().
void abort();
}; };
// A class to manage claiming of subtasks within a group of tasks. The // A class to manage claiming of subtasks within a group of tasks. The
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册