Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp @ 2149:7e37af9d69ef
7011379: G1: overly long concurrent marking cycles
Summary: This changeset introduces filtering of SATB buffers at the point when they are about to be enqueued. If this filtering clears enough entries on each buffer, the buffer can then be re-used and not enqueued. This cuts down the number of SATB buffers that need to be processed by the concurrent marking threads.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 09:35:17 -0500 |
parents | f95d63e2154a |
children | bca17e38de00 |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 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 | |
0 | 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 // A free list of Monitor*'s. | |
49 class MonitorSupply; | |
50 | |
51 // Forward declarations of classes referenced in this file via pointer. | |
52 class GCTaskThread; | |
53 class Mutex; | |
54 class Monitor; | |
55 class ThreadClosure; | |
56 | |
57 // The abstract base GCTask. | |
58 class GCTask : public ResourceObj { | |
59 public: | |
60 // Known kinds of GCTasks, for predicates. | |
61 class Kind : AllStatic { | |
62 public: | |
63 enum kind { | |
64 unknown_task, | |
65 ordinary_task, | |
66 barrier_task, | |
67 noop_task | |
68 }; | |
69 static const char* to_string(kind value); | |
70 }; | |
71 private: | |
72 // Instance state. | |
73 const Kind::kind _kind; // For runtime type checking. | |
74 const uint _affinity; // Which worker should run task. | |
75 GCTask* _newer; // Tasks are on doubly-linked ... | |
76 GCTask* _older; // ... lists. | |
77 public: | |
78 virtual char* name() { return (char *)"task"; } | |
79 | |
80 // Abstract do_it method | |
81 virtual void do_it(GCTaskManager* manager, uint which) = 0; | |
82 // Accessors | |
83 Kind::kind kind() const { | |
84 return _kind; | |
85 } | |
86 uint affinity() const { | |
87 return _affinity; | |
88 } | |
89 GCTask* newer() const { | |
90 return _newer; | |
91 } | |
92 void set_newer(GCTask* n) { | |
93 _newer = n; | |
94 } | |
95 GCTask* older() const { | |
96 return _older; | |
97 } | |
98 void set_older(GCTask* p) { | |
99 _older = p; | |
100 } | |
101 // Predicates. | |
102 bool is_ordinary_task() const { | |
103 return kind()==Kind::ordinary_task; | |
104 } | |
105 bool is_barrier_task() const { | |
106 return kind()==Kind::barrier_task; | |
107 } | |
108 bool is_noop_task() const { | |
109 return kind()==Kind::noop_task; | |
110 } | |
111 void print(const char* message) const PRODUCT_RETURN; | |
112 protected: | |
113 // Constructors: Only create subclasses. | |
114 // An ordinary GCTask. | |
115 GCTask(); | |
116 // A GCTask of a particular kind, usually barrier or noop. | |
117 GCTask(Kind::kind kind); | |
118 // An ordinary GCTask with an affinity. | |
119 GCTask(uint affinity); | |
120 // A GCTask of a particular kind, with and affinity. | |
121 GCTask(Kind::kind kind, uint affinity); | |
122 // We want a virtual destructor because virtual methods, | |
123 // but since ResourceObj's don't have their destructors | |
124 // called, we don't have one at all. Instead we have | |
125 // this method, which gets called by subclasses to clean up. | |
126 virtual void destruct(); | |
127 // Methods. | |
128 void initialize(); | |
129 }; | |
130 | |
131 // A doubly-linked list of GCTasks. | |
132 // The list is not synchronized, because sometimes we want to | |
133 // build up a list and then make it available to other threads. | |
134 // See also: SynchronizedGCTaskQueue. | |
135 class GCTaskQueue : public ResourceObj { | |
136 private: | |
137 // Instance state. | |
138 GCTask* _insert_end; // Tasks are enqueued at this end. | |
139 GCTask* _remove_end; // Tasks are dequeued from this end. | |
140 uint _length; // The current length of the queue. | |
141 const bool _is_c_heap_obj; // Is this a CHeapObj? | |
142 public: | |
143 // Factory create and destroy methods. | |
144 // Create as ResourceObj. | |
145 static GCTaskQueue* create(); | |
146 // Create as CHeapObj. | |
147 static GCTaskQueue* create_on_c_heap(); | |
148 // Destroyer. | |
149 static void destroy(GCTaskQueue* that); | |
150 // Accessors. | |
151 // These just examine the state of the queue. | |
152 bool is_empty() const { | |
153 assert(((insert_end() == NULL && remove_end() == NULL) || | |
154 (insert_end() != NULL && remove_end() != NULL)), | |
155 "insert_end and remove_end don't match"); | |
156 return insert_end() == NULL; | |
157 } | |
158 uint length() const { | |
159 return _length; | |
160 } | |
161 // Methods. | |
162 // Enqueue one task. | |
163 void enqueue(GCTask* task); | |
164 // Enqueue a list of tasks. Empties the argument list. | |
165 void enqueue(GCTaskQueue* list); | |
166 // Dequeue one task. | |
167 GCTask* dequeue(); | |
168 // Dequeue one task, preferring one with affinity. | |
169 GCTask* dequeue(uint affinity); | |
170 protected: | |
171 // Constructor. Clients use factory, but there might be subclasses. | |
172 GCTaskQueue(bool on_c_heap); | |
173 // Destructor-like method. | |
174 // Because ResourceMark doesn't call destructors. | |
175 // This method cleans up like one. | |
176 virtual void destruct(); | |
177 // Accessors. | |
178 GCTask* insert_end() const { | |
179 return _insert_end; | |
180 } | |
181 void set_insert_end(GCTask* value) { | |
182 _insert_end = value; | |
183 } | |
184 GCTask* remove_end() const { | |
185 return _remove_end; | |
186 } | |
187 void set_remove_end(GCTask* value) { | |
188 _remove_end = value; | |
189 } | |
190 void increment_length() { | |
191 _length += 1; | |
192 } | |
193 void decrement_length() { | |
194 _length -= 1; | |
195 } | |
196 void set_length(uint value) { | |
197 _length = value; | |
198 } | |
199 bool is_c_heap_obj() const { | |
200 return _is_c_heap_obj; | |
201 } | |
202 // Methods. | |
203 void initialize(); | |
204 GCTask* remove(); // Remove from remove end. | |
205 GCTask* remove(GCTask* task); // Remove from the middle. | |
206 void print(const char* message) const PRODUCT_RETURN; | |
207 }; | |
208 | |
209 // A GCTaskQueue that can be synchronized. | |
210 // This "has-a" GCTaskQueue and a mutex to do the exclusion. | |
211 class SynchronizedGCTaskQueue : public CHeapObj { | |
212 private: | |
213 // Instance state. | |
214 GCTaskQueue* _unsynchronized_queue; // Has-a unsynchronized queue. | |
215 Monitor * _lock; // Lock to control access. | |
216 public: | |
217 // Factory create and destroy methods. | |
218 static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) { | |
219 return new SynchronizedGCTaskQueue(queue, lock); | |
220 } | |
221 static void destroy(SynchronizedGCTaskQueue* that) { | |
222 if (that != NULL) { | |
223 delete that; | |
224 } | |
225 } | |
226 // Accessors | |
227 GCTaskQueue* unsynchronized_queue() const { | |
228 return _unsynchronized_queue; | |
229 } | |
230 Monitor * lock() const { | |
231 return _lock; | |
232 } | |
233 // GCTaskQueue wrapper methods. | |
234 // These check that you hold the lock | |
235 // and then call the method on the queue. | |
236 bool is_empty() const { | |
237 guarantee(own_lock(), "don't own the lock"); | |
238 return unsynchronized_queue()->is_empty(); | |
239 } | |
240 void enqueue(GCTask* task) { | |
241 guarantee(own_lock(), "don't own the lock"); | |
242 unsynchronized_queue()->enqueue(task); | |
243 } | |
244 void enqueue(GCTaskQueue* list) { | |
245 guarantee(own_lock(), "don't own the lock"); | |
246 unsynchronized_queue()->enqueue(list); | |
247 } | |
248 GCTask* dequeue() { | |
249 guarantee(own_lock(), "don't own the lock"); | |
250 return unsynchronized_queue()->dequeue(); | |
251 } | |
252 GCTask* dequeue(uint affinity) { | |
253 guarantee(own_lock(), "don't own the lock"); | |
254 return unsynchronized_queue()->dequeue(affinity); | |
255 } | |
256 uint length() const { | |
257 guarantee(own_lock(), "don't own the lock"); | |
258 return unsynchronized_queue()->length(); | |
259 } | |
260 // For guarantees. | |
261 bool own_lock() const { | |
262 return lock()->owned_by_self(); | |
263 } | |
264 protected: | |
265 // Constructor. Clients use factory, but there might be subclasses. | |
266 SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock); | |
267 // Destructor. Not virtual because no virtuals. | |
268 ~SynchronizedGCTaskQueue(); | |
269 }; | |
270 | |
271 // This is an abstract base class for getting notifications | |
272 // when a GCTaskManager is done. | |
273 class NotifyDoneClosure : public CHeapObj { | |
274 public: | |
275 // The notification callback method. | |
276 virtual void notify(GCTaskManager* manager) = 0; | |
277 protected: | |
278 // Constructor. | |
279 NotifyDoneClosure() { | |
280 // Nothing to do. | |
281 } | |
282 // Virtual destructor because virtual methods. | |
283 virtual ~NotifyDoneClosure() { | |
284 // Nothing to do. | |
285 } | |
286 }; | |
287 | |
288 class GCTaskManager : public CHeapObj { | |
289 friend class ParCompactionManager; | |
290 friend class PSParallelCompact; | |
291 friend class PSScavenge; | |
292 friend class PSRefProcTaskExecutor; | |
293 friend class RefProcTaskExecutor; | |
294 private: | |
295 // Instance state. | |
296 NotifyDoneClosure* _ndc; // Notify on completion. | |
297 const uint _workers; // Number of workers. | |
298 Monitor* _monitor; // Notification of changes. | |
299 SynchronizedGCTaskQueue* _queue; // Queue of tasks. | |
300 GCTaskThread** _thread; // Array of worker threads. | |
301 uint _busy_workers; // Number of busy workers. | |
302 uint _blocking_worker; // The worker that's blocking. | |
303 bool* _resource_flag; // Array of flag per threads. | |
304 uint _delivered_tasks; // Count of delivered tasks. | |
305 uint _completed_tasks; // Count of completed tasks. | |
306 uint _barriers; // Count of barrier tasks. | |
307 uint _emptied_queue; // Times we emptied the queue. | |
308 NoopGCTask* _noop_task; // The NoopGCTask instance. | |
309 uint _noop_tasks; // Count of noop tasks. | |
310 public: | |
311 // Factory create and destroy methods. | |
312 static GCTaskManager* create(uint workers) { | |
313 return new GCTaskManager(workers); | |
314 } | |
315 static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) { | |
316 return new GCTaskManager(workers, ndc); | |
317 } | |
318 static void destroy(GCTaskManager* that) { | |
319 if (that != NULL) { | |
320 delete that; | |
321 } | |
322 } | |
323 // Accessors. | |
324 uint busy_workers() const { | |
325 return _busy_workers; | |
326 } | |
327 // Pun between Monitor* and Mutex* | |
328 Monitor* monitor() const { | |
329 return _monitor; | |
330 } | |
331 Monitor * lock() const { | |
332 return _monitor; | |
333 } | |
334 // Methods. | |
335 // Add the argument task to be run. | |
336 void add_task(GCTask* task); | |
337 // Add a list of tasks. Removes task from the argument list. | |
338 void add_list(GCTaskQueue* list); | |
339 // Claim a task for argument worker. | |
340 GCTask* get_task(uint which); | |
341 // Note the completion of a task by the argument worker. | |
342 void note_completion(uint which); | |
343 // Is the queue blocked from handing out new tasks? | |
344 bool is_blocked() const { | |
345 return (blocking_worker() != sentinel_worker()); | |
346 } | |
347 // Request that all workers release their resources. | |
348 void release_all_resources(); | |
349 // Ask if a particular worker should release its resources. | |
350 bool should_release_resources(uint which); // Predicate. | |
351 // Note the release of resources by the argument worker. | |
352 void note_release(uint which); | |
353 // Constants. | |
354 // A sentinel worker identifier. | |
355 static uint sentinel_worker() { | |
356 return (uint) -1; // Why isn't there a max_uint? | |
357 } | |
358 | |
359 // Execute the task queue and wait for the completion. | |
360 void execute_and_wait(GCTaskQueue* list); | |
361 | |
362 void print_task_time_stamps(); | |
363 void print_threads_on(outputStream* st); | |
364 void threads_do(ThreadClosure* tc); | |
365 | |
366 protected: | |
367 // Constructors. Clients use factory, but there might be subclasses. | |
368 // Create a GCTaskManager with the appropriate number of workers. | |
369 GCTaskManager(uint workers); | |
370 // Create a GCTaskManager that calls back when there's no more work. | |
371 GCTaskManager(uint workers, NotifyDoneClosure* ndc); | |
372 // Make virtual if necessary. | |
373 ~GCTaskManager(); | |
374 // Accessors. | |
375 uint workers() const { | |
376 return _workers; | |
377 } | |
378 NotifyDoneClosure* notify_done_closure() const { | |
379 return _ndc; | |
380 } | |
381 SynchronizedGCTaskQueue* queue() const { | |
382 return _queue; | |
383 } | |
384 NoopGCTask* noop_task() const { | |
385 return _noop_task; | |
386 } | |
387 // Bounds-checking per-thread data accessors. | |
388 GCTaskThread* thread(uint which); | |
389 void set_thread(uint which, GCTaskThread* value); | |
390 bool resource_flag(uint which); | |
391 void set_resource_flag(uint which, bool value); | |
392 // Modifier methods with some semantics. | |
393 // Is any worker blocking handing out new tasks? | |
394 uint blocking_worker() const { | |
395 return _blocking_worker; | |
396 } | |
397 void set_blocking_worker(uint value) { | |
398 _blocking_worker = value; | |
399 } | |
400 void set_unblocked() { | |
401 set_blocking_worker(sentinel_worker()); | |
402 } | |
403 // Count of busy workers. | |
404 void reset_busy_workers() { | |
405 _busy_workers = 0; | |
406 } | |
407 uint increment_busy_workers(); | |
408 uint decrement_busy_workers(); | |
409 // Count of tasks delivered to workers. | |
410 uint delivered_tasks() const { | |
411 return _delivered_tasks; | |
412 } | |
413 void increment_delivered_tasks() { | |
414 _delivered_tasks += 1; | |
415 } | |
416 void reset_delivered_tasks() { | |
417 _delivered_tasks = 0; | |
418 } | |
419 // Count of tasks completed by workers. | |
420 uint completed_tasks() const { | |
421 return _completed_tasks; | |
422 } | |
423 void increment_completed_tasks() { | |
424 _completed_tasks += 1; | |
425 } | |
426 void reset_completed_tasks() { | |
427 _completed_tasks = 0; | |
428 } | |
429 // Count of barrier tasks completed. | |
430 uint barriers() const { | |
431 return _barriers; | |
432 } | |
433 void increment_barriers() { | |
434 _barriers += 1; | |
435 } | |
436 void reset_barriers() { | |
437 _barriers = 0; | |
438 } | |
439 // Count of how many times the queue has emptied. | |
440 uint emptied_queue() const { | |
441 return _emptied_queue; | |
442 } | |
443 void increment_emptied_queue() { | |
444 _emptied_queue += 1; | |
445 } | |
446 void reset_emptied_queue() { | |
447 _emptied_queue = 0; | |
448 } | |
449 // Count of the number of noop tasks we've handed out, | |
450 // e.g., to handle resource release requests. | |
451 uint noop_tasks() const { | |
452 return _noop_tasks; | |
453 } | |
454 void increment_noop_tasks() { | |
455 _noop_tasks += 1; | |
456 } | |
457 void reset_noop_tasks() { | |
458 _noop_tasks = 0; | |
459 } | |
460 // Other methods. | |
461 void initialize(); | |
462 }; | |
463 | |
464 // | |
465 // Some exemplary GCTasks. | |
466 // | |
467 | |
468 // A noop task that does nothing, | |
469 // except take us around the GCTaskThread loop. | |
470 class NoopGCTask : public GCTask { | |
471 private: | |
472 const bool _is_c_heap_obj; // Is this a CHeapObj? | |
473 public: | |
474 // Factory create and destroy methods. | |
475 static NoopGCTask* create(); | |
476 static NoopGCTask* create_on_c_heap(); | |
477 static void destroy(NoopGCTask* that); | |
478 // Methods from GCTask. | |
479 void do_it(GCTaskManager* manager, uint which) { | |
480 // Nothing to do. | |
481 } | |
482 protected: | |
483 // Constructor. | |
484 NoopGCTask(bool on_c_heap) : | |
485 GCTask(GCTask::Kind::noop_task), | |
486 _is_c_heap_obj(on_c_heap) { | |
487 // Nothing to do. | |
488 } | |
489 // Destructor-like method. | |
490 void destruct(); | |
491 // Accessors. | |
492 bool is_c_heap_obj() const { | |
493 return _is_c_heap_obj; | |
494 } | |
495 }; | |
496 | |
497 // A BarrierGCTask blocks other tasks from starting, | |
498 // and waits until it is the only task running. | |
499 class BarrierGCTask : public GCTask { | |
500 public: | |
501 // Factory create and destroy methods. | |
502 static BarrierGCTask* create() { | |
503 return new BarrierGCTask(); | |
504 } | |
505 static void destroy(BarrierGCTask* that) { | |
506 if (that != NULL) { | |
507 that->destruct(); | |
508 delete that; | |
509 } | |
510 } | |
511 // Methods from GCTask. | |
512 void do_it(GCTaskManager* manager, uint which); | |
513 protected: | |
514 // Constructor. Clients use factory, but there might be subclasses. | |
515 BarrierGCTask() : | |
516 GCTask(GCTask::Kind::barrier_task) { | |
517 // Nothing to do. | |
518 } | |
519 // Destructor-like method. | |
520 void destruct(); | |
521 // Methods. | |
522 // Wait for this to be the only task running. | |
523 void do_it_internal(GCTaskManager* manager, uint which); | |
524 }; | |
525 | |
526 // A ReleasingBarrierGCTask is a BarrierGCTask | |
527 // that tells all the tasks to release their resource areas. | |
528 class ReleasingBarrierGCTask : public BarrierGCTask { | |
529 public: | |
530 // Factory create and destroy methods. | |
531 static ReleasingBarrierGCTask* create() { | |
532 return new ReleasingBarrierGCTask(); | |
533 } | |
534 static void destroy(ReleasingBarrierGCTask* that) { | |
535 if (that != NULL) { | |
536 that->destruct(); | |
537 delete that; | |
538 } | |
539 } | |
540 // Methods from GCTask. | |
541 void do_it(GCTaskManager* manager, uint which); | |
542 protected: | |
543 // Constructor. Clients use factory, but there might be subclasses. | |
544 ReleasingBarrierGCTask() : | |
545 BarrierGCTask() { | |
546 // Nothing to do. | |
547 } | |
548 // Destructor-like method. | |
549 void destruct(); | |
550 }; | |
551 | |
552 // A NotifyingBarrierGCTask is a BarrierGCTask | |
553 // that calls a notification method when it is the only task running. | |
554 class NotifyingBarrierGCTask : public BarrierGCTask { | |
555 private: | |
556 // Instance state. | |
557 NotifyDoneClosure* _ndc; // The callback object. | |
558 public: | |
559 // Factory create and destroy methods. | |
560 static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) { | |
561 return new NotifyingBarrierGCTask(ndc); | |
562 } | |
563 static void destroy(NotifyingBarrierGCTask* that) { | |
564 if (that != NULL) { | |
565 that->destruct(); | |
566 delete that; | |
567 } | |
568 } | |
569 // Methods from GCTask. | |
570 void do_it(GCTaskManager* manager, uint which); | |
571 protected: | |
572 // Constructor. Clients use factory, but there might be subclasses. | |
573 NotifyingBarrierGCTask(NotifyDoneClosure* ndc) : | |
574 BarrierGCTask(), | |
575 _ndc(ndc) { | |
576 assert(notify_done_closure() != NULL, "can't notify on NULL"); | |
577 } | |
578 // Destructor-like method. | |
579 void destruct(); | |
580 // Accessor. | |
581 NotifyDoneClosure* notify_done_closure() const { return _ndc; } | |
582 }; | |
583 | |
584 // A WaitForBarrierGCTask is a BarrierGCTask | |
585 // with a method you can call to wait until | |
586 // the BarrierGCTask is done. | |
587 // This may cover many of the uses of NotifyingBarrierGCTasks. | |
588 class WaitForBarrierGCTask : public BarrierGCTask { | |
589 private: | |
590 // Instance state. | |
591 Monitor* _monitor; // Guard and notify changes. | |
592 bool _should_wait; // true=>wait, false=>proceed. | |
593 const bool _is_c_heap_obj; // Was allocated on the heap. | |
594 public: | |
595 virtual char* name() { return (char *) "waitfor-barrier-task"; } | |
596 | |
597 // Factory create and destroy methods. | |
598 static WaitForBarrierGCTask* create(); | |
599 static WaitForBarrierGCTask* create_on_c_heap(); | |
600 static void destroy(WaitForBarrierGCTask* that); | |
601 // Methods. | |
602 void do_it(GCTaskManager* manager, uint which); | |
603 void wait_for(); | |
604 protected: | |
605 // Constructor. Clients use factory, but there might be subclasses. | |
606 WaitForBarrierGCTask(bool on_c_heap); | |
607 // Destructor-like method. | |
608 void destruct(); | |
609 // Accessors. | |
610 Monitor* monitor() const { | |
611 return _monitor; | |
612 } | |
613 bool should_wait() const { | |
614 return _should_wait; | |
615 } | |
616 void set_should_wait(bool value) { | |
617 _should_wait = value; | |
618 } | |
619 bool is_c_heap_obj() { | |
620 return _is_c_heap_obj; | |
621 } | |
622 }; | |
623 | |
624 class MonitorSupply : public AllStatic { | |
625 private: | |
626 // State. | |
627 // Control multi-threaded access. | |
628 static Mutex* _lock; | |
629 // The list of available Monitor*'s. | |
630 static GrowableArray<Monitor*>* _freelist; | |
631 public: | |
632 // Reserve a Monitor*. | |
633 static Monitor* reserve(); | |
634 // Release a Monitor*. | |
635 static void release(Monitor* instance); | |
636 private: | |
637 // Accessors. | |
638 static Mutex* lock() { | |
639 return _lock; | |
640 } | |
641 static GrowableArray<Monitor*>* freelist() { | |
642 return _freelist; | |
643 } | |
644 }; | |
1972 | 645 |
646 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GCTASKMANAGER_HPP |