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

Tue, 09 Aug 2011 10:16:01 -0700

author
jmasa
date
Tue, 09 Aug 2011 10:16:01 -0700
changeset 3294
bca17e38de00
parent 2314
f95d63e2154a
child 3328
6d7d0790074d
permissions
-rw-r--r--

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

duke@435 1 /*
stefank@2314 2 * Copyright (c) 2002, 2010, 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
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
stefank@2314 27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp"
jmasa@3294 28 #include "gc_implementation/shared/adaptiveSizePolicy.hpp"
stefank@2314 29 #include "memory/allocation.hpp"
stefank@2314 30 #include "memory/allocation.inline.hpp"
stefank@2314 31 #include "runtime/mutex.hpp"
stefank@2314 32 #include "runtime/mutexLocker.hpp"
duke@435 33
duke@435 34 //
duke@435 35 // GCTask
duke@435 36 //
duke@435 37
duke@435 38 const char* GCTask::Kind::to_string(kind value) {
duke@435 39 const char* result = "unknown GCTask kind";
duke@435 40 switch (value) {
duke@435 41 default:
duke@435 42 result = "unknown GCTask kind";
duke@435 43 break;
duke@435 44 case unknown_task:
duke@435 45 result = "unknown task";
duke@435 46 break;
duke@435 47 case ordinary_task:
duke@435 48 result = "ordinary task";
duke@435 49 break;
duke@435 50 case barrier_task:
duke@435 51 result = "barrier task";
duke@435 52 break;
duke@435 53 case noop_task:
duke@435 54 result = "noop task";
duke@435 55 break;
duke@435 56 }
duke@435 57 return result;
duke@435 58 };
duke@435 59
duke@435 60 GCTask::GCTask() :
duke@435 61 _kind(Kind::ordinary_task),
duke@435 62 _affinity(GCTaskManager::sentinel_worker()){
duke@435 63 initialize();
duke@435 64 }
duke@435 65
duke@435 66 GCTask::GCTask(Kind::kind kind) :
duke@435 67 _kind(kind),
duke@435 68 _affinity(GCTaskManager::sentinel_worker()) {
duke@435 69 initialize();
duke@435 70 }
duke@435 71
duke@435 72 GCTask::GCTask(uint affinity) :
duke@435 73 _kind(Kind::ordinary_task),
duke@435 74 _affinity(affinity) {
duke@435 75 initialize();
duke@435 76 }
duke@435 77
duke@435 78 GCTask::GCTask(Kind::kind kind, uint affinity) :
duke@435 79 _kind(kind),
duke@435 80 _affinity(affinity) {
duke@435 81 initialize();
duke@435 82 }
duke@435 83
duke@435 84 void GCTask::initialize() {
duke@435 85 _older = NULL;
duke@435 86 _newer = NULL;
duke@435 87 }
duke@435 88
duke@435 89 void GCTask::destruct() {
duke@435 90 assert(older() == NULL, "shouldn't have an older task");
duke@435 91 assert(newer() == NULL, "shouldn't have a newer task");
duke@435 92 // Nothing to do.
duke@435 93 }
duke@435 94
duke@435 95 NOT_PRODUCT(
duke@435 96 void GCTask::print(const char* message) const {
duke@435 97 tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
duke@435 98 newer(), this, affinity(), older());
duke@435 99 }
duke@435 100 )
duke@435 101
duke@435 102 //
duke@435 103 // GCTaskQueue
duke@435 104 //
duke@435 105
duke@435 106 GCTaskQueue* GCTaskQueue::create() {
duke@435 107 GCTaskQueue* result = new GCTaskQueue(false);
duke@435 108 if (TraceGCTaskQueue) {
duke@435 109 tty->print_cr("GCTaskQueue::create()"
duke@435 110 " returns " INTPTR_FORMAT, result);
duke@435 111 }
duke@435 112 return result;
duke@435 113 }
duke@435 114
duke@435 115 GCTaskQueue* GCTaskQueue::create_on_c_heap() {
duke@435 116 GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
duke@435 117 if (TraceGCTaskQueue) {
duke@435 118 tty->print_cr("GCTaskQueue::create_on_c_heap()"
duke@435 119 " returns " INTPTR_FORMAT,
duke@435 120 result);
duke@435 121 }
duke@435 122 return result;
duke@435 123 }
duke@435 124
duke@435 125 GCTaskQueue::GCTaskQueue(bool on_c_heap) :
duke@435 126 _is_c_heap_obj(on_c_heap) {
duke@435 127 initialize();
duke@435 128 if (TraceGCTaskQueue) {
duke@435 129 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 130 " GCTaskQueue::GCTaskQueue() constructor",
duke@435 131 this);
duke@435 132 }
duke@435 133 }
duke@435 134
duke@435 135 void GCTaskQueue::destruct() {
duke@435 136 // Nothing to do.
duke@435 137 }
duke@435 138
duke@435 139 void GCTaskQueue::destroy(GCTaskQueue* that) {
duke@435 140 if (TraceGCTaskQueue) {
duke@435 141 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 142 " GCTaskQueue::destroy()"
duke@435 143 " is_c_heap_obj: %s",
duke@435 144 that,
duke@435 145 that->is_c_heap_obj() ? "true" : "false");
duke@435 146 }
duke@435 147 // That instance may have been allocated as a CHeapObj,
duke@435 148 // in which case we have to free it explicitly.
duke@435 149 if (that != NULL) {
duke@435 150 that->destruct();
duke@435 151 assert(that->is_empty(), "should be empty");
duke@435 152 if (that->is_c_heap_obj()) {
duke@435 153 FreeHeap(that);
duke@435 154 }
duke@435 155 }
duke@435 156 }
duke@435 157
duke@435 158 void GCTaskQueue::initialize() {
duke@435 159 set_insert_end(NULL);
duke@435 160 set_remove_end(NULL);
duke@435 161 set_length(0);
duke@435 162 }
duke@435 163
duke@435 164 // Enqueue one task.
duke@435 165 void GCTaskQueue::enqueue(GCTask* task) {
duke@435 166 if (TraceGCTaskQueue) {
duke@435 167 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 168 " GCTaskQueue::enqueue(task: "
duke@435 169 INTPTR_FORMAT ")",
duke@435 170 this, task);
duke@435 171 print("before:");
duke@435 172 }
duke@435 173 assert(task != NULL, "shouldn't have null task");
duke@435 174 assert(task->older() == NULL, "shouldn't be on queue");
duke@435 175 assert(task->newer() == NULL, "shouldn't be on queue");
duke@435 176 task->set_newer(NULL);
duke@435 177 task->set_older(insert_end());
duke@435 178 if (is_empty()) {
duke@435 179 set_remove_end(task);
duke@435 180 } else {
duke@435 181 insert_end()->set_newer(task);
duke@435 182 }
duke@435 183 set_insert_end(task);
duke@435 184 increment_length();
jmasa@3294 185 verify_length();
duke@435 186 if (TraceGCTaskQueue) {
duke@435 187 print("after:");
duke@435 188 }
duke@435 189 }
duke@435 190
duke@435 191 // Enqueue a whole list of tasks. Empties the argument list.
duke@435 192 void GCTaskQueue::enqueue(GCTaskQueue* list) {
duke@435 193 if (TraceGCTaskQueue) {
duke@435 194 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 195 " GCTaskQueue::enqueue(list: "
duke@435 196 INTPTR_FORMAT ")",
jmasa@3294 197 this, list);
duke@435 198 print("before:");
duke@435 199 list->print("list:");
duke@435 200 }
duke@435 201 if (list->is_empty()) {
duke@435 202 // Enqueuing the empty list: nothing to do.
duke@435 203 return;
duke@435 204 }
duke@435 205 uint list_length = list->length();
duke@435 206 if (is_empty()) {
duke@435 207 // Enqueuing to empty list: just acquire elements.
duke@435 208 set_insert_end(list->insert_end());
duke@435 209 set_remove_end(list->remove_end());
duke@435 210 set_length(list_length);
duke@435 211 } else {
duke@435 212 // Prepend argument list to our queue.
duke@435 213 list->remove_end()->set_older(insert_end());
duke@435 214 insert_end()->set_newer(list->remove_end());
duke@435 215 set_insert_end(list->insert_end());
jmasa@3294 216 set_length(length() + list_length);
duke@435 217 // empty the argument list.
duke@435 218 }
duke@435 219 list->initialize();
duke@435 220 if (TraceGCTaskQueue) {
duke@435 221 print("after:");
duke@435 222 list->print("list:");
duke@435 223 }
jmasa@3294 224 verify_length();
duke@435 225 }
duke@435 226
duke@435 227 // Dequeue one task.
duke@435 228 GCTask* GCTaskQueue::dequeue() {
duke@435 229 if (TraceGCTaskQueue) {
duke@435 230 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 231 " GCTaskQueue::dequeue()", this);
duke@435 232 print("before:");
duke@435 233 }
duke@435 234 assert(!is_empty(), "shouldn't dequeue from empty list");
duke@435 235 GCTask* result = remove();
duke@435 236 assert(result != NULL, "shouldn't have NULL task");
duke@435 237 if (TraceGCTaskQueue) {
duke@435 238 tty->print_cr(" return: " INTPTR_FORMAT, result);
duke@435 239 print("after:");
duke@435 240 }
duke@435 241 return result;
duke@435 242 }
duke@435 243
duke@435 244 // Dequeue one task, preferring one with affinity.
duke@435 245 GCTask* GCTaskQueue::dequeue(uint affinity) {
duke@435 246 if (TraceGCTaskQueue) {
duke@435 247 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 248 " GCTaskQueue::dequeue(%u)", this, affinity);
duke@435 249 print("before:");
duke@435 250 }
duke@435 251 assert(!is_empty(), "shouldn't dequeue from empty list");
duke@435 252 // Look down to the next barrier for a task with this affinity.
duke@435 253 GCTask* result = NULL;
duke@435 254 for (GCTask* element = remove_end();
duke@435 255 element != NULL;
duke@435 256 element = element->newer()) {
duke@435 257 if (element->is_barrier_task()) {
duke@435 258 // Don't consider barrier tasks, nor past them.
duke@435 259 result = NULL;
duke@435 260 break;
duke@435 261 }
duke@435 262 if (element->affinity() == affinity) {
duke@435 263 result = remove(element);
duke@435 264 break;
duke@435 265 }
duke@435 266 }
duke@435 267 // If we didn't find anything with affinity, just take the next task.
duke@435 268 if (result == NULL) {
duke@435 269 result = remove();
duke@435 270 }
duke@435 271 if (TraceGCTaskQueue) {
duke@435 272 tty->print_cr(" return: " INTPTR_FORMAT, result);
duke@435 273 print("after:");
duke@435 274 }
duke@435 275 return result;
duke@435 276 }
duke@435 277
duke@435 278 GCTask* GCTaskQueue::remove() {
duke@435 279 // Dequeue from remove end.
duke@435 280 GCTask* result = remove_end();
duke@435 281 assert(result != NULL, "shouldn't have null task");
duke@435 282 assert(result->older() == NULL, "not the remove_end");
duke@435 283 set_remove_end(result->newer());
duke@435 284 if (remove_end() == NULL) {
duke@435 285 assert(insert_end() == result, "not a singleton");
duke@435 286 set_insert_end(NULL);
duke@435 287 } else {
duke@435 288 remove_end()->set_older(NULL);
duke@435 289 }
duke@435 290 result->set_newer(NULL);
duke@435 291 decrement_length();
duke@435 292 assert(result->newer() == NULL, "shouldn't be on queue");
duke@435 293 assert(result->older() == NULL, "shouldn't be on queue");
jmasa@3294 294 verify_length();
duke@435 295 return result;
duke@435 296 }
duke@435 297
duke@435 298 GCTask* GCTaskQueue::remove(GCTask* task) {
duke@435 299 // This is slightly more work, and has slightly fewer asserts
duke@435 300 // than removing from the remove end.
duke@435 301 assert(task != NULL, "shouldn't have null task");
duke@435 302 GCTask* result = task;
duke@435 303 if (result->newer() != NULL) {
duke@435 304 result->newer()->set_older(result->older());
duke@435 305 } else {
duke@435 306 assert(insert_end() == result, "not youngest");
duke@435 307 set_insert_end(result->older());
duke@435 308 }
duke@435 309 if (result->older() != NULL) {
duke@435 310 result->older()->set_newer(result->newer());
duke@435 311 } else {
duke@435 312 assert(remove_end() == result, "not oldest");
duke@435 313 set_remove_end(result->newer());
duke@435 314 }
duke@435 315 result->set_newer(NULL);
duke@435 316 result->set_older(NULL);
duke@435 317 decrement_length();
jmasa@3294 318 verify_length();
duke@435 319 return result;
duke@435 320 }
duke@435 321
duke@435 322 NOT_PRODUCT(
jmasa@3294 323 // Count the elements in the queue and verify the length against
jmasa@3294 324 // that count.
jmasa@3294 325 void GCTaskQueue::verify_length() const {
jmasa@3294 326 uint count = 0;
jmasa@3294 327 for (GCTask* element = insert_end();
jmasa@3294 328 element != NULL;
jmasa@3294 329 element = element->older()) {
jmasa@3294 330
jmasa@3294 331 count++;
jmasa@3294 332 }
jmasa@3294 333 assert(count == length(), "Length does not match queue");
jmasa@3294 334 }
jmasa@3294 335
duke@435 336 void GCTaskQueue::print(const char* message) const {
duke@435 337 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
duke@435 338 " insert_end: " INTPTR_FORMAT
duke@435 339 " remove_end: " INTPTR_FORMAT
jmasa@3294 340 " length: %d"
duke@435 341 " %s",
jmasa@3294 342 this, insert_end(), remove_end(), length(), message);
jmasa@3294 343 uint count = 0;
duke@435 344 for (GCTask* element = insert_end();
duke@435 345 element != NULL;
duke@435 346 element = element->older()) {
duke@435 347 element->print(" ");
jmasa@3294 348 count++;
duke@435 349 tty->cr();
duke@435 350 }
jmasa@3294 351 tty->print("Total tasks: %d", count);
duke@435 352 }
duke@435 353 )
duke@435 354
duke@435 355 //
duke@435 356 // SynchronizedGCTaskQueue
duke@435 357 //
duke@435 358
duke@435 359 SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
duke@435 360 Monitor * lock_arg) :
duke@435 361 _unsynchronized_queue(queue_arg),
duke@435 362 _lock(lock_arg) {
duke@435 363 assert(unsynchronized_queue() != NULL, "null queue");
duke@435 364 assert(lock() != NULL, "null lock");
duke@435 365 }
duke@435 366
duke@435 367 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
duke@435 368 // Nothing to do.
duke@435 369 }
duke@435 370
duke@435 371 //
duke@435 372 // GCTaskManager
duke@435 373 //
duke@435 374 GCTaskManager::GCTaskManager(uint workers) :
duke@435 375 _workers(workers),
jmasa@3294 376 _active_workers(0),
jmasa@3294 377 _idle_workers(0),
duke@435 378 _ndc(NULL) {
duke@435 379 initialize();
duke@435 380 }
duke@435 381
duke@435 382 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
duke@435 383 _workers(workers),
jmasa@3294 384 _active_workers(0),
jmasa@3294 385 _idle_workers(0),
duke@435 386 _ndc(ndc) {
duke@435 387 initialize();
duke@435 388 }
duke@435 389
duke@435 390 void GCTaskManager::initialize() {
duke@435 391 if (TraceGCTaskManager) {
duke@435 392 tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
duke@435 393 }
duke@435 394 assert(workers() != 0, "no workers");
duke@435 395 _monitor = new Monitor(Mutex::barrier, // rank
duke@435 396 "GCTaskManager monitor", // name
duke@435 397 Mutex::_allow_vm_block_flag); // allow_vm_block
duke@435 398 // The queue for the GCTaskManager must be a CHeapObj.
duke@435 399 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
duke@435 400 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
duke@435 401 _noop_task = NoopGCTask::create_on_c_heap();
jmasa@3294 402 _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap();
duke@435 403 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
duke@435 404 {
duke@435 405 // Set up worker threads.
duke@435 406 // Distribute the workers among the available processors,
duke@435 407 // unless we were told not to, or if the os doesn't want to.
duke@435 408 uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
duke@435 409 if (!BindGCTaskThreadsToCPUs ||
duke@435 410 !os::distribute_processes(workers(), processor_assignment)) {
duke@435 411 for (uint a = 0; a < workers(); a += 1) {
duke@435 412 processor_assignment[a] = sentinel_worker();
duke@435 413 }
duke@435 414 }
duke@435 415 _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
duke@435 416 for (uint t = 0; t < workers(); t += 1) {
duke@435 417 set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
duke@435 418 }
duke@435 419 if (TraceGCTaskThread) {
duke@435 420 tty->print("GCTaskManager::initialize: distribution:");
duke@435 421 for (uint t = 0; t < workers(); t += 1) {
duke@435 422 tty->print(" %u", processor_assignment[t]);
duke@435 423 }
duke@435 424 tty->cr();
duke@435 425 }
duke@435 426 FREE_C_HEAP_ARRAY(uint, processor_assignment);
duke@435 427 }
duke@435 428 reset_busy_workers();
duke@435 429 set_unblocked();
duke@435 430 for (uint w = 0; w < workers(); w += 1) {
duke@435 431 set_resource_flag(w, false);
duke@435 432 }
duke@435 433 reset_delivered_tasks();
duke@435 434 reset_completed_tasks();
duke@435 435 reset_noop_tasks();
duke@435 436 reset_barriers();
duke@435 437 reset_emptied_queue();
duke@435 438 for (uint s = 0; s < workers(); s += 1) {
duke@435 439 thread(s)->start();
duke@435 440 }
duke@435 441 }
duke@435 442
duke@435 443 GCTaskManager::~GCTaskManager() {
duke@435 444 assert(busy_workers() == 0, "still have busy workers");
duke@435 445 assert(queue()->is_empty(), "still have queued work");
duke@435 446 NoopGCTask::destroy(_noop_task);
duke@435 447 _noop_task = NULL;
jmasa@3294 448 WaitForBarrierGCTask::destroy(_idle_inactive_task);
jmasa@3294 449 _idle_inactive_task = NULL;
duke@435 450 if (_thread != NULL) {
duke@435 451 for (uint i = 0; i < workers(); i += 1) {
duke@435 452 GCTaskThread::destroy(thread(i));
duke@435 453 set_thread(i, NULL);
duke@435 454 }
duke@435 455 FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
duke@435 456 _thread = NULL;
duke@435 457 }
duke@435 458 if (_resource_flag != NULL) {
duke@435 459 FREE_C_HEAP_ARRAY(bool, _resource_flag);
duke@435 460 _resource_flag = NULL;
duke@435 461 }
duke@435 462 if (queue() != NULL) {
duke@435 463 GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
duke@435 464 GCTaskQueue::destroy(unsynchronized_queue);
duke@435 465 SynchronizedGCTaskQueue::destroy(queue());
duke@435 466 _queue = NULL;
duke@435 467 }
duke@435 468 if (monitor() != NULL) {
duke@435 469 delete monitor();
duke@435 470 _monitor = NULL;
duke@435 471 }
duke@435 472 }
duke@435 473
jmasa@3294 474 void GCTaskManager::set_active_gang() {
jmasa@3294 475 _active_workers =
jmasa@3294 476 AdaptiveSizePolicy::calc_active_workers(workers(),
jmasa@3294 477 active_workers(),
jmasa@3294 478 Threads::number_of_non_daemon_threads());
jmasa@3294 479
jmasa@3294 480 assert(!all_workers_active() || active_workers() == ParallelGCThreads,
jmasa@3294 481 err_msg("all_workers_active() is incorrect: "
jmasa@3294 482 "active %d ParallelGCThreads %d", active_workers(),
jmasa@3294 483 ParallelGCThreads));
jmasa@3294 484 if (TraceDynamicGCThreads) {
jmasa@3294 485 gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): "
jmasa@3294 486 "all_workers_active() %d workers %d "
jmasa@3294 487 "active %d ParallelGCThreads %d ",
jmasa@3294 488 all_workers_active(), workers(), active_workers(),
jmasa@3294 489 ParallelGCThreads);
jmasa@3294 490 }
jmasa@3294 491 }
jmasa@3294 492
jmasa@3294 493 // Create IdleGCTasks for inactive workers.
jmasa@3294 494 // Creates tasks in a ResourceArea and assumes
jmasa@3294 495 // an appropriate ResourceMark.
jmasa@3294 496 void GCTaskManager::task_idle_workers() {
jmasa@3294 497 {
jmasa@3294 498 int more_inactive_workers = 0;
jmasa@3294 499 {
jmasa@3294 500 // Stop any idle tasks from exiting their IdleGCTask's
jmasa@3294 501 // and get the count for additional IdleGCTask's under
jmasa@3294 502 // the GCTaskManager's monitor so that the "more_inactive_workers"
jmasa@3294 503 // count is correct.
jmasa@3294 504 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
jmasa@3294 505 _idle_inactive_task->set_should_wait(true);
jmasa@3294 506 // active_workers are a number being requested. idle_workers
jmasa@3294 507 // are the number currently idle. If all the workers are being
jmasa@3294 508 // requested to be active but some are already idle, reduce
jmasa@3294 509 // the number of active_workers to be consistent with the
jmasa@3294 510 // number of idle_workers. The idle_workers are stuck in
jmasa@3294 511 // idle tasks and will no longer be release (since a new GC
jmasa@3294 512 // is starting). Try later to release enough idle_workers
jmasa@3294 513 // to allow the desired number of active_workers.
jmasa@3294 514 more_inactive_workers =
jmasa@3294 515 workers() - active_workers() - idle_workers();
jmasa@3294 516 if (more_inactive_workers < 0) {
jmasa@3294 517 int reduced_active_workers = active_workers() + more_inactive_workers;
jmasa@3294 518 set_active_workers(reduced_active_workers);
jmasa@3294 519 more_inactive_workers = 0;
jmasa@3294 520 }
jmasa@3294 521 if (TraceDynamicGCThreads) {
jmasa@3294 522 gclog_or_tty->print_cr("JT: %d workers %d active %d "
jmasa@3294 523 "idle %d more %d",
jmasa@3294 524 Threads::number_of_non_daemon_threads(),
jmasa@3294 525 workers(),
jmasa@3294 526 active_workers(),
jmasa@3294 527 idle_workers(),
jmasa@3294 528 more_inactive_workers);
jmasa@3294 529 }
jmasa@3294 530 }
jmasa@3294 531 GCTaskQueue* q = GCTaskQueue::create();
jmasa@3294 532 for(uint i = 0; i < (uint) more_inactive_workers; i++) {
jmasa@3294 533 q->enqueue(IdleGCTask::create_on_c_heap());
jmasa@3294 534 increment_idle_workers();
jmasa@3294 535 }
jmasa@3294 536 assert(workers() == active_workers() + idle_workers(),
jmasa@3294 537 "total workers should equal active + inactive");
jmasa@3294 538 add_list(q);
jmasa@3294 539 // GCTaskQueue* q was created in a ResourceArea so a
jmasa@3294 540 // destroy() call is not needed.
jmasa@3294 541 }
jmasa@3294 542 }
jmasa@3294 543
jmasa@3294 544 void GCTaskManager::release_idle_workers() {
jmasa@3294 545 {
jmasa@3294 546 MutexLockerEx ml(monitor(),
jmasa@3294 547 Mutex::_no_safepoint_check_flag);
jmasa@3294 548 _idle_inactive_task->set_should_wait(false);
jmasa@3294 549 monitor()->notify_all();
jmasa@3294 550 // Release monitor
jmasa@3294 551 }
jmasa@3294 552 }
jmasa@3294 553
duke@435 554 void GCTaskManager::print_task_time_stamps() {
duke@435 555 for(uint i=0; i<ParallelGCThreads; i++) {
duke@435 556 GCTaskThread* t = thread(i);
duke@435 557 t->print_task_time_stamps();
duke@435 558 }
duke@435 559 }
duke@435 560
duke@435 561 void GCTaskManager::print_threads_on(outputStream* st) {
duke@435 562 uint num_thr = workers();
duke@435 563 for (uint i = 0; i < num_thr; i++) {
duke@435 564 thread(i)->print_on(st);
duke@435 565 st->cr();
duke@435 566 }
duke@435 567 }
duke@435 568
duke@435 569 void GCTaskManager::threads_do(ThreadClosure* tc) {
duke@435 570 assert(tc != NULL, "Null ThreadClosure");
duke@435 571 uint num_thr = workers();
duke@435 572 for (uint i = 0; i < num_thr; i++) {
duke@435 573 tc->do_thread(thread(i));
duke@435 574 }
duke@435 575 }
duke@435 576
duke@435 577 GCTaskThread* GCTaskManager::thread(uint which) {
duke@435 578 assert(which < workers(), "index out of bounds");
duke@435 579 assert(_thread[which] != NULL, "shouldn't have null thread");
duke@435 580 return _thread[which];
duke@435 581 }
duke@435 582
duke@435 583 void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
duke@435 584 assert(which < workers(), "index out of bounds");
duke@435 585 assert(value != NULL, "shouldn't have null thread");
duke@435 586 _thread[which] = value;
duke@435 587 }
duke@435 588
duke@435 589 void GCTaskManager::add_task(GCTask* task) {
duke@435 590 assert(task != NULL, "shouldn't have null task");
duke@435 591 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 592 if (TraceGCTaskManager) {
duke@435 593 tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
duke@435 594 task, GCTask::Kind::to_string(task->kind()));
duke@435 595 }
duke@435 596 queue()->enqueue(task);
duke@435 597 // Notify with the lock held to avoid missed notifies.
duke@435 598 if (TraceGCTaskManager) {
duke@435 599 tty->print_cr(" GCTaskManager::add_task (%s)->notify_all",
duke@435 600 monitor()->name());
duke@435 601 }
duke@435 602 (void) monitor()->notify_all();
duke@435 603 // Release monitor().
duke@435 604 }
duke@435 605
duke@435 606 void GCTaskManager::add_list(GCTaskQueue* list) {
duke@435 607 assert(list != NULL, "shouldn't have null task");
duke@435 608 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 609 if (TraceGCTaskManager) {
duke@435 610 tty->print_cr("GCTaskManager::add_list(%u)", list->length());
duke@435 611 }
duke@435 612 queue()->enqueue(list);
duke@435 613 // Notify with the lock held to avoid missed notifies.
duke@435 614 if (TraceGCTaskManager) {
duke@435 615 tty->print_cr(" GCTaskManager::add_list (%s)->notify_all",
duke@435 616 monitor()->name());
duke@435 617 }
duke@435 618 (void) monitor()->notify_all();
duke@435 619 // Release monitor().
duke@435 620 }
duke@435 621
jmasa@3294 622 // GC workers wait in get_task() for new work to be added
jmasa@3294 623 // to the GCTaskManager's queue. When new work is added,
jmasa@3294 624 // a notify is sent to the waiting GC workers which then
jmasa@3294 625 // compete to get tasks. If a GC worker wakes up and there
jmasa@3294 626 // is no work on the queue, it is given a noop_task to execute
jmasa@3294 627 // and then loops to find more work.
jmasa@3294 628
duke@435 629 GCTask* GCTaskManager::get_task(uint which) {
duke@435 630 GCTask* result = NULL;
duke@435 631 // Grab the queue lock.
duke@435 632 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 633 // Wait while the queue is block or
duke@435 634 // there is nothing to do, except maybe release resources.
duke@435 635 while (is_blocked() ||
duke@435 636 (queue()->is_empty() && !should_release_resources(which))) {
duke@435 637 if (TraceGCTaskManager) {
duke@435 638 tty->print_cr("GCTaskManager::get_task(%u)"
duke@435 639 " blocked: %s"
duke@435 640 " empty: %s"
duke@435 641 " release: %s",
duke@435 642 which,
duke@435 643 is_blocked() ? "true" : "false",
duke@435 644 queue()->is_empty() ? "true" : "false",
duke@435 645 should_release_resources(which) ? "true" : "false");
duke@435 646 tty->print_cr(" => (%s)->wait()",
duke@435 647 monitor()->name());
duke@435 648 }
duke@435 649 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
duke@435 650 }
duke@435 651 // We've reacquired the queue lock here.
duke@435 652 // Figure out which condition caused us to exit the loop above.
duke@435 653 if (!queue()->is_empty()) {
duke@435 654 if (UseGCTaskAffinity) {
duke@435 655 result = queue()->dequeue(which);
duke@435 656 } else {
duke@435 657 result = queue()->dequeue();
duke@435 658 }
duke@435 659 if (result->is_barrier_task()) {
duke@435 660 assert(which != sentinel_worker(),
duke@435 661 "blocker shouldn't be bogus");
duke@435 662 set_blocking_worker(which);
duke@435 663 }
duke@435 664 } else {
duke@435 665 // The queue is empty, but we were woken up.
duke@435 666 // Just hand back a Noop task,
duke@435 667 // in case someone wanted us to release resources, or whatever.
duke@435 668 result = noop_task();
duke@435 669 increment_noop_tasks();
duke@435 670 }
duke@435 671 assert(result != NULL, "shouldn't have null task");
duke@435 672 if (TraceGCTaskManager) {
duke@435 673 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
duke@435 674 which, result, GCTask::Kind::to_string(result->kind()));
duke@435 675 tty->print_cr(" %s", result->name());
duke@435 676 }
jmasa@3294 677 if (!result->is_idle_task()) {
jmasa@3294 678 increment_busy_workers();
jmasa@3294 679 increment_delivered_tasks();
jmasa@3294 680 }
duke@435 681 return result;
duke@435 682 // Release monitor().
duke@435 683 }
duke@435 684
duke@435 685 void GCTaskManager::note_completion(uint which) {
duke@435 686 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 687 if (TraceGCTaskManager) {
duke@435 688 tty->print_cr("GCTaskManager::note_completion(%u)", which);
duke@435 689 }
duke@435 690 // If we are blocked, check if the completing thread is the blocker.
duke@435 691 if (blocking_worker() == which) {
duke@435 692 assert(blocking_worker() != sentinel_worker(),
duke@435 693 "blocker shouldn't be bogus");
duke@435 694 increment_barriers();
duke@435 695 set_unblocked();
duke@435 696 }
duke@435 697 increment_completed_tasks();
duke@435 698 uint active = decrement_busy_workers();
duke@435 699 if ((active == 0) && (queue()->is_empty())) {
duke@435 700 increment_emptied_queue();
duke@435 701 if (TraceGCTaskManager) {
duke@435 702 tty->print_cr(" GCTaskManager::note_completion(%u) done", which);
duke@435 703 }
duke@435 704 // Notify client that we are done.
duke@435 705 NotifyDoneClosure* ndc = notify_done_closure();
duke@435 706 if (ndc != NULL) {
duke@435 707 ndc->notify(this);
duke@435 708 }
duke@435 709 }
duke@435 710 if (TraceGCTaskManager) {
duke@435 711 tty->print_cr(" GCTaskManager::note_completion(%u) (%s)->notify_all",
duke@435 712 which, monitor()->name());
duke@435 713 tty->print_cr(" "
duke@435 714 " blocked: %s"
duke@435 715 " empty: %s"
duke@435 716 " release: %s",
duke@435 717 is_blocked() ? "true" : "false",
duke@435 718 queue()->is_empty() ? "true" : "false",
duke@435 719 should_release_resources(which) ? "true" : "false");
duke@435 720 tty->print_cr(" "
duke@435 721 " delivered: %u"
duke@435 722 " completed: %u"
duke@435 723 " barriers: %u"
duke@435 724 " emptied: %u",
duke@435 725 delivered_tasks(),
duke@435 726 completed_tasks(),
duke@435 727 barriers(),
duke@435 728 emptied_queue());
duke@435 729 }
duke@435 730 // Tell everyone that a task has completed.
duke@435 731 (void) monitor()->notify_all();
duke@435 732 // Release monitor().
duke@435 733 }
duke@435 734
duke@435 735 uint GCTaskManager::increment_busy_workers() {
duke@435 736 assert(queue()->own_lock(), "don't own the lock");
duke@435 737 _busy_workers += 1;
duke@435 738 return _busy_workers;
duke@435 739 }
duke@435 740
duke@435 741 uint GCTaskManager::decrement_busy_workers() {
duke@435 742 assert(queue()->own_lock(), "don't own the lock");
jmasa@3294 743 assert(_busy_workers > 0, "About to make a mistake");
duke@435 744 _busy_workers -= 1;
duke@435 745 return _busy_workers;
duke@435 746 }
duke@435 747
duke@435 748 void GCTaskManager::release_all_resources() {
duke@435 749 // If you want this to be done atomically, do it in a BarrierGCTask.
duke@435 750 for (uint i = 0; i < workers(); i += 1) {
duke@435 751 set_resource_flag(i, true);
duke@435 752 }
duke@435 753 }
duke@435 754
duke@435 755 bool GCTaskManager::should_release_resources(uint which) {
duke@435 756 // This can be done without a lock because each thread reads one element.
duke@435 757 return resource_flag(which);
duke@435 758 }
duke@435 759
duke@435 760 void GCTaskManager::note_release(uint which) {
duke@435 761 // This can be done without a lock because each thread writes one element.
duke@435 762 set_resource_flag(which, false);
duke@435 763 }
duke@435 764
jmasa@3294 765 // "list" contains tasks that are ready to execute. Those
jmasa@3294 766 // tasks are added to the GCTaskManager's queue of tasks and
jmasa@3294 767 // then the GC workers are notified that there is new work to
jmasa@3294 768 // do.
jmasa@3294 769 //
jmasa@3294 770 // Typically different types of tasks can be added to the "list".
jmasa@3294 771 // For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask,
jmasa@3294 772 // ScavengeRootsTask, and StealTask tasks are all added to the list
jmasa@3294 773 // and then the GC workers are notified of new work. The tasks are
jmasa@3294 774 // handed out in the order in which they are added to the list
jmasa@3294 775 // (although execution is not necessarily in that order). As long
jmasa@3294 776 // as any tasks are running the GCTaskManager will wait for execution
jmasa@3294 777 // to complete. GC workers that execute a stealing task remain in
jmasa@3294 778 // the stealing task until all stealing tasks have completed. The load
jmasa@3294 779 // balancing afforded by the stealing tasks work best if the stealing
jmasa@3294 780 // tasks are added last to the list.
jmasa@3294 781
duke@435 782 void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
duke@435 783 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
duke@435 784 list->enqueue(fin);
duke@435 785 add_list(list);
jmasa@3294 786 fin->wait_for(true /* reset */);
duke@435 787 // We have to release the barrier tasks!
duke@435 788 WaitForBarrierGCTask::destroy(fin);
duke@435 789 }
duke@435 790
duke@435 791 bool GCTaskManager::resource_flag(uint which) {
duke@435 792 assert(which < workers(), "index out of bounds");
duke@435 793 return _resource_flag[which];
duke@435 794 }
duke@435 795
duke@435 796 void GCTaskManager::set_resource_flag(uint which, bool value) {
duke@435 797 assert(which < workers(), "index out of bounds");
duke@435 798 _resource_flag[which] = value;
duke@435 799 }
duke@435 800
duke@435 801 //
duke@435 802 // NoopGCTask
duke@435 803 //
duke@435 804
duke@435 805 NoopGCTask* NoopGCTask::create() {
duke@435 806 NoopGCTask* result = new NoopGCTask(false);
duke@435 807 return result;
duke@435 808 }
duke@435 809
duke@435 810 NoopGCTask* NoopGCTask::create_on_c_heap() {
duke@435 811 NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
duke@435 812 return result;
duke@435 813 }
duke@435 814
duke@435 815 void NoopGCTask::destroy(NoopGCTask* that) {
duke@435 816 if (that != NULL) {
duke@435 817 that->destruct();
duke@435 818 if (that->is_c_heap_obj()) {
duke@435 819 FreeHeap(that);
duke@435 820 }
duke@435 821 }
duke@435 822 }
duke@435 823
duke@435 824 void NoopGCTask::destruct() {
duke@435 825 // This has to know it's superclass structure, just like the constructor.
duke@435 826 this->GCTask::destruct();
duke@435 827 // Nothing else to do.
duke@435 828 }
duke@435 829
duke@435 830 //
jmasa@3294 831 // IdleGCTask
jmasa@3294 832 //
jmasa@3294 833
jmasa@3294 834 IdleGCTask* IdleGCTask::create() {
jmasa@3294 835 IdleGCTask* result = new IdleGCTask(false);
jmasa@3294 836 return result;
jmasa@3294 837 }
jmasa@3294 838
jmasa@3294 839 IdleGCTask* IdleGCTask::create_on_c_heap() {
jmasa@3294 840 IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true);
jmasa@3294 841 return result;
jmasa@3294 842 }
jmasa@3294 843
jmasa@3294 844 void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
jmasa@3294 845 WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task();
jmasa@3294 846 if (TraceGCTaskManager) {
jmasa@3294 847 tty->print_cr("[" INTPTR_FORMAT "]"
jmasa@3294 848 " IdleGCTask:::do_it()"
jmasa@3294 849 " should_wait: %s",
jmasa@3294 850 this, wait_for_task->should_wait() ? "true" : "false");
jmasa@3294 851 }
jmasa@3294 852 MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
jmasa@3294 853 if (TraceDynamicGCThreads) {
jmasa@3294 854 gclog_or_tty->print_cr("--- idle %d", which);
jmasa@3294 855 }
jmasa@3294 856 // Increment has to be done when the idle tasks are created.
jmasa@3294 857 // manager->increment_idle_workers();
jmasa@3294 858 manager->monitor()->notify_all();
jmasa@3294 859 while (wait_for_task->should_wait()) {
jmasa@3294 860 if (TraceGCTaskManager) {
jmasa@3294 861 tty->print_cr("[" INTPTR_FORMAT "]"
jmasa@3294 862 " IdleGCTask::do_it()"
jmasa@3294 863 " [" INTPTR_FORMAT "] (%s)->wait()",
jmasa@3294 864 this, manager->monitor(), manager->monitor()->name());
jmasa@3294 865 }
jmasa@3294 866 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
jmasa@3294 867 }
jmasa@3294 868 manager->decrement_idle_workers();
jmasa@3294 869 if (TraceDynamicGCThreads) {
jmasa@3294 870 gclog_or_tty->print_cr("--- release %d", which);
jmasa@3294 871 }
jmasa@3294 872 if (TraceGCTaskManager) {
jmasa@3294 873 tty->print_cr("[" INTPTR_FORMAT "]"
jmasa@3294 874 " IdleGCTask::do_it() returns"
jmasa@3294 875 " should_wait: %s",
jmasa@3294 876 this, wait_for_task->should_wait() ? "true" : "false");
jmasa@3294 877 }
jmasa@3294 878 // Release monitor().
jmasa@3294 879 }
jmasa@3294 880
jmasa@3294 881 void IdleGCTask::destroy(IdleGCTask* that) {
jmasa@3294 882 if (that != NULL) {
jmasa@3294 883 that->destruct();
jmasa@3294 884 if (that->is_c_heap_obj()) {
jmasa@3294 885 FreeHeap(that);
jmasa@3294 886 }
jmasa@3294 887 }
jmasa@3294 888 }
jmasa@3294 889
jmasa@3294 890 void IdleGCTask::destruct() {
jmasa@3294 891 // This has to know it's superclass structure, just like the constructor.
jmasa@3294 892 this->GCTask::destruct();
jmasa@3294 893 // Nothing else to do.
jmasa@3294 894 }
jmasa@3294 895
jmasa@3294 896 //
duke@435 897 // BarrierGCTask
duke@435 898 //
duke@435 899
duke@435 900 void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
duke@435 901 // Wait for this to be the only busy worker.
duke@435 902 // ??? I thought of having a StackObj class
duke@435 903 // whose constructor would grab the lock and come to the barrier,
duke@435 904 // and whose destructor would release the lock,
duke@435 905 // but that seems like too much mechanism for two lines of code.
duke@435 906 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
duke@435 907 do_it_internal(manager, which);
duke@435 908 // Release manager->lock().
duke@435 909 }
duke@435 910
duke@435 911 void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
duke@435 912 // Wait for this to be the only busy worker.
duke@435 913 assert(manager->monitor()->owned_by_self(), "don't own the lock");
duke@435 914 assert(manager->is_blocked(), "manager isn't blocked");
duke@435 915 while (manager->busy_workers() > 1) {
duke@435 916 if (TraceGCTaskManager) {
duke@435 917 tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
duke@435 918 which, manager->busy_workers());
duke@435 919 }
duke@435 920 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
duke@435 921 }
duke@435 922 }
duke@435 923
duke@435 924 void BarrierGCTask::destruct() {
duke@435 925 this->GCTask::destruct();
duke@435 926 // Nothing else to do.
duke@435 927 }
duke@435 928
duke@435 929 //
duke@435 930 // ReleasingBarrierGCTask
duke@435 931 //
duke@435 932
duke@435 933 void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
duke@435 934 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
duke@435 935 do_it_internal(manager, which);
duke@435 936 manager->release_all_resources();
duke@435 937 // Release manager->lock().
duke@435 938 }
duke@435 939
duke@435 940 void ReleasingBarrierGCTask::destruct() {
duke@435 941 this->BarrierGCTask::destruct();
duke@435 942 // Nothing else to do.
duke@435 943 }
duke@435 944
duke@435 945 //
duke@435 946 // NotifyingBarrierGCTask
duke@435 947 //
duke@435 948
duke@435 949 void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
duke@435 950 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
duke@435 951 do_it_internal(manager, which);
duke@435 952 NotifyDoneClosure* ndc = notify_done_closure();
duke@435 953 if (ndc != NULL) {
duke@435 954 ndc->notify(manager);
duke@435 955 }
duke@435 956 // Release manager->lock().
duke@435 957 }
duke@435 958
duke@435 959 void NotifyingBarrierGCTask::destruct() {
duke@435 960 this->BarrierGCTask::destruct();
duke@435 961 // Nothing else to do.
duke@435 962 }
duke@435 963
duke@435 964 //
duke@435 965 // WaitForBarrierGCTask
duke@435 966 //
duke@435 967 WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
duke@435 968 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
duke@435 969 return result;
duke@435 970 }
duke@435 971
duke@435 972 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
jmasa@3294 973 WaitForBarrierGCTask* result =
jmasa@3294 974 new (ResourceObj::C_HEAP) WaitForBarrierGCTask(true);
duke@435 975 return result;
duke@435 976 }
duke@435 977
duke@435 978 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
duke@435 979 _is_c_heap_obj(on_c_heap) {
duke@435 980 _monitor = MonitorSupply::reserve();
duke@435 981 set_should_wait(true);
duke@435 982 if (TraceGCTaskManager) {
duke@435 983 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 984 " WaitForBarrierGCTask::WaitForBarrierGCTask()"
duke@435 985 " monitor: " INTPTR_FORMAT,
duke@435 986 this, monitor());
duke@435 987 }
duke@435 988 }
duke@435 989
duke@435 990 void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
duke@435 991 if (that != NULL) {
duke@435 992 if (TraceGCTaskManager) {
duke@435 993 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 994 " WaitForBarrierGCTask::destroy()"
duke@435 995 " is_c_heap_obj: %s"
duke@435 996 " monitor: " INTPTR_FORMAT,
duke@435 997 that,
duke@435 998 that->is_c_heap_obj() ? "true" : "false",
duke@435 999 that->monitor());
duke@435 1000 }
duke@435 1001 that->destruct();
duke@435 1002 if (that->is_c_heap_obj()) {
duke@435 1003 FreeHeap(that);
duke@435 1004 }
duke@435 1005 }
duke@435 1006 }
duke@435 1007
duke@435 1008 void WaitForBarrierGCTask::destruct() {
duke@435 1009 assert(monitor() != NULL, "monitor should not be NULL");
duke@435 1010 if (TraceGCTaskManager) {
duke@435 1011 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1012 " WaitForBarrierGCTask::destruct()"
duke@435 1013 " monitor: " INTPTR_FORMAT,
duke@435 1014 this, monitor());
duke@435 1015 }
duke@435 1016 this->BarrierGCTask::destruct();
duke@435 1017 // Clean up that should be in the destructor,
duke@435 1018 // except that ResourceMarks don't call destructors.
duke@435 1019 if (monitor() != NULL) {
duke@435 1020 MonitorSupply::release(monitor());
duke@435 1021 }
duke@435 1022 _monitor = (Monitor*) 0xDEAD000F;
duke@435 1023 }
duke@435 1024
duke@435 1025 void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
duke@435 1026 if (TraceGCTaskManager) {
duke@435 1027 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1028 " WaitForBarrierGCTask::do_it() waiting for idle"
duke@435 1029 " monitor: " INTPTR_FORMAT,
duke@435 1030 this, monitor());
duke@435 1031 }
duke@435 1032 {
duke@435 1033 // First, wait for the barrier to arrive.
duke@435 1034 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
duke@435 1035 do_it_internal(manager, which);
duke@435 1036 // Release manager->lock().
duke@435 1037 }
duke@435 1038 {
duke@435 1039 // Then notify the waiter.
duke@435 1040 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 1041 set_should_wait(false);
duke@435 1042 // Waiter doesn't miss the notify in the wait_for method
duke@435 1043 // since it checks the flag after grabbing the monitor.
duke@435 1044 if (TraceGCTaskManager) {
duke@435 1045 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1046 " WaitForBarrierGCTask::do_it()"
duke@435 1047 " [" INTPTR_FORMAT "] (%s)->notify_all()",
duke@435 1048 this, monitor(), monitor()->name());
duke@435 1049 }
duke@435 1050 monitor()->notify_all();
duke@435 1051 // Release monitor().
duke@435 1052 }
duke@435 1053 }
duke@435 1054
jmasa@3294 1055 void WaitForBarrierGCTask::wait_for(bool reset) {
duke@435 1056 if (TraceGCTaskManager) {
duke@435 1057 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1058 " WaitForBarrierGCTask::wait_for()"
duke@435 1059 " should_wait: %s",
duke@435 1060 this, should_wait() ? "true" : "false");
duke@435 1061 }
duke@435 1062 {
duke@435 1063 // Grab the lock and check again.
duke@435 1064 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
duke@435 1065 while (should_wait()) {
duke@435 1066 if (TraceGCTaskManager) {
duke@435 1067 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1068 " WaitForBarrierGCTask::wait_for()"
duke@435 1069 " [" INTPTR_FORMAT "] (%s)->wait()",
duke@435 1070 this, monitor(), monitor()->name());
duke@435 1071 }
duke@435 1072 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
duke@435 1073 }
duke@435 1074 // Reset the flag in case someone reuses this task.
jmasa@3294 1075 if (reset) {
jmasa@3294 1076 set_should_wait(true);
jmasa@3294 1077 }
duke@435 1078 if (TraceGCTaskManager) {
duke@435 1079 tty->print_cr("[" INTPTR_FORMAT "]"
duke@435 1080 " WaitForBarrierGCTask::wait_for() returns"
duke@435 1081 " should_wait: %s",
duke@435 1082 this, should_wait() ? "true" : "false");
duke@435 1083 }
duke@435 1084 // Release monitor().
duke@435 1085 }
duke@435 1086 }
duke@435 1087
duke@435 1088 Mutex* MonitorSupply::_lock = NULL;
duke@435 1089 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
duke@435 1090
duke@435 1091 Monitor* MonitorSupply::reserve() {
duke@435 1092 Monitor* result = NULL;
duke@435 1093 // Lazy initialization: possible race.
duke@435 1094 if (lock() == NULL) {
duke@435 1095 _lock = new Mutex(Mutex::barrier, // rank
duke@435 1096 "MonitorSupply mutex", // name
duke@435 1097 Mutex::_allow_vm_block_flag); // allow_vm_block
duke@435 1098 }
duke@435 1099 {
duke@435 1100 MutexLockerEx ml(lock());
duke@435 1101 // Lazy initialization.
duke@435 1102 if (freelist() == NULL) {
duke@435 1103 _freelist =
duke@435 1104 new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
duke@435 1105 true);
duke@435 1106 }
duke@435 1107 if (! freelist()->is_empty()) {
duke@435 1108 result = freelist()->pop();
duke@435 1109 } else {
duke@435 1110 result = new Monitor(Mutex::barrier, // rank
duke@435 1111 "MonitorSupply monitor", // name
duke@435 1112 Mutex::_allow_vm_block_flag); // allow_vm_block
duke@435 1113 }
duke@435 1114 guarantee(result != NULL, "shouldn't return NULL");
duke@435 1115 assert(!result->is_locked(), "shouldn't be locked");
duke@435 1116 // release lock().
duke@435 1117 }
duke@435 1118 return result;
duke@435 1119 }
duke@435 1120
duke@435 1121 void MonitorSupply::release(Monitor* instance) {
duke@435 1122 assert(instance != NULL, "shouldn't release NULL");
duke@435 1123 assert(!instance->is_locked(), "shouldn't be locked");
duke@435 1124 {
duke@435 1125 MutexLockerEx ml(lock());
duke@435 1126 freelist()->push(instance);
duke@435 1127 // release lock().
duke@435 1128 }
duke@435 1129 }

mercurial