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

Fri, 29 Apr 2016 00:06:10 +0800

author
aoqi
date
Fri, 29 Apr 2016 00:06:10 +0800
changeset 1
2d8a650513c2
parent 0
f90c822e73f8
child 25
873fd82b133d
permissions
-rw-r--r--

Added MIPS 64-bit port.

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

mercurial