1 /*
   2  * Copyright (c) 2005, 2011, 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  */
  24 
  25 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PCTASKS_HPP
  26 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PCTASKS_HPP
  27 
  28 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
  29 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
  30 #include "gc_implementation/parallelScavenge/psTasks.hpp"
  31 
  32 
  33 // Tasks for parallel compaction of the old generation
  34 //
  35 // Tasks are created and enqueued on a task queue. The
  36 // tasks for parallel old collector for marking objects
  37 // are MarkFromRootsTask and ThreadRootsMarkingTask.
  38 //
  39 // MarkFromRootsTask's are created
  40 // with a root group (e.g., jni_handles) and when the do_it()
  41 // method of a MarkFromRootsTask is executed, it starts marking
  42 // form it's root group.
  43 //
  44 // ThreadRootsMarkingTask's are created for each Java thread.  When
  45 // the do_it() method of a ThreadRootsMarkingTask is executed, it
  46 // starts marking from the thread's roots.
  47 //
  48 // The enqueuing of the MarkFromRootsTask and ThreadRootsMarkingTask
  49 // do little more than create the task and put it on a queue.  The
  50 // queue is a GCTaskQueue and threads steal tasks from this GCTaskQueue.
  51 //
  52 // In addition to the MarkFromRootsTask and ThreadRootsMarkingTask
  53 // tasks there are StealMarkingTask tasks.  The StealMarkingTask's
  54 // steal a reference from the marking stack of another
  55 // thread and transitively marks the object of the reference
  56 // and internal references.  After successfully stealing a reference
  57 // and marking it, the StealMarkingTask drains its marking stack
  58 // stack before attempting another steal.
  59 //
  60 // ThreadRootsMarkingTask
  61 //
  62 // This task marks from the roots of a single thread. This task
  63 // enables marking of thread roots in parallel.
  64 //
  65 
  66 class ParallelTaskTerminator;
  67 
  68 class ThreadRootsMarkingTask : public GCTask {
  69  private:
  70   JavaThread* _java_thread;
  71   VMThread* _vm_thread;
  72  public:
  73   ThreadRootsMarkingTask(JavaThread* root) : _java_thread(root), _vm_thread(NULL) {}
  74   ThreadRootsMarkingTask(VMThread* root) : _java_thread(NULL), _vm_thread(root) {}
  75 
  76   char* name() { return (char *)"thread-roots-marking-task"; }
  77 
  78   virtual void do_it(GCTaskManager* manager, uint which);
  79 };
  80 
  81 
  82 //
  83 // MarkFromRootsTask
  84 //
  85 // This task marks from all the roots to all live
  86 // objects.
  87 //
  88 //
  89 
  90 class MarkFromRootsTask : public GCTask {
  91  public:
  92   enum RootType {
  93     universe              = 1,
  94     jni_handles           = 2,
  95     threads               = 3,
  96     object_synchronizer   = 4,
  97     flat_profiler         = 5,
  98     management            = 6,
  99     jvmti                 = 7,
 100     system_dictionary     = 8,
 101     reference_processing  = 9,
 102     code_cache            = 10
 103   };
 104  private:
 105   RootType _root_type;
 106  public:
 107   MarkFromRootsTask(RootType value) : _root_type(value) {}
 108 
 109   char* name() { return (char *)"mark-from-roots-task"; }
 110 
 111   virtual void do_it(GCTaskManager* manager, uint which);
 112 };
 113 
 114 //
 115 // RefProcTaskProxy
 116 //
 117 // This task is used as a proxy to parallel reference processing tasks .
 118 //
 119 
 120 class RefProcTaskProxy : public GCTask {
 121   typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
 122   ProcessTask & _rp_task;
 123   uint          _work_id;
 124 public:
 125   RefProcTaskProxy(ProcessTask & rp_task, uint work_id)
 126     : _rp_task(rp_task),
 127       _work_id(work_id)
 128   { }
 129 
 130 private:
 131   virtual char* name() { return (char *)"Process referents by policy in parallel"; }
 132 
 133   virtual void do_it(GCTaskManager* manager, uint which);
 134 };
 135 
 136 
 137 
 138 //
 139 // RefEnqueueTaskProxy
 140 //
 141 // This task is used as a proxy to parallel reference processing tasks .
 142 //
 143 
 144 class RefEnqueueTaskProxy: public GCTask {
 145   typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
 146   EnqueueTask& _enq_task;
 147   uint         _work_id;
 148 
 149 public:
 150   RefEnqueueTaskProxy(EnqueueTask& enq_task, uint work_id)
 151     : _enq_task(enq_task),
 152       _work_id(work_id)
 153   { }
 154 
 155   virtual char* name() { return (char *)"Enqueue reference objects in parallel"; }
 156   virtual void do_it(GCTaskManager* manager, uint which)
 157   {
 158     _enq_task.work(_work_id);
 159   }
 160 };
 161 
 162 
 163 //
 164 // RefProcTaskExecutor
 165 //
 166 // Task executor is an interface for the reference processor to run
 167 // tasks using GCTaskManager.
 168 //
 169 
 170 class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
 171   virtual void execute(ProcessTask& task);
 172   virtual void execute(EnqueueTask& task);
 173 };
 174 
 175 
 176 //
 177 // StealMarkingTask
 178 //
 179 // This task is used to distribute work to idle threads.
 180 //
 181 
 182 class StealMarkingTask : public GCTask {
 183  private:
 184    ParallelTaskTerminator* const _terminator;
 185  private:
 186 
 187  public:
 188   char* name() { return (char *)"steal-marking-task"; }
 189 
 190   StealMarkingTask(ParallelTaskTerminator* t);
 191 
 192   ParallelTaskTerminator* terminator() { return _terminator; }
 193 
 194   virtual void do_it(GCTaskManager* manager, uint which);
 195 };
 196 
 197 //
 198 // StealRegionCompactionTask
 199 //
 200 // This task is used to distribute work to idle threads.
 201 //
 202 
 203 class StealRegionCompactionTask : public GCTask {
 204  private:
 205    ParallelTaskTerminator* const _terminator;
 206  public:
 207   StealRegionCompactionTask(ParallelTaskTerminator* t);
 208 
 209   char* name() { return (char *)"steal-region-task"; }
 210   ParallelTaskTerminator* terminator() { return _terminator; }
 211 
 212   virtual void do_it(GCTaskManager* manager, uint which);
 213 };
 214 
 215 //
 216 // UpdateDensePrefixTask
 217 //
 218 // This task is used to update the dense prefix
 219 // of a space.
 220 //
 221 
 222 class UpdateDensePrefixTask : public GCTask {
 223  private:
 224   PSParallelCompact::SpaceId _space_id;
 225   size_t _region_index_start;
 226   size_t _region_index_end;
 227 
 228  public:
 229   char* name() { return (char *)"update-dense_prefix-task"; }
 230 
 231   UpdateDensePrefixTask(PSParallelCompact::SpaceId space_id,
 232                         size_t region_index_start,
 233                         size_t region_index_end);
 234 
 235   virtual void do_it(GCTaskManager* manager, uint which);
 236 };
 237 
 238 //
 239 // DrainStacksCompactionTask
 240 //
 241 // This task processes regions that have been added to the stacks of each
 242 // compaction manager.
 243 //
 244 // Trying to use one draining thread does not work because there are no
 245 // guarantees about which task will be picked up by which thread.  For example,
 246 // if thread A gets all the preloaded regions, thread A may not get a draining
 247 // task (they may all be done by other threads).
 248 //
 249 
 250 class DrainStacksCompactionTask : public GCTask {
 251  uint _stack_index;
 252  uint stack_index() { return _stack_index; }
 253  public:
 254   DrainStacksCompactionTask(uint stack_index) : GCTask(),
 255                                                 _stack_index(stack_index) {};
 256   char* name() { return (char *)"drain-region-task"; }
 257   virtual void do_it(GCTaskManager* manager, uint which);
 258 };
 259 
 260 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PCTASKS_HPP