Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 4095:bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
Summary: Select number of GC threads dynamically based on heap usage and number of Java threads
Reviewed-by: johnc, ysr, jcoomes
author | jmasa |
---|---|
date | Tue, 09 Aug 2011 10:16:01 -0700 |
parents | f95d63e2154a |
children | 6d7d0790074d |
comparison
equal
deleted
inserted
replaced
4094:3a298e04d914 | 4095:bca17e38de00 |
---|---|
23 */ | 23 */ |
24 | 24 |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" | 26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" |
27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp" | 27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp" |
28 #include "gc_implementation/shared/adaptiveSizePolicy.hpp" | |
28 #include "memory/allocation.hpp" | 29 #include "memory/allocation.hpp" |
29 #include "memory/allocation.inline.hpp" | 30 #include "memory/allocation.inline.hpp" |
30 #include "runtime/mutex.hpp" | 31 #include "runtime/mutex.hpp" |
31 #include "runtime/mutexLocker.hpp" | 32 #include "runtime/mutexLocker.hpp" |
32 | 33 |
179 } else { | 180 } else { |
180 insert_end()->set_newer(task); | 181 insert_end()->set_newer(task); |
181 } | 182 } |
182 set_insert_end(task); | 183 set_insert_end(task); |
183 increment_length(); | 184 increment_length(); |
185 verify_length(); | |
184 if (TraceGCTaskQueue) { | 186 if (TraceGCTaskQueue) { |
185 print("after:"); | 187 print("after:"); |
186 } | 188 } |
187 } | 189 } |
188 | 190 |
190 void GCTaskQueue::enqueue(GCTaskQueue* list) { | 192 void GCTaskQueue::enqueue(GCTaskQueue* list) { |
191 if (TraceGCTaskQueue) { | 193 if (TraceGCTaskQueue) { |
192 tty->print_cr("[" INTPTR_FORMAT "]" | 194 tty->print_cr("[" INTPTR_FORMAT "]" |
193 " GCTaskQueue::enqueue(list: " | 195 " GCTaskQueue::enqueue(list: " |
194 INTPTR_FORMAT ")", | 196 INTPTR_FORMAT ")", |
195 this); | 197 this, list); |
196 print("before:"); | 198 print("before:"); |
197 list->print("list:"); | 199 list->print("list:"); |
198 } | 200 } |
199 if (list->is_empty()) { | 201 if (list->is_empty()) { |
200 // Enqueuing the empty list: nothing to do. | 202 // Enqueuing the empty list: nothing to do. |
209 } else { | 211 } else { |
210 // Prepend argument list to our queue. | 212 // Prepend argument list to our queue. |
211 list->remove_end()->set_older(insert_end()); | 213 list->remove_end()->set_older(insert_end()); |
212 insert_end()->set_newer(list->remove_end()); | 214 insert_end()->set_newer(list->remove_end()); |
213 set_insert_end(list->insert_end()); | 215 set_insert_end(list->insert_end()); |
216 set_length(length() + list_length); | |
214 // empty the argument list. | 217 // empty the argument list. |
215 } | 218 } |
216 set_length(length() + list_length); | |
217 list->initialize(); | 219 list->initialize(); |
218 if (TraceGCTaskQueue) { | 220 if (TraceGCTaskQueue) { |
219 print("after:"); | 221 print("after:"); |
220 list->print("list:"); | 222 list->print("list:"); |
221 } | 223 } |
224 verify_length(); | |
222 } | 225 } |
223 | 226 |
224 // Dequeue one task. | 227 // Dequeue one task. |
225 GCTask* GCTaskQueue::dequeue() { | 228 GCTask* GCTaskQueue::dequeue() { |
226 if (TraceGCTaskQueue) { | 229 if (TraceGCTaskQueue) { |
286 } | 289 } |
287 result->set_newer(NULL); | 290 result->set_newer(NULL); |
288 decrement_length(); | 291 decrement_length(); |
289 assert(result->newer() == NULL, "shouldn't be on queue"); | 292 assert(result->newer() == NULL, "shouldn't be on queue"); |
290 assert(result->older() == NULL, "shouldn't be on queue"); | 293 assert(result->older() == NULL, "shouldn't be on queue"); |
294 verify_length(); | |
291 return result; | 295 return result; |
292 } | 296 } |
293 | 297 |
294 GCTask* GCTaskQueue::remove(GCTask* task) { | 298 GCTask* GCTaskQueue::remove(GCTask* task) { |
295 // This is slightly more work, and has slightly fewer asserts | 299 // This is slightly more work, and has slightly fewer asserts |
309 set_remove_end(result->newer()); | 313 set_remove_end(result->newer()); |
310 } | 314 } |
311 result->set_newer(NULL); | 315 result->set_newer(NULL); |
312 result->set_older(NULL); | 316 result->set_older(NULL); |
313 decrement_length(); | 317 decrement_length(); |
318 verify_length(); | |
314 return result; | 319 return result; |
315 } | 320 } |
316 | 321 |
317 NOT_PRODUCT( | 322 NOT_PRODUCT( |
323 // Count the elements in the queue and verify the length against | |
324 // that count. | |
325 void GCTaskQueue::verify_length() const { | |
326 uint count = 0; | |
327 for (GCTask* element = insert_end(); | |
328 element != NULL; | |
329 element = element->older()) { | |
330 | |
331 count++; | |
332 } | |
333 assert(count == length(), "Length does not match queue"); | |
334 } | |
335 | |
318 void GCTaskQueue::print(const char* message) const { | 336 void GCTaskQueue::print(const char* message) const { |
319 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:" | 337 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:" |
320 " insert_end: " INTPTR_FORMAT | 338 " insert_end: " INTPTR_FORMAT |
321 " remove_end: " INTPTR_FORMAT | 339 " remove_end: " INTPTR_FORMAT |
340 " length: %d" | |
322 " %s", | 341 " %s", |
323 this, insert_end(), remove_end(), message); | 342 this, insert_end(), remove_end(), length(), message); |
343 uint count = 0; | |
324 for (GCTask* element = insert_end(); | 344 for (GCTask* element = insert_end(); |
325 element != NULL; | 345 element != NULL; |
326 element = element->older()) { | 346 element = element->older()) { |
327 element->print(" "); | 347 element->print(" "); |
348 count++; | |
328 tty->cr(); | 349 tty->cr(); |
329 } | 350 } |
351 tty->print("Total tasks: %d", count); | |
330 } | 352 } |
331 ) | 353 ) |
332 | 354 |
333 // | 355 // |
334 // SynchronizedGCTaskQueue | 356 // SynchronizedGCTaskQueue |
349 // | 371 // |
350 // GCTaskManager | 372 // GCTaskManager |
351 // | 373 // |
352 GCTaskManager::GCTaskManager(uint workers) : | 374 GCTaskManager::GCTaskManager(uint workers) : |
353 _workers(workers), | 375 _workers(workers), |
376 _active_workers(0), | |
377 _idle_workers(0), | |
354 _ndc(NULL) { | 378 _ndc(NULL) { |
355 initialize(); | 379 initialize(); |
356 } | 380 } |
357 | 381 |
358 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : | 382 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : |
359 _workers(workers), | 383 _workers(workers), |
384 _active_workers(0), | |
385 _idle_workers(0), | |
360 _ndc(ndc) { | 386 _ndc(ndc) { |
361 initialize(); | 387 initialize(); |
362 } | 388 } |
363 | 389 |
364 void GCTaskManager::initialize() { | 390 void GCTaskManager::initialize() { |
371 Mutex::_allow_vm_block_flag); // allow_vm_block | 397 Mutex::_allow_vm_block_flag); // allow_vm_block |
372 // The queue for the GCTaskManager must be a CHeapObj. | 398 // The queue for the GCTaskManager must be a CHeapObj. |
373 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); | 399 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); |
374 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); | 400 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); |
375 _noop_task = NoopGCTask::create_on_c_heap(); | 401 _noop_task = NoopGCTask::create_on_c_heap(); |
402 _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap(); | |
376 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers()); | 403 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers()); |
377 { | 404 { |
378 // Set up worker threads. | 405 // Set up worker threads. |
379 // Distribute the workers among the available processors, | 406 // Distribute the workers among the available processors, |
380 // unless we were told not to, or if the os doesn't want to. | 407 // unless we were told not to, or if the os doesn't want to. |
416 GCTaskManager::~GCTaskManager() { | 443 GCTaskManager::~GCTaskManager() { |
417 assert(busy_workers() == 0, "still have busy workers"); | 444 assert(busy_workers() == 0, "still have busy workers"); |
418 assert(queue()->is_empty(), "still have queued work"); | 445 assert(queue()->is_empty(), "still have queued work"); |
419 NoopGCTask::destroy(_noop_task); | 446 NoopGCTask::destroy(_noop_task); |
420 _noop_task = NULL; | 447 _noop_task = NULL; |
448 WaitForBarrierGCTask::destroy(_idle_inactive_task); | |
449 _idle_inactive_task = NULL; | |
421 if (_thread != NULL) { | 450 if (_thread != NULL) { |
422 for (uint i = 0; i < workers(); i += 1) { | 451 for (uint i = 0; i < workers(); i += 1) { |
423 GCTaskThread::destroy(thread(i)); | 452 GCTaskThread::destroy(thread(i)); |
424 set_thread(i, NULL); | 453 set_thread(i, NULL); |
425 } | 454 } |
440 delete monitor(); | 469 delete monitor(); |
441 _monitor = NULL; | 470 _monitor = NULL; |
442 } | 471 } |
443 } | 472 } |
444 | 473 |
474 void GCTaskManager::set_active_gang() { | |
475 _active_workers = | |
476 AdaptiveSizePolicy::calc_active_workers(workers(), | |
477 active_workers(), | |
478 Threads::number_of_non_daemon_threads()); | |
479 | |
480 assert(!all_workers_active() || active_workers() == ParallelGCThreads, | |
481 err_msg("all_workers_active() is incorrect: " | |
482 "active %d ParallelGCThreads %d", active_workers(), | |
483 ParallelGCThreads)); | |
484 if (TraceDynamicGCThreads) { | |
485 gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): " | |
486 "all_workers_active() %d workers %d " | |
487 "active %d ParallelGCThreads %d ", | |
488 all_workers_active(), workers(), active_workers(), | |
489 ParallelGCThreads); | |
490 } | |
491 } | |
492 | |
493 // Create IdleGCTasks for inactive workers. | |
494 // Creates tasks in a ResourceArea and assumes | |
495 // an appropriate ResourceMark. | |
496 void GCTaskManager::task_idle_workers() { | |
497 { | |
498 int more_inactive_workers = 0; | |
499 { | |
500 // Stop any idle tasks from exiting their IdleGCTask's | |
501 // and get the count for additional IdleGCTask's under | |
502 // the GCTaskManager's monitor so that the "more_inactive_workers" | |
503 // count is correct. | |
504 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
505 _idle_inactive_task->set_should_wait(true); | |
506 // active_workers are a number being requested. idle_workers | |
507 // are the number currently idle. If all the workers are being | |
508 // requested to be active but some are already idle, reduce | |
509 // the number of active_workers to be consistent with the | |
510 // number of idle_workers. The idle_workers are stuck in | |
511 // idle tasks and will no longer be release (since a new GC | |
512 // is starting). Try later to release enough idle_workers | |
513 // to allow the desired number of active_workers. | |
514 more_inactive_workers = | |
515 workers() - active_workers() - idle_workers(); | |
516 if (more_inactive_workers < 0) { | |
517 int reduced_active_workers = active_workers() + more_inactive_workers; | |
518 set_active_workers(reduced_active_workers); | |
519 more_inactive_workers = 0; | |
520 } | |
521 if (TraceDynamicGCThreads) { | |
522 gclog_or_tty->print_cr("JT: %d workers %d active %d " | |
523 "idle %d more %d", | |
524 Threads::number_of_non_daemon_threads(), | |
525 workers(), | |
526 active_workers(), | |
527 idle_workers(), | |
528 more_inactive_workers); | |
529 } | |
530 } | |
531 GCTaskQueue* q = GCTaskQueue::create(); | |
532 for(uint i = 0; i < (uint) more_inactive_workers; i++) { | |
533 q->enqueue(IdleGCTask::create_on_c_heap()); | |
534 increment_idle_workers(); | |
535 } | |
536 assert(workers() == active_workers() + idle_workers(), | |
537 "total workers should equal active + inactive"); | |
538 add_list(q); | |
539 // GCTaskQueue* q was created in a ResourceArea so a | |
540 // destroy() call is not needed. | |
541 } | |
542 } | |
543 | |
544 void GCTaskManager::release_idle_workers() { | |
545 { | |
546 MutexLockerEx ml(monitor(), | |
547 Mutex::_no_safepoint_check_flag); | |
548 _idle_inactive_task->set_should_wait(false); | |
549 monitor()->notify_all(); | |
550 // Release monitor | |
551 } | |
552 } | |
553 | |
445 void GCTaskManager::print_task_time_stamps() { | 554 void GCTaskManager::print_task_time_stamps() { |
446 for(uint i=0; i<ParallelGCThreads; i++) { | 555 for(uint i=0; i<ParallelGCThreads; i++) { |
447 GCTaskThread* t = thread(i); | 556 GCTaskThread* t = thread(i); |
448 t->print_task_time_stamps(); | 557 t->print_task_time_stamps(); |
449 } | 558 } |
507 monitor()->name()); | 616 monitor()->name()); |
508 } | 617 } |
509 (void) monitor()->notify_all(); | 618 (void) monitor()->notify_all(); |
510 // Release monitor(). | 619 // Release monitor(). |
511 } | 620 } |
621 | |
622 // GC workers wait in get_task() for new work to be added | |
623 // to the GCTaskManager's queue. When new work is added, | |
624 // a notify is sent to the waiting GC workers which then | |
625 // compete to get tasks. If a GC worker wakes up and there | |
626 // is no work on the queue, it is given a noop_task to execute | |
627 // and then loops to find more work. | |
512 | 628 |
513 GCTask* GCTaskManager::get_task(uint which) { | 629 GCTask* GCTaskManager::get_task(uint which) { |
514 GCTask* result = NULL; | 630 GCTask* result = NULL; |
515 // Grab the queue lock. | 631 // Grab the queue lock. |
516 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | 632 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); |
556 if (TraceGCTaskManager) { | 672 if (TraceGCTaskManager) { |
557 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]", | 673 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]", |
558 which, result, GCTask::Kind::to_string(result->kind())); | 674 which, result, GCTask::Kind::to_string(result->kind())); |
559 tty->print_cr(" %s", result->name()); | 675 tty->print_cr(" %s", result->name()); |
560 } | 676 } |
561 increment_busy_workers(); | 677 if (!result->is_idle_task()) { |
562 increment_delivered_tasks(); | 678 increment_busy_workers(); |
679 increment_delivered_tasks(); | |
680 } | |
563 return result; | 681 return result; |
564 // Release monitor(). | 682 // Release monitor(). |
565 } | 683 } |
566 | 684 |
567 void GCTaskManager::note_completion(uint which) { | 685 void GCTaskManager::note_completion(uint which) { |
620 return _busy_workers; | 738 return _busy_workers; |
621 } | 739 } |
622 | 740 |
623 uint GCTaskManager::decrement_busy_workers() { | 741 uint GCTaskManager::decrement_busy_workers() { |
624 assert(queue()->own_lock(), "don't own the lock"); | 742 assert(queue()->own_lock(), "don't own the lock"); |
743 assert(_busy_workers > 0, "About to make a mistake"); | |
625 _busy_workers -= 1; | 744 _busy_workers -= 1; |
626 return _busy_workers; | 745 return _busy_workers; |
627 } | 746 } |
628 | 747 |
629 void GCTaskManager::release_all_resources() { | 748 void GCTaskManager::release_all_resources() { |
641 void GCTaskManager::note_release(uint which) { | 760 void GCTaskManager::note_release(uint which) { |
642 // This can be done without a lock because each thread writes one element. | 761 // This can be done without a lock because each thread writes one element. |
643 set_resource_flag(which, false); | 762 set_resource_flag(which, false); |
644 } | 763 } |
645 | 764 |
765 // "list" contains tasks that are ready to execute. Those | |
766 // tasks are added to the GCTaskManager's queue of tasks and | |
767 // then the GC workers are notified that there is new work to | |
768 // do. | |
769 // | |
770 // Typically different types of tasks can be added to the "list". | |
771 // For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask, | |
772 // ScavengeRootsTask, and StealTask tasks are all added to the list | |
773 // and then the GC workers are notified of new work. The tasks are | |
774 // handed out in the order in which they are added to the list | |
775 // (although execution is not necessarily in that order). As long | |
776 // as any tasks are running the GCTaskManager will wait for execution | |
777 // to complete. GC workers that execute a stealing task remain in | |
778 // the stealing task until all stealing tasks have completed. The load | |
779 // balancing afforded by the stealing tasks work best if the stealing | |
780 // tasks are added last to the list. | |
781 | |
646 void GCTaskManager::execute_and_wait(GCTaskQueue* list) { | 782 void GCTaskManager::execute_and_wait(GCTaskQueue* list) { |
647 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create(); | 783 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create(); |
648 list->enqueue(fin); | 784 list->enqueue(fin); |
649 add_list(list); | 785 add_list(list); |
650 fin->wait_for(); | 786 fin->wait_for(true /* reset */); |
651 // We have to release the barrier tasks! | 787 // We have to release the barrier tasks! |
652 WaitForBarrierGCTask::destroy(fin); | 788 WaitForBarrierGCTask::destroy(fin); |
653 } | 789 } |
654 | 790 |
655 bool GCTaskManager::resource_flag(uint which) { | 791 bool GCTaskManager::resource_flag(uint which) { |
684 } | 820 } |
685 } | 821 } |
686 } | 822 } |
687 | 823 |
688 void NoopGCTask::destruct() { | 824 void NoopGCTask::destruct() { |
825 // This has to know it's superclass structure, just like the constructor. | |
826 this->GCTask::destruct(); | |
827 // Nothing else to do. | |
828 } | |
829 | |
830 // | |
831 // IdleGCTask | |
832 // | |
833 | |
834 IdleGCTask* IdleGCTask::create() { | |
835 IdleGCTask* result = new IdleGCTask(false); | |
836 return result; | |
837 } | |
838 | |
839 IdleGCTask* IdleGCTask::create_on_c_heap() { | |
840 IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true); | |
841 return result; | |
842 } | |
843 | |
844 void IdleGCTask::do_it(GCTaskManager* manager, uint which) { | |
845 WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task(); | |
846 if (TraceGCTaskManager) { | |
847 tty->print_cr("[" INTPTR_FORMAT "]" | |
848 " IdleGCTask:::do_it()" | |
849 " should_wait: %s", | |
850 this, wait_for_task->should_wait() ? "true" : "false"); | |
851 } | |
852 MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag); | |
853 if (TraceDynamicGCThreads) { | |
854 gclog_or_tty->print_cr("--- idle %d", which); | |
855 } | |
856 // Increment has to be done when the idle tasks are created. | |
857 // manager->increment_idle_workers(); | |
858 manager->monitor()->notify_all(); | |
859 while (wait_for_task->should_wait()) { | |
860 if (TraceGCTaskManager) { | |
861 tty->print_cr("[" INTPTR_FORMAT "]" | |
862 " IdleGCTask::do_it()" | |
863 " [" INTPTR_FORMAT "] (%s)->wait()", | |
864 this, manager->monitor(), manager->monitor()->name()); | |
865 } | |
866 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0); | |
867 } | |
868 manager->decrement_idle_workers(); | |
869 if (TraceDynamicGCThreads) { | |
870 gclog_or_tty->print_cr("--- release %d", which); | |
871 } | |
872 if (TraceGCTaskManager) { | |
873 tty->print_cr("[" INTPTR_FORMAT "]" | |
874 " IdleGCTask::do_it() returns" | |
875 " should_wait: %s", | |
876 this, wait_for_task->should_wait() ? "true" : "false"); | |
877 } | |
878 // Release monitor(). | |
879 } | |
880 | |
881 void IdleGCTask::destroy(IdleGCTask* that) { | |
882 if (that != NULL) { | |
883 that->destruct(); | |
884 if (that->is_c_heap_obj()) { | |
885 FreeHeap(that); | |
886 } | |
887 } | |
888 } | |
889 | |
890 void IdleGCTask::destruct() { | |
689 // This has to know it's superclass structure, just like the constructor. | 891 // This has to know it's superclass structure, just like the constructor. |
690 this->GCTask::destruct(); | 892 this->GCTask::destruct(); |
691 // Nothing else to do. | 893 // Nothing else to do. |
692 } | 894 } |
693 | 895 |
766 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); | 968 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); |
767 return result; | 969 return result; |
768 } | 970 } |
769 | 971 |
770 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { | 972 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { |
771 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true); | 973 WaitForBarrierGCTask* result = |
974 new (ResourceObj::C_HEAP) WaitForBarrierGCTask(true); | |
772 return result; | 975 return result; |
773 } | 976 } |
774 | 977 |
775 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) : | 978 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) : |
776 _is_c_heap_obj(on_c_heap) { | 979 _is_c_heap_obj(on_c_heap) { |
847 monitor()->notify_all(); | 1050 monitor()->notify_all(); |
848 // Release monitor(). | 1051 // Release monitor(). |
849 } | 1052 } |
850 } | 1053 } |
851 | 1054 |
852 void WaitForBarrierGCTask::wait_for() { | 1055 void WaitForBarrierGCTask::wait_for(bool reset) { |
853 if (TraceGCTaskManager) { | 1056 if (TraceGCTaskManager) { |
854 tty->print_cr("[" INTPTR_FORMAT "]" | 1057 tty->print_cr("[" INTPTR_FORMAT "]" |
855 " WaitForBarrierGCTask::wait_for()" | 1058 " WaitForBarrierGCTask::wait_for()" |
856 " should_wait: %s", | 1059 " should_wait: %s", |
857 this, should_wait() ? "true" : "false"); | 1060 this, should_wait() ? "true" : "false"); |
867 this, monitor(), monitor()->name()); | 1070 this, monitor(), monitor()->name()); |
868 } | 1071 } |
869 monitor()->wait(Mutex::_no_safepoint_check_flag, 0); | 1072 monitor()->wait(Mutex::_no_safepoint_check_flag, 0); |
870 } | 1073 } |
871 // Reset the flag in case someone reuses this task. | 1074 // Reset the flag in case someone reuses this task. |
872 set_should_wait(true); | 1075 if (reset) { |
1076 set_should_wait(true); | |
1077 } | |
873 if (TraceGCTaskManager) { | 1078 if (TraceGCTaskManager) { |
874 tty->print_cr("[" INTPTR_FORMAT "]" | 1079 tty->print_cr("[" INTPTR_FORMAT "]" |
875 " WaitForBarrierGCTask::wait_for() returns" | 1080 " WaitForBarrierGCTask::wait_for() returns" |
876 " should_wait: %s", | 1081 " should_wait: %s", |
877 this, should_wait() ? "true" : "false"); | 1082 this, should_wait() ? "true" : "false"); |