# HG changeset patch # User coleenp # Date 1444157507 0 # Node ID 0d1360a45a3b640e8eeda7ec6b5838e3c3810de9 # Parent 0dfbcf8b7d7ab273355f6adcb7384008f38bb63b# Parent 260ff671354b285fd2609e1b9e1387a1da663c52 Merge diff -r 0dfbcf8b7d7a -r 0d1360a45a3b hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp --- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp Tue Oct 06 14:27:39 2015 -0400 +++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp Tue Oct 06 18:51:47 2015 +0000 @@ -26,6 +26,7 @@ #include "gc/parallel/gcTaskManager.hpp" #include "gc/parallel/gcTaskThread.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" +#include "gc/shared/gcId.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "runtime/mutex.hpp" @@ -48,8 +49,8 @@ case ordinary_task: result = "ordinary task"; break; - case barrier_task: - result = "barrier task"; + case wait_for_barrier_task: + result = "wait for barrier task"; break; case noop_task: result = "noop task"; @@ -61,33 +62,24 @@ return result; }; -GCTask::GCTask() : - _kind(Kind::ordinary_task), - _affinity(GCTaskManager::sentinel_worker()){ - initialize(); +GCTask::GCTask() { + initialize(Kind::ordinary_task, GCId::current()); } -GCTask::GCTask(Kind::kind kind) : - _kind(kind), - _affinity(GCTaskManager::sentinel_worker()) { - initialize(); +GCTask::GCTask(Kind::kind kind) { + initialize(kind, GCId::current()); } -GCTask::GCTask(uint affinity) : - _kind(Kind::ordinary_task), - _affinity(affinity) { - initialize(); +GCTask::GCTask(Kind::kind kind, uint gc_id) { + initialize(kind, gc_id); } -GCTask::GCTask(Kind::kind kind, uint affinity) : - _kind(kind), - _affinity(affinity) { - initialize(); -} - -void GCTask::initialize() { +void GCTask::initialize(Kind::kind kind, uint gc_id) { + _kind = kind; + _affinity = GCTaskManager::sentinel_worker(); _older = NULL; _newer = NULL; + _gc_id = gc_id; } void GCTask::destruct() { @@ -378,16 +370,7 @@ GCTaskManager::GCTaskManager(uint workers) : _workers(workers), _active_workers(0), - _idle_workers(0), - _ndc(NULL) { - initialize(); -} - -GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : - _workers(workers), - _active_workers(0), - _idle_workers(0), - _ndc(ndc) { + _idle_workers(0) { initialize(); } @@ -404,7 +387,6 @@ GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); _noop_task = NoopGCTask::create_on_c_heap(); - _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap(); _resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC); { // Set up worker threads. @@ -437,7 +419,6 @@ } reset_delivered_tasks(); reset_completed_tasks(); - reset_noop_tasks(); reset_barriers(); reset_emptied_queue(); for (uint s = 0; s < workers(); s += 1) { @@ -450,8 +431,6 @@ assert(queue()->is_empty(), "still have queued work"); NoopGCTask::destroy(_noop_task); _noop_task = NULL; - WaitForBarrierGCTask::destroy(_idle_inactive_task); - _idle_inactive_task = NULL; if (_thread != NULL) { for (uint i = 0; i < workers(); i += 1) { GCTaskThread::destroy(thread(i)); @@ -507,7 +486,7 @@ // the GCTaskManager's monitor so that the "more_inactive_workers" // count is correct. 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 // are the number currently idle. If all the workers are being // requested to be active but some are already idle, reduce @@ -550,7 +529,7 @@ { MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); - _idle_inactive_task->set_should_wait(false); + _wait_helper.set_should_wait(false); monitor()->notify_all(); // Release monitor } @@ -671,7 +650,6 @@ // Just hand back a Noop task, // in case someone wanted us to release resources, or whatever. result = noop_task(); - increment_noop_tasks(); } assert(result != NULL, "shouldn't have null task"); if (TraceGCTaskManager) { @@ -706,11 +684,6 @@ if (TraceGCTaskManager) { tty->print_cr(" GCTaskManager::note_completion(%u) done", which); } - // Notify client that we are done. - NotifyDoneClosure* ndc = notify_done_closure(); - if (ndc != NULL) { - ndc->notify(this); - } } if (TraceGCTaskManager) { tty->print_cr(" GCTaskManager::note_completion(%u) (%s)->notify_all", @@ -751,7 +724,7 @@ } void GCTaskManager::release_all_resources() { - // If you want this to be done atomically, do it in a BarrierGCTask. + // If you want this to be done atomically, do it in a WaitForBarrierGCTask. for (uint i = 0; i < workers(); i += 1) { set_resource_flag(i, true); } @@ -813,25 +786,22 @@ // NoopGCTask // -NoopGCTask* NoopGCTask::create() { - NoopGCTask* result = new NoopGCTask(false); - return result; -} - NoopGCTask* NoopGCTask::create_on_c_heap() { - NoopGCTask* result = new(ResourceObj::C_HEAP, mtGC) NoopGCTask(true); + NoopGCTask* result = new(ResourceObj::C_HEAP, mtGC) NoopGCTask(); return result; } void NoopGCTask::destroy(NoopGCTask* that) { if (that != NULL) { that->destruct(); - if (that->is_c_heap_obj()) { - FreeHeap(that); - } + FreeHeap(that); } } +// This task should never be performing GC work that require +// a valid GC id. +NoopGCTask::NoopGCTask() : GCTask(GCTask::Kind::noop_task, GCId::undefined()) { } + void NoopGCTask::destruct() { // This has to know it's superclass structure, just like the constructor. this->GCTask::destruct(); @@ -857,12 +827,12 @@ } void IdleGCTask::do_it(GCTaskManager* manager, uint which) { - WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task(); + WaitHelper* wait_helper = manager->wait_helper(); if (TraceGCTaskManager) { tty->print_cr("[" INTPTR_FORMAT "]" " IdleGCTask:::do_it()" " 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); if (TraceDynamicGCThreads) { @@ -871,7 +841,7 @@ // Increment has to be done when the idle tasks are created. // manager->increment_idle_workers(); manager->monitor()->notify_all(); - while (wait_for_task->should_wait()) { + while (wait_helper->should_wait()) { if (TraceGCTaskManager) { tty->print_cr("[" INTPTR_FORMAT "]" " IdleGCTask::do_it()" @@ -888,7 +858,7 @@ tty->print_cr("[" INTPTR_FORMAT "]" " IdleGCTask::do_it() returns" " should_wait: %s", - p2i(this), wait_for_task->should_wait() ? "true" : "false"); + p2i(this), wait_helper->should_wait() ? "true" : "false"); } // Release monitor(). } @@ -909,140 +879,52 @@ } // -// BarrierGCTask +// WaitForBarrierGCTask // - -void BarrierGCTask::do_it(GCTaskManager* manager, uint which) { - // Wait for this to be the only busy worker. - // ??? I thought of having a StackObj class - // whose constructor would grab the lock and come to the barrier, - // and whose destructor would release the lock, - // but that seems like too much mechanism for two lines of code. - MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); - do_it_internal(manager, which); - // Release manager->lock(). +WaitForBarrierGCTask* WaitForBarrierGCTask::create() { + WaitForBarrierGCTask* result = new WaitForBarrierGCTask(); + return result; } -void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) { +WaitForBarrierGCTask::WaitForBarrierGCTask() : GCTask(GCTask::Kind::wait_for_barrier_task) { } + +void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) { + if (that != NULL) { + if (TraceGCTaskManager) { + tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destroy()", p2i(that)); + } + that->destruct(); + } +} + +void WaitForBarrierGCTask::destruct() { + if (TraceGCTaskManager) { + tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destruct()", p2i(this)); + } + this->GCTask::destruct(); + // Clean up that should be in the destructor, + // except that ResourceMarks don't call destructors. + _wait_helper.release_monitor(); +} + +void WaitForBarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) { // Wait for this to be the only busy worker. assert(manager->monitor()->owned_by_self(), "don't own the lock"); assert(manager->is_blocked(), "manager isn't blocked"); while (manager->busy_workers() > 1) { if (TraceGCTaskManager) { - tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers", + tty->print_cr("WaitForBarrierGCTask::do_it(%u) waiting on %u workers", which, manager->busy_workers()); } manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0); } } -void BarrierGCTask::destruct() { - this->GCTask::destruct(); - // Nothing else to do. -} - -// -// ReleasingBarrierGCTask -// - -void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) { - MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); - do_it_internal(manager, which); - manager->release_all_resources(); - // Release manager->lock(). -} - -void ReleasingBarrierGCTask::destruct() { - this->BarrierGCTask::destruct(); - // Nothing else to do. -} - -// -// NotifyingBarrierGCTask -// - -void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) { - MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); - do_it_internal(manager, which); - NotifyDoneClosure* ndc = notify_done_closure(); - if (ndc != NULL) { - ndc->notify(manager); - } - // Release manager->lock(). -} - -void NotifyingBarrierGCTask::destruct() { - this->BarrierGCTask::destruct(); - // Nothing else to do. -} - -// -// WaitForBarrierGCTask -// -WaitForBarrierGCTask* WaitForBarrierGCTask::create() { - WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); - return result; -} - -WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { - WaitForBarrierGCTask* result = - new (ResourceObj::C_HEAP, mtGC) WaitForBarrierGCTask(true); - return result; -} - -WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) : - _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) { - if (that != NULL) { - if (TraceGCTaskManager) { - tty->print_cr("[" INTPTR_FORMAT "]" - " WaitForBarrierGCTask::destroy()" - " is_c_heap_obj: %s" - " monitor: " INTPTR_FORMAT, - p2i(that), - that->is_c_heap_obj() ? "true" : "false", - p2i(that->monitor())); - } - that->destruct(); - if (that->is_c_heap_obj()) { - FreeHeap(that); - } - } -} - -void WaitForBarrierGCTask::destruct() { - assert(monitor() != NULL, "monitor should not be NULL"); - if (TraceGCTaskManager) { - tty->print_cr("[" INTPTR_FORMAT "]" - " WaitForBarrierGCTask::destruct()" - " monitor: " INTPTR_FORMAT, - p2i(this), p2i(monitor())); - } - this->BarrierGCTask::destruct(); - // Clean up that should be in the destructor, - // except that ResourceMarks don't call destructors. - if (monitor() != NULL) { - MonitorSupply::release(monitor()); - } - _monitor = (Monitor*) 0xDEAD000F; -} - void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) { if (TraceGCTaskManager) { tty->print_cr("[" INTPTR_FORMAT "]" - " WaitForBarrierGCTask::do_it() waiting for idle" - " monitor: " INTPTR_FORMAT, - p2i(this), p2i(monitor())); + " WaitForBarrierGCTask::do_it() waiting for idle", + p2i(this)); } { // First, wait for the barrier to arrive. @@ -1050,24 +932,30 @@ do_it_internal(manager, which); // Release manager->lock(). } - { - // Then notify the waiter. - 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(); - // Release monitor(). + // Then notify the waiter. + _wait_helper.notify(); +} + +WaitHelper::WaitHelper() : _should_wait(true), _monitor(MonitorSupply::reserve()) { + if (TraceGCTaskManager) { + tty->print_cr("[" INTPTR_FORMAT "]" + " WaitHelper::WaitHelper()" + " monitor: " INTPTR_FORMAT, + p2i(this), p2i(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) { tty->print_cr("[" INTPTR_FORMAT "]" " WaitForBarrierGCTask::wait_for()" @@ -1100,6 +988,20 @@ } } +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; GrowableArray* MonitorSupply::_freelist = NULL; diff -r 0dfbcf8b7d7a -r 0d1360a45a3b hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp --- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp Tue Oct 06 14:27:39 2015 -0400 +++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp Tue Oct 06 18:51:47 2015 +0000 @@ -38,12 +38,8 @@ class GCTaskQueue; class SynchronizedGCTaskQueue; class GCTaskManager; -class NotifyDoneClosure; // Some useful subclasses of GCTask. You can also make up your own. class NoopGCTask; -class BarrierGCTask; -class ReleasingBarrierGCTask; -class NotifyingBarrierGCTask; class WaitForBarrierGCTask; class IdleGCTask; // A free list of Monitor*'s. @@ -64,7 +60,7 @@ enum kind { unknown_task, ordinary_task, - barrier_task, + wait_for_barrier_task, noop_task, idle_task }; @@ -72,13 +68,16 @@ }; private: // Instance state. - const Kind::kind _kind; // For runtime type checking. - const uint _affinity; // Which worker should run task. + Kind::kind _kind; // For runtime type checking. + uint _affinity; // Which worker should run task. GCTask* _newer; // Tasks are on doubly-linked ... GCTask* _older; // ... lists. + uint _gc_id; // GC Id to use for the thread that executes this task public: virtual char* name() { return (char *)"task"; } + uint gc_id() { return _gc_id; } + // Abstract do_it method virtual void do_it(GCTaskManager* manager, uint which) = 0; // Accessors @@ -105,7 +104,7 @@ return kind()==Kind::ordinary_task; } bool is_barrier_task() const { - return kind()==Kind::barrier_task; + return kind()==Kind::wait_for_barrier_task; } bool is_noop_task() const { return kind()==Kind::noop_task; @@ -120,17 +119,14 @@ GCTask(); // A GCTask of a particular kind, usually barrier or noop. GCTask(Kind::kind kind); - // An ordinary GCTask with an affinity. - GCTask(uint affinity); - // A GCTask of a particular kind, with and affinity. - GCTask(Kind::kind kind, uint affinity); + GCTask(Kind::kind kind, uint gc_id); // We want a virtual destructor because virtual methods, // but since ResourceObj's don't have their destructors // called, we don't have one at all. Instead we have // this method, which gets called by subclasses to clean up. virtual void destruct(); // Methods. - void initialize(); + void initialize(Kind::kind kind, uint gc_id); }; // A doubly-linked list of GCTasks. @@ -276,21 +272,26 @@ ~SynchronizedGCTaskQueue(); }; -// This is an abstract base class for getting notifications -// when a GCTaskManager is done. -class NotifyDoneClosure : public CHeapObj { -public: - // The notification callback method. - virtual void notify(GCTaskManager* manager) = 0; -protected: - // Constructor. - NotifyDoneClosure() { - // Nothing to do. +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; } - // Virtual destructor because virtual methods. - virtual ~NotifyDoneClosure() { - // Nothing to do. + + Monitor* monitor() const { + return _monitor; } + bool should_wait() const { + return _should_wait; + } + void release_monitor(); }; // Dynamic number of GC threads @@ -365,7 +366,6 @@ friend class IdleGCTask; private: // Instance state. - NotifyDoneClosure* _ndc; // Notify on completion. const uint _workers; // Number of workers. Monitor* _monitor; // Notification of changes. SynchronizedGCTaskQueue* _queue; // Queue of tasks. @@ -379,17 +379,13 @@ uint _barriers; // Count of barrier tasks. uint _emptied_queue; // Times we emptied the queue. NoopGCTask* _noop_task; // The NoopGCTask instance. - uint _noop_tasks; // Count of noop tasks. - WaitForBarrierGCTask* _idle_inactive_task;// Task for inactive workers + WaitHelper _wait_helper; // Used by inactive worker volatile uint _idle_workers; // Number of idled workers public: // Factory create and destroy methods. static GCTaskManager* create(uint workers) { return new GCTaskManager(workers); } - static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) { - return new GCTaskManager(workers, ndc); - } static void destroy(GCTaskManager* that) { if (that != NULL) { delete that; @@ -409,8 +405,8 @@ Monitor * lock() const { return _monitor; } - WaitForBarrierGCTask* idle_inactive_task() { - return _idle_inactive_task; + WaitHelper* wait_helper() { + return &_wait_helper; } // Methods. // Add the argument task to be run. @@ -452,8 +448,6 @@ // Constructors. Clients use factory, but there might be subclasses. // Create a GCTaskManager with the appropriate number of workers. GCTaskManager(uint workers); - // Create a GCTaskManager that calls back when there's no more work. - GCTaskManager(uint workers, NotifyDoneClosure* ndc); // Make virtual if necessary. ~GCTaskManager(); // Accessors. @@ -469,9 +463,6 @@ // Sets the number of threads that will be used in a collection void set_active_gang(); - NotifyDoneClosure* notify_done_closure() const { - return _ndc; - } SynchronizedGCTaskQueue* queue() const { return _queue; } @@ -540,17 +531,6 @@ void reset_emptied_queue() { _emptied_queue = 0; } - // Count of the number of noop tasks we've handed out, - // e.g., to handle resource release requests. - uint noop_tasks() const { - return _noop_tasks; - } - void increment_noop_tasks() { - _noop_tasks += 1; - } - void reset_noop_tasks() { - _noop_tasks = 0; - } void increment_idle_workers() { _idle_workers++; } @@ -575,11 +555,8 @@ // A noop task that does nothing, // except take us around the GCTaskThread loop. class NoopGCTask : public GCTask { -private: - const bool _is_c_heap_obj; // Is this a CHeapObj? public: // Factory create and destroy methods. - static NoopGCTask* create(); static NoopGCTask* create_on_c_heap(); static void destroy(NoopGCTask* that); @@ -590,147 +567,39 @@ } protected: // Constructor. - NoopGCTask(bool on_c_heap) : - GCTask(GCTask::Kind::noop_task), - _is_c_heap_obj(on_c_heap) { - // Nothing to do. - } - // Destructor-like method. - void destruct(); - // Accessors. - bool is_c_heap_obj() const { - return _is_c_heap_obj; - } -}; - -// A BarrierGCTask blocks other tasks from starting, -// and waits until it is the only task running. -class BarrierGCTask : public GCTask { -public: - // Factory create and destroy methods. - static BarrierGCTask* create() { - return new BarrierGCTask(); - } - static void destroy(BarrierGCTask* that) { - if (that != NULL) { - that->destruct(); - delete that; - } - } - // Methods from GCTask. - void do_it(GCTaskManager* manager, uint which); -protected: - // Constructor. Clients use factory, but there might be subclasses. - BarrierGCTask() : - GCTask(GCTask::Kind::barrier_task) { - // Nothing to do. - } - // Destructor-like method. - void destruct(); - - virtual char* name() { return (char *)"barrier task"; } - // Methods. - // Wait for this to be the only task running. - void do_it_internal(GCTaskManager* manager, uint which); -}; - -// A ReleasingBarrierGCTask is a BarrierGCTask -// that tells all the tasks to release their resource areas. -class ReleasingBarrierGCTask : public BarrierGCTask { -public: - // Factory create and destroy methods. - static ReleasingBarrierGCTask* create() { - return new ReleasingBarrierGCTask(); - } - static void destroy(ReleasingBarrierGCTask* that) { - if (that != NULL) { - that->destruct(); - delete that; - } - } - // Methods from GCTask. - void do_it(GCTaskManager* manager, uint which); -protected: - // Constructor. Clients use factory, but there might be subclasses. - ReleasingBarrierGCTask() : - BarrierGCTask() { - // Nothing to do. - } + NoopGCTask(); // Destructor-like method. void destruct(); }; -// A NotifyingBarrierGCTask is a BarrierGCTask -// that calls a notification method when it is the only task running. -class NotifyingBarrierGCTask : public BarrierGCTask { -private: - // Instance state. - NotifyDoneClosure* _ndc; // The callback object. -public: - // Factory create and destroy methods. - static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) { - return new NotifyingBarrierGCTask(ndc); - } - static void destroy(NotifyingBarrierGCTask* that) { - if (that != NULL) { - that->destruct(); - delete that; - } - } - // Methods from GCTask. - void do_it(GCTaskManager* manager, uint which); -protected: - // Constructor. Clients use factory, but there might be subclasses. - NotifyingBarrierGCTask(NotifyDoneClosure* ndc) : - BarrierGCTask(), - _ndc(ndc) { - assert(notify_done_closure() != NULL, "can't notify on NULL"); - } - // Destructor-like method. - void destruct(); - // Accessor. - NotifyDoneClosure* notify_done_closure() const { return _ndc; } -}; - -// A WaitForBarrierGCTask is a BarrierGCTask +// A WaitForBarrierGCTask is a GCTask // with a method you can call to wait until // the BarrierGCTask is done. -// This may cover many of the uses of NotifyingBarrierGCTasks. -class WaitForBarrierGCTask : public BarrierGCTask { +class WaitForBarrierGCTask : public GCTask { friend class GCTaskManager; friend class IdleGCTask; private: // Instance state. - Monitor* _monitor; // Guard and notify changes. - volatile bool _should_wait; // true=>wait, false=>proceed. - const bool _is_c_heap_obj; // Was allocated on the heap. + WaitHelper _wait_helper; + WaitForBarrierGCTask(); public: virtual char* name() { return (char *) "waitfor-barrier-task"; } // Factory create and destroy methods. static WaitForBarrierGCTask* create(); - static WaitForBarrierGCTask* create_on_c_heap(); static void destroy(WaitForBarrierGCTask* that); // Methods. void do_it(GCTaskManager* manager, uint which); - void wait_for(bool reset); - void set_should_wait(bool value) { - _should_wait = value; - } protected: - // Constructor. Clients use factory, but there might be subclasses. - WaitForBarrierGCTask(bool on_c_heap); // Destructor-like method. void destruct(); - // Accessors. - Monitor* monitor() const { - return _monitor; - } - bool should_wait() const { - return _should_wait; - } - bool is_c_heap_obj() { - return _is_c_heap_obj; + + // Methods. + // Wait for this to be the only task running. + void do_it_internal(GCTaskManager* manager, uint which); + + void wait_for(bool reset) { + _wait_helper.wait_for(reset); } }; diff -r 0dfbcf8b7d7a -r 0d1360a45a3b hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp --- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp Tue Oct 06 14:27:39 2015 -0400 +++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp Tue Oct 06 18:51:47 2015 +0000 @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "gc/parallel/gcTaskManager.hpp" #include "gc/parallel/gcTaskThread.hpp" +#include "gc/shared/gcId.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -124,6 +125,7 @@ for (; /* break */; ) { // This will block until there is a task to be gotten. GCTask* task = manager()->get_task(which()); + GCIdMark gc_id_mark(task->gc_id()); // Record if this is an idle task for later use. bool is_idle_task = task->is_idle_task(); // In case the update is costly