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

Wed, 24 Apr 2013 20:13:37 +0200

author
stefank
date
Wed, 24 Apr 2013 20:13:37 +0200
changeset 5018
b06ac540229e
parent 4153
b9a9ed0f8eeb
child 6876
710a3c8b516e
permissions
-rw-r--r--

8013132: Add a flag to turn off the output of the verbose verification code
Reviewed-by: johnc, brutisso

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

mercurial