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 */ 24 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" 32 33 // 34 // GCTask 35 // 36 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 }; 58 59 GCTask::GCTask() : 60 _kind(Kind::ordinary_task), 61 _affinity(GCTaskManager::sentinel_worker()){ 62 initialize(); 63 } 64 65 GCTask::GCTask(Kind::kind kind) : 66 _kind(kind), 67 _affinity(GCTaskManager::sentinel_worker()) { 68 initialize(); 69 } 70 71 GCTask::GCTask(uint affinity) : 72 _kind(Kind::ordinary_task), 73 _affinity(affinity) { 74 initialize(); 75 } 76 77 GCTask::GCTask(Kind::kind kind, uint affinity) : 78 _kind(kind), 79 _affinity(affinity) { 80 initialize(); 81 } 82 83 void GCTask::initialize() { 84 _older = NULL; 85 _newer = NULL; 86 } 87 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 } 93 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 ) 100 101 // 102 // GCTaskQueue 103 // 104 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 } 113 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 } 123 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 } 133 134 void GCTaskQueue::destruct() { 135 // Nothing to do. 136 } 137 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 } 156 157 void GCTaskQueue::initialize() { 158 set_insert_end(NULL); 159 set_remove_end(NULL); 160 set_length(0); 161 } 162 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 } 188 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 } 223 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 } 240 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 } 274 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 } 293 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 } 316 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 ) 332 333 // 334 // SynchronizedGCTaskQueue 335 // 336 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 } 344 345 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() { 346 // Nothing to do. 347 } 348 349 // 350 // GCTaskManager 351 // 352 GCTaskManager::GCTaskManager(uint workers) : 353 _workers(workers), 354 _ndc(NULL) { 355 initialize(); 356 } 357 358 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : 359 _workers(workers), 360 _ndc(ndc) { 361 initialize(); 362 } 363 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 } 415 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 } 444 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 } 451 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 } 459 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 } 467 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 } 473 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 } 479 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 } 496 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 } 512 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 } 566 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 } 616 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 } 622 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 } 628 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 } 635 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 } 640 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 } 645 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 } 654 655 bool GCTaskManager::resource_flag(uint which) { 656 assert(which < workers(), "index out of bounds"); 657 return _resource_flag[which]; 658 } 659 660 void GCTaskManager::set_resource_flag(uint which, bool value) { 661 assert(which < workers(), "index out of bounds"); 662 _resource_flag[which] = value; 663 } 664 665 // 666 // NoopGCTask 667 // 668 669 NoopGCTask* NoopGCTask::create() { 670 NoopGCTask* result = new NoopGCTask(false); 671 return result; 672 } 673 674 NoopGCTask* NoopGCTask::create_on_c_heap() { 675 NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true); 676 return result; 677 } 678 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 } 687 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 } 693 694 // 695 // BarrierGCTask 696 // 697 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 } 708 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 } 721 722 void BarrierGCTask::destruct() { 723 this->GCTask::destruct(); 724 // Nothing else to do. 725 } 726 727 // 728 // ReleasingBarrierGCTask 729 // 730 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 } 737 738 void ReleasingBarrierGCTask::destruct() { 739 this->BarrierGCTask::destruct(); 740 // Nothing else to do. 741 } 742 743 // 744 // NotifyingBarrierGCTask 745 // 746 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 } 756 757 void NotifyingBarrierGCTask::destruct() { 758 this->BarrierGCTask::destruct(); 759 // Nothing else to do. 760 } 761 762 // 763 // WaitForBarrierGCTask 764 // 765 WaitForBarrierGCTask* WaitForBarrierGCTask::create() { 766 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); 767 return result; 768 } 769 770 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { 771 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true); 772 return result; 773 } 774 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 } 786 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 } 804 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 } 821 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 } 851 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 } 882 883 Mutex* MonitorSupply::_lock = NULL; 884 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL; 885 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 } 915 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 }