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

Thu, 12 Oct 2017 21:27:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 21:27:07 +0800
changeset 7535
7ae4e26cb1e0
parent 6911
ce8f6bb717c9
parent 6876
710a3c8b516e
child 9448
73d689add964
permissions
-rw-r--r--

merge

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

mercurial