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