src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp

Mon, 22 Apr 2013 20:27:36 +0200

author
stefank
date
Mon, 22 Apr 2013 20:27:36 +0200
changeset 5011
a08c80e9e1e5
parent 4153
b9a9ed0f8eeb
child 6876
710a3c8b516e
permissions
-rw-r--r--

8012687: Remove unused is_root checks and closures
Reviewed-by: tschatzl, jmasa

     1 /*
     2  * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP
    28 #include "runtime/mutex.hpp"
    29 #include "utilities/growableArray.hpp"
    31 //
    32 // The GCTaskManager is a queue of GCTasks, and accessors
    33 // to allow the queue to be accessed from many threads.
    34 //
    36 // Forward declarations of types defined in this file.
    37 class GCTask;
    38 class GCTaskQueue;
    39 class SynchronizedGCTaskQueue;
    40 class GCTaskManager;
    41 class NotifyDoneClosure;
    42 // Some useful subclasses of GCTask.  You can also make up your own.
    43 class NoopGCTask;
    44 class BarrierGCTask;
    45 class ReleasingBarrierGCTask;
    46 class NotifyingBarrierGCTask;
    47 class WaitForBarrierGCTask;
    48 class IdleGCTask;
    49 // A free list of Monitor*'s.
    50 class MonitorSupply;
    52 // Forward declarations of classes referenced in this file via pointer.
    53 class GCTaskThread;
    54 class Mutex;
    55 class Monitor;
    56 class ThreadClosure;
    58 // The abstract base GCTask.
    59 class GCTask : public ResourceObj {
    60 public:
    61   // Known kinds of GCTasks, for predicates.
    62   class Kind : AllStatic {
    63   public:
    64     enum kind {
    65       unknown_task,
    66       ordinary_task,
    67       barrier_task,
    68       noop_task,
    69       idle_task
    70     };
    71     static const char* to_string(kind value);
    72   };
    73 private:
    74   // Instance state.
    75   const Kind::kind _kind;               // For runtime type checking.
    76   const uint       _affinity;           // Which worker should run task.
    77   GCTask*          _newer;              // Tasks are on doubly-linked ...
    78   GCTask*          _older;              // ... lists.
    79 public:
    80   virtual char* name() { return (char *)"task"; }
    82   // Abstract do_it method
    83   virtual void do_it(GCTaskManager* manager, uint which) = 0;
    84   // Accessors
    85   Kind::kind kind() const {
    86     return _kind;
    87   }
    88   uint affinity() const {
    89     return _affinity;
    90   }
    91   GCTask* newer() const {
    92     return _newer;
    93   }
    94   void set_newer(GCTask* n) {
    95     _newer = n;
    96   }
    97   GCTask* older() const {
    98     return _older;
    99   }
   100   void set_older(GCTask* p) {
   101     _older = p;
   102   }
   103   // Predicates.
   104   bool is_ordinary_task() const {
   105     return kind()==Kind::ordinary_task;
   106   }
   107   bool is_barrier_task() const {
   108     return kind()==Kind::barrier_task;
   109   }
   110   bool is_noop_task() const {
   111     return kind()==Kind::noop_task;
   112   }
   113   bool is_idle_task() const {
   114     return kind()==Kind::idle_task;
   115   }
   116   void print(const char* message) const PRODUCT_RETURN;
   117 protected:
   118   // Constructors: Only create subclasses.
   119   //     An ordinary GCTask.
   120   GCTask();
   121   //     A GCTask of a particular kind, usually barrier or noop.
   122   GCTask(Kind::kind kind);
   123   //     An ordinary GCTask with an affinity.
   124   GCTask(uint affinity);
   125   //     A GCTask of a particular kind, with and affinity.
   126   GCTask(Kind::kind kind, uint affinity);
   127   // We want a virtual destructor because virtual methods,
   128   // but since ResourceObj's don't have their destructors
   129   // called, we don't have one at all.  Instead we have
   130   // this method, which gets called by subclasses to clean up.
   131   virtual void destruct();
   132   // Methods.
   133   void initialize();
   134 };
   136 // A doubly-linked list of GCTasks.
   137 // The list is not synchronized, because sometimes we want to
   138 // build up a list and then make it available to other threads.
   139 // See also: SynchronizedGCTaskQueue.
   140 class GCTaskQueue : public ResourceObj {
   141 private:
   142   // Instance state.
   143   GCTask*    _insert_end;               // Tasks are enqueued at this end.
   144   GCTask*    _remove_end;               // Tasks are dequeued from this end.
   145   uint       _length;                   // The current length of the queue.
   146   const bool _is_c_heap_obj;            // Is this a CHeapObj?
   147 public:
   148   // Factory create and destroy methods.
   149   //     Create as ResourceObj.
   150   static GCTaskQueue* create();
   151   //     Create as CHeapObj.
   152   static GCTaskQueue* create_on_c_heap();
   153   //     Destroyer.
   154   static void destroy(GCTaskQueue* that);
   155   // Accessors.
   156   //     These just examine the state of the queue.
   157   bool is_empty() const {
   158     assert(((insert_end() == NULL && remove_end() == NULL) ||
   159             (insert_end() != NULL && remove_end() != NULL)),
   160            "insert_end and remove_end don't match");
   161     assert((insert_end() != NULL) || (_length == 0), "Not empty");
   162     return insert_end() == NULL;
   163   }
   164   uint length() const {
   165     return _length;
   166   }
   167   // Methods.
   168   //     Enqueue one task.
   169   void enqueue(GCTask* task);
   170   //     Enqueue a list of tasks.  Empties the argument list.
   171   void enqueue(GCTaskQueue* list);
   172   //     Dequeue one task.
   173   GCTask* dequeue();
   174   //     Dequeue one task, preferring one with affinity.
   175   GCTask* dequeue(uint affinity);
   176 protected:
   177   // Constructor. Clients use factory, but there might be subclasses.
   178   GCTaskQueue(bool on_c_heap);
   179   // Destructor-like method.
   180   // Because ResourceMark doesn't call destructors.
   181   // This method cleans up like one.
   182   virtual void destruct();
   183   // Accessors.
   184   GCTask* insert_end() const {
   185     return _insert_end;
   186   }
   187   void set_insert_end(GCTask* value) {
   188     _insert_end = value;
   189   }
   190   GCTask* remove_end() const {
   191     return _remove_end;
   192   }
   193   void set_remove_end(GCTask* value) {
   194     _remove_end = value;
   195   }
   196   void increment_length() {
   197     _length += 1;
   198   }
   199   void decrement_length() {
   200     _length -= 1;
   201   }
   202   void set_length(uint value) {
   203     _length = value;
   204   }
   205   bool is_c_heap_obj() const {
   206     return _is_c_heap_obj;
   207   }
   208   // Methods.
   209   void initialize();
   210   GCTask* remove();                     // Remove from remove end.
   211   GCTask* remove(GCTask* task);         // Remove from the middle.
   212   void print(const char* message) const PRODUCT_RETURN;
   213   // Debug support
   214   void verify_length() const PRODUCT_RETURN;
   215 };
   217 // A GCTaskQueue that can be synchronized.
   218 // This "has-a" GCTaskQueue and a mutex to do the exclusion.
   219 class SynchronizedGCTaskQueue : public CHeapObj<mtGC> {
   220 private:
   221   // Instance state.
   222   GCTaskQueue* _unsynchronized_queue;   // Has-a unsynchronized queue.
   223   Monitor *    _lock;                   // Lock to control access.
   224 public:
   225   // Factory create and destroy methods.
   226   static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) {
   227     return new SynchronizedGCTaskQueue(queue, lock);
   228   }
   229   static void destroy(SynchronizedGCTaskQueue* that) {
   230     if (that != NULL) {
   231       delete that;
   232     }
   233   }
   234   // Accessors
   235   GCTaskQueue* unsynchronized_queue() const {
   236     return _unsynchronized_queue;
   237   }
   238   Monitor * lock() const {
   239     return _lock;
   240   }
   241   // GCTaskQueue wrapper methods.
   242   // These check that you hold the lock
   243   // and then call the method on the queue.
   244   bool is_empty() const {
   245     guarantee(own_lock(), "don't own the lock");
   246     return unsynchronized_queue()->is_empty();
   247   }
   248   void enqueue(GCTask* task) {
   249     guarantee(own_lock(), "don't own the lock");
   250     unsynchronized_queue()->enqueue(task);
   251   }
   252   void enqueue(GCTaskQueue* list) {
   253     guarantee(own_lock(), "don't own the lock");
   254     unsynchronized_queue()->enqueue(list);
   255   }
   256   GCTask* dequeue() {
   257     guarantee(own_lock(), "don't own the lock");
   258     return unsynchronized_queue()->dequeue();
   259   }
   260   GCTask* dequeue(uint affinity) {
   261     guarantee(own_lock(), "don't own the lock");
   262     return unsynchronized_queue()->dequeue(affinity);
   263   }
   264   uint length() const {
   265     guarantee(own_lock(), "don't own the lock");
   266     return unsynchronized_queue()->length();
   267   }
   268   // For guarantees.
   269   bool own_lock() const {
   270     return lock()->owned_by_self();
   271   }
   272 protected:
   273   // Constructor.  Clients use factory, but there might be subclasses.
   274   SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock);
   275   // Destructor.  Not virtual because no virtuals.
   276   ~SynchronizedGCTaskQueue();
   277 };
   279 // This is an abstract base class for getting notifications
   280 // when a GCTaskManager is done.
   281 class NotifyDoneClosure : public CHeapObj<mtGC> {
   282 public:
   283   // The notification callback method.
   284   virtual void notify(GCTaskManager* manager) = 0;
   285 protected:
   286   // Constructor.
   287   NotifyDoneClosure() {
   288     // Nothing to do.
   289   }
   290   // Virtual destructor because virtual methods.
   291   virtual ~NotifyDoneClosure() {
   292     // Nothing to do.
   293   }
   294 };
   296 // Dynamic number of GC threads
   297 //
   298 //  GC threads wait in get_task() for work (i.e., a task) to perform.
   299 // When the number of GC threads was static, the number of tasks
   300 // created to do a job was equal to or greater than the maximum
   301 // number of GC threads (ParallelGCThreads).  The job might be divided
   302 // into a number of tasks greater than the number of GC threads for
   303 // load balancing (i.e., over partitioning).  The last task to be
   304 // executed by a GC thread in a job is a work stealing task.  A
   305 // GC  thread that gets a work stealing task continues to execute
   306 // that task until the job is done.  In the static number of GC theads
   307 // case, tasks are added to a queue (FIFO).  The work stealing tasks are
   308 // the last to be added.  Once the tasks are added, the GC threads grab
   309 // a task and go.  A single thread can do all the non-work stealing tasks
   310 // and then execute a work stealing and wait for all the other GC threads
   311 // to execute their work stealing task.
   312 //  In the dynamic number of GC threads implementation, idle-tasks are
   313 // created to occupy the non-participating or "inactive" threads.  An
   314 // idle-task makes the GC thread wait on a barrier that is part of the
   315 // GCTaskManager.  The GC threads that have been "idled" in a IdleGCTask
   316 // are released once all the active GC threads have finished their work
   317 // stealing tasks.  The GCTaskManager does not wait for all the "idled"
   318 // GC threads to resume execution. When those GC threads do resume
   319 // execution in the course of the thread scheduling, they call get_tasks()
   320 // as all the other GC threads do.  Because all the "idled" threads are
   321 // not required to execute in order to finish a job, it is possible for
   322 // a GC thread to still be "idled" when the next job is started.  Such
   323 // a thread stays "idled" for the next job.  This can result in a new
   324 // job not having all the expected active workers.  For example if on
   325 // job requests 4 active workers out of a total of 10 workers so the
   326 // remaining 6 are "idled", if the next job requests 6 active workers
   327 // but all 6 of the "idled" workers are still idle, then the next job
   328 // will only get 4 active workers.
   329 //  The implementation for the parallel old compaction phase has an
   330 // added complication.  In the static case parold partitions the chunks
   331 // ready to be filled into stacks, one for each GC thread.  A GC thread
   332 // executing a draining task (drains the stack of ready chunks)
   333 // claims a stack according to it's id (the unique ordinal value assigned
   334 // to each GC thread).  In the dynamic case not all GC threads will
   335 // actively participate so stacks with ready to fill chunks can only be
   336 // given to the active threads.  An initial implementation chose stacks
   337 // number 1-n to get the ready chunks and required that GC threads
   338 // 1-n be the active workers.  This was undesirable because it required
   339 // certain threads to participate.  In the final implementation a
   340 // list of stacks equal in number to the active workers are filled
   341 // with ready chunks.  GC threads that participate get a stack from
   342 // the task (DrainStacksCompactionTask), empty the stack, and then add it to a
   343 // recycling list at the end of the task.  If the same GC thread gets
   344 // a second task, it gets a second stack to drain and returns it.  The
   345 // stacks are added to a recycling list so that later stealing tasks
   346 // for this tasks can get a stack from the recycling list.  Stealing tasks
   347 // use the stacks in its work in a way similar to the draining tasks.
   348 // A thread is not guaranteed to get anything but a stealing task and
   349 // a thread that only gets a stealing task has to get a stack. A failed
   350 // implementation tried to have the GC threads keep the stack they used
   351 // during a draining task for later use in the stealing task but that didn't
   352 // work because as noted a thread is not guaranteed to get a draining task.
   353 //
   354 // For PSScavenge and ParCompactionManager the GC threads are
   355 // held in the GCTaskThread** _thread array in GCTaskManager.
   358 class GCTaskManager : public CHeapObj<mtGC> {
   359  friend class ParCompactionManager;
   360  friend class PSParallelCompact;
   361  friend class PSScavenge;
   362  friend class PSRefProcTaskExecutor;
   363  friend class RefProcTaskExecutor;
   364  friend class GCTaskThread;
   365  friend class IdleGCTask;
   366 private:
   367   // Instance state.
   368   NotifyDoneClosure*        _ndc;               // Notify on completion.
   369   const uint                _workers;           // Number of workers.
   370   Monitor*                  _monitor;           // Notification of changes.
   371   SynchronizedGCTaskQueue*  _queue;             // Queue of tasks.
   372   GCTaskThread**            _thread;            // Array of worker threads.
   373   uint                      _active_workers;    // Number of active workers.
   374   uint                      _busy_workers;      // Number of busy workers.
   375   uint                      _blocking_worker;   // The worker that's blocking.
   376   bool*                     _resource_flag;     // Array of flag per threads.
   377   uint                      _delivered_tasks;   // Count of delivered tasks.
   378   uint                      _completed_tasks;   // Count of completed tasks.
   379   uint                      _barriers;          // Count of barrier tasks.
   380   uint                      _emptied_queue;     // Times we emptied the queue.
   381   NoopGCTask*               _noop_task;         // The NoopGCTask instance.
   382   uint                      _noop_tasks;        // Count of noop tasks.
   383   WaitForBarrierGCTask*     _idle_inactive_task;// Task for inactive workers
   384   volatile uint             _idle_workers;      // Number of idled workers
   385 public:
   386   // Factory create and destroy methods.
   387   static GCTaskManager* create(uint workers) {
   388     return new GCTaskManager(workers);
   389   }
   390   static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) {
   391     return new GCTaskManager(workers, ndc);
   392   }
   393   static void destroy(GCTaskManager* that) {
   394     if (that != NULL) {
   395       delete that;
   396     }
   397   }
   398   // Accessors.
   399   uint busy_workers() const {
   400     return _busy_workers;
   401   }
   402   volatile uint idle_workers() const {
   403     return _idle_workers;
   404   }
   405   //     Pun between Monitor* and Mutex*
   406   Monitor* monitor() const {
   407     return _monitor;
   408   }
   409   Monitor * lock() const {
   410     return _monitor;
   411   }
   412   WaitForBarrierGCTask* idle_inactive_task() {
   413     return _idle_inactive_task;
   414   }
   415   // Methods.
   416   //     Add the argument task to be run.
   417   void add_task(GCTask* task);
   418   //     Add a list of tasks.  Removes task from the argument list.
   419   void add_list(GCTaskQueue* list);
   420   //     Claim a task for argument worker.
   421   GCTask* get_task(uint which);
   422   //     Note the completion of a task by the argument worker.
   423   void note_completion(uint which);
   424   //     Is the queue blocked from handing out new tasks?
   425   bool is_blocked() const {
   426     return (blocking_worker() != sentinel_worker());
   427   }
   428   //     Request that all workers release their resources.
   429   void release_all_resources();
   430   //     Ask if a particular worker should release its resources.
   431   bool should_release_resources(uint which); // Predicate.
   432   //     Note the release of resources by the argument worker.
   433   void note_release(uint which);
   434   //     Create IdleGCTasks for inactive workers and start workers
   435   void task_idle_workers();
   436   //     Release the workers in IdleGCTasks
   437   void release_idle_workers();
   438   // Constants.
   439   //     A sentinel worker identifier.
   440   static uint sentinel_worker() {
   441     return (uint) -1;                   // Why isn't there a max_uint?
   442   }
   444   //     Execute the task queue and wait for the completion.
   445   void execute_and_wait(GCTaskQueue* list);
   447   void print_task_time_stamps();
   448   void print_threads_on(outputStream* st);
   449   void threads_do(ThreadClosure* tc);
   451 protected:
   452   // Constructors.  Clients use factory, but there might be subclasses.
   453   //     Create a GCTaskManager with the appropriate number of workers.
   454   GCTaskManager(uint workers);
   455   //     Create a GCTaskManager that calls back when there's no more work.
   456   GCTaskManager(uint workers, NotifyDoneClosure* ndc);
   457   //     Make virtual if necessary.
   458   ~GCTaskManager();
   459   // Accessors.
   460   uint workers() const {
   461     return _workers;
   462   }
   463   void set_active_workers(uint v) {
   464     assert(v <= _workers, "Trying to set more workers active than there are");
   465     _active_workers = MIN2(v, _workers);
   466     assert(v != 0, "Trying to set active workers to 0");
   467     _active_workers = MAX2(1U, _active_workers);
   468   }
   469   // Sets the number of threads that will be used in a collection
   470   void set_active_gang();
   472   NotifyDoneClosure* notify_done_closure() const {
   473     return _ndc;
   474   }
   475   SynchronizedGCTaskQueue* queue() const {
   476     return _queue;
   477   }
   478   NoopGCTask* noop_task() const {
   479     return _noop_task;
   480   }
   481   //     Bounds-checking per-thread data accessors.
   482   GCTaskThread* thread(uint which);
   483   void set_thread(uint which, GCTaskThread* value);
   484   bool resource_flag(uint which);
   485   void set_resource_flag(uint which, bool value);
   486   // Modifier methods with some semantics.
   487   //     Is any worker blocking handing out new tasks?
   488   uint blocking_worker() const {
   489     return _blocking_worker;
   490   }
   491   void set_blocking_worker(uint value) {
   492     _blocking_worker = value;
   493   }
   494   void set_unblocked() {
   495     set_blocking_worker(sentinel_worker());
   496   }
   497   //     Count of busy workers.
   498   void reset_busy_workers() {
   499     _busy_workers = 0;
   500   }
   501   uint increment_busy_workers();
   502   uint decrement_busy_workers();
   503   //     Count of tasks delivered to workers.
   504   uint delivered_tasks() const {
   505     return _delivered_tasks;
   506   }
   507   void increment_delivered_tasks() {
   508     _delivered_tasks += 1;
   509   }
   510   void reset_delivered_tasks() {
   511     _delivered_tasks = 0;
   512   }
   513   //     Count of tasks completed by workers.
   514   uint completed_tasks() const {
   515     return _completed_tasks;
   516   }
   517   void increment_completed_tasks() {
   518     _completed_tasks += 1;
   519   }
   520   void reset_completed_tasks() {
   521     _completed_tasks = 0;
   522   }
   523   //     Count of barrier tasks completed.
   524   uint barriers() const {
   525     return _barriers;
   526   }
   527   void increment_barriers() {
   528     _barriers += 1;
   529   }
   530   void reset_barriers() {
   531     _barriers = 0;
   532   }
   533   //     Count of how many times the queue has emptied.
   534   uint emptied_queue() const {
   535     return _emptied_queue;
   536   }
   537   void increment_emptied_queue() {
   538     _emptied_queue += 1;
   539   }
   540   void reset_emptied_queue() {
   541     _emptied_queue = 0;
   542   }
   543   //     Count of the number of noop tasks we've handed out,
   544   //     e.g., to handle resource release requests.
   545   uint noop_tasks() const {
   546     return _noop_tasks;
   547   }
   548   void increment_noop_tasks() {
   549     _noop_tasks += 1;
   550   }
   551   void reset_noop_tasks() {
   552     _noop_tasks = 0;
   553   }
   554   void increment_idle_workers() {
   555     _idle_workers++;
   556   }
   557   void decrement_idle_workers() {
   558     _idle_workers--;
   559   }
   560   // Other methods.
   561   void initialize();
   563  public:
   564   // Return true if all workers are currently active.
   565   bool all_workers_active() { return workers() == active_workers(); }
   566   uint active_workers() const {
   567     return _active_workers;
   568   }
   569 };
   571 //
   572 // Some exemplary GCTasks.
   573 //
   575 // A noop task that does nothing,
   576 // except take us around the GCTaskThread loop.
   577 class NoopGCTask : public GCTask {
   578 private:
   579   const bool _is_c_heap_obj;            // Is this a CHeapObj?
   580 public:
   581   // Factory create and destroy methods.
   582   static NoopGCTask* create();
   583   static NoopGCTask* create_on_c_heap();
   584   static void destroy(NoopGCTask* that);
   586   virtual char* name() { return (char *)"noop task"; }
   587   // Methods from GCTask.
   588   void do_it(GCTaskManager* manager, uint which) {
   589     // Nothing to do.
   590   }
   591 protected:
   592   // Constructor.
   593   NoopGCTask(bool on_c_heap) :
   594     GCTask(GCTask::Kind::noop_task),
   595     _is_c_heap_obj(on_c_heap) {
   596     // Nothing to do.
   597   }
   598   // Destructor-like method.
   599   void destruct();
   600   // Accessors.
   601   bool is_c_heap_obj() const {
   602     return _is_c_heap_obj;
   603   }
   604 };
   606 // A BarrierGCTask blocks other tasks from starting,
   607 // and waits until it is the only task running.
   608 class BarrierGCTask : public GCTask {
   609 public:
   610   // Factory create and destroy methods.
   611   static BarrierGCTask* create() {
   612     return new BarrierGCTask();
   613   }
   614   static void destroy(BarrierGCTask* that) {
   615     if (that != NULL) {
   616       that->destruct();
   617       delete that;
   618     }
   619   }
   620   // Methods from GCTask.
   621   void do_it(GCTaskManager* manager, uint which);
   622 protected:
   623   // Constructor.  Clients use factory, but there might be subclasses.
   624   BarrierGCTask() :
   625     GCTask(GCTask::Kind::barrier_task) {
   626     // Nothing to do.
   627   }
   628   // Destructor-like method.
   629   void destruct();
   631   virtual char* name() { return (char *)"barrier task"; }
   632   // Methods.
   633   //     Wait for this to be the only task running.
   634   void do_it_internal(GCTaskManager* manager, uint which);
   635 };
   637 // A ReleasingBarrierGCTask is a BarrierGCTask
   638 // that tells all the tasks to release their resource areas.
   639 class ReleasingBarrierGCTask : public BarrierGCTask {
   640 public:
   641   // Factory create and destroy methods.
   642   static ReleasingBarrierGCTask* create() {
   643     return new ReleasingBarrierGCTask();
   644   }
   645   static void destroy(ReleasingBarrierGCTask* that) {
   646     if (that != NULL) {
   647       that->destruct();
   648       delete that;
   649     }
   650   }
   651   // Methods from GCTask.
   652   void do_it(GCTaskManager* manager, uint which);
   653 protected:
   654   // Constructor.  Clients use factory, but there might be subclasses.
   655   ReleasingBarrierGCTask() :
   656     BarrierGCTask() {
   657     // Nothing to do.
   658   }
   659   // Destructor-like method.
   660   void destruct();
   661 };
   663 // A NotifyingBarrierGCTask is a BarrierGCTask
   664 // that calls a notification method when it is the only task running.
   665 class NotifyingBarrierGCTask : public BarrierGCTask {
   666 private:
   667   // Instance state.
   668   NotifyDoneClosure* _ndc;              // The callback object.
   669 public:
   670   // Factory create and destroy methods.
   671   static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) {
   672     return new NotifyingBarrierGCTask(ndc);
   673   }
   674   static void destroy(NotifyingBarrierGCTask* that) {
   675     if (that != NULL) {
   676       that->destruct();
   677       delete that;
   678     }
   679   }
   680   // Methods from GCTask.
   681   void do_it(GCTaskManager* manager, uint which);
   682 protected:
   683   // Constructor.  Clients use factory, but there might be subclasses.
   684   NotifyingBarrierGCTask(NotifyDoneClosure* ndc) :
   685     BarrierGCTask(),
   686     _ndc(ndc) {
   687     assert(notify_done_closure() != NULL, "can't notify on NULL");
   688   }
   689   // Destructor-like method.
   690   void destruct();
   691   // Accessor.
   692   NotifyDoneClosure* notify_done_closure() const { return _ndc; }
   693 };
   695 // A WaitForBarrierGCTask is a BarrierGCTask
   696 // with a method you can call to wait until
   697 // the BarrierGCTask is done.
   698 // This may cover many of the uses of NotifyingBarrierGCTasks.
   699 class WaitForBarrierGCTask : public BarrierGCTask {
   700   friend class GCTaskManager;
   701   friend class IdleGCTask;
   702 private:
   703   // Instance state.
   704   Monitor*      _monitor;                  // Guard and notify changes.
   705   volatile bool _should_wait;              // true=>wait, false=>proceed.
   706   const bool    _is_c_heap_obj;            // Was allocated on the heap.
   707 public:
   708   virtual char* name() { return (char *) "waitfor-barrier-task"; }
   710   // Factory create and destroy methods.
   711   static WaitForBarrierGCTask* create();
   712   static WaitForBarrierGCTask* create_on_c_heap();
   713   static void destroy(WaitForBarrierGCTask* that);
   714   // Methods.
   715   void     do_it(GCTaskManager* manager, uint which);
   716   void     wait_for(bool reset);
   717   void set_should_wait(bool value) {
   718     _should_wait = value;
   719   }
   720 protected:
   721   // Constructor.  Clients use factory, but there might be subclasses.
   722   WaitForBarrierGCTask(bool on_c_heap);
   723   // Destructor-like method.
   724   void destruct();
   725   // Accessors.
   726   Monitor* monitor() const {
   727     return _monitor;
   728   }
   729   bool should_wait() const {
   730     return _should_wait;
   731   }
   732   bool is_c_heap_obj() {
   733     return _is_c_heap_obj;
   734   }
   735 };
   737 // Task that is used to idle a GC task when fewer than
   738 // the maximum workers are wanted.
   739 class IdleGCTask : public GCTask {
   740   const bool    _is_c_heap_obj;            // Was allocated on the heap.
   741  public:
   742   bool is_c_heap_obj() {
   743     return _is_c_heap_obj;
   744   }
   745   // Factory create and destroy methods.
   746   static IdleGCTask* create();
   747   static IdleGCTask* create_on_c_heap();
   748   static void destroy(IdleGCTask* that);
   750   virtual char* name() { return (char *)"idle task"; }
   751   // Methods from GCTask.
   752   virtual void do_it(GCTaskManager* manager, uint which);
   753 protected:
   754   // Constructor.
   755   IdleGCTask(bool on_c_heap) :
   756     GCTask(GCTask::Kind::idle_task),
   757     _is_c_heap_obj(on_c_heap) {
   758     // Nothing to do.
   759   }
   760   // Destructor-like method.
   761   void destruct();
   762 };
   764 class MonitorSupply : public AllStatic {
   765 private:
   766   // State.
   767   //     Control multi-threaded access.
   768   static Mutex*                   _lock;
   769   //     The list of available Monitor*'s.
   770   static GrowableArray<Monitor*>* _freelist;
   771 public:
   772   // Reserve a Monitor*.
   773   static Monitor* reserve();
   774   // Release a Monitor*.
   775   static void release(Monitor* instance);
   776 private:
   777   // Accessors.
   778   static Mutex* lock() {
   779     return _lock;
   780   }
   781   static GrowableArray<Monitor*>* freelist() {
   782     return _freelist;
   783   }
   784 };
   786 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP

mercurial