src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp

Fri, 16 Jul 2010 21:33:21 -0700

author
jcoomes
date
Fri, 16 Jul 2010 21:33:21 -0700
changeset 2020
a93a9eda13f7
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

6962947: shared TaskQueue statistics
Reviewed-by: tonyp, ysr

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

mercurial