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

Thu, 09 Apr 2015 15:58:49 +0200

author
mlarsson
date
Thu, 09 Apr 2015 15:58:49 +0200
changeset 7686
fb69749583e8
parent 6911
ce8f6bb717c9
child 7535
7ae4e26cb1e0
child 9351
bae7d3cdf6af
permissions
-rw-r--r--

8072621: Clean up around VM_GC_Operations
Reviewed-by: brutisso, jmasa

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

mercurial