|  | /* | 
|  | * Copyright (c) 2002, 2012, 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_PARALLELSCAVENGE_GCTASKMANAGER_HPP | 
|  | #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP | 
|  |  | 
|  | #include "runtime/mutex.hpp" | 
|  | #include "utilities/growableArray.hpp" | 
|  |  | 
|  | // | 
|  | // The GCTaskManager is a queue of GCTasks, and accessors | 
|  | // to allow the queue to be accessed from many threads. | 
|  | // | 
|  |  | 
|  | // Forward declarations of types defined in this file. | 
|  | class GCTask; | 
|  | 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. | 
|  | class MonitorSupply; | 
|  |  | 
|  | // Forward declarations of classes referenced in this file via pointer. | 
|  | class GCTaskThread; | 
|  | class Mutex; | 
|  | class Monitor; | 
|  | class ThreadClosure; | 
|  |  | 
|  | // The abstract base GCTask. | 
|  | class GCTask : public ResourceObj { | 
|  | public: | 
|  | // Known kinds of GCTasks, for predicates. | 
|  | class Kind : AllStatic { | 
|  | public: | 
|  | enum kind { | 
|  | unknown_task, | 
|  | ordinary_task, | 
|  | barrier_task, | 
|  | noop_task, | 
|  | idle_task | 
|  | }; | 
|  | static const char* to_string(kind value); | 
|  | }; | 
|  | private: | 
|  | // Instance state. | 
|  | const Kind::kind _kind;               // For runtime type checking. | 
|  | const uint       _affinity;           // Which worker should run task. | 
|  | GCTask*          _newer;              // Tasks are on doubly-linked ... | 
|  | GCTask*          _older;              // ... lists. | 
|  | public: | 
|  | virtual char* name() { return (char *)"task"; } | 
|  |  | 
|  | // Abstract do_it method | 
|  | virtual void do_it(GCTaskManager* manager, uint which) = 0; | 
|  | // Accessors | 
|  | Kind::kind kind() const { | 
|  | return _kind; | 
|  | } | 
|  | uint affinity() const { | 
|  | return _affinity; | 
|  | } | 
|  | GCTask* newer() const { | 
|  | return _newer; | 
|  | } | 
|  | void set_newer(GCTask* n) { | 
|  | _newer = n; | 
|  | } | 
|  | GCTask* older() const { | 
|  | return _older; | 
|  | } | 
|  | void set_older(GCTask* p) { | 
|  | _older = p; | 
|  | } | 
|  | // Predicates. | 
|  | bool is_ordinary_task() const { | 
|  | return kind()==Kind::ordinary_task; | 
|  | } | 
|  | bool is_barrier_task() const { | 
|  | return kind()==Kind::barrier_task; | 
|  | } | 
|  | bool is_noop_task() const { | 
|  | return kind()==Kind::noop_task; | 
|  | } | 
|  | bool is_idle_task() const { | 
|  | return kind()==Kind::idle_task; | 
|  | } | 
|  | void print(const char* message) const PRODUCT_RETURN; | 
|  | protected: | 
|  | // Constructors: Only create subclasses. | 
|  | //     An ordinary GCTask. | 
|  | 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); | 
|  | // 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(); | 
|  | }; | 
|  |  | 
|  | // A doubly-linked list of GCTasks. | 
|  | // The list is not synchronized, because sometimes we want to | 
|  | // build up a list and then make it available to other threads. | 
|  | // See also: SynchronizedGCTaskQueue. | 
|  | class GCTaskQueue : public ResourceObj { | 
|  | private: | 
|  | // Instance state. | 
|  | GCTask*    _insert_end;               // Tasks are enqueued at this end. | 
|  | GCTask*    _remove_end;               // Tasks are dequeued from this end. | 
|  | uint       _length;                   // The current length of the queue. | 
|  | const bool _is_c_heap_obj;            // Is this a CHeapObj? | 
|  | public: | 
|  | // Factory create and destroy methods. | 
|  | //     Create as ResourceObj. | 
|  | static GCTaskQueue* create(); | 
|  | //     Create as CHeapObj. | 
|  | static GCTaskQueue* create_on_c_heap(); | 
|  | //     Destroyer. | 
|  | static void destroy(GCTaskQueue* that); | 
|  | // Accessors. | 
|  | //     These just examine the state of the queue. | 
|  | bool is_empty() const { | 
|  | assert(((insert_end() == NULL && remove_end() == NULL) || | 
|  | (insert_end() != NULL && remove_end() != NULL)), | 
|  | "insert_end and remove_end don't match"); | 
|  | assert((insert_end() != NULL) || (_length == 0), "Not empty"); | 
|  | return insert_end() == NULL; | 
|  | } | 
|  | uint length() const { | 
|  | return _length; | 
|  | } | 
|  | // Methods. | 
|  | //     Enqueue one task. | 
|  | void enqueue(GCTask* task); | 
|  | //     Enqueue a list of tasks.  Empties the argument list. | 
|  | void enqueue(GCTaskQueue* list); | 
|  | //     Dequeue one task. | 
|  | GCTask* dequeue(); | 
|  | //     Dequeue one task, preferring one with affinity. | 
|  | GCTask* dequeue(uint affinity); | 
|  | protected: | 
|  | // Constructor. Clients use factory, but there might be subclasses. | 
|  | GCTaskQueue(bool on_c_heap); | 
|  | // Destructor-like method. | 
|  | // Because ResourceMark doesn't call destructors. | 
|  | // This method cleans up like one. | 
|  | virtual void destruct(); | 
|  | // Accessors. | 
|  | GCTask* insert_end() const { | 
|  | return _insert_end; | 
|  | } | 
|  | void set_insert_end(GCTask* value) { | 
|  | _insert_end = value; | 
|  | } | 
|  | GCTask* remove_end() const { | 
|  | return _remove_end; | 
|  | } | 
|  | void set_remove_end(GCTask* value) { | 
|  | _remove_end = value; | 
|  | } | 
|  | void increment_length() { | 
|  | _length += 1; | 
|  | } | 
|  | void decrement_length() { | 
|  | _length -= 1; | 
|  | } | 
|  | void set_length(uint value) { | 
|  | _length = value; | 
|  | } | 
|  | bool is_c_heap_obj() const { | 
|  | return _is_c_heap_obj; | 
|  | } | 
|  | // Methods. | 
|  | void initialize(); | 
|  | GCTask* remove();                     // Remove from remove end. | 
|  | GCTask* remove(GCTask* task);         // Remove from the middle. | 
|  | void print(const char* message) const PRODUCT_RETURN; | 
|  | // Debug support | 
|  | void verify_length() const PRODUCT_RETURN; | 
|  | }; | 
|  |  | 
|  | // A GCTaskQueue that can be synchronized. | 
|  | // This "has-a" GCTaskQueue and a mutex to do the exclusion. | 
|  | class SynchronizedGCTaskQueue : public CHeapObj<mtGC> { | 
|  | private: | 
|  | // Instance state. | 
|  | GCTaskQueue* _unsynchronized_queue;   // Has-a unsynchronized queue. | 
|  | Monitor *    _lock;                   // Lock to control access. | 
|  | public: | 
|  | // Factory create and destroy methods. | 
|  | static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) { | 
|  | return new SynchronizedGCTaskQueue(queue, lock); | 
|  | } | 
|  | static void destroy(SynchronizedGCTaskQueue* that) { | 
|  | if (that != NULL) { | 
|  | delete that; | 
|  | } | 
|  | } | 
|  | // Accessors | 
|  | GCTaskQueue* unsynchronized_queue() const { | 
|  | return _unsynchronized_queue; | 
|  | } | 
|  | Monitor * lock() const { | 
|  | return _lock; | 
|  | } | 
|  | // GCTaskQueue wrapper methods. | 
|  | // These check that you hold the lock | 
|  | // and then call the method on the queue. | 
|  | bool is_empty() const { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | return unsynchronized_queue()->is_empty(); | 
|  | } | 
|  | void enqueue(GCTask* task) { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | unsynchronized_queue()->enqueue(task); | 
|  | } | 
|  | void enqueue(GCTaskQueue* list) { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | unsynchronized_queue()->enqueue(list); | 
|  | } | 
|  | GCTask* dequeue() { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | return unsynchronized_queue()->dequeue(); | 
|  | } | 
|  | GCTask* dequeue(uint affinity) { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | return unsynchronized_queue()->dequeue(affinity); | 
|  | } | 
|  | uint length() const { | 
|  | guarantee(own_lock(), "don't own the lock"); | 
|  | return unsynchronized_queue()->length(); | 
|  | } | 
|  | // For guarantees. | 
|  | bool own_lock() const { | 
|  | return lock()->owned_by_self(); | 
|  | } | 
|  | protected: | 
|  | // Constructor.  Clients use factory, but there might be subclasses. | 
|  | SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock); | 
|  | // Destructor.  Not virtual because no virtuals. | 
|  | ~SynchronizedGCTaskQueue(); | 
|  | }; | 
|  |  | 
|  | // This is an abstract base class for getting notifications | 
|  | // when a GCTaskManager is done. | 
|  | class NotifyDoneClosure : public CHeapObj<mtGC> { | 
|  | public: | 
|  | // The notification callback method. | 
|  | virtual void notify(GCTaskManager* manager) = 0; | 
|  | protected: | 
|  | // Constructor. | 
|  | NotifyDoneClosure() { | 
|  | // Nothing to do. | 
|  | } | 
|  | // Virtual destructor because virtual methods. | 
|  | virtual ~NotifyDoneClosure() { | 
|  | // Nothing to do. | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Dynamic number of GC threads | 
|  | // | 
|  | //  GC threads wait in get_task() for work (i.e., a task) to perform. | 
|  | // When the number of GC threads was static, the number of tasks | 
|  | // created to do a job was equal to or greater than the maximum | 
|  | // number of GC threads (ParallelGCThreads).  The job might be divided | 
|  | // into a number of tasks greater than the number of GC threads for | 
|  | // load balancing (i.e., over partitioning).  The last task to be | 
|  | // executed by a GC thread in a job is a work stealing task.  A | 
|  | // GC  thread that gets a work stealing task continues to execute | 
|  | // that task until the job is done.  In the static number of GC theads | 
|  | // case, tasks are added to a queue (FIFO).  The work stealing tasks are | 
|  | // the last to be added.  Once the tasks are added, the GC threads grab | 
|  | // a task and go.  A single thread can do all the non-work stealing tasks | 
|  | // and then execute a work stealing and wait for all the other GC threads | 
|  | // to execute their work stealing task. | 
|  | //  In the dynamic number of GC threads implementation, idle-tasks are | 
|  | // created to occupy the non-participating or "inactive" threads.  An | 
|  | // idle-task makes the GC thread wait on a barrier that is part of the | 
|  | // GCTaskManager.  The GC threads that have been "idled" in a IdleGCTask | 
|  | // are released once all the active GC threads have finished their work | 
|  | // stealing tasks.  The GCTaskManager does not wait for all the "idled" | 
|  | // GC threads to resume execution. When those GC threads do resume | 
|  | // execution in the course of the thread scheduling, they call get_tasks() | 
|  | // as all the other GC threads do.  Because all the "idled" threads are | 
|  | // not required to execute in order to finish a job, it is possible for | 
|  | // a GC thread to still be "idled" when the next job is started.  Such | 
|  | // a thread stays "idled" for the next job.  This can result in a new | 
|  | // job not having all the expected active workers.  For example if on | 
|  | // job requests 4 active workers out of a total of 10 workers so the | 
|  | // remaining 6 are "idled", if the next job requests 6 active workers | 
|  | // but all 6 of the "idled" workers are still idle, then the next job | 
|  | // will only get 4 active workers. | 
|  | //  The implementation for the parallel old compaction phase has an | 
|  | // added complication.  In the static case parold partitions the chunks | 
|  | // ready to be filled into stacks, one for each GC thread.  A GC thread | 
|  | // executing a draining task (drains the stack of ready chunks) | 
|  | // claims a stack according to it's id (the unique ordinal value assigned | 
|  | // to each GC thread).  In the dynamic case not all GC threads will | 
|  | // actively participate so stacks with ready to fill chunks can only be | 
|  | // given to the active threads.  An initial implementation chose stacks | 
|  | // number 1-n to get the ready chunks and required that GC threads | 
|  | // 1-n be the active workers.  This was undesirable because it required | 
|  | // certain threads to participate.  In the final implementation a | 
|  | // list of stacks equal in number to the active workers are filled | 
|  | // with ready chunks.  GC threads that participate get a stack from | 
|  | // the task (DrainStacksCompactionTask), empty the stack, and then add it to a | 
|  | // recycling list at the end of the task.  If the same GC thread gets | 
|  | // a second task, it gets a second stack to drain and returns it.  The | 
|  | // stacks are added to a recycling list so that later stealing tasks | 
|  | // for this tasks can get a stack from the recycling list.  Stealing tasks | 
|  | // use the stacks in its work in a way similar to the draining tasks. | 
|  | // A thread is not guaranteed to get anything but a stealing task and | 
|  | // a thread that only gets a stealing task has to get a stack. A failed | 
|  | // implementation tried to have the GC threads keep the stack they used | 
|  | // during a draining task for later use in the stealing task but that didn't | 
|  | // work because as noted a thread is not guaranteed to get a draining task. | 
|  | // | 
|  | // For PSScavenge and ParCompactionManager the GC threads are | 
|  | // held in the GCTaskThread** _thread array in GCTaskManager. | 
|  |  | 
|  |  | 
|  | class GCTaskManager : public CHeapObj<mtGC> { | 
|  | friend class ParCompactionManager; | 
|  | friend class PSParallelCompact; | 
|  | friend class PSScavenge; | 
|  | friend class PSRefProcTaskExecutor; | 
|  | friend class RefProcTaskExecutor; | 
|  | friend class GCTaskThread; | 
|  | 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. | 
|  | GCTaskThread**            _thread;            // Array of worker threads. | 
|  | uint                      _active_workers;    // Number of active workers. | 
|  | uint                      _busy_workers;      // Number of busy workers. | 
|  | uint                      _blocking_worker;   // The worker that's blocking. | 
|  | bool*                     _resource_flag;     // Array of flag per threads. | 
|  | uint                      _delivered_tasks;   // Count of delivered tasks. | 
|  | uint                      _completed_tasks;   // Count of completed tasks. | 
|  | 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 | 
|  | 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; | 
|  | } | 
|  | } | 
|  | // Accessors. | 
|  | uint busy_workers() const { | 
|  | return _busy_workers; | 
|  | } | 
|  | volatile uint idle_workers() const { | 
|  | return _idle_workers; | 
|  | } | 
|  | //     Pun between Monitor* and Mutex* | 
|  | Monitor* monitor() const { | 
|  | return _monitor; | 
|  | } | 
|  | Monitor * lock() const { | 
|  | return _monitor; | 
|  | } | 
|  | WaitForBarrierGCTask* idle_inactive_task() { | 
|  | return _idle_inactive_task; | 
|  | } | 
|  | // Methods. | 
|  | //     Add the argument task to be run. | 
|  | void add_task(GCTask* task); | 
|  | //     Add a list of tasks.  Removes task from the argument list. | 
|  | void add_list(GCTaskQueue* list); | 
|  | //     Claim a task for argument worker. | 
|  | GCTask* get_task(uint which); | 
|  | //     Note the completion of a task by the argument worker. | 
|  | void note_completion(uint which); | 
|  | //     Is the queue blocked from handing out new tasks? | 
|  | bool is_blocked() const { | 
|  | return (blocking_worker() != sentinel_worker()); | 
|  | } | 
|  | //     Request that all workers release their resources. | 
|  | void release_all_resources(); | 
|  | //     Ask if a particular worker should release its resources. | 
|  | bool should_release_resources(uint which); // Predicate. | 
|  | //     Note the release of resources by the argument worker. | 
|  | void note_release(uint which); | 
|  | //     Create IdleGCTasks for inactive workers and start workers | 
|  | void task_idle_workers(); | 
|  | //     Release the workers in IdleGCTasks | 
|  | void release_idle_workers(); | 
|  | // Constants. | 
|  | //     A sentinel worker identifier. | 
|  | static uint sentinel_worker() { | 
|  | return (uint) -1;                   // Why isn't there a max_uint? | 
|  | } | 
|  |  | 
|  | //     Execute the task queue and wait for the completion. | 
|  | void execute_and_wait(GCTaskQueue* list); | 
|  |  | 
|  | void print_task_time_stamps(); | 
|  | void print_threads_on(outputStream* st); | 
|  | void threads_do(ThreadClosure* tc); | 
|  |  | 
|  | protected: | 
|  | // 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. | 
|  | uint workers() const { | 
|  | return _workers; | 
|  | } | 
|  | void set_active_workers(uint v) { | 
|  | assert(v <= _workers, "Trying to set more workers active than there are"); | 
|  | _active_workers = MIN2(v, _workers); | 
|  | assert(v != 0, "Trying to set active workers to 0"); | 
|  | _active_workers = MAX2(1U, _active_workers); | 
|  | } | 
|  | // 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; | 
|  | } | 
|  | NoopGCTask* noop_task() const { | 
|  | return _noop_task; | 
|  | } | 
|  | //     Bounds-checking per-thread data accessors. | 
|  | GCTaskThread* thread(uint which); | 
|  | void set_thread(uint which, GCTaskThread* value); | 
|  | bool resource_flag(uint which); | 
|  | void set_resource_flag(uint which, bool value); | 
|  | // Modifier methods with some semantics. | 
|  | //     Is any worker blocking handing out new tasks? | 
|  | uint blocking_worker() const { | 
|  | return _blocking_worker; | 
|  | } | 
|  | void set_blocking_worker(uint value) { | 
|  | _blocking_worker = value; | 
|  | } | 
|  | void set_unblocked() { | 
|  | set_blocking_worker(sentinel_worker()); | 
|  | } | 
|  | //     Count of busy workers. | 
|  | void reset_busy_workers() { | 
|  | _busy_workers = 0; | 
|  | } | 
|  | uint increment_busy_workers(); | 
|  | uint decrement_busy_workers(); | 
|  | //     Count of tasks delivered to workers. | 
|  | uint delivered_tasks() const { | 
|  | return _delivered_tasks; | 
|  | } | 
|  | void increment_delivered_tasks() { | 
|  | _delivered_tasks += 1; | 
|  | } | 
|  | void reset_delivered_tasks() { | 
|  | _delivered_tasks = 0; | 
|  | } | 
|  | //     Count of tasks completed by workers. | 
|  | uint completed_tasks() const { | 
|  | return _completed_tasks; | 
|  | } | 
|  | void increment_completed_tasks() { | 
|  | _completed_tasks += 1; | 
|  | } | 
|  | void reset_completed_tasks() { | 
|  | _completed_tasks = 0; | 
|  | } | 
|  | //     Count of barrier tasks completed. | 
|  | uint barriers() const { | 
|  | return _barriers; | 
|  | } | 
|  | void increment_barriers() { | 
|  | _barriers += 1; | 
|  | } | 
|  | void reset_barriers() { | 
|  | _barriers = 0; | 
|  | } | 
|  | //     Count of how many times the queue has emptied. | 
|  | uint emptied_queue() const { | 
|  | return _emptied_queue; | 
|  | } | 
|  | void increment_emptied_queue() { | 
|  | _emptied_queue += 1; | 
|  | } | 
|  | 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++; | 
|  | } | 
|  | void decrement_idle_workers() { | 
|  | _idle_workers--; | 
|  | } | 
|  | // Other methods. | 
|  | void initialize(); | 
|  |  | 
|  | public: | 
|  | // Return true if all workers are currently active. | 
|  | bool all_workers_active() { return workers() == active_workers(); } | 
|  | uint active_workers() const { | 
|  | return _active_workers; | 
|  | } | 
|  | }; | 
|  |  | 
|  | // | 
|  | // Some exemplary GCTasks. | 
|  | // | 
|  |  | 
|  | // 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); | 
|  |  | 
|  | virtual char* name() { return (char *)"noop task"; } | 
|  | // Methods from GCTask. | 
|  | void do_it(GCTaskManager* manager, uint which) { | 
|  | // Nothing to do. | 
|  | } | 
|  | 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. | 
|  | } | 
|  | // 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 | 
|  | // 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 { | 
|  | 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. | 
|  | 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; | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Task that is used to idle a GC task when fewer than | 
|  | // the maximum workers are wanted. | 
|  | class IdleGCTask : public GCTask { | 
|  | const bool    _is_c_heap_obj;            // Was allocated on the heap. | 
|  | public: | 
|  | bool is_c_heap_obj() { | 
|  | return _is_c_heap_obj; | 
|  | } | 
|  | // Factory create and destroy methods. | 
|  | static IdleGCTask* create(); | 
|  | static IdleGCTask* create_on_c_heap(); | 
|  | static void destroy(IdleGCTask* that); | 
|  |  | 
|  | virtual char* name() { return (char *)"idle task"; } | 
|  | // Methods from GCTask. | 
|  | virtual void do_it(GCTaskManager* manager, uint which); | 
|  | protected: | 
|  | // Constructor. | 
|  | IdleGCTask(bool on_c_heap) : | 
|  | GCTask(GCTask::Kind::idle_task), | 
|  | _is_c_heap_obj(on_c_heap) { | 
|  | // Nothing to do. | 
|  | } | 
|  | // Destructor-like method. | 
|  | void destruct(); | 
|  | }; | 
|  |  | 
|  | class MonitorSupply : public AllStatic { | 
|  | private: | 
|  | // State. | 
|  | //     Control multi-threaded access. | 
|  | static Mutex*                   _lock; | 
|  | //     The list of available Monitor*'s. | 
|  | static GrowableArray<Monitor*>* _freelist; | 
|  | public: | 
|  | // Reserve a Monitor*. | 
|  | static Monitor* reserve(); | 
|  | // Release a Monitor*. | 
|  | static void release(Monitor* instance); | 
|  | private: | 
|  | // Accessors. | 
|  | static Mutex* lock() { | 
|  | return _lock; | 
|  | } | 
|  | static GrowableArray<Monitor*>* freelist() { | 
|  | return _freelist; | 
|  | } | 
|  | }; | 
|  |  | 
|  | #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP |