8138863: Refactor WaitForBarrierGCTask

Reviewed-by: mgerdin, jwilhelm
This commit is contained in:
Bengt Rutisson 2015-10-06 14:26:13 +02:00
parent ef3a3a84bc
commit 48bbdafeed
2 changed files with 77 additions and 87 deletions

View File

@ -395,7 +395,6 @@ void GCTaskManager::initialize() {
GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
_queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
_noop_task = NoopGCTask::create_on_c_heap(); _noop_task = NoopGCTask::create_on_c_heap();
_idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap();
_resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC); _resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC);
{ {
// Set up worker threads. // Set up worker threads.
@ -440,8 +439,6 @@ GCTaskManager::~GCTaskManager() {
assert(queue()->is_empty(), "still have queued work"); assert(queue()->is_empty(), "still have queued work");
NoopGCTask::destroy(_noop_task); NoopGCTask::destroy(_noop_task);
_noop_task = NULL; _noop_task = NULL;
WaitForBarrierGCTask::destroy(_idle_inactive_task);
_idle_inactive_task = NULL;
if (_thread != NULL) { if (_thread != NULL) {
for (uint i = 0; i < workers(); i += 1) { for (uint i = 0; i < workers(); i += 1) {
GCTaskThread::destroy(thread(i)); GCTaskThread::destroy(thread(i));
@ -497,7 +494,7 @@ void GCTaskManager::task_idle_workers() {
// the GCTaskManager's monitor so that the "more_inactive_workers" // the GCTaskManager's monitor so that the "more_inactive_workers"
// count is correct. // count is correct.
MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
_idle_inactive_task->set_should_wait(true); _wait_helper.set_should_wait(true);
// active_workers are a number being requested. idle_workers // active_workers are a number being requested. idle_workers
// are the number currently idle. If all the workers are being // are the number currently idle. If all the workers are being
// requested to be active but some are already idle, reduce // requested to be active but some are already idle, reduce
@ -540,7 +537,7 @@ void GCTaskManager::release_idle_workers() {
{ {
MutexLockerEx ml(monitor(), MutexLockerEx ml(monitor(),
Mutex::_no_safepoint_check_flag); Mutex::_no_safepoint_check_flag);
_idle_inactive_task->set_should_wait(false); _wait_helper.set_should_wait(false);
monitor()->notify_all(); monitor()->notify_all();
// Release monitor // Release monitor
} }
@ -834,12 +831,12 @@ IdleGCTask* IdleGCTask::create_on_c_heap() {
} }
void IdleGCTask::do_it(GCTaskManager* manager, uint which) { void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task(); WaitHelper* wait_helper = manager->wait_helper();
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "]"
" IdleGCTask:::do_it()" " IdleGCTask:::do_it()"
" should_wait: %s", " should_wait: %s",
p2i(this), wait_for_task->should_wait() ? "true" : "false"); p2i(this), wait_helper->should_wait() ? "true" : "false");
} }
MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag); MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
if (TraceDynamicGCThreads) { if (TraceDynamicGCThreads) {
@ -848,7 +845,7 @@ void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
// Increment has to be done when the idle tasks are created. // Increment has to be done when the idle tasks are created.
// manager->increment_idle_workers(); // manager->increment_idle_workers();
manager->monitor()->notify_all(); manager->monitor()->notify_all();
while (wait_for_task->should_wait()) { while (wait_helper->should_wait()) {
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "]"
" IdleGCTask::do_it()" " IdleGCTask::do_it()"
@ -865,7 +862,7 @@ void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "]"
" IdleGCTask::do_it() returns" " IdleGCTask::do_it() returns"
" should_wait: %s", " should_wait: %s",
p2i(this), wait_for_task->should_wait() ? "true" : "false"); p2i(this), wait_helper->should_wait() ? "true" : "false");
} }
// Release monitor(). // Release monitor().
} }
@ -889,62 +886,29 @@ void IdleGCTask::destruct() {
// WaitForBarrierGCTask // WaitForBarrierGCTask
// //
WaitForBarrierGCTask* WaitForBarrierGCTask::create() { WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); WaitForBarrierGCTask* result = new WaitForBarrierGCTask();
return result; return result;
} }
WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { WaitForBarrierGCTask::WaitForBarrierGCTask() : GCTask(GCTask::Kind::wait_for_barrier_task) { }
WaitForBarrierGCTask* result =
new (ResourceObj::C_HEAP, mtGC) WaitForBarrierGCTask(true);
return result;
}
WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
GCTask(GCTask::Kind::wait_for_barrier_task),
_is_c_heap_obj(on_c_heap) {
_monitor = MonitorSupply::reserve();
set_should_wait(true);
if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]"
" WaitForBarrierGCTask::WaitForBarrierGCTask()"
" monitor: " INTPTR_FORMAT,
p2i(this), p2i(monitor()));
}
}
void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) { void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
if (that != NULL) { if (that != NULL) {
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destroy()", p2i(that));
" WaitForBarrierGCTask::destroy()"
" is_c_heap_obj: %s"
" monitor: " INTPTR_FORMAT,
p2i(that),
that->is_c_heap_obj() ? "true" : "false",
p2i(that->monitor()));
} }
that->destruct(); that->destruct();
if (that->is_c_heap_obj()) {
FreeHeap(that);
}
} }
} }
void WaitForBarrierGCTask::destruct() { void WaitForBarrierGCTask::destruct() {
assert(monitor() != NULL, "monitor should not be NULL");
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destruct()", p2i(this));
" WaitForBarrierGCTask::destruct()"
" monitor: " INTPTR_FORMAT,
p2i(this), p2i(monitor()));
} }
this->GCTask::destruct(); this->GCTask::destruct();
// Clean up that should be in the destructor, // Clean up that should be in the destructor,
// except that ResourceMarks don't call destructors. // except that ResourceMarks don't call destructors.
if (monitor() != NULL) { _wait_helper.release_monitor();
MonitorSupply::release(monitor());
}
_monitor = (Monitor*) 0xDEAD000F;
} }
void WaitForBarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) { void WaitForBarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
@ -963,9 +927,8 @@ void WaitForBarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) { void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "]"
" WaitForBarrierGCTask::do_it() waiting for idle" " WaitForBarrierGCTask::do_it() waiting for idle",
" monitor: " INTPTR_FORMAT, p2i(this));
p2i(this), p2i(monitor()));
} }
{ {
// First, wait for the barrier to arrive. // First, wait for the barrier to arrive.
@ -973,24 +936,30 @@ void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
do_it_internal(manager, which); do_it_internal(manager, which);
// Release manager->lock(). // Release manager->lock().
} }
{ // Then notify the waiter.
// Then notify the waiter. _wait_helper.notify();
MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); }
set_should_wait(false);
// Waiter doesn't miss the notify in the wait_for method WaitHelper::WaitHelper() : _should_wait(true), _monitor(MonitorSupply::reserve()) {
// since it checks the flag after grabbing the monitor. if (TraceGCTaskManager) {
if (TraceGCTaskManager) { tty->print_cr("[" INTPTR_FORMAT "]"
tty->print_cr("[" INTPTR_FORMAT "]" " WaitHelper::WaitHelper()"
" WaitForBarrierGCTask::do_it()" " monitor: " INTPTR_FORMAT,
" [" INTPTR_FORMAT "] (%s)->notify_all()", p2i(this), p2i(monitor()));
p2i(this), p2i(monitor()), monitor()->name());
}
monitor()->notify_all();
// Release monitor().
} }
} }
void WaitForBarrierGCTask::wait_for(bool reset) { void WaitHelper::release_monitor() {
assert(_monitor != NULL, "");
MonitorSupply::release(_monitor);
_monitor = NULL;
}
WaitHelper::~WaitHelper() {
release_monitor();
}
void WaitHelper::wait_for(bool reset) {
if (TraceGCTaskManager) { if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]" tty->print_cr("[" INTPTR_FORMAT "]"
" WaitForBarrierGCTask::wait_for()" " WaitForBarrierGCTask::wait_for()"
@ -1023,6 +992,20 @@ void WaitForBarrierGCTask::wait_for(bool reset) {
} }
} }
void WaitHelper::notify() {
MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
set_should_wait(false);
// Waiter doesn't miss the notify in the wait_for method
// since it checks the flag after grabbing the monitor.
if (TraceGCTaskManager) {
tty->print_cr("[" INTPTR_FORMAT "]"
" WaitForBarrierGCTask::do_it()"
" [" INTPTR_FORMAT "] (%s)->notify_all()",
p2i(this), p2i(monitor()), monitor()->name());
}
monitor()->notify_all();
}
Mutex* MonitorSupply::_lock = NULL; Mutex* MonitorSupply::_lock = NULL;
GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL; GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;

