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

Fri, 24 Jun 2016 17:12:13 +0800

author
aoqi<aoqi@loongson.cn>
date
Fri, 24 Jun 2016 17:12:13 +0800
changeset 25
873fd82b133d
parent 1
2d8a650513c2
child 6876
710a3c8b516e
permissions
-rw-r--r--

[Code Reorganization] Removed GC related modifications made by Loongson, for example, UseOldNUMA.

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

mercurial