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

Wed, 24 Apr 2013 20:13:37 +0200

author
stefank
date
Wed, 24 Apr 2013 20:13:37 +0200
changeset 5018
b06ac540229e
parent 4153
b9a9ed0f8eeb
child 6680
78bbf4d43a14
permissions
-rw-r--r--

8013132: Add a flag to turn off the output of the verbose verification code
Reviewed-by: johnc, brutisso

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

mercurial