View File

@ -272,6 +272,28 @@ protected:
~SynchronizedGCTaskQueue(); ~SynchronizedGCTaskQueue();
}; };
class WaitHelper VALUE_OBJ_CLASS_SPEC {
private:
Monitor* _monitor;
volatile bool _should_wait;
public:
WaitHelper();
~WaitHelper();
void wait_for(bool reset);
void notify();
void set_should_wait(bool value) {
_should_wait = value;
}
Monitor* monitor() const {
return _monitor;
}
bool should_wait() const {
return _should_wait;
}
void release_monitor();
};
// Dynamic number of GC threads // Dynamic number of GC threads
// //
// GC threads wait in get_task() for work (i.e., a task) to perform. // GC threads wait in get_task() for work (i.e., a task) to perform.
@ -357,7 +379,7 @@ private:
uint _barriers; // Count of barrier tasks. uint _barriers; // Count of barrier tasks.
uint _emptied_queue; // Times we emptied the queue. uint _emptied_queue; // Times we emptied the queue.
NoopGCTask* _noop_task; // The NoopGCTask instance. NoopGCTask* _noop_task; // The NoopGCTask instance.
WaitForBarrierGCTask* _idle_inactive_task;// Task for inactive workers WaitHelper _wait_helper; // Used by inactive worker
volatile uint _idle_workers; // Number of idled workers volatile uint _idle_workers; // Number of idled workers
public: public:
// Factory create and destroy methods. // Factory create and destroy methods.
@ -383,8 +405,8 @@ public:
Monitor * lock() const { Monitor * lock() const {
return _monitor; return _monitor;
} }
WaitForBarrierGCTask* idle_inactive_task() { WaitHelper* wait_helper() {
return _idle_inactive_task; return &_wait_helper;
} }
// Methods. // Methods.
// Add the argument task to be run. // Add the argument task to be run.
@ -559,25 +581,17 @@ class WaitForBarrierGCTask : public GCTask {
friend class IdleGCTask; friend class IdleGCTask;
private: private:
// Instance state. // Instance state.
Monitor* _monitor; // Guard and notify changes. WaitHelper _wait_helper;
volatile bool _should_wait; // true=>wait, false=>proceed. WaitForBarrierGCTask();
const bool _is_c_heap_obj; // Was allocated on the heap.
public: public:
virtual char* name() { return (char *) "waitfor-barrier-task"; } virtual char* name() { return (char *) "waitfor-barrier-task"; }
// Factory create and destroy methods. // Factory create and destroy methods.
static WaitForBarrierGCTask* create(); static WaitForBarrierGCTask* create();
static WaitForBarrierGCTask* create_on_c_heap();
static void destroy(WaitForBarrierGCTask* that); static void destroy(WaitForBarrierGCTask* that);
// Methods. // Methods.
void do_it(GCTaskManager* manager, uint which); void do_it(GCTaskManager* manager, uint which);
void wait_for(bool reset);
void set_should_wait(bool value) {
_should_wait = value;
}
protected: protected:
// Constructor. Clients use factory, but there might be subclasses.
WaitForBarrierGCTask(bool on_c_heap);
// Destructor-like method. // Destructor-like method.
void destruct(); void destruct();
@ -585,15 +599,8 @@ protected:
// Wait for this to be the only task running. // Wait for this to be the only task running.
void do_it_internal(GCTaskManager* manager, uint which); void do_it_internal(GCTaskManager* manager, uint which);
// Accessors. void wait_for(bool reset) {
Monitor* monitor() const { _wait_helper.wait_for(reset);
return _monitor;
}
bool should_wait() const {
return _should_wait;
}
bool is_c_heap_obj() {
return _is_c_heap_obj;
} }
}; };