Tue, 23 Nov 2010 13:22:55 -0800
6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg
1 /*
2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp"
28 #include "memory/allocation.hpp"
29 #include "memory/allocation.inline.hpp"
30 #include "runtime/mutex.hpp"
31 #include "runtime/mutexLocker.hpp"
33 //
34 // GCTask
35 //
37 const char* GCTask::Kind::to_string(kind value) {
38 const char* result = "unknown GCTask kind";
39 switch (value) {
40 default:
41 result = "unknown GCTask kind";
42 break;
43 case unknown_task:
44 result = "unknown task";
45 break;
46 case ordinary_task:
47 result = "ordinary task";
48 break;
49 case barrier_task:
50 result = "barrier task";
51 break;
52 case noop_task:
53 result = "noop task";
54 break;
55 }
56 return result;
57 };
59 GCTask::GCTask() :
60 _kind(Kind::ordinary_task),
61 _affinity(GCTaskManager::sentinel_worker()){
62 initialize();
63 }
65 GCTask::GCTask(Kind::kind kind) :
66 _kind(kind),
67 _affinity(GCTaskManager::sentinel_worker()) {
68 initialize();
69 }
71 GCTask::GCTask(uint affinity) :
72 _kind(Kind::ordinary_task),
73 _affinity(affinity) {
74 initialize();
75 }
77 GCTask::GCTask(Kind::kind kind, uint affinity) :
78 _kind(kind),
79 _affinity(affinity) {
80 initialize();
81 }
83 void GCTask::initialize() {
84 _older = NULL;
85 _newer = NULL;
86 }
88 void GCTask::destruct() {
89 assert(older() == NULL, "shouldn't have an older task");
90 assert(newer() == NULL, "shouldn't have a newer task");
91 // Nothing to do.
92 }
94 NOT_PRODUCT(
95 void GCTask::print(const char* message) const {
96 tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
97 newer(), this, affinity(), older());
98 }
99 )
101 //
102 // GCTaskQueue
103 //
105 GCTaskQueue* GCTaskQueue::create() {
106 GCTaskQueue* result = new GCTaskQueue(false);
107 if (TraceGCTaskQueue) {
108 tty->print_cr("GCTaskQueue::create()"
109 " returns " INTPTR_FORMAT, result);
110 }
111 return result;
112 }
114 GCTaskQueue* GCTaskQueue::create_on_c_heap() {
115 GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
116 if (TraceGCTaskQueue) {
117 tty->print_cr("GCTaskQueue::create_on_c_heap()"
118 " returns " INTPTR_FORMAT,
119 result);
120 }
121 return result;
122 }
124 GCTaskQueue::GCTaskQueue(bool on_c_heap) :
125 _is_c_heap_obj(on_c_heap) {
126 initialize();
127 if (TraceGCTaskQueue) {
128 tty->print_cr("[" INTPTR_FORMAT "]"
129 " GCTaskQueue::GCTaskQueue() constructor",
130 this);
131 }
132 }
134 void GCTaskQueue::destruct() {
135 // Nothing to do.
136 }
138 void GCTaskQueue::destroy(GCTaskQueue* that) {
139 if (TraceGCTaskQueue) {
140 tty->print_cr("[" INTPTR_FORMAT "]"
141 " GCTaskQueue::destroy()"
142 " is_c_heap_obj: %s",
143 that,
144 that->is_c_heap_obj() ? "true" : "false");
145 }
146 // That instance may have been allocated as a CHeapObj,
147 // in which case we have to free it explicitly.
148 if (that != NULL) {
149 that->destruct();
150 assert(that->is_empty(), "should be empty");
151 if (that->is_c_heap_obj()) {
152 FreeHeap(that);
153 }
154 }
155 }
157 void GCTaskQueue::initialize() {
158 set_insert_end(NULL);
159 set_remove_end(NULL);
160 set_length(0);
161 }
163 // Enqueue one task.
164 void GCTaskQueue::enqueue(GCTask* task) {
165 if (TraceGCTaskQueue) {
166 tty->print_cr("[" INTPTR_FORMAT "]"
167 " GCTaskQueue::enqueue(task: "
168 INTPTR_FORMAT ")",
169 this, task);
170 print("before:");
171 }
172 assert(task != NULL, "shouldn't have null task");
173 assert(task->older() == NULL, "shouldn't be on queue");
174 assert(task->newer() == NULL, "shouldn't be on queue");
175 task->set_newer(NULL);
176 task->set_older(insert_end());
177 if (is_empty()) {
178 set_remove_end(task);
179 } else {
180 insert_end()->set_newer(task);
181 }
182 set_insert_end(task);
183 increment_length();
184 if (TraceGCTaskQueue) {
185 print("after:");
186 }
187 }
189 // Enqueue a whole list of tasks. Empties the argument list.
190 void GCTaskQueue::enqueue(GCTaskQueue* list) {
191 if (TraceGCTaskQueue) {
192 tty->print_cr("[" INTPTR_FORMAT "]"
193 " GCTaskQueue::enqueue(list: "
194 INTPTR_FORMAT ")",
195 this);
196 print("before:");
197 list->print("list:");
198 }
199 if (list->is_empty()) {
200 // Enqueuing the empty list: nothing to do.
201 return;
202 }
203 uint list_length = list->length();
204 if (is_empty()) {
205 // Enqueuing to empty list: just acquire elements.
206 set_insert_end(list->insert_end());
207 set_remove_end(list->remove_end());
208 set_length(list_length);
209 } else {
210 // Prepend argument list to our queue.
211 list->remove_end()->set_older(insert_end());
212 insert_end()->set_newer(list->remove_end());
213 set_insert_end(list->insert_end());
214 // empty the argument list.
215 }
216 set_length(length() + list_length);
217 list->initialize();
218 if (TraceGCTaskQueue) {
219 print("after:");
220 list->print("list:");
221 }
222 }
224 // Dequeue one task.
225 GCTask* GCTaskQueue::dequeue() {
226 if (TraceGCTaskQueue) {
227 tty->print_cr("[" INTPTR_FORMAT "]"
228 " GCTaskQueue::dequeue()", this);
229 print("before:");
230 }
231 assert(!is_empty(), "shouldn't dequeue from empty list");
232 GCTask* result = remove();
233 assert(result != NULL, "shouldn't have NULL task");
234 if (TraceGCTaskQueue) {
235 tty->print_cr(" return: " INTPTR_FORMAT, result);
236 print("after:");
237 }
238 return result;
239 }
241 // Dequeue one task, preferring one with affinity.
242 GCTask* GCTaskQueue::dequeue(uint affinity) {
243 if (TraceGCTaskQueue) {
244 tty->print_cr("[" INTPTR_FORMAT "]"
245 " GCTaskQueue::dequeue(%u)", this, affinity);
246 print("before:");
247 }
248 assert(!is_empty(), "shouldn't dequeue from empty list");
249 // Look down to the next barrier for a task with this affinity.
250 GCTask* result = NULL;
251 for (GCTask* element = remove_end();
252 element != NULL;
253 element = element->newer()) {
254 if (element->is_barrier_task()) {
255 // Don't consider barrier tasks, nor past them.
256 result = NULL;
257 break;
258 }
259 if (element->affinity() == affinity) {
260 result = remove(element);
261 break;
262 }
263 }
264 // If we didn't find anything with affinity, just take the next task.
265 if (result == NULL) {
266 result = remove();
267 }
268 if (TraceGCTaskQueue) {
269 tty->print_cr(" return: " INTPTR_FORMAT, result);
270 print("after:");
271 }
272 return result;
273 }
275 GCTask* GCTaskQueue::remove() {
276 // Dequeue from remove end.
277 GCTask* result = remove_end();
278 assert(result != NULL, "shouldn't have null task");
279 assert(result->older() == NULL, "not the remove_end");
280 set_remove_end(result->newer());
281 if (remove_end() == NULL) {
282 assert(insert_end() == result, "not a singleton");
283 set_insert_end(NULL);
284 } else {
285 remove_end()->set_older(NULL);
286 }
287 result->set_newer(NULL);
288 decrement_length();
289 assert(result->newer() == NULL, "shouldn't be on queue");
290 assert(result->older() == NULL, "shouldn't be on queue");
291 return result;
292 }
294 GCTask* GCTaskQueue::remove(GCTask* task) {
295 // This is slightly more work, and has slightly fewer asserts
296 // than removing from the remove end.
297 assert(task != NULL, "shouldn't have null task");
298 GCTask* result = task;
299 if (result->newer() != NULL) {
300 result->newer()->set_older(result->older());
301 } else {
302 assert(insert_end() == result, "not youngest");
303 set_insert_end(result->older());
304 }
305 if (result->older() != NULL) {
306 result->older()->set_newer(result->newer());
307 } else {
308 assert(remove_end() == result, "not oldest");
309 set_remove_end(result->newer());
310 }
311 result->set_newer(NULL);
312 result->set_older(NULL);
313 decrement_length();
314 return result;
315 }
317 NOT_PRODUCT(
318 void GCTaskQueue::print(const char* message) const {
319 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
320 " insert_end: " INTPTR_FORMAT
321 " remove_end: " INTPTR_FORMAT
322 " %s",
323 this, insert_end(), remove_end(), message);
324 for (GCTask* element = insert_end();
325 element != NULL;
326 element = element->older()) {
327 element->print(" ");
328 tty->cr();
329 }
330 }
331 )
333 //
334 // SynchronizedGCTaskQueue
335 //
337 SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
338 Monitor * lock_arg) :
339 _unsynchronized_queue(queue_arg),
340 _lock(lock_arg) {
341 assert(unsynchronized_queue() != NULL, "null queue");
342 assert(lock() != NULL, "null lock");
343 }
345 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
346 // Nothing to do.
347 }
349 //
350 // GCTaskManager
351 //
352 GCTaskManager::GCTaskManager(uint workers) :
353 _workers(workers),
354 _ndc(NULL) {
355 initialize();
356 }
358 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
359 _workers(workers),
360 _ndc(ndc) {
361 initialize();
362 }
364 void GCTaskManager::initialize() {
365 if (TraceGCTaskManager) {
366 tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
367 }
368 assert(workers() != 0, "no workers");
369 _monitor = new Monitor(Mutex::barrier, // rank
370 "GCTaskManager monitor", // name
371 Mutex::_allow_vm_block_flag); // allow_vm_block
372 // The queue for the GCTaskManager must be a CHeapObj.
373 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
374 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
375 _noop_task = NoopGCTask::create_on_c_heap();
376 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
377 {
378 // Set up worker threads.
379 // Distribute the workers among the available processors,
380 // unless we were told not to, or if the os doesn't want to.
381 uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
382 if (!BindGCTaskThreadsToCPUs ||
383 !os::distribute_processes(workers(), processor_assignment)) {
384 for (uint a = 0; a < workers(); a += 1) {
385 processor_assignment[a] = sentinel_worker();
386 }
387 }
388 _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
389 for (uint t = 0; t < workers(); t += 1) {
390 set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
391 }
392 if (TraceGCTaskThread) {
393 tty->print("GCTaskManager::initialize: distribution:");
394 for (uint t = 0; t < workers(); t += 1) {
395 tty->print(" %u", processor_assignment[t]);
396 }
397 tty->cr();
398 }
399 FREE_C_HEAP_ARRAY(uint, processor_assignment);
400 }
401 reset_busy_workers();
402 set_unblocked();
403 for (uint w = 0; w < workers(); w += 1) {
404 set_resource_flag(w, false);
405 }
406 reset_delivered_tasks();
407 reset_completed_tasks();
408 reset_noop_tasks();
409 reset_barriers();
410 reset_emptied_queue();
411 for (uint s = 0; s < workers(); s += 1) {
412 thread(s)->start();
413 }
414 }
416 GCTaskManager::~GCTaskManager() {
417 assert(busy_workers() == 0, "still have busy workers");
418 assert(queue()->is_empty(), "still have queued work");
419 NoopGCTask::destroy(_noop_task);
420 _noop_task = NULL;
421 if (_thread != NULL) {
422 for (uint i = 0; i < workers(); i += 1) {
423 GCTaskThread::destroy(thread(i));
424 set_thread(i, NULL);
425 }
426 FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
427 _thread = NULL;
428 }
429 if (_resource_flag != NULL) {
430 FREE_C_HEAP_ARRAY(bool, _resource_flag);
431 _resource_flag = NULL;
432 }
433 if (queue() != NULL) {
434 GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
435 GCTaskQueue::destroy(unsynchronized_queue);
436 SynchronizedGCTaskQueue::destroy(queue());
437 _queue = NULL;
438 }
439 if (monitor() != NULL) {
440 delete monitor();
441 _monitor = NULL;
442 }
443 }
445 void GCTaskManager::print_task_time_stamps() {
446 for(uint i=0; i<ParallelGCThreads; i++) {
447 GCTaskThread* t = thread(i);
448 t->print_task_time_stamps();
449 }
450 }
452 void GCTaskManager::print_threads_on(outputStream* st) {
453 uint num_thr = workers();
454 for (uint i = 0; i < num_thr; i++) {
455 thread(i)->print_on(st);
456 st->cr();
457 }
458 }
460 void GCTaskManager::threads_do(ThreadClosure* tc) {
461 assert(tc != NULL, "Null ThreadClosure");
462 uint num_thr = workers();
463 for (uint i = 0; i < num_thr; i++) {
464 tc->do_thread(thread(i));
465 }
466 }
468 GCTaskThread* GCTaskManager::thread(uint which) {
469 assert(which < workers(), "index out of bounds");
470 assert(_thread[which] != NULL, "shouldn't have null thread");
471 return _thread[which];
472 }
474 void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
475 assert(which < workers(), "index out of bounds");
476 assert(value != NULL, "shouldn't have null thread");
477 _thread[which] = value;
478 }
480 void GCTaskManager::add_task(GCTask* task) {
481 assert(task != NULL, "shouldn't have null task");
482 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
483 if (TraceGCTaskManager) {
484 tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
485 task, GCTask::Kind::to_string(task->kind()));
486 }
487 queue()->enqueue(task);
488 // Notify with the lock held to avoid missed notifies.
489 if (TraceGCTaskManager) {
490 tty->print_cr(" GCTaskManager::add_task (%s)->notify_all",
491 monitor()->name());
492 }
493 (void) monitor()->notify_all();
494 // Release monitor().
495 }
497 void GCTaskManager::add_list(GCTaskQueue* list) {
498 assert(list != NULL, "shouldn't have null task");
499 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
500 if (TraceGCTaskManager) {
501 tty->print_cr("GCTaskManager::add_list(%u)", list->length());
502 }
503 queue()->enqueue(list);
504 // Notify with the lock held to avoid missed notifies.
505 if (TraceGCTaskManager) {
506 tty->print_cr(" GCTaskManager::add_list (%s)->notify_all",
507 monitor()->name());
508 }
509 (void) monitor()->notify_all();
510 // Release monitor().
511 }
513 GCTask* GCTaskManager::get_task(uint which) {
514 GCTask* result = NULL;
515 // Grab the queue lock.
516 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
517 // Wait while the queue is block or
518 // there is nothing to do, except maybe release resources.
519 while (is_blocked() ||
520 (queue()->is_empty() && !should_release_resources(which))) {
521 if (TraceGCTaskManager) {
522 tty->print_cr("GCTaskManager::get_task(%u)"
523 " blocked: %s"
524 " empty: %s"
525 " release: %s",
526 which,
527 is_blocked() ? "true" : "false",
528 queue()->is_empty() ? "true" : "false",
529 should_release_resources(which) ? "true" : "false");
530 tty->print_cr(" => (%s)->wait()",
531 monitor()->name());
532 }
533 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
534 }
535 // We've reacquired the queue lock here.
536 // Figure out which condition caused us to exit the loop above.
537 if (!queue()->is_empty()) {
538 if (UseGCTaskAffinity) {
539 result = queue()->dequeue(which);
540 } else {
541 result = queue()->dequeue();
542 }
543 if (result->is_barrier_task()) {
544 assert(which != sentinel_worker(),
545 "blocker shouldn't be bogus");
546 set_blocking_worker(which);
547 }
548 } else {
549 // The queue is empty, but we were woken up.
550 // Just hand back a Noop task,
551 // in case someone wanted us to release resources, or whatever.
552 result = noop_task();
553 increment_noop_tasks();
554 }
555 assert(result != NULL, "shouldn't have null task");
556 if (TraceGCTaskManager) {
557 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
558 which, result, GCTask::Kind::to_string(result->kind()));
559 tty->print_cr(" %s", result->name());
560 }
561 increment_busy_workers();
562 increment_delivered_tasks();
563 return result;
564 // Release monitor().
565 }
567 void GCTaskManager::note_completion(uint which) {
568 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
569 if (TraceGCTaskManager) {
570 tty->print_cr("GCTaskManager::note_completion(%u)", which);
571 }
572 // If we are blocked, check if the completing thread is the blocker.
573 if (blocking_worker() == which) {
574 assert(blocking_worker() != sentinel_worker(),
575 "blocker shouldn't be bogus");
576 increment_barriers();
577 set_unblocked();
578 }
579 increment_completed_tasks();
580 uint active = decrement_busy_workers();
581 if ((active == 0) && (queue()->is_empty())) {
582 increment_emptied_queue();
583 if (TraceGCTaskManager) {
584 tty->print_cr(" GCTaskManager::note_completion(%u) done", which);
585 }
586 // Notify client that we are done.
587 NotifyDoneClosure* ndc = notify_done_closure();
588 if (ndc != NULL) {
589 ndc->notify(this);
590 }
591 }
592 if (TraceGCTaskManager) {
593 tty->print_cr(" GCTaskManager::note_completion(%u) (%s)->notify_all",
594 which, monitor()->name());
595 tty->print_cr(" "
596 " blocked: %s"
597 " empty: %s"
598 " release: %s",
599 is_blocked() ? "true" : "false",
600 queue()->is_empty() ? "true" : "false",
601 should_release_resources(which) ? "true" : "false");
602 tty->print_cr(" "
603 " delivered: %u"
604 " completed: %u"
605 " barriers: %u"
606 " emptied: %u",
607 delivered_tasks(),
608 completed_tasks(),
609 barriers(),
610 emptied_queue());
611 }
612 // Tell everyone that a task has completed.
613 (void) monitor()->notify_all();
614 // Release monitor().
615 }
617 uint GCTaskManager::increment_busy_workers() {
618 assert(queue()->own_lock(), "don't own the lock");
619 _busy_workers += 1;
620 return _busy_workers;
621 }
623 uint GCTaskManager::decrement_busy_workers() {
624 assert(queue()->own_lock(), "don't own the lock");
625 _busy_workers -= 1;
626 return _busy_workers;
627 }
629 void GCTaskManager::release_all_resources() {
630 // If you want this to be done atomically, do it in a BarrierGCTask.
631 for (uint i = 0; i < workers(); i += 1) {
632 set_resource_flag(i, true);
633 }
634 }
636 bool GCTaskManager::should_release_resources(uint which) {
637 // This can be done without a lock because each thread reads one element.
638 return resource_flag(which);
639 }
641 void GCTaskManager::note_release(uint which) {
642 // This can be done without a lock because each thread writes one element.
643 set_resource_flag(which, false);
644 }
646 void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
647 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
648 list->enqueue(fin);
649 add_list(list);
650 fin->wait_for();
651 // We have to release the barrier tasks!
652 WaitForBarrierGCTask::destroy(fin);
653 }
655 bool GCTaskManager::resource_flag(uint which) {
656 assert(which < workers(), "index out of bounds");
657 return _resource_flag[which];
658 }
660 void GCTaskManager::set_resource_flag(uint which, bool value) {
661 assert(which < workers(), "index out of bounds");
662 _resource_flag[which] = value;
663 }
665 //
666 // NoopGCTask
667 //
669 NoopGCTask* NoopGCTask::create() {
670 NoopGCTask* result = new NoopGCTask(false);
671 return result;
672 }
674 NoopGCTask* NoopGCTask::create_on_c_heap() {
675 NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
676 return result;
677 }
679 void NoopGCTask::destroy(NoopGCTask* that) {
680 if (that != NULL) {
681 that->destruct();
682 if (that->is_c_heap_obj()) {
683 FreeHeap(that);
684 }
685 }
686 }
688 void NoopGCTask::destruct() {
689 // This has to know it's superclass structure, just like the constructor.
690 this->GCTask::destruct();
691 // Nothing else to do.
692 }
694 //
695 // BarrierGCTask
696 //
698 void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
699 // Wait for this to be the only busy worker.
700 // ??? I thought of having a StackObj class
701 // whose constructor would grab the lock and come to the barrier,
702 // and whose destructor would release the lock,
703 // but that seems like too much mechanism for two lines of code.
704 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
705 do_it_internal(manager, which);
706 // Release manager->lock().
707 }
709 void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
710 // Wait for this to be the only busy worker.
711 assert(manager->monitor()->owned_by_self(), "don't own the lock");
712 assert(manager->is_blocked(), "manager isn't blocked");
713 while (manager->busy_workers() > 1) {
714 if (TraceGCTaskManager) {
715 tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
716 which, manager->busy_workers());
717 }
718 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
719 }
720 }
722 void BarrierGCTask::destruct() {
723 this->GCTask::destruct();
724 // Nothing else to do.
725 }
727 //
728 // ReleasingBarrierGCTask
729 //
731 void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
732 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
733 do_it_internal(manager, which);
734 manager->release_all_resources();
735 // Release manager->lock().
736 }
738 void ReleasingBarrierGCTask::destruct() {
739 this->BarrierGCTask::destruct();
740 // Nothing else to do.
741 }
743 //
744 // NotifyingBarrierGCTask
745 //
747 void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
748 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
749 do_it_internal(manager, which);
750 NotifyDoneClosure* ndc = notify_done_closure();
751 if (ndc != NULL) {
752 ndc->notify(manager);
753 }
754 // Release manager->lock().
755 }
757 void NotifyingBarrierGCTask::destruct() {
758 this->BarrierGCTask::destruct();
759 // Nothing else to do.
760 }
762 //
763 // WaitForBarrierGCTask
764 //
765 WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
766 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
767 return result;
768 }
770 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
771 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true);
772 return result;
773 }
775 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
776 _is_c_heap_obj(on_c_heap) {
777 _monitor = MonitorSupply::reserve();
778 set_should_wait(true);
779 if (TraceGCTaskManager) {
780 tty->print_cr("[" INTPTR_FORMAT "]"
781 " WaitForBarrierGCTask::WaitForBarrierGCTask()"
782 " monitor: " INTPTR_FORMAT,
783 this, monitor());
784 }
785 }
787 void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
788 if (that != NULL) {
789 if (TraceGCTaskManager) {
790 tty->print_cr("[" INTPTR_FORMAT "]"
791 " WaitForBarrierGCTask::destroy()"
792 " is_c_heap_obj: %s"
793 " monitor: " INTPTR_FORMAT,
794 that,
795 that->is_c_heap_obj() ? "true" : "false",
796 that->monitor());
797 }
798 that->destruct();
799 if (that->is_c_heap_obj()) {
800 FreeHeap(that);
801 }
802 }
803 }
805 void WaitForBarrierGCTask::destruct() {
806 assert(monitor() != NULL, "monitor should not be NULL");
807 if (TraceGCTaskManager) {
808 tty->print_cr("[" INTPTR_FORMAT "]"
809 " WaitForBarrierGCTask::destruct()"
810 " monitor: " INTPTR_FORMAT,
811 this, monitor());
812 }
813 this->BarrierGCTask::destruct();
814 // Clean up that should be in the destructor,
815 // except that ResourceMarks don't call destructors.
816 if (monitor() != NULL) {
817 MonitorSupply::release(monitor());
818 }
819 _monitor = (Monitor*) 0xDEAD000F;
820 }
822 void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
823 if (TraceGCTaskManager) {
824 tty->print_cr("[" INTPTR_FORMAT "]"
825 " WaitForBarrierGCTask::do_it() waiting for idle"
826 " monitor: " INTPTR_FORMAT,
827 this, monitor());
828 }
829 {
830 // First, wait for the barrier to arrive.
831 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
832 do_it_internal(manager, which);
833 // Release manager->lock().
834 }
835 {
836 // Then notify the waiter.
837 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
838 set_should_wait(false);
839 // Waiter doesn't miss the notify in the wait_for method
840 // since it checks the flag after grabbing the monitor.
841 if (TraceGCTaskManager) {
842 tty->print_cr("[" INTPTR_FORMAT "]"
843 " WaitForBarrierGCTask::do_it()"
844 " [" INTPTR_FORMAT "] (%s)->notify_all()",
845 this, monitor(), monitor()->name());
846 }
847 monitor()->notify_all();
848 // Release monitor().
849 }
850 }
852 void WaitForBarrierGCTask::wait_for() {
853 if (TraceGCTaskManager) {
854 tty->print_cr("[" INTPTR_FORMAT "]"
855 " WaitForBarrierGCTask::wait_for()"
856 " should_wait: %s",
857 this, should_wait() ? "true" : "false");
858 }
859 {
860 // Grab the lock and check again.
861 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
862 while (should_wait()) {
863 if (TraceGCTaskManager) {
864 tty->print_cr("[" INTPTR_FORMAT "]"
865 " WaitForBarrierGCTask::wait_for()"
866 " [" INTPTR_FORMAT "] (%s)->wait()",
867 this, monitor(), monitor()->name());
868 }
869 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
870 }
871 // Reset the flag in case someone reuses this task.
872 set_should_wait(true);
873 if (TraceGCTaskManager) {
874 tty->print_cr("[" INTPTR_FORMAT "]"
875 " WaitForBarrierGCTask::wait_for() returns"
876 " should_wait: %s",
877 this, should_wait() ? "true" : "false");
878 }
879 // Release monitor().
880 }
881 }
883 Mutex* MonitorSupply::_lock = NULL;
884 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
886 Monitor* MonitorSupply::reserve() {
887 Monitor* result = NULL;
888 // Lazy initialization: possible race.
889 if (lock() == NULL) {
890 _lock = new Mutex(Mutex::barrier, // rank
891 "MonitorSupply mutex", // name
892 Mutex::_allow_vm_block_flag); // allow_vm_block
893 }
894 {
895 MutexLockerEx ml(lock());
896 // Lazy initialization.
897 if (freelist() == NULL) {
898 _freelist =
899 new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
900 true);
901 }
902 if (! freelist()->is_empty()) {
903 result = freelist()->pop();
904 } else {
905 result = new Monitor(Mutex::barrier, // rank
906 "MonitorSupply monitor", // name
907 Mutex::_allow_vm_block_flag); // allow_vm_block
908 }
909 guarantee(result != NULL, "shouldn't return NULL");
910 assert(!result->is_locked(), "shouldn't be locked");
911 // release lock().
912 }
913 return result;
914 }
916 void MonitorSupply::release(Monitor* instance) {
917 assert(instance != NULL, "shouldn't release NULL");
918 assert(!instance->is_locked(), "shouldn't be locked");
919 {
920 MutexLockerEx ml(lock());
921 freelist()->push(instance);
922 // release lock().
923 }
924 }