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

changeset 0
f90c822e73f8
child 1
2d8a650513c2
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,1144 @@
     1.4 +/*
     1.5 + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
    1.30 +#include "gc_implementation/parallelScavenge/gcTaskThread.hpp"
    1.31 +#include "gc_implementation/shared/adaptiveSizePolicy.hpp"
    1.32 +#include "memory/allocation.hpp"
    1.33 +#include "memory/allocation.inline.hpp"
    1.34 +#include "runtime/mutex.hpp"
    1.35 +#include "runtime/mutexLocker.hpp"
    1.36 +
    1.37 +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    1.38 +
    1.39 +//
    1.40 +// GCTask
    1.41 +//
    1.42 +
    1.43 +const char* GCTask::Kind::to_string(kind value) {
    1.44 +  const char* result = "unknown GCTask kind";
    1.45 +  switch (value) {
    1.46 +  default:
    1.47 +    result = "unknown GCTask kind";
    1.48 +    break;
    1.49 +  case unknown_task:
    1.50 +    result = "unknown task";
    1.51 +    break;
    1.52 +  case ordinary_task:
    1.53 +    result = "ordinary task";
    1.54 +    break;
    1.55 +  case barrier_task:
    1.56 +    result = "barrier task";
    1.57 +    break;
    1.58 +  case noop_task:
    1.59 +    result = "noop task";
    1.60 +    break;
    1.61 +  case idle_task:
    1.62 +    result = "idle task";
    1.63 +    break;
    1.64 +  }
    1.65 +  return result;
    1.66 +};
    1.67 +
    1.68 +GCTask::GCTask() :
    1.69 +  _kind(Kind::ordinary_task),
    1.70 +  _affinity(GCTaskManager::sentinel_worker()){
    1.71 +  initialize();
    1.72 +}
    1.73 +
    1.74 +GCTask::GCTask(Kind::kind kind) :
    1.75 +  _kind(kind),
    1.76 +  _affinity(GCTaskManager::sentinel_worker()) {
    1.77 +  initialize();
    1.78 +}
    1.79 +
    1.80 +GCTask::GCTask(uint affinity) :
    1.81 +  _kind(Kind::ordinary_task),
    1.82 +  _affinity(affinity) {
    1.83 +  initialize();
    1.84 +}
    1.85 +
    1.86 +GCTask::GCTask(Kind::kind kind, uint affinity) :
    1.87 +  _kind(kind),
    1.88 +  _affinity(affinity) {
    1.89 +  initialize();
    1.90 +}
    1.91 +
    1.92 +void GCTask::initialize() {
    1.93 +  _older = NULL;
    1.94 +  _newer = NULL;
    1.95 +}
    1.96 +
    1.97 +void GCTask::destruct() {
    1.98 +  assert(older() == NULL, "shouldn't have an older task");
    1.99 +  assert(newer() == NULL, "shouldn't have a newer task");
   1.100 +  // Nothing to do.
   1.101 +}
   1.102 +
   1.103 +NOT_PRODUCT(
   1.104 +void GCTask::print(const char* message) const {
   1.105 +  tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
   1.106 +             newer(), this, affinity(), older());
   1.107 +}
   1.108 +)
   1.109 +
   1.110 +//
   1.111 +// GCTaskQueue
   1.112 +//
   1.113 +
   1.114 +GCTaskQueue* GCTaskQueue::create() {
   1.115 +  GCTaskQueue* result = new GCTaskQueue(false);
   1.116 +  if (TraceGCTaskQueue) {
   1.117 +    tty->print_cr("GCTaskQueue::create()"
   1.118 +                  " returns " INTPTR_FORMAT, result);
   1.119 +  }
   1.120 +  return result;
   1.121 +}
   1.122 +
   1.123 +GCTaskQueue* GCTaskQueue::create_on_c_heap() {
   1.124 +  GCTaskQueue* result = new(ResourceObj::C_HEAP, mtGC) GCTaskQueue(true);
   1.125 +  if (TraceGCTaskQueue) {
   1.126 +    tty->print_cr("GCTaskQueue::create_on_c_heap()"
   1.127 +                  " returns " INTPTR_FORMAT,
   1.128 +                  result);
   1.129 +  }
   1.130 +  return result;
   1.131 +}
   1.132 +
   1.133 +GCTaskQueue::GCTaskQueue(bool on_c_heap) :
   1.134 +  _is_c_heap_obj(on_c_heap) {
   1.135 +  initialize();
   1.136 +  if (TraceGCTaskQueue) {
   1.137 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.138 +                  " GCTaskQueue::GCTaskQueue() constructor",
   1.139 +                  this);
   1.140 +  }
   1.141 +}
   1.142 +
   1.143 +void GCTaskQueue::destruct() {
   1.144 +  // Nothing to do.
   1.145 +}
   1.146 +
   1.147 +void GCTaskQueue::destroy(GCTaskQueue* that) {
   1.148 +  if (TraceGCTaskQueue) {
   1.149 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.150 +                  " GCTaskQueue::destroy()"
   1.151 +                  "  is_c_heap_obj:  %s",
   1.152 +                  that,
   1.153 +                  that->is_c_heap_obj() ? "true" : "false");
   1.154 +  }
   1.155 +  // That instance may have been allocated as a CHeapObj,
   1.156 +  // in which case we have to free it explicitly.
   1.157 +  if (that != NULL) {
   1.158 +    that->destruct();
   1.159 +    assert(that->is_empty(), "should be empty");
   1.160 +    if (that->is_c_heap_obj()) {
   1.161 +      FreeHeap(that);
   1.162 +    }
   1.163 +  }
   1.164 +}
   1.165 +
   1.166 +void GCTaskQueue::initialize() {
   1.167 +  set_insert_end(NULL);
   1.168 +  set_remove_end(NULL);
   1.169 +  set_length(0);
   1.170 +}
   1.171 +
   1.172 +// Enqueue one task.
   1.173 +void GCTaskQueue::enqueue(GCTask* task) {
   1.174 +  if (TraceGCTaskQueue) {
   1.175 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.176 +                  " GCTaskQueue::enqueue(task: "
   1.177 +                  INTPTR_FORMAT ")",
   1.178 +                  this, task);
   1.179 +    print("before:");
   1.180 +  }
   1.181 +  assert(task != NULL, "shouldn't have null task");
   1.182 +  assert(task->older() == NULL, "shouldn't be on queue");
   1.183 +  assert(task->newer() == NULL, "shouldn't be on queue");
   1.184 +  task->set_newer(NULL);
   1.185 +  task->set_older(insert_end());
   1.186 +  if (is_empty()) {
   1.187 +    set_remove_end(task);
   1.188 +  } else {
   1.189 +    insert_end()->set_newer(task);
   1.190 +  }
   1.191 +  set_insert_end(task);
   1.192 +  increment_length();
   1.193 +  verify_length();
   1.194 +  if (TraceGCTaskQueue) {
   1.195 +    print("after:");
   1.196 +  }
   1.197 +}
   1.198 +
   1.199 +// Enqueue a whole list of tasks.  Empties the argument list.
   1.200 +void GCTaskQueue::enqueue(GCTaskQueue* list) {
   1.201 +  if (TraceGCTaskQueue) {
   1.202 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.203 +                  " GCTaskQueue::enqueue(list: "
   1.204 +                  INTPTR_FORMAT ")",
   1.205 +                  this, list);
   1.206 +    print("before:");
   1.207 +    list->print("list:");
   1.208 +  }
   1.209 +  if (list->is_empty()) {
   1.210 +    // Enqueuing the empty list: nothing to do.
   1.211 +    return;
   1.212 +  }
   1.213 +  uint list_length = list->length();
   1.214 +  if (is_empty()) {
   1.215 +    // Enqueuing to empty list: just acquire elements.
   1.216 +    set_insert_end(list->insert_end());
   1.217 +    set_remove_end(list->remove_end());
   1.218 +    set_length(list_length);
   1.219 +  } else {
   1.220 +    // Prepend argument list to our queue.
   1.221 +    list->remove_end()->set_older(insert_end());
   1.222 +    insert_end()->set_newer(list->remove_end());
   1.223 +    set_insert_end(list->insert_end());
   1.224 +    set_length(length() + list_length);
   1.225 +    // empty the argument list.
   1.226 +  }
   1.227 +  list->initialize();
   1.228 +  if (TraceGCTaskQueue) {
   1.229 +    print("after:");
   1.230 +    list->print("list:");
   1.231 +  }
   1.232 +  verify_length();
   1.233 +}
   1.234 +
   1.235 +// Dequeue one task.
   1.236 +GCTask* GCTaskQueue::dequeue() {
   1.237 +  if (TraceGCTaskQueue) {
   1.238 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.239 +                  " GCTaskQueue::dequeue()", this);
   1.240 +    print("before:");
   1.241 +  }
   1.242 +  assert(!is_empty(), "shouldn't dequeue from empty list");
   1.243 +  GCTask* result = remove();
   1.244 +  assert(result != NULL, "shouldn't have NULL task");
   1.245 +  if (TraceGCTaskQueue) {
   1.246 +    tty->print_cr("    return: " INTPTR_FORMAT, result);
   1.247 +    print("after:");
   1.248 +  }
   1.249 +  return result;
   1.250 +}
   1.251 +
   1.252 +// Dequeue one task, preferring one with affinity.
   1.253 +GCTask* GCTaskQueue::dequeue(uint affinity) {
   1.254 +  if (TraceGCTaskQueue) {
   1.255 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.256 +                  " GCTaskQueue::dequeue(%u)", this, affinity);
   1.257 +    print("before:");
   1.258 +  }
   1.259 +  assert(!is_empty(), "shouldn't dequeue from empty list");
   1.260 +  // Look down to the next barrier for a task with this affinity.
   1.261 +  GCTask* result = NULL;
   1.262 +  for (GCTask* element = remove_end();
   1.263 +       element != NULL;
   1.264 +       element = element->newer()) {
   1.265 +    if (element->is_barrier_task()) {
   1.266 +      // Don't consider barrier tasks, nor past them.
   1.267 +      result = NULL;
   1.268 +      break;
   1.269 +    }
   1.270 +    if (element->affinity() == affinity) {
   1.271 +      result = remove(element);
   1.272 +      break;
   1.273 +    }
   1.274 +  }
   1.275 +  // If we didn't find anything with affinity, just take the next task.
   1.276 +  if (result == NULL) {
   1.277 +    result = remove();
   1.278 +  }
   1.279 +  if (TraceGCTaskQueue) {
   1.280 +    tty->print_cr("    return: " INTPTR_FORMAT, result);
   1.281 +    print("after:");
   1.282 +  }
   1.283 +  return result;
   1.284 +}
   1.285 +
   1.286 +GCTask* GCTaskQueue::remove() {
   1.287 +  // Dequeue from remove end.
   1.288 +  GCTask* result = remove_end();
   1.289 +  assert(result != NULL, "shouldn't have null task");
   1.290 +  assert(result->older() == NULL, "not the remove_end");
   1.291 +  set_remove_end(result->newer());
   1.292 +  if (remove_end() == NULL) {
   1.293 +    assert(insert_end() == result, "not a singleton");
   1.294 +    set_insert_end(NULL);
   1.295 +  } else {
   1.296 +    remove_end()->set_older(NULL);
   1.297 +  }
   1.298 +  result->set_newer(NULL);
   1.299 +  decrement_length();
   1.300 +  assert(result->newer() == NULL, "shouldn't be on queue");
   1.301 +  assert(result->older() == NULL, "shouldn't be on queue");
   1.302 +  verify_length();
   1.303 +  return result;
   1.304 +}
   1.305 +
   1.306 +GCTask* GCTaskQueue::remove(GCTask* task) {
   1.307 +  // This is slightly more work, and has slightly fewer asserts
   1.308 +  // than removing from the remove end.
   1.309 +  assert(task != NULL, "shouldn't have null task");
   1.310 +  GCTask* result = task;
   1.311 +  if (result->newer() != NULL) {
   1.312 +    result->newer()->set_older(result->older());
   1.313 +  } else {
   1.314 +    assert(insert_end() == result, "not youngest");
   1.315 +    set_insert_end(result->older());
   1.316 +  }
   1.317 +  if (result->older() != NULL) {
   1.318 +    result->older()->set_newer(result->newer());
   1.319 +  } else {
   1.320 +    assert(remove_end() == result, "not oldest");
   1.321 +    set_remove_end(result->newer());
   1.322 +  }
   1.323 +  result->set_newer(NULL);
   1.324 +  result->set_older(NULL);
   1.325 +  decrement_length();
   1.326 +  verify_length();
   1.327 +  return result;
   1.328 +}
   1.329 +
   1.330 +NOT_PRODUCT(
   1.331 +// Count the elements in the queue and verify the length against
   1.332 +// that count.
   1.333 +void GCTaskQueue::verify_length() const {
   1.334 +  uint count = 0;
   1.335 +  for (GCTask* element = insert_end();
   1.336 +       element != NULL;
   1.337 +       element = element->older()) {
   1.338 +
   1.339 +    count++;
   1.340 +  }
   1.341 +  assert(count == length(), "Length does not match queue");
   1.342 +}
   1.343 +
   1.344 +void GCTaskQueue::print(const char* message) const {
   1.345 +  tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
   1.346 +                "  insert_end: " INTPTR_FORMAT
   1.347 +                "  remove_end: " INTPTR_FORMAT
   1.348 +                "  length:       %d"
   1.349 +                "  %s",
   1.350 +                this, insert_end(), remove_end(), length(), message);
   1.351 +  uint count = 0;
   1.352 +  for (GCTask* element = insert_end();
   1.353 +       element != NULL;
   1.354 +       element = element->older()) {
   1.355 +    element->print("    ");
   1.356 +    count++;
   1.357 +    tty->cr();
   1.358 +  }
   1.359 +  tty->print("Total tasks: %d", count);
   1.360 +}
   1.361 +)
   1.362 +
   1.363 +//
   1.364 +// SynchronizedGCTaskQueue
   1.365 +//
   1.366 +
   1.367 +SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
   1.368 +                                                 Monitor *       lock_arg) :
   1.369 +  _unsynchronized_queue(queue_arg),
   1.370 +  _lock(lock_arg) {
   1.371 +  assert(unsynchronized_queue() != NULL, "null queue");
   1.372 +  assert(lock() != NULL, "null lock");
   1.373 +}
   1.374 +
   1.375 +SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
   1.376 +  // Nothing to do.
   1.377 +}
   1.378 +
   1.379 +//
   1.380 +// GCTaskManager
   1.381 +//
   1.382 +GCTaskManager::GCTaskManager(uint workers) :
   1.383 +  _workers(workers),
   1.384 +  _active_workers(0),
   1.385 +  _idle_workers(0),
   1.386 +  _ndc(NULL) {
   1.387 +  initialize();
   1.388 +}
   1.389 +
   1.390 +GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
   1.391 +  _workers(workers),
   1.392 +  _active_workers(0),
   1.393 +  _idle_workers(0),
   1.394 +  _ndc(ndc) {
   1.395 +  initialize();
   1.396 +}
   1.397 +
   1.398 +void GCTaskManager::initialize() {
   1.399 +  if (TraceGCTaskManager) {
   1.400 +    tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
   1.401 +  }
   1.402 +  assert(workers() != 0, "no workers");
   1.403 +  _monitor = new Monitor(Mutex::barrier,                // rank
   1.404 +                         "GCTaskManager monitor",       // name
   1.405 +                         Mutex::_allow_vm_block_flag);  // allow_vm_block
   1.406 +  // The queue for the GCTaskManager must be a CHeapObj.
   1.407 +  GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
   1.408 +  _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
   1.409 +  _noop_task = NoopGCTask::create_on_c_heap();
   1.410 +  _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap();
   1.411 +  _resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC);
   1.412 +  {
   1.413 +    // Set up worker threads.
   1.414 +    //     Distribute the workers among the available processors,
   1.415 +    //     unless we were told not to, or if the os doesn't want to.
   1.416 +    uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
   1.417 +    if (!BindGCTaskThreadsToCPUs ||
   1.418 +        !os::distribute_processes(workers(), processor_assignment)) {
   1.419 +      for (uint a = 0; a < workers(); a += 1) {
   1.420 +        processor_assignment[a] = sentinel_worker();
   1.421 +      }
   1.422 +    }
   1.423 +    _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
   1.424 +    for (uint t = 0; t < workers(); t += 1) {
   1.425 +      set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
   1.426 +    }
   1.427 +    if (TraceGCTaskThread) {
   1.428 +      tty->print("GCTaskManager::initialize: distribution:");
   1.429 +      for (uint t = 0; t < workers(); t += 1) {
   1.430 +        tty->print("  %u", processor_assignment[t]);
   1.431 +      }
   1.432 +      tty->cr();
   1.433 +    }
   1.434 +    FREE_C_HEAP_ARRAY(uint, processor_assignment, mtGC);
   1.435 +  }
   1.436 +  reset_busy_workers();
   1.437 +  set_unblocked();
   1.438 +  for (uint w = 0; w < workers(); w += 1) {
   1.439 +    set_resource_flag(w, false);
   1.440 +  }
   1.441 +  reset_delivered_tasks();
   1.442 +  reset_completed_tasks();
   1.443 +  reset_noop_tasks();
   1.444 +  reset_barriers();
   1.445 +  reset_emptied_queue();
   1.446 +  for (uint s = 0; s < workers(); s += 1) {
   1.447 +    thread(s)->start();
   1.448 +  }
   1.449 +}
   1.450 +
   1.451 +GCTaskManager::~GCTaskManager() {
   1.452 +  assert(busy_workers() == 0, "still have busy workers");
   1.453 +  assert(queue()->is_empty(), "still have queued work");
   1.454 +  NoopGCTask::destroy(_noop_task);
   1.455 +  _noop_task = NULL;
   1.456 +  WaitForBarrierGCTask::destroy(_idle_inactive_task);
   1.457 +  _idle_inactive_task = NULL;
   1.458 +  if (_thread != NULL) {
   1.459 +    for (uint i = 0; i < workers(); i += 1) {
   1.460 +      GCTaskThread::destroy(thread(i));
   1.461 +      set_thread(i, NULL);
   1.462 +    }
   1.463 +    FREE_C_HEAP_ARRAY(GCTaskThread*, _thread, mtGC);
   1.464 +    _thread = NULL;
   1.465 +  }
   1.466 +  if (_resource_flag != NULL) {
   1.467 +    FREE_C_HEAP_ARRAY(bool, _resource_flag, mtGC);
   1.468 +    _resource_flag = NULL;
   1.469 +  }
   1.470 +  if (queue() != NULL) {
   1.471 +    GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
   1.472 +    GCTaskQueue::destroy(unsynchronized_queue);
   1.473 +    SynchronizedGCTaskQueue::destroy(queue());
   1.474 +    _queue = NULL;
   1.475 +  }
   1.476 +  if (monitor() != NULL) {
   1.477 +    delete monitor();
   1.478 +    _monitor = NULL;
   1.479 +  }
   1.480 +}
   1.481 +
   1.482 +void GCTaskManager::set_active_gang() {
   1.483 +  _active_workers =
   1.484 +    AdaptiveSizePolicy::calc_active_workers(workers(),
   1.485 +                                 active_workers(),
   1.486 +                                 Threads::number_of_non_daemon_threads());
   1.487 +
   1.488 +  assert(!all_workers_active() || active_workers() == ParallelGCThreads,
   1.489 +         err_msg("all_workers_active() is  incorrect: "
   1.490 +                 "active %d  ParallelGCThreads %d", active_workers(),
   1.491 +                 ParallelGCThreads));
   1.492 +  if (TraceDynamicGCThreads) {
   1.493 +    gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): "
   1.494 +                           "all_workers_active()  %d  workers %d  "
   1.495 +                           "active  %d  ParallelGCThreads %d ",
   1.496 +                           all_workers_active(), workers(),  active_workers(),
   1.497 +                           ParallelGCThreads);
   1.498 +  }
   1.499 +}
   1.500 +
   1.501 +// Create IdleGCTasks for inactive workers.
   1.502 +// Creates tasks in a ResourceArea and assumes
   1.503 +// an appropriate ResourceMark.
   1.504 +void GCTaskManager::task_idle_workers() {
   1.505 +  {
   1.506 +    int more_inactive_workers = 0;
   1.507 +    {
   1.508 +      // Stop any idle tasks from exiting their IdleGCTask's
   1.509 +      // and get the count for additional IdleGCTask's under
   1.510 +      // the GCTaskManager's monitor so that the "more_inactive_workers"
   1.511 +      // count is correct.
   1.512 +      MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   1.513 +      _idle_inactive_task->set_should_wait(true);
   1.514 +      // active_workers are a number being requested.  idle_workers
   1.515 +      // are the number currently idle.  If all the workers are being
   1.516 +      // requested to be active but some are already idle, reduce
   1.517 +      // the number of active_workers to be consistent with the
   1.518 +      // number of idle_workers.  The idle_workers are stuck in
   1.519 +      // idle tasks and will no longer be release (since a new GC
   1.520 +      // is starting).  Try later to release enough idle_workers
   1.521 +      // to allow the desired number of active_workers.
   1.522 +      more_inactive_workers =
   1.523 +        workers() - active_workers() - idle_workers();
   1.524 +      if (more_inactive_workers < 0) {
   1.525 +        int reduced_active_workers = active_workers() + more_inactive_workers;
   1.526 +        set_active_workers(reduced_active_workers);
   1.527 +        more_inactive_workers = 0;
   1.528 +      }
   1.529 +      if (TraceDynamicGCThreads) {
   1.530 +        gclog_or_tty->print_cr("JT: %d  workers %d  active  %d  "
   1.531 +                                "idle %d  more %d",
   1.532 +                                Threads::number_of_non_daemon_threads(),
   1.533 +                                workers(),
   1.534 +                                active_workers(),
   1.535 +                                idle_workers(),
   1.536 +                                more_inactive_workers);
   1.537 +      }
   1.538 +    }
   1.539 +    GCTaskQueue* q = GCTaskQueue::create();
   1.540 +    for(uint i = 0; i < (uint) more_inactive_workers; i++) {
   1.541 +      q->enqueue(IdleGCTask::create_on_c_heap());
   1.542 +      increment_idle_workers();
   1.543 +    }
   1.544 +    assert(workers() == active_workers() + idle_workers(),
   1.545 +      "total workers should equal active + inactive");
   1.546 +    add_list(q);
   1.547 +    // GCTaskQueue* q was created in a ResourceArea so a
   1.548 +    // destroy() call is not needed.
   1.549 +  }
   1.550 +}
   1.551 +
   1.552 +void  GCTaskManager::release_idle_workers() {
   1.553 +  {
   1.554 +    MutexLockerEx ml(monitor(),
   1.555 +      Mutex::_no_safepoint_check_flag);
   1.556 +    _idle_inactive_task->set_should_wait(false);
   1.557 +    monitor()->notify_all();
   1.558 +  // Release monitor
   1.559 +  }
   1.560 +}
   1.561 +
   1.562 +void GCTaskManager::print_task_time_stamps() {
   1.563 +  for(uint i=0; i<ParallelGCThreads; i++) {
   1.564 +    GCTaskThread* t = thread(i);
   1.565 +    t->print_task_time_stamps();
   1.566 +  }
   1.567 +}
   1.568 +
   1.569 +void GCTaskManager::print_threads_on(outputStream* st) {
   1.570 +  uint num_thr = workers();
   1.571 +  for (uint i = 0; i < num_thr; i++) {
   1.572 +    thread(i)->print_on(st);
   1.573 +    st->cr();
   1.574 +  }
   1.575 +}
   1.576 +
   1.577 +void GCTaskManager::threads_do(ThreadClosure* tc) {
   1.578 +  assert(tc != NULL, "Null ThreadClosure");
   1.579 +  uint num_thr = workers();
   1.580 +  for (uint i = 0; i < num_thr; i++) {
   1.581 +    tc->do_thread(thread(i));
   1.582 +  }
   1.583 +}
   1.584 +
   1.585 +GCTaskThread* GCTaskManager::thread(uint which) {
   1.586 +  assert(which < workers(), "index out of bounds");
   1.587 +  assert(_thread[which] != NULL, "shouldn't have null thread");
   1.588 +  return _thread[which];
   1.589 +}
   1.590 +
   1.591 +void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
   1.592 +  assert(which < workers(), "index out of bounds");
   1.593 +  assert(value != NULL, "shouldn't have null thread");
   1.594 +  _thread[which] = value;
   1.595 +}
   1.596 +
   1.597 +void GCTaskManager::add_task(GCTask* task) {
   1.598 +  assert(task != NULL, "shouldn't have null task");
   1.599 +  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   1.600 +  if (TraceGCTaskManager) {
   1.601 +    tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
   1.602 +                  task, GCTask::Kind::to_string(task->kind()));
   1.603 +  }
   1.604 +  queue()->enqueue(task);
   1.605 +  // Notify with the lock held to avoid missed notifies.
   1.606 +  if (TraceGCTaskManager) {
   1.607 +    tty->print_cr("    GCTaskManager::add_task (%s)->notify_all",
   1.608 +                  monitor()->name());
   1.609 +  }
   1.610 +  (void) monitor()->notify_all();
   1.611 +  // Release monitor().
   1.612 +}
   1.613 +
   1.614 +void GCTaskManager::add_list(GCTaskQueue* list) {
   1.615 +  assert(list != NULL, "shouldn't have null task");
   1.616 +  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   1.617 +  if (TraceGCTaskManager) {
   1.618 +    tty->print_cr("GCTaskManager::add_list(%u)", list->length());
   1.619 +  }
   1.620 +  queue()->enqueue(list);
   1.621 +  // Notify with the lock held to avoid missed notifies.
   1.622 +  if (TraceGCTaskManager) {
   1.623 +    tty->print_cr("    GCTaskManager::add_list (%s)->notify_all",
   1.624 +                  monitor()->name());
   1.625 +  }
   1.626 +  (void) monitor()->notify_all();
   1.627 +  // Release monitor().
   1.628 +}
   1.629 +
   1.630 +// GC workers wait in get_task() for new work to be added
   1.631 +// to the GCTaskManager's queue.  When new work is added,
   1.632 +// a notify is sent to the waiting GC workers which then
   1.633 +// compete to get tasks.  If a GC worker wakes up and there
   1.634 +// is no work on the queue, it is given a noop_task to execute
   1.635 +// and then loops to find more work.
   1.636 +
   1.637 +GCTask* GCTaskManager::get_task(uint which) {
   1.638 +  GCTask* result = NULL;
   1.639 +  // Grab the queue lock.
   1.640 +  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   1.641 +  // Wait while the queue is block or
   1.642 +  // there is nothing to do, except maybe release resources.
   1.643 +  while (is_blocked() ||
   1.644 +         (queue()->is_empty() && !should_release_resources(which))) {
   1.645 +    if (TraceGCTaskManager) {
   1.646 +      tty->print_cr("GCTaskManager::get_task(%u)"
   1.647 +                    "  blocked: %s"
   1.648 +                    "  empty: %s"
   1.649 +                    "  release: %s",
   1.650 +                    which,
   1.651 +                    is_blocked() ? "true" : "false",
   1.652 +                    queue()->is_empty() ? "true" : "false",
   1.653 +                    should_release_resources(which) ? "true" : "false");
   1.654 +      tty->print_cr("    => (%s)->wait()",
   1.655 +                    monitor()->name());
   1.656 +    }
   1.657 +    monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   1.658 +  }
   1.659 +  // We've reacquired the queue lock here.
   1.660 +  // Figure out which condition caused us to exit the loop above.
   1.661 +  if (!queue()->is_empty()) {
   1.662 +    if (UseGCTaskAffinity) {
   1.663 +      result = queue()->dequeue(which);
   1.664 +    } else {
   1.665 +      result = queue()->dequeue();
   1.666 +    }
   1.667 +    if (result->is_barrier_task()) {
   1.668 +      assert(which != sentinel_worker(),
   1.669 +             "blocker shouldn't be bogus");
   1.670 +      set_blocking_worker(which);
   1.671 +    }
   1.672 +  } else {
   1.673 +    // The queue is empty, but we were woken up.
   1.674 +    // Just hand back a Noop task,
   1.675 +    // in case someone wanted us to release resources, or whatever.
   1.676 +    result = noop_task();
   1.677 +    increment_noop_tasks();
   1.678 +  }
   1.679 +  assert(result != NULL, "shouldn't have null task");
   1.680 +  if (TraceGCTaskManager) {
   1.681 +    tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
   1.682 +                  which, result, GCTask::Kind::to_string(result->kind()));
   1.683 +    tty->print_cr("     %s", result->name());
   1.684 +  }
   1.685 +  if (!result->is_idle_task()) {
   1.686 +    increment_busy_workers();
   1.687 +    increment_delivered_tasks();
   1.688 +  }
   1.689 +  return result;
   1.690 +  // Release monitor().
   1.691 +}
   1.692 +
   1.693 +void GCTaskManager::note_completion(uint which) {
   1.694 +  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   1.695 +  if (TraceGCTaskManager) {
   1.696 +    tty->print_cr("GCTaskManager::note_completion(%u)", which);
   1.697 +  }
   1.698 +  // If we are blocked, check if the completing thread is the blocker.
   1.699 +  if (blocking_worker() == which) {
   1.700 +    assert(blocking_worker() != sentinel_worker(),
   1.701 +           "blocker shouldn't be bogus");
   1.702 +    increment_barriers();
   1.703 +    set_unblocked();
   1.704 +  }
   1.705 +  increment_completed_tasks();
   1.706 +  uint active = decrement_busy_workers();
   1.707 +  if ((active == 0) && (queue()->is_empty())) {
   1.708 +    increment_emptied_queue();
   1.709 +    if (TraceGCTaskManager) {
   1.710 +      tty->print_cr("    GCTaskManager::note_completion(%u) done", which);
   1.711 +    }
   1.712 +    // Notify client that we are done.
   1.713 +    NotifyDoneClosure* ndc = notify_done_closure();
   1.714 +    if (ndc != NULL) {
   1.715 +      ndc->notify(this);
   1.716 +    }
   1.717 +  }
   1.718 +  if (TraceGCTaskManager) {
   1.719 +    tty->print_cr("    GCTaskManager::note_completion(%u) (%s)->notify_all",
   1.720 +                  which, monitor()->name());
   1.721 +    tty->print_cr("  "
   1.722 +                  "  blocked: %s"
   1.723 +                  "  empty: %s"
   1.724 +                  "  release: %s",
   1.725 +                  is_blocked() ? "true" : "false",
   1.726 +                  queue()->is_empty() ? "true" : "false",
   1.727 +                  should_release_resources(which) ? "true" : "false");
   1.728 +    tty->print_cr("  "
   1.729 +                  "  delivered: %u"
   1.730 +                  "  completed: %u"
   1.731 +                  "  barriers: %u"
   1.732 +                  "  emptied: %u",
   1.733 +                  delivered_tasks(),
   1.734 +                  completed_tasks(),
   1.735 +                  barriers(),
   1.736 +                  emptied_queue());
   1.737 +  }
   1.738 +  // Tell everyone that a task has completed.
   1.739 +  (void) monitor()->notify_all();
   1.740 +  // Release monitor().
   1.741 +}
   1.742 +
   1.743 +uint GCTaskManager::increment_busy_workers() {
   1.744 +  assert(queue()->own_lock(), "don't own the lock");
   1.745 +  _busy_workers += 1;
   1.746 +  return _busy_workers;
   1.747 +}
   1.748 +
   1.749 +uint GCTaskManager::decrement_busy_workers() {
   1.750 +  assert(queue()->own_lock(), "don't own the lock");
   1.751 +  assert(_busy_workers > 0, "About to make a mistake");
   1.752 +  _busy_workers -= 1;
   1.753 +  return _busy_workers;
   1.754 +}
   1.755 +
   1.756 +void GCTaskManager::release_all_resources() {
   1.757 +  // If you want this to be done atomically, do it in a BarrierGCTask.
   1.758 +  for (uint i = 0; i < workers(); i += 1) {
   1.759 +    set_resource_flag(i, true);
   1.760 +  }
   1.761 +}
   1.762 +
   1.763 +bool GCTaskManager::should_release_resources(uint which) {
   1.764 +  // This can be done without a lock because each thread reads one element.
   1.765 +  return resource_flag(which);
   1.766 +}
   1.767 +
   1.768 +void GCTaskManager::note_release(uint which) {
   1.769 +  // This can be done without a lock because each thread writes one element.
   1.770 +  set_resource_flag(which, false);
   1.771 +}
   1.772 +
   1.773 +// "list" contains tasks that are ready to execute.  Those
   1.774 +// tasks are added to the GCTaskManager's queue of tasks and
   1.775 +// then the GC workers are notified that there is new work to
   1.776 +// do.
   1.777 +//
   1.778 +// Typically different types of tasks can be added to the "list".
   1.779 +// For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask,
   1.780 +// ScavengeRootsTask, and StealTask tasks are all added to the list
   1.781 +// and then the GC workers are notified of new work.  The tasks are
   1.782 +// handed out in the order in which they are added to the list
   1.783 +// (although execution is not necessarily in that order).  As long
   1.784 +// as any tasks are running the GCTaskManager will wait for execution
   1.785 +// to complete.  GC workers that execute a stealing task remain in
   1.786 +// the stealing task until all stealing tasks have completed.  The load
   1.787 +// balancing afforded by the stealing tasks work best if the stealing
   1.788 +// tasks are added last to the list.
   1.789 +
   1.790 +void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
   1.791 +  WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
   1.792 +  list->enqueue(fin);
   1.793 +  // The barrier task will be read by one of the GC
   1.794 +  // workers once it is added to the list of tasks.
   1.795 +  // Be sure that is globally visible before the
   1.796 +  // GC worker reads it (which is after the task is added
   1.797 +  // to the list of tasks below).
   1.798 +  OrderAccess::storestore();
   1.799 +  add_list(list);
   1.800 +  fin->wait_for(true /* reset */);
   1.801 +  // We have to release the barrier tasks!
   1.802 +  WaitForBarrierGCTask::destroy(fin);
   1.803 +}
   1.804 +
   1.805 +bool GCTaskManager::resource_flag(uint which) {
   1.806 +  assert(which < workers(), "index out of bounds");
   1.807 +  return _resource_flag[which];
   1.808 +}
   1.809 +
   1.810 +void GCTaskManager::set_resource_flag(uint which, bool value) {
   1.811 +  assert(which < workers(), "index out of bounds");
   1.812 +  _resource_flag[which] = value;
   1.813 +}
   1.814 +
   1.815 +//
   1.816 +// NoopGCTask
   1.817 +//
   1.818 +
   1.819 +NoopGCTask* NoopGCTask::create() {
   1.820 +  NoopGCTask* result = new NoopGCTask(false);
   1.821 +  return result;
   1.822 +}
   1.823 +
   1.824 +NoopGCTask* NoopGCTask::create_on_c_heap() {
   1.825 +  NoopGCTask* result = new(ResourceObj::C_HEAP, mtGC) NoopGCTask(true);
   1.826 +  return result;
   1.827 +}
   1.828 +
   1.829 +void NoopGCTask::destroy(NoopGCTask* that) {
   1.830 +  if (that != NULL) {
   1.831 +    that->destruct();
   1.832 +    if (that->is_c_heap_obj()) {
   1.833 +      FreeHeap(that);
   1.834 +    }
   1.835 +  }
   1.836 +}
   1.837 +
   1.838 +void NoopGCTask::destruct() {
   1.839 +  // This has to know it's superclass structure, just like the constructor.
   1.840 +  this->GCTask::destruct();
   1.841 +  // Nothing else to do.
   1.842 +}
   1.843 +
   1.844 +//
   1.845 +// IdleGCTask
   1.846 +//
   1.847 +
   1.848 +IdleGCTask* IdleGCTask::create() {
   1.849 +  IdleGCTask* result = new IdleGCTask(false);
   1.850 +  assert(UseDynamicNumberOfGCThreads,
   1.851 +    "Should only be used with dynamic GC thread");
   1.852 +  return result;
   1.853 +}
   1.854 +
   1.855 +IdleGCTask* IdleGCTask::create_on_c_heap() {
   1.856 +  IdleGCTask* result = new(ResourceObj::C_HEAP, mtGC) IdleGCTask(true);
   1.857 +  assert(UseDynamicNumberOfGCThreads,
   1.858 +    "Should only be used with dynamic GC thread");
   1.859 +  return result;
   1.860 +}
   1.861 +
   1.862 +void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
   1.863 +  WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task();
   1.864 +  if (TraceGCTaskManager) {
   1.865 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.866 +                  " IdleGCTask:::do_it()"
   1.867 +      "  should_wait: %s",
   1.868 +      this, wait_for_task->should_wait() ? "true" : "false");
   1.869 +  }
   1.870 +  MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
   1.871 +  if (TraceDynamicGCThreads) {
   1.872 +    gclog_or_tty->print_cr("--- idle %d", which);
   1.873 +  }
   1.874 +  // Increment has to be done when the idle tasks are created.
   1.875 +  // manager->increment_idle_workers();
   1.876 +  manager->monitor()->notify_all();
   1.877 +  while (wait_for_task->should_wait()) {
   1.878 +    if (TraceGCTaskManager) {
   1.879 +      tty->print_cr("[" INTPTR_FORMAT "]"
   1.880 +                    " IdleGCTask::do_it()"
   1.881 +        "  [" INTPTR_FORMAT "] (%s)->wait()",
   1.882 +        this, manager->monitor(), manager->monitor()->name());
   1.883 +    }
   1.884 +    manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   1.885 +  }
   1.886 +  manager->decrement_idle_workers();
   1.887 +  if (TraceDynamicGCThreads) {
   1.888 +    gclog_or_tty->print_cr("--- release %d", which);
   1.889 +  }
   1.890 +  if (TraceGCTaskManager) {
   1.891 +    tty->print_cr("[" INTPTR_FORMAT "]"
   1.892 +                  " IdleGCTask::do_it() returns"
   1.893 +      "  should_wait: %s",
   1.894 +      this, wait_for_task->should_wait() ? "true" : "false");
   1.895 +  }
   1.896 +  // Release monitor().
   1.897 +}
   1.898 +
   1.899 +void IdleGCTask::destroy(IdleGCTask* that) {
   1.900 +  if (that != NULL) {
   1.901 +    that->destruct();
   1.902 +    if (that->is_c_heap_obj()) {
   1.903 +      FreeHeap(that);
   1.904 +    }
   1.905 +  }
   1.906 +}
   1.907 +
   1.908 +void IdleGCTask::destruct() {
   1.909 +  // This has to know it's superclass structure, just like the constructor.
   1.910 +  this->GCTask::destruct();
   1.911 +  // Nothing else to do.
   1.912 +}
   1.913 +
   1.914 +//
   1.915 +// BarrierGCTask
   1.916 +//
   1.917 +
   1.918 +void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   1.919 +  // Wait for this to be the only busy worker.
   1.920 +  // ??? I thought of having a StackObj class
   1.921 +  //     whose constructor would grab the lock and come to the barrier,
   1.922 +  //     and whose destructor would release the lock,
   1.923 +  //     but that seems like too much mechanism for two lines of code.
   1.924 +  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   1.925 +  do_it_internal(manager, which);
   1.926 +  // Release manager->lock().
   1.927 +}
   1.928 +
   1.929 +void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
   1.930 +  // Wait for this to be the only busy worker.
   1.931 +  assert(manager->monitor()->owned_by_self(), "don't own the lock");
   1.932 +  assert(manager->is_blocked(), "manager isn't blocked");
   1.933 +  while (manager->busy_workers() > 1) {
   1.934 +    if (TraceGCTaskManager) {
   1.935 +      tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
   1.936 +                    which, manager->busy_workers());
   1.937 +    }
   1.938 +    manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   1.939 +  }
   1.940 +}
   1.941 +
   1.942 +void BarrierGCTask::destruct() {
   1.943 +  this->GCTask::destruct();
   1.944 +  // Nothing else to do.
   1.945 +}
   1.946 +
   1.947 +//
   1.948 +// ReleasingBarrierGCTask
   1.949 +//
   1.950 +
   1.951 +void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   1.952 +  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   1.953 +  do_it_internal(manager, which);
   1.954 +  manager->release_all_resources();
   1.955 +  // Release manager->lock().
   1.956 +}
   1.957 +
   1.958 +void ReleasingBarrierGCTask::destruct() {
   1.959 +  this->BarrierGCTask::destruct();
   1.960 +  // Nothing else to do.
   1.961 +}
   1.962 +
   1.963 +//
   1.964 +// NotifyingBarrierGCTask
   1.965 +//
   1.966 +
   1.967 +void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   1.968 +  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   1.969 +  do_it_internal(manager, which);
   1.970 +  NotifyDoneClosure* ndc = notify_done_closure();
   1.971 +  if (ndc != NULL) {
   1.972 +    ndc->notify(manager);
   1.973 +  }
   1.974 +  // Release manager->lock().
   1.975 +}
   1.976 +
   1.977 +void NotifyingBarrierGCTask::destruct() {
   1.978 +  this->BarrierGCTask::destruct();
   1.979 +  // Nothing else to do.
   1.980 +}
   1.981 +
   1.982 +//
   1.983 +// WaitForBarrierGCTask
   1.984 +//
   1.985 +WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
   1.986 +  WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
   1.987 +  return result;
   1.988 +}
   1.989 +
   1.990 +WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
   1.991 +  WaitForBarrierGCTask* result =
   1.992 +    new (ResourceObj::C_HEAP, mtGC) WaitForBarrierGCTask(true);
   1.993 +  return result;
   1.994 +}
   1.995 +
   1.996 +WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
   1.997 +  _is_c_heap_obj(on_c_heap) {
   1.998 +  _monitor = MonitorSupply::reserve();
   1.999 +  set_should_wait(true);
  1.1000 +  if (TraceGCTaskManager) {
  1.1001 +    tty->print_cr("[" INTPTR_FORMAT "]"
  1.1002 +                  " WaitForBarrierGCTask::WaitForBarrierGCTask()"
  1.1003 +                  "  monitor: " INTPTR_FORMAT,
  1.1004 +                  this, monitor());
  1.1005 +  }
  1.1006 +}
  1.1007 +
  1.1008 +void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
  1.1009 +  if (that != NULL) {
  1.1010 +    if (TraceGCTaskManager) {
  1.1011 +      tty->print_cr("[" INTPTR_FORMAT "]"
  1.1012 +                    " WaitForBarrierGCTask::destroy()"
  1.1013 +                    "  is_c_heap_obj: %s"
  1.1014 +                    "  monitor: " INTPTR_FORMAT,
  1.1015 +                    that,
  1.1016 +                    that->is_c_heap_obj() ? "true" : "false",
  1.1017 +                    that->monitor());
  1.1018 +    }
  1.1019 +    that->destruct();
  1.1020 +    if (that->is_c_heap_obj()) {
  1.1021 +      FreeHeap(that);
  1.1022 +    }
  1.1023 +  }
  1.1024 +}
  1.1025 +
  1.1026 +void WaitForBarrierGCTask::destruct() {
  1.1027 +  assert(monitor() != NULL, "monitor should not be NULL");
  1.1028 +  if (TraceGCTaskManager) {
  1.1029 +    tty->print_cr("[" INTPTR_FORMAT "]"
  1.1030 +                  " WaitForBarrierGCTask::destruct()"
  1.1031 +                  "  monitor: " INTPTR_FORMAT,
  1.1032 +                  this, monitor());
  1.1033 +  }
  1.1034 +  this->BarrierGCTask::destruct();
  1.1035 +  // Clean up that should be in the destructor,
  1.1036 +  // except that ResourceMarks don't call destructors.
  1.1037 +   if (monitor() != NULL) {
  1.1038 +     MonitorSupply::release(monitor());
  1.1039 +  }
  1.1040 +  _monitor = (Monitor*) 0xDEAD000F;
  1.1041 +}
  1.1042 +
  1.1043 +void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
  1.1044 +  if (TraceGCTaskManager) {
  1.1045 +    tty->print_cr("[" INTPTR_FORMAT "]"
  1.1046 +                  " WaitForBarrierGCTask::do_it() waiting for idle"
  1.1047 +                  "  monitor: " INTPTR_FORMAT,
  1.1048 +                  this, monitor());
  1.1049 +  }
  1.1050 +  {
  1.1051 +    // First, wait for the barrier to arrive.
  1.1052 +    MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
  1.1053 +    do_it_internal(manager, which);
  1.1054 +    // Release manager->lock().
  1.1055 +  }
  1.1056 +  {
  1.1057 +    // Then notify the waiter.
  1.1058 +    MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  1.1059 +    set_should_wait(false);
  1.1060 +    // Waiter doesn't miss the notify in the wait_for method
  1.1061 +    // since it checks the flag after grabbing the monitor.
  1.1062 +    if (TraceGCTaskManager) {
  1.1063 +      tty->print_cr("[" INTPTR_FORMAT "]"
  1.1064 +                    " WaitForBarrierGCTask::do_it()"
  1.1065 +                    "  [" INTPTR_FORMAT "] (%s)->notify_all()",
  1.1066 +                    this, monitor(), monitor()->name());
  1.1067 +    }
  1.1068 +    monitor()->notify_all();
  1.1069 +    // Release monitor().
  1.1070 +  }
  1.1071 +}
  1.1072 +
  1.1073 +void WaitForBarrierGCTask::wait_for(bool reset) {
  1.1074 +  if (TraceGCTaskManager) {
  1.1075 +    tty->print_cr("[" INTPTR_FORMAT "]"
  1.1076 +                  " WaitForBarrierGCTask::wait_for()"
  1.1077 +      "  should_wait: %s",
  1.1078 +      this, should_wait() ? "true" : "false");
  1.1079 +  }
  1.1080 +  {
  1.1081 +    // Grab the lock and check again.
  1.1082 +    MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  1.1083 +    while (should_wait()) {
  1.1084 +      if (TraceGCTaskManager) {
  1.1085 +        tty->print_cr("[" INTPTR_FORMAT "]"
  1.1086 +                      " WaitForBarrierGCTask::wait_for()"
  1.1087 +          "  [" INTPTR_FORMAT "] (%s)->wait()",
  1.1088 +          this, monitor(), monitor()->name());
  1.1089 +      }
  1.1090 +      monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
  1.1091 +    }
  1.1092 +    // Reset the flag in case someone reuses this task.
  1.1093 +    if (reset) {
  1.1094 +      set_should_wait(true);
  1.1095 +    }
  1.1096 +    if (TraceGCTaskManager) {
  1.1097 +      tty->print_cr("[" INTPTR_FORMAT "]"
  1.1098 +                    " WaitForBarrierGCTask::wait_for() returns"
  1.1099 +        "  should_wait: %s",
  1.1100 +        this, should_wait() ? "true" : "false");
  1.1101 +    }
  1.1102 +    // Release monitor().
  1.1103 +  }
  1.1104 +}
  1.1105 +
  1.1106 +Mutex*                   MonitorSupply::_lock     = NULL;
  1.1107 +GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
  1.1108 +
  1.1109 +Monitor* MonitorSupply::reserve() {
  1.1110 +  Monitor* result = NULL;
  1.1111 +  // Lazy initialization: possible race.
  1.1112 +  if (lock() == NULL) {
  1.1113 +    _lock = new Mutex(Mutex::barrier,                  // rank
  1.1114 +                      "MonitorSupply mutex",           // name
  1.1115 +                      Mutex::_allow_vm_block_flag);    // allow_vm_block
  1.1116 +  }
  1.1117 +  {
  1.1118 +    MutexLockerEx ml(lock());
  1.1119 +    // Lazy initialization.
  1.1120 +    if (freelist() == NULL) {
  1.1121 +      _freelist =
  1.1122 +        new(ResourceObj::C_HEAP, mtGC) GrowableArray<Monitor*>(ParallelGCThreads,
  1.1123 +                                                         true);
  1.1124 +    }
  1.1125 +    if (! freelist()->is_empty()) {
  1.1126 +      result = freelist()->pop();
  1.1127 +    } else {
  1.1128 +      result = new Monitor(Mutex::barrier,                  // rank
  1.1129 +                           "MonitorSupply monitor",         // name
  1.1130 +                           Mutex::_allow_vm_block_flag);    // allow_vm_block
  1.1131 +    }
  1.1132 +    guarantee(result != NULL, "shouldn't return NULL");
  1.1133 +    assert(!result->is_locked(), "shouldn't be locked");
  1.1134 +    // release lock().
  1.1135 +  }
  1.1136 +  return result;
  1.1137 +}
  1.1138 +
  1.1139 +void MonitorSupply::release(Monitor* instance) {
  1.1140 +  assert(instance != NULL, "shouldn't release NULL");
  1.1141 +  assert(!instance->is_locked(), "shouldn't be locked");
  1.1142 +  {
  1.1143 +    MutexLockerEx ml(lock());
  1.1144 +    freelist()->push(instance);
  1.1145 +    // release lock().
  1.1146 +  }
  1.1147 +}

mercurial