Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp
38920 views
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
*/
24
25
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP
26
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP
27
28
#include "runtime/mutex.hpp"
29
#include "utilities/growableArray.hpp"
30
31
//
32
// The GCTaskManager is a queue of GCTasks, and accessors
33
// to allow the queue to be accessed from many threads.
34
//
35
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;
51
52
// Forward declarations of classes referenced in this file via pointer.
53
class GCTaskThread;
54
class Mutex;
55
class Monitor;
56
class ThreadClosure;
57
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"; }
81
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
};
135
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
};
216
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
};
278
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
};
295
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.
356
357
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
}
443
444
// Execute the task queue and wait for the completion.
445
void execute_and_wait(GCTaskQueue* list);
446
447
void print_task_time_stamps();
448
void print_threads_on(outputStream* st);
449
void threads_do(ThreadClosure* tc);
450
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();
471
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();
562
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
};
570
571
//
572
// Some exemplary GCTasks.
573
//
574
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);
585
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
};
605
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();
630
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
};
636
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
};
662
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
};
694
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"; }
709
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
};
736
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);
749
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
};
763
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
};
785
786
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP
787
788