8224665: Parallel GC: Use WorkGang (7: remove task manager)
authorlkorinth
Fri, 16 Aug 2019 09:18:38 +0200
changeset 57773 5cbc3bd9fdfd
parent 57772 2410b04f074f
child 57774 21dccfac0ec5
8224665: Parallel GC: Use WorkGang (7: remove task manager) Reviewed-by: stefank, kbarrett, tschatzl
src/hotspot/share/gc/parallel/gcTaskManager.cpp
src/hotspot/share/gc/parallel/gcTaskManager.hpp
src/hotspot/share/gc/parallel/gcTaskThread.cpp
src/hotspot/share/gc/parallel/gcTaskThread.hpp
src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp
src/hotspot/share/gc/parallel/parallel_globals.hpp
src/hotspot/share/gc/parallel/psCardTable.cpp
src/hotspot/share/gc/parallel/psCardTable.hpp
src/hotspot/share/gc/parallel/psCompactionManager.cpp
src/hotspot/share/gc/parallel/psCompactionManager.hpp
src/hotspot/share/gc/parallel/psParallelCompact.cpp
src/hotspot/share/gc/parallel/psParallelCompact.hpp
src/hotspot/share/gc/parallel/psPromotionManager.cpp
src/hotspot/share/gc/parallel/psScavenge.cpp
src/hotspot/share/gc/parallel/psScavenge.hpp
src/hotspot/share/runtime/mutexLocker.cpp
src/hotspot/share/runtime/thread.hpp
--- a/src/hotspot/share/gc/parallel/gcTaskManager.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1074 +0,0 @@
-/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
-#include "gc/parallel/gcTaskThread.hpp"
-#include "gc/shared/gcId.hpp"
-#include "gc/shared/workerManager.hpp"
-#include "gc/shared/workerPolicy.hpp"
-#include "logging/log.hpp"
-#include "logging/logStream.hpp"
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
-#include "runtime/os.hpp"
-
-//
-// GCTask
-//
-
-const char* GCTask::Kind::to_string(kind value) {
-  const char* result = "unknown GCTask kind";
-  switch (value) {
-  default:
-    result = "unknown GCTask kind";
-    break;
-  case unknown_task:
-    result = "unknown task";
-    break;
-  case ordinary_task:
-    result = "ordinary task";
-    break;
-  case wait_for_barrier_task:
-    result = "wait for barrier task";
-    break;
-  case noop_task:
-    result = "noop task";
-    break;
-  case idle_task:
-    result = "idle task";
-    break;
-  }
-  return result;
-};
-
-GCTask::GCTask() {
-  initialize(Kind::ordinary_task, GCId::current());
-}
-
-GCTask::GCTask(Kind::kind kind) {
-  initialize(kind, GCId::current());
-}
-
-GCTask::GCTask(Kind::kind kind, uint gc_id) {
-  initialize(kind, gc_id);
-}
-
-void GCTask::initialize(Kind::kind kind, uint gc_id) {
-  _kind = kind;
-  _affinity = GCTaskManager::sentinel_worker();
-  _older = NULL;
-  _newer = NULL;
-  _gc_id = gc_id;
-}
-
-void GCTask::destruct() {
-  assert(older() == NULL, "shouldn't have an older task");
-  assert(newer() == NULL, "shouldn't have a newer task");
-  // Nothing to do.
-}
-
-NOT_PRODUCT(
-void GCTask::print(const char* message) const {
-  tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
-             p2i(newer()), p2i(this), affinity(), p2i(older()));
-}
-)
-
-//
-// GCTaskQueue
-//
-
-GCTaskQueue* GCTaskQueue::create() {
-  GCTaskQueue* result = new GCTaskQueue(false);
-  if (TraceGCTaskQueue) {
-    tty->print_cr("GCTaskQueue::create()"
-                  " returns " INTPTR_FORMAT, p2i(result));
-  }
-  return result;
-}
-
-GCTaskQueue* GCTaskQueue::create_on_c_heap() {
-  GCTaskQueue* result = new(ResourceObj::C_HEAP, mtGC) GCTaskQueue(true);
-  if (TraceGCTaskQueue) {
-    tty->print_cr("GCTaskQueue::create_on_c_heap()"
-                  " returns " INTPTR_FORMAT,
-                  p2i(result));
-  }
-  return result;
-}
-
-GCTaskQueue::GCTaskQueue(bool on_c_heap) :
-  _is_c_heap_obj(on_c_heap) {
-  initialize();
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::GCTaskQueue() constructor",
-                  p2i(this));
-  }
-}
-
-void GCTaskQueue::destruct() {
-  // Nothing to do.
-}
-
-void GCTaskQueue::destroy(GCTaskQueue* that) {
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::destroy()"
-                  "  is_c_heap_obj:  %s",
-                  p2i(that),
-                  that->is_c_heap_obj() ? "true" : "false");
-  }
-  // That instance may have been allocated as a CHeapObj,
-  // in which case we have to free it explicitly.
-  if (that != NULL) {
-    that->destruct();
-    assert(that->is_empty(), "should be empty");
-    if (that->is_c_heap_obj()) {
-      FreeHeap(that);
-    }
-  }
-}
-
-void GCTaskQueue::initialize() {
-  set_insert_end(NULL);
-  set_remove_end(NULL);
-  set_length(0);
-}
-
-// Enqueue one task.
-void GCTaskQueue::enqueue(GCTask* task) {
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::enqueue(task: "
-                  INTPTR_FORMAT ")",
-                  p2i(this), p2i(task));
-    print("before:");
-  }
-  assert(task != NULL, "shouldn't have null task");
-  assert(task->older() == NULL, "shouldn't be on queue");
-  assert(task->newer() == NULL, "shouldn't be on queue");
-  task->set_newer(NULL);
-  task->set_older(insert_end());
-  if (is_empty()) {
-    set_remove_end(task);
-  } else {
-    insert_end()->set_newer(task);
-  }
-  set_insert_end(task);
-  increment_length();
-  verify_length();
-  if (TraceGCTaskQueue) {
-    print("after:");
-  }
-}
-
-// Enqueue a whole list of tasks.  Empties the argument list.
-void GCTaskQueue::enqueue(GCTaskQueue* list) {
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::enqueue(list: "
-                  INTPTR_FORMAT ")",
-                  p2i(this), p2i(list));
-    print("before:");
-    list->print("list:");
-  }
-  if (list->is_empty()) {
-    // Enqueueing the empty list: nothing to do.
-    return;
-  }
-  uint list_length = list->length();
-  if (is_empty()) {
-    // Enqueueing to empty list: just acquire elements.
-    set_insert_end(list->insert_end());
-    set_remove_end(list->remove_end());
-    set_length(list_length);
-  } else {
-    // Prepend argument list to our queue.
-    list->remove_end()->set_older(insert_end());
-    insert_end()->set_newer(list->remove_end());
-    set_insert_end(list->insert_end());
-    set_length(length() + list_length);
-    // empty the argument list.
-  }
-  list->initialize();
-  if (TraceGCTaskQueue) {
-    print("after:");
-    list->print("list:");
-  }
-  verify_length();
-}
-
-// Dequeue one task.
-GCTask* GCTaskQueue::dequeue() {
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::dequeue()", p2i(this));
-    print("before:");
-  }
-  assert(!is_empty(), "shouldn't dequeue from empty list");
-  GCTask* result = remove();
-  assert(result != NULL, "shouldn't have NULL task");
-  if (TraceGCTaskQueue) {
-    tty->print_cr("    return: " INTPTR_FORMAT, p2i(result));
-    print("after:");
-  }
-  return result;
-}
-
-// Dequeue one task, preferring one with affinity.
-GCTask* GCTaskQueue::dequeue(uint affinity) {
-  if (TraceGCTaskQueue) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " GCTaskQueue::dequeue(%u)", p2i(this), affinity);
-    print("before:");
-  }
-  assert(!is_empty(), "shouldn't dequeue from empty list");
-  // Look down to the next barrier for a task with this affinity.
-  GCTask* result = NULL;
-  for (GCTask* element = remove_end();
-       element != NULL;
-       element = element->newer()) {
-    if (element->is_barrier_task()) {
-      // Don't consider barrier tasks, nor past them.
-      result = NULL;
-      break;
-    }
-    if (element->affinity() == affinity) {
-      result = remove(element);
-      break;
-    }
-  }
-  // If we didn't find anything with affinity, just take the next task.
-  if (result == NULL) {
-    result = remove();
-  }
-  if (TraceGCTaskQueue) {
-    tty->print_cr("    return: " INTPTR_FORMAT, p2i(result));
-    print("after:");
-  }
-  return result;
-}
-
-GCTask* GCTaskQueue::remove() {
-  // Dequeue from remove end.
-  GCTask* result = remove_end();
-  assert(result != NULL, "shouldn't have null task");
-  assert(result->older() == NULL, "not the remove_end");
-  set_remove_end(result->newer());
-  if (remove_end() == NULL) {
-    assert(insert_end() == result, "not a singleton");
-    set_insert_end(NULL);
-  } else {
-    remove_end()->set_older(NULL);
-  }
-  result->set_newer(NULL);
-  decrement_length();
-  assert(result->newer() == NULL, "shouldn't be on queue");
-  assert(result->older() == NULL, "shouldn't be on queue");
-  verify_length();
-  return result;
-}
-
-GCTask* GCTaskQueue::remove(GCTask* task) {
-  // This is slightly more work, and has slightly fewer asserts
-  // than removing from the remove end.
-  assert(task != NULL, "shouldn't have null task");
-  GCTask* result = task;
-  if (result->newer() != NULL) {
-    result->newer()->set_older(result->older());
-  } else {
-    assert(insert_end() == result, "not youngest");
-    set_insert_end(result->older());
-  }
-  if (result->older() != NULL) {
-    result->older()->set_newer(result->newer());
-  } else {
-    assert(remove_end() == result, "not oldest");
-    set_remove_end(result->newer());
-  }
-  result->set_newer(NULL);
-  result->set_older(NULL);
-  decrement_length();
-  verify_length();
-  return result;
-}
-
-NOT_PRODUCT(
-// Count the elements in the queue and verify the length against
-// that count.
-void GCTaskQueue::verify_length() const {
-  uint count = 0;
-  for (GCTask* element = insert_end();
-       element != NULL;
-       element = element->older()) {
-
-    count++;
-  }
-  assert(count == length(), "Length does not match queue");
-}
-
-void GCTaskQueue::print(const char* message) const {
-  tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
-                "  insert_end: " INTPTR_FORMAT
-                "  remove_end: " INTPTR_FORMAT
-                "  length:       %d"
-                "  %s",
-                p2i(this), p2i(insert_end()), p2i(remove_end()), length(), message);
-  uint count = 0;
-  for (GCTask* element = insert_end();
-       element != NULL;
-       element = element->older()) {
-    element->print("    ");
-    count++;
-    tty->cr();
-  }
-  tty->print("Total tasks: %d", count);
-}
-)
-
-//
-// SynchronizedGCTaskQueue
-//
-
-SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
-                                                 Monitor *       lock_arg) :
-  _unsynchronized_queue(queue_arg),
-  _lock(lock_arg) {
-  assert(unsynchronized_queue() != NULL, "null queue");
-  assert(lock() != NULL, "null lock");
-}
-
-SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
-  // Nothing to do.
-}
-
-//
-// GCTaskManager
-//
-GCTaskManager::GCTaskManager(uint workers) :
-  _workers(workers),
-  _created_workers(0),
-  _active_workers(0),
-  _idle_workers(0) {
-  initialize();
-}
-
-GCTaskThread* GCTaskManager::install_worker(uint t) {
-  GCTaskThread* new_worker = GCTaskThread::create(this, t, _processor_assignment[t]);
-  set_thread(t, new_worker);
-  return new_worker;
-}
-
-void GCTaskManager::add_workers(bool initializing) {
-  os::ThreadType worker_type = os::pgc_thread;
-  uint previous_created_workers = _created_workers;
-
-  _created_workers = WorkerManager::add_workers(this,
-                                                _active_workers,
-                                                _workers,
-                                                _created_workers,
-                                                worker_type,
-                                                initializing);
-  _active_workers = MIN2(_created_workers, _active_workers);
-
-  WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
-}
-
-const char* GCTaskManager::group_name() {
-  return "ParGC Thread";
-}
-
-void GCTaskManager::initialize() {
-  if (TraceGCTaskManager) {
-    tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
-  }
-  assert(workers() != 0, "no workers");
-  _monitor = new Monitor(Mutex::barrier,                // rank
-                         "GCTaskManager monitor",       // name
-                         Mutex::_allow_vm_block_flag,   // allow_vm_block
-                         Monitor::_safepoint_check_never);
-  // The queue for the GCTaskManager must be a CHeapObj.
-  GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
-  _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
-  _noop_task = NoopGCTask::create_on_c_heap();
-  _resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC);
-  {
-    // Set up worker threads.
-    //     Distribute the workers among the available processors,
-    //     unless we were told not to, or if the os doesn't want to.
-    _processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
-    if (!BindGCTaskThreadsToCPUs ||
-        !os::distribute_processes(workers(), _processor_assignment)) {
-      for (uint a = 0; a < workers(); a += 1) {
-        _processor_assignment[a] = sentinel_worker();
-      }
-    }
-
-    _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
-    _active_workers = ParallelGCThreads;
-    if (UseDynamicNumberOfGCThreads && !FLAG_IS_CMDLINE(ParallelGCThreads)) {
-      _active_workers = 1U;
-    }
-
-    Log(gc, task, thread) log;
-    if (log.is_trace()) {
-      LogStream ls(log.trace());
-      ls.print("GCTaskManager::initialize: distribution:");
-      for (uint t = 0; t < workers(); t += 1) {
-        ls.print("  %u", _processor_assignment[t]);
-      }
-      ls.cr();
-    }
-  }
-  reset_busy_workers();
-  set_unblocked();
-  for (uint w = 0; w < workers(); w += 1) {
-    set_resource_flag(w, false);
-  }
-  reset_delivered_tasks();
-  reset_completed_tasks();
-  reset_barriers();
-  reset_emptied_queue();
-
-  add_workers(true);
-}
-
-GCTaskManager::~GCTaskManager() {
-  assert(busy_workers() == 0, "still have busy workers");
-  assert(queue()->is_empty(), "still have queued work");
-  NoopGCTask::destroy(_noop_task);
-  _noop_task = NULL;
-  if (_thread != NULL) {
-    for (uint i = 0; i < created_workers(); i += 1) {
-      GCTaskThread::destroy(thread(i));
-      set_thread(i, NULL);
-    }
-    FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
-    _thread = NULL;
-  }
-  if (_processor_assignment != NULL) {
-    FREE_C_HEAP_ARRAY(uint, _processor_assignment);
-    _processor_assignment = NULL;
-  }
-  if (_resource_flag != NULL) {
-    FREE_C_HEAP_ARRAY(bool, _resource_flag);
-    _resource_flag = NULL;
-  }
-  if (queue() != NULL) {
-    GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
-    GCTaskQueue::destroy(unsynchronized_queue);
-    SynchronizedGCTaskQueue::destroy(queue());
-    _queue = NULL;
-  }
-  if (monitor() != NULL) {
-    delete monitor();
-    _monitor = NULL;
-  }
-}
-
-void GCTaskManager::set_active_gang() {
-  _active_workers =
-    WorkerPolicy::calc_active_workers(workers(),
-                                      active_workers(),
-                                      Threads::number_of_non_daemon_threads());
-
-  assert(!all_workers_active() || active_workers() == ParallelGCThreads,
-         "all_workers_active() is  incorrect: "
-         "active %d  ParallelGCThreads %u", active_workers(),
-         ParallelGCThreads);
-  _active_workers = MIN2(_active_workers, _workers);
-  // "add_workers" does not guarantee any additional workers
-  add_workers(false);
-  log_trace(gc, task)("GCTaskManager::set_active_gang(): "
-                      "all_workers_active()  %d  workers %d  "
-                      "active  %d  ParallelGCThreads %u",
-                      all_workers_active(), workers(),  active_workers(),
-                      ParallelGCThreads);
-}
-
-// Create IdleGCTasks for inactive workers.
-// Creates tasks in a ResourceArea and assumes
-// an appropriate ResourceMark.
-void GCTaskManager::task_idle_workers() {
-  {
-    int more_inactive_workers = 0;
-    {
-      // Stop any idle tasks from exiting their IdleGCTask's
-      // and get the count for additional IdleGCTask's under
-      // the GCTaskManager's monitor so that the "more_inactive_workers"
-      // count is correct.
-      MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-      _wait_helper.set_should_wait(true);
-      // active_workers are a number being requested.  idle_workers
-      // are the number currently idle.  If all the workers are being
-      // requested to be active but some are already idle, reduce
-      // the number of active_workers to be consistent with the
-      // number of idle_workers.  The idle_workers are stuck in
-      // idle tasks and will no longer be release (since a new GC
-      // is starting).  Try later to release enough idle_workers
-      // to allow the desired number of active_workers.
-      more_inactive_workers =
-        created_workers() - active_workers() - idle_workers();
-      if (more_inactive_workers < 0) {
-        int reduced_active_workers = active_workers() + more_inactive_workers;
-        update_active_workers(reduced_active_workers);
-        more_inactive_workers = 0;
-      }
-      log_trace(gc, task)("JT: %d  workers %d  active  %d  idle %d  more %d",
-                          Threads::number_of_non_daemon_threads(),
-                          created_workers(),
-                          active_workers(),
-                          idle_workers(),
-                          more_inactive_workers);
-    }
-    GCTaskQueue* q = GCTaskQueue::create();
-    for(uint i = 0; i < (uint) more_inactive_workers; i++) {
-      q->enqueue(IdleGCTask::create_on_c_heap());
-      increment_idle_workers();
-    }
-    assert(created_workers() == active_workers() + idle_workers(),
-      "total workers should equal active + inactive");
-    add_list(q);
-    // GCTaskQueue* q was created in a ResourceArea so a
-    // destroy() call is not needed.
-  }
-}
-
-void  GCTaskManager::release_idle_workers() {
-  {
-    MutexLocker ml(monitor(),
-      Mutex::_no_safepoint_check_flag);
-    _wait_helper.set_should_wait(false);
-    monitor()->notify_all();
-  // Release monitor
-  }
-}
-
-void GCTaskManager::print_task_time_stamps() {
-  if (!log_is_enabled(Debug, gc, task, time)) {
-    return;
-  }
-  uint num_thr = created_workers();
-  for(uint i=0; i < num_thr; i++) {
-    GCTaskThread* t = thread(i);
-    t->print_task_time_stamps();
-  }
-}
-
-void GCTaskManager::print_threads_on(outputStream* st) {
-  uint num_thr = created_workers();
-  for (uint i = 0; i < num_thr; i++) {
-    thread(i)->print_on(st);
-    st->cr();
-  }
-}
-
-void GCTaskManager::threads_do(ThreadClosure* tc) {
-  assert(tc != NULL, "Null ThreadClosure");
-  uint num_thr = created_workers();
-  for (uint i = 0; i < num_thr; i++) {
-    tc->do_thread(thread(i));
-  }
-}
-
-GCTaskThread* GCTaskManager::thread(uint which) {
-  assert(which < created_workers(), "index out of bounds");
-  assert(_thread[which] != NULL, "shouldn't have null thread");
-  return _thread[which];
-}
-
-void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
-  // "_created_workers" may not have been updated yet so use workers()
-  assert(which < workers(), "index out of bounds");
-  assert(value != NULL, "shouldn't have null thread");
-  _thread[which] = value;
-}
-
-void GCTaskManager::add_task(GCTask* task) {
-  assert(task != NULL, "shouldn't have null task");
-  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-  if (TraceGCTaskManager) {
-    tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
-                  p2i(task), GCTask::Kind::to_string(task->kind()));
-  }
-  queue()->enqueue(task);
-  // Notify with the lock held to avoid missed notifies.
-  if (TraceGCTaskManager) {
-    tty->print_cr("    GCTaskManager::add_task (%s)->notify_all",
-                  monitor()->name());
-  }
-  (void) monitor()->notify_all();
-  // Release monitor().
-}
-
-void GCTaskManager::add_list(GCTaskQueue* list) {
-  assert(list != NULL, "shouldn't have null task");
-  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-  if (TraceGCTaskManager) {
-    tty->print_cr("GCTaskManager::add_list(%u)", list->length());
-  }
-  queue()->enqueue(list);
-  // Notify with the lock held to avoid missed notifies.
-  if (TraceGCTaskManager) {
-    tty->print_cr("    GCTaskManager::add_list (%s)->notify_all",
-                  monitor()->name());
-  }
-  (void) monitor()->notify_all();
-  // Release monitor().
-}
-
-// GC workers wait in get_task() for new work to be added
-// to the GCTaskManager's queue.  When new work is added,
-// a notify is sent to the waiting GC workers which then
-// compete to get tasks.  If a GC worker wakes up and there
-// is no work on the queue, it is given a noop_task to execute
-// and then loops to find more work.
-
-GCTask* GCTaskManager::get_task(uint which) {
-  GCTask* result = NULL;
-  // Grab the queue lock.
-  MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-  // Wait while the queue is block or
-  // there is nothing to do, except maybe release resources.
-  while (is_blocked() ||
-         (queue()->is_empty() && !should_release_resources(which))) {
-    if (TraceGCTaskManager) {
-      tty->print_cr("GCTaskManager::get_task(%u)"
-                    "  blocked: %s"
-                    "  empty: %s"
-                    "  release: %s",
-                    which,
-                    is_blocked() ? "true" : "false",
-                    queue()->is_empty() ? "true" : "false",
-                    should_release_resources(which) ? "true" : "false");
-      tty->print_cr("    => (%s)->wait()",
-                    monitor()->name());
-    }
-    ml.wait(0);
-  }
-  // We've reacquired the queue lock here.
-  // Figure out which condition caused us to exit the loop above.
-  if (!queue()->is_empty()) {
-    if (UseGCTaskAffinity) {
-      result = queue()->dequeue(which);
-    } else {
-      result = queue()->dequeue();
-    }
-    if (result->is_barrier_task()) {
-      assert(which != sentinel_worker(),
-             "blocker shouldn't be bogus");
-      set_blocking_worker(which);
-    }
-  } else {
-    // The queue is empty, but we were woken up.
-    // Just hand back a Noop task,
-    // in case someone wanted us to release resources, or whatever.
-    result = noop_task();
-  }
-  assert(result != NULL, "shouldn't have null task");
-  if (TraceGCTaskManager) {
-    tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
-                  which, p2i(result), GCTask::Kind::to_string(result->kind()));
-    tty->print_cr("     %s", result->name());
-  }
-  if (!result->is_idle_task()) {
-    increment_busy_workers();
-    increment_delivered_tasks();
-  }
-  return result;
-  // Release monitor().
-}
-
-void GCTaskManager::note_completion(uint which) {
-  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-  if (TraceGCTaskManager) {
-    tty->print_cr("GCTaskManager::note_completion(%u)", which);
-  }
-  // If we are blocked, check if the completing thread is the blocker.
-  if (blocking_worker() == which) {
-    assert(blocking_worker() != sentinel_worker(),
-           "blocker shouldn't be bogus");
-    increment_barriers();
-    set_unblocked();
-  }
-  increment_completed_tasks();
-  uint active = decrement_busy_workers();
-  if ((active == 0) && (queue()->is_empty())) {
-    increment_emptied_queue();
-    if (TraceGCTaskManager) {
-      tty->print_cr("    GCTaskManager::note_completion(%u) done", which);
-    }
-  }
-  if (TraceGCTaskManager) {
-    tty->print_cr("    GCTaskManager::note_completion(%u) (%s)->notify_all",
-                  which, monitor()->name());
-    tty->print_cr("  "
-                  "  blocked: %s"
-                  "  empty: %s"
-                  "  release: %s",
-                  is_blocked() ? "true" : "false",
-                  queue()->is_empty() ? "true" : "false",
-                  should_release_resources(which) ? "true" : "false");
-    tty->print_cr("  "
-                  "  delivered: %u"
-                  "  completed: %u"
-                  "  barriers: %u"
-                  "  emptied: %u",
-                  delivered_tasks(),
-                  completed_tasks(),
-                  barriers(),
-                  emptied_queue());
-  }
-  // Tell everyone that a task has completed.
-  (void) monitor()->notify_all();
-  // Release monitor().
-}
-
-uint GCTaskManager::increment_busy_workers() {
-  assert(queue()->own_lock(), "don't own the lock");
-  _busy_workers += 1;
-  return _busy_workers;
-}
-
-uint GCTaskManager::decrement_busy_workers() {
-  assert(queue()->own_lock(), "don't own the lock");
-  assert(_busy_workers > 0, "About to make a mistake");
-  _busy_workers -= 1;
-  return _busy_workers;
-}
-
-void GCTaskManager::release_all_resources() {
-  // If you want this to be done atomically, do it in a WaitForBarrierGCTask.
-  for (uint i = 0; i < created_workers(); i += 1) {
-    set_resource_flag(i, true);
-  }
-}
-
-bool GCTaskManager::should_release_resources(uint which) {
-  // This can be done without a lock because each thread reads one element.
-  return resource_flag(which);
-}
-
-void GCTaskManager::note_release(uint which) {
-  // This can be done without a lock because each thread writes one element.
-  set_resource_flag(which, false);
-}
-
-// "list" contains tasks that are ready to execute.  Those
-// tasks are added to the GCTaskManager's queue of tasks and
-// then the GC workers are notified that there is new work to
-// do.
-//
-// Typically different types of tasks can be added to the "list".
-// For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask,
-// ScavengeRootsTask, and StealTask tasks are all added to the list
-// and then the GC workers are notified of new work.  The tasks are
-// handed out in the order in which they are added to the list
-// (although execution is not necessarily in that order).  As long
-// as any tasks are running the GCTaskManager will wait for execution
-// to complete.  GC workers that execute a stealing task remain in
-// the stealing task until all stealing tasks have completed.  The load
-// balancing afforded by the stealing tasks work best if the stealing
-// tasks are added last to the list.
-
-void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
-  WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
-  list->enqueue(fin);
-  // The barrier task will be read by one of the GC
-  // workers once it is added to the list of tasks.
-  // Be sure that is globally visible before the
-  // GC worker reads it (which is after the task is added
-  // to the list of tasks below).
-  OrderAccess::storestore();
-  add_list(list);
-  fin->wait_for(true /* reset */);
-  // We have to release the barrier tasks!
-  WaitForBarrierGCTask::destroy(fin);
-}
-
-bool GCTaskManager::resource_flag(uint which) {
-  assert(which < workers(), "index out of bounds");
-  return _resource_flag[which];
-}
-
-void GCTaskManager::set_resource_flag(uint which, bool value) {
-  assert(which < workers(), "index out of bounds");
-  _resource_flag[which] = value;
-}
-
-//
-// NoopGCTask
-//
-
-NoopGCTask* NoopGCTask::create_on_c_heap() {
-  NoopGCTask* result = new(ResourceObj::C_HEAP, mtGC) NoopGCTask();
-  return result;
-}
-
-void NoopGCTask::destroy(NoopGCTask* that) {
-  if (that != NULL) {
-    that->destruct();
-    FreeHeap(that);
-  }
-}
-
-// This task should never be performing GC work that require
-// a valid GC id.
-NoopGCTask::NoopGCTask() : GCTask(GCTask::Kind::noop_task, GCId::undefined()) { }
-
-void NoopGCTask::destruct() {
-  // This has to know it's superclass structure, just like the constructor.
-  this->GCTask::destruct();
-  // Nothing else to do.
-}
-
-//
-// IdleGCTask
-//
-
-IdleGCTask* IdleGCTask::create() {
-  IdleGCTask* result = new IdleGCTask(false);
-  assert(UseDynamicNumberOfGCThreads,
-    "Should only be used with dynamic GC thread");
-  return result;
-}
-
-IdleGCTask* IdleGCTask::create_on_c_heap() {
-  IdleGCTask* result = new(ResourceObj::C_HEAP, mtGC) IdleGCTask(true);
-  assert(UseDynamicNumberOfGCThreads,
-    "Should only be used with dynamic GC thread");
-  return result;
-}
-
-void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
-  WaitHelper* wait_helper = manager->wait_helper();
-  log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask:::do_it() should_wait: %s",
-      p2i(this), wait_helper->should_wait() ? "true" : "false");
-
-  MonitorLocker ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
-  log_trace(gc, task)("--- idle %d", which);
-  // Increment has to be done when the idle tasks are created.
-  // manager->increment_idle_workers();
-  ml.notify_all();
-  while (wait_helper->should_wait()) {
-    log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask::do_it()  [" INTPTR_FORMAT "] (%s)->wait()",
-      p2i(this), p2i(manager->monitor()), manager->monitor()->name());
-    ml.wait(0);
-  }
-  manager->decrement_idle_workers();
-
-  log_trace(gc, task)("--- release %d", which);
-  log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask::do_it() returns should_wait: %s",
-    p2i(this), wait_helper->should_wait() ? "true" : "false");
-  // Release monitor().
-}
-
-void IdleGCTask::destroy(IdleGCTask* that) {
-  if (that != NULL) {
-    that->destruct();
-    if (that->is_c_heap_obj()) {
-      FreeHeap(that);
-    }
-  }
-}
-
-void IdleGCTask::destruct() {
-  // This has to know it's superclass structure, just like the constructor.
-  this->GCTask::destruct();
-  // Nothing else to do.
-}
-
-//
-// WaitForBarrierGCTask
-//
-WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
-  WaitForBarrierGCTask* result = new WaitForBarrierGCTask();
-  return result;
-}
-
-WaitForBarrierGCTask::WaitForBarrierGCTask() : GCTask(GCTask::Kind::wait_for_barrier_task) { }
-
-void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
-  if (that != NULL) {
-    if (TraceGCTaskManager) {
-      tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destroy()", p2i(that));
-    }
-    that->destruct();
-  }
-}
-
-void WaitForBarrierGCTask::destruct() {
-  if (TraceGCTaskManager) {
-    tty->print_cr("[" INTPTR_FORMAT "] WaitForBarrierGCTask::destruct()", p2i(this));
-  }
-  this->GCTask::destruct();
-  // Clean up that should be in the destructor,
-  // except that ResourceMarks don't call destructors.
-  _wait_helper.release_monitor();
-}
-
-void WaitForBarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
-  // Wait for this to be the only busy worker.
-  assert(manager->monitor()->owned_by_self(), "don't own the lock");
-  assert(manager->is_blocked(), "manager isn't blocked");
-  while (manager->busy_workers() > 1) {
-    if (TraceGCTaskManager) {
-      tty->print_cr("WaitForBarrierGCTask::do_it(%u) waiting on %u workers",
-                    which, manager->busy_workers());
-    }
-    manager->monitor()->wait_without_safepoint_check(0);
-  }
-}
-
-void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
-  if (TraceGCTaskManager) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " WaitForBarrierGCTask::do_it() waiting for idle",
-                  p2i(this));
-  }
-  {
-    // First, wait for the barrier to arrive.
-    MutexLocker ml(manager->lock(), Mutex::_no_safepoint_check_flag);
-    do_it_internal(manager, which);
-    // Release manager->lock().
-  }
-  // Then notify the waiter.
-  _wait_helper.notify();
-}
-
-WaitHelper::WaitHelper() : _monitor(MonitorSupply::reserve()), _should_wait(true) {
-  if (TraceGCTaskManager) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " WaitHelper::WaitHelper()"
-                  "  monitor: " INTPTR_FORMAT,
-                  p2i(this), p2i(monitor()));
-  }
-}
-
-void WaitHelper::release_monitor() {
-  assert(_monitor != NULL, "");
-  MonitorSupply::release(_monitor);
-  _monitor = NULL;
-}
-
-WaitHelper::~WaitHelper() {
-  release_monitor();
-}
-
-void WaitHelper::wait_for(bool reset) {
-  if (TraceGCTaskManager) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " WaitForBarrierGCTask::wait_for()"
-      "  should_wait: %s",
-      p2i(this), should_wait() ? "true" : "false");
-  }
-  {
-    // Grab the lock and check again.
-    MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-    while (should_wait()) {
-      if (TraceGCTaskManager) {
-        tty->print_cr("[" INTPTR_FORMAT "]"
-                      " WaitForBarrierGCTask::wait_for()"
-          "  [" INTPTR_FORMAT "] (%s)->wait()",
-          p2i(this), p2i(monitor()), monitor()->name());
-      }
-      ml.wait(0);
-    }
-    // Reset the flag in case someone reuses this task.
-    if (reset) {
-      set_should_wait(true);
-    }
-    if (TraceGCTaskManager) {
-      tty->print_cr("[" INTPTR_FORMAT "]"
-                    " WaitForBarrierGCTask::wait_for() returns"
-        "  should_wait: %s",
-        p2i(this), should_wait() ? "true" : "false");
-    }
-    // Release monitor().
-  }
-}
-
-void WaitHelper::notify() {
-  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
-  set_should_wait(false);
-  // Waiter doesn't miss the notify in the wait_for method
-  // since it checks the flag after grabbing the monitor.
-  if (TraceGCTaskManager) {
-    tty->print_cr("[" INTPTR_FORMAT "]"
-                  " WaitForBarrierGCTask::do_it()"
-                  "  [" INTPTR_FORMAT "] (%s)->notify_all()",
-                  p2i(this), p2i(monitor()), monitor()->name());
-  }
-  monitor()->notify_all();
-}
-
-Mutex*                   MonitorSupply::_lock     = NULL;
-GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
-
-Monitor* MonitorSupply::reserve() {
-  Monitor* result = NULL;
-  // Lazy initialization: possible race.
-  if (lock() == NULL) {
-    _lock = new Mutex(Mutex::barrier,                  // rank
-                      "MonitorSupply mutex",           // name
-                      Mutex::_allow_vm_block_flag);    // allow_vm_block
-  }
-  {
-    MutexLocker ml(lock());
-    // Lazy initialization.
-    if (freelist() == NULL) {
-      _freelist =
-        new(ResourceObj::C_HEAP, mtGC) GrowableArray<Monitor*>(ParallelGCThreads,
-                                                         true);
-    }
-    if (! freelist()->is_empty()) {
-      result = freelist()->pop();
-    } else {
-      result = new Monitor(Mutex::barrier,                  // rank
-                           "MonitorSupply monitor",         // name
-                           Mutex::_allow_vm_block_flag,     // allow_vm_block
-                           Monitor::_safepoint_check_never);
-    }
-    guarantee(result != NULL, "shouldn't return NULL");
-    assert(!result->is_locked(), "shouldn't be locked");
-    // release lock().
-  }
-  return result;
-}
-
-void MonitorSupply::release(Monitor* instance) {
-  assert(instance != NULL, "shouldn't release NULL");
-  assert(!instance->is_locked(), "shouldn't be locked");
-  {
-    MutexLocker ml(lock());
-    freelist()->push(instance);
-    // release lock().
-  }
-}
--- a/src/hotspot/share/gc/parallel/gcTaskManager.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,668 +0,0 @@
-/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_GC_PARALLEL_GCTASKMANAGER_HPP
-#define SHARE_GC_PARALLEL_GCTASKMANAGER_HPP
-
-#include "runtime/mutex.hpp"
-#include "utilities/growableArray.hpp"
-
-//
-// The GCTaskManager is a queue of GCTasks, and accessors
-// to allow the queue to be accessed from many threads.
-//
-
-// Forward declarations of types defined in this file.
-class GCTask;
-class GCTaskQueue;
-class SynchronizedGCTaskQueue;
-class GCTaskManager;
-// Some useful subclasses of GCTask.  You can also make up your own.
-class NoopGCTask;
-class WaitForBarrierGCTask;
-class IdleGCTask;
-// A free list of Monitor*'s.
-class MonitorSupply;
-
-// Forward declarations of classes referenced in this file via pointer.
-class GCTaskThread;
-class Mutex;
-class Monitor;
-class ThreadClosure;
-
-// The abstract base GCTask.
-class GCTask : public ResourceObj {
-public:
-  // Known kinds of GCTasks, for predicates.
-  class Kind : AllStatic {
-  public:
-    enum kind {
-      unknown_task,
-      ordinary_task,
-      wait_for_barrier_task,
-      noop_task,
-      idle_task
-    };
-    static const char* to_string(kind value);
-  };
-private:
-  // Instance state.
-  Kind::kind       _kind;               // For runtime type checking.
-  uint             _affinity;           // Which worker should run task.
-  GCTask*          _newer;              // Tasks are on doubly-linked ...
-  GCTask*          _older;              // ... lists.
-  uint             _gc_id;              // GC Id to use for the thread that executes this task
-public:
-  virtual char* name() { return (char *)"task"; }
-
-  uint gc_id() { return _gc_id; }
-
-  // Abstract do_it method
-  virtual void do_it(GCTaskManager* manager, uint which) = 0;
-  // Accessors
-  Kind::kind kind() const {
-    return _kind;
-  }
-  uint affinity() const {
-    return _affinity;
-  }
-  GCTask* newer() const {
-    return _newer;
-  }
-  void set_newer(GCTask* n) {
-    _newer = n;
-  }
-  GCTask* older() const {
-    return _older;
-  }
-  void set_older(GCTask* p) {
-    _older = p;
-  }
-  // Predicates.
-  bool is_ordinary_task() const {
-    return kind()==Kind::ordinary_task;
-  }
-  bool is_barrier_task() const {
-    return kind()==Kind::wait_for_barrier_task;
-  }
-  bool is_noop_task() const {
-    return kind()==Kind::noop_task;
-  }
-  bool is_idle_task() const {
-    return kind()==Kind::idle_task;
-  }
-  void print(const char* message) const PRODUCT_RETURN;
-protected:
-  // Constructors: Only create subclasses.
-  //     An ordinary GCTask.
-  GCTask();
-  //     A GCTask of a particular kind, usually barrier or noop.
-  GCTask(Kind::kind kind);
-  GCTask(Kind::kind kind, uint gc_id);
-  // We want a virtual destructor because virtual methods,
-  // but since ResourceObj's don't have their destructors
-  // called, we don't have one at all.  Instead we have
-  // this method, which gets called by subclasses to clean up.
-  virtual void destruct();
-  // Methods.
-  void initialize(Kind::kind kind, uint gc_id);
-};
-
-// A doubly-linked list of GCTasks.
-// The list is not synchronized, because sometimes we want to
-// build up a list and then make it available to other threads.
-// See also: SynchronizedGCTaskQueue.
-class GCTaskQueue : public ResourceObj {
-private:
-  // Instance state.
-  GCTask*    _insert_end;               // Tasks are enqueued at this end.
-  GCTask*    _remove_end;               // Tasks are dequeued from this end.
-  uint       _length;                   // The current length of the queue.
-  const bool _is_c_heap_obj;            // Is this a CHeapObj?
-public:
-  // Factory create and destroy methods.
-  //     Create as ResourceObj.
-  static GCTaskQueue* create();
-  //     Create as CHeapObj.
-  static GCTaskQueue* create_on_c_heap();
-  //     Destroyer.
-  static void destroy(GCTaskQueue* that);
-  // Accessors.
-  //     These just examine the state of the queue.
-  bool is_empty() const {
-    assert(((insert_end() == NULL && remove_end() == NULL) ||
-            (insert_end() != NULL && remove_end() != NULL)),
-           "insert_end and remove_end don't match");
-    assert((insert_end() != NULL) || (_length == 0), "Not empty");
-    return insert_end() == NULL;
-  }
-  uint length() const {
-    return _length;
-  }
-  // Methods.
-  //     Enqueue one task.
-  void enqueue(GCTask* task);
-  //     Enqueue a list of tasks.  Empties the argument list.
-  void enqueue(GCTaskQueue* list);
-  //     Dequeue one task.
-  GCTask* dequeue();
-  //     Dequeue one task, preferring one with affinity.
-  GCTask* dequeue(uint affinity);
-protected:
-  // Constructor. Clients use factory, but there might be subclasses.
-  GCTaskQueue(bool on_c_heap);
-  // Destructor-like method.
-  // Because ResourceMark doesn't call destructors.
-  // This method cleans up like one.
-  virtual void destruct();
-  // Accessors.
-  GCTask* insert_end() const {
-    return _insert_end;
-  }
-  void set_insert_end(GCTask* value) {
-    _insert_end = value;
-  }
-  GCTask* remove_end() const {
-    return _remove_end;
-  }
-  void set_remove_end(GCTask* value) {
-    _remove_end = value;
-  }
-  void increment_length() {
-    _length += 1;
-  }
-  void decrement_length() {
-    _length -= 1;
-  }
-  void set_length(uint value) {
-    _length = value;
-  }
-  bool is_c_heap_obj() const {
-    return _is_c_heap_obj;
-  }
-  // Methods.
-  void initialize();
-  GCTask* remove();                     // Remove from remove end.
-  GCTask* remove(GCTask* task);         // Remove from the middle.
-  void print(const char* message) const PRODUCT_RETURN;
-  // Debug support
-  void verify_length() const PRODUCT_RETURN;
-};
-
-// A GCTaskQueue that can be synchronized.
-// This "has-a" GCTaskQueue and a mutex to do the exclusion.
-class SynchronizedGCTaskQueue : public CHeapObj<mtGC> {
-private:
-  // Instance state.
-  GCTaskQueue* _unsynchronized_queue;   // Has-a unsynchronized queue.
-  Monitor *    _lock;                   // Lock to control access.
-public:
-  // Factory create and destroy methods.
-  static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) {
-    return new SynchronizedGCTaskQueue(queue, lock);
-  }
-  static void destroy(SynchronizedGCTaskQueue* that) {
-    if (that != NULL) {
-      delete that;
-    }
-  }
-  // Accessors
-  GCTaskQueue* unsynchronized_queue() const {
-    return _unsynchronized_queue;
-  }
-  Monitor * lock() const {
-    return _lock;
-  }
-  // GCTaskQueue wrapper methods.
-  // These check that you hold the lock
-  // and then call the method on the queue.
-  bool is_empty() const {
-    guarantee(own_lock(), "don't own the lock");
-    return unsynchronized_queue()->is_empty();
-  }
-  void enqueue(GCTask* task) {
-    guarantee(own_lock(), "don't own the lock");
-    unsynchronized_queue()->enqueue(task);
-  }
-  void enqueue(GCTaskQueue* list) {
-    guarantee(own_lock(), "don't own the lock");
-    unsynchronized_queue()->enqueue(list);
-  }
-  GCTask* dequeue() {
-    guarantee(own_lock(), "don't own the lock");
-    return unsynchronized_queue()->dequeue();
-  }
-  GCTask* dequeue(uint affinity) {
-    guarantee(own_lock(), "don't own the lock");
-    return unsynchronized_queue()->dequeue(affinity);
-  }
-  uint length() const {
-    guarantee(own_lock(), "don't own the lock");
-    return unsynchronized_queue()->length();
-  }
-  // For guarantees.
-  bool own_lock() const {
-    return lock()->owned_by_self();
-  }
-protected:
-  // Constructor.  Clients use factory, but there might be subclasses.
-  SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock);
-  // Destructor.  Not virtual because no virtuals.
-  ~SynchronizedGCTaskQueue();
-};
-
-class WaitHelper {
- private:
-  Monitor*      _monitor;
-  volatile bool _should_wait;
- public:
-  WaitHelper();
-  ~WaitHelper();
-  void wait_for(bool reset);
-  void notify();
-  void set_should_wait(bool value) {
-    _should_wait = value;
-  }
-
-  Monitor* monitor() const {
-    return _monitor;
-  }
-  bool should_wait() const {
-    return _should_wait;
-  }
-  void release_monitor();
-};
-
-// Dynamic number of GC threads
-//
-//  GC threads wait in get_task() for work (i.e., a task) to perform.
-// When the number of GC threads was static, the number of tasks
-// created to do a job was equal to or greater than the maximum
-// number of GC threads (ParallelGCThreads).  The job might be divided
-// into a number of tasks greater than the number of GC threads for
-// load balancing (i.e., over partitioning).  The last task to be
-// executed by a GC thread in a job is a work stealing task.  A
-// GC  thread that gets a work stealing task continues to execute
-// that task until the job is done.  In the static number of GC threads
-// case, tasks are added to a queue (FIFO).  The work stealing tasks are
-// the last to be added.  Once the tasks are added, the GC threads grab
-// a task and go.  A single thread can do all the non-work stealing tasks
-// and then execute a work stealing and wait for all the other GC threads
-// to execute their work stealing task.
-//  In the dynamic number of GC threads implementation, idle-tasks are
-// created to occupy the non-participating or "inactive" threads.  An
-// idle-task makes the GC thread wait on a barrier that is part of the
-// GCTaskManager.  The GC threads that have been "idled" in a IdleGCTask
-// are released once all the active GC threads have finished their work
-// stealing tasks.  The GCTaskManager does not wait for all the "idled"
-// GC threads to resume execution. When those GC threads do resume
-// execution in the course of the thread scheduling, they call get_tasks()
-// as all the other GC threads do.  Because all the "idled" threads are
-// not required to execute in order to finish a job, it is possible for
-// a GC thread to still be "idled" when the next job is started.  Such
-// a thread stays "idled" for the next job.  This can result in a new
-// job not having all the expected active workers.  For example if on
-// job requests 4 active workers out of a total of 10 workers so the
-// remaining 6 are "idled", if the next job requests 6 active workers
-// but all 6 of the "idled" workers are still idle, then the next job
-// will only get 4 active workers.
-//  The implementation for the parallel old compaction phase has an
-// added complication.  In the static case parold partitions the chunks
-// ready to be filled into stacks, one for each GC thread.  A GC thread
-// executing a draining task (drains the stack of ready chunks)
-// claims a stack according to it's id (the unique ordinal value assigned
-// to each GC thread).  In the dynamic case not all GC threads will
-// actively participate so stacks with ready to fill chunks can only be
-// given to the active threads.  An initial implementation chose stacks
-// number 1-n to get the ready chunks and required that GC threads
-// 1-n be the active workers.  This was undesirable because it required
-// certain threads to participate.  In the final implementation a
-// list of stacks equal in number to the active workers are filled
-// with ready chunks.  GC threads that participate get a stack from
-// the task (DrainStacksCompactionTask), empty the stack, and then add it to a
-// recycling list at the end of the task.  If the same GC thread gets
-// a second task, it gets a second stack to drain and returns it.  The
-// stacks are added to a recycling list so that later stealing tasks
-// for this tasks can get a stack from the recycling list.  Stealing tasks
-// use the stacks in its work in a way similar to the draining tasks.
-// A thread is not guaranteed to get anything but a stealing task and
-// a thread that only gets a stealing task has to get a stack. A failed
-// implementation tried to have the GC threads keep the stack they used
-// during a draining task for later use in the stealing task but that didn't
-// work because as noted a thread is not guaranteed to get a draining task.
-//
-// For PSScavenge and ParCompactionManager the GC threads are
-// held in the GCTaskThread** _thread array in GCTaskManager.
-
-
-class GCTaskManager : public CHeapObj<mtGC> {
- friend class ParCompactionManager;
- friend class PSParallelCompact;
- friend class PSScavenge;
- friend class PSRefProcTaskExecutor;
- friend class RefProcTaskExecutor;
- friend class GCTaskThread;
- friend class IdleGCTask;
-private:
-  // Instance state.
-  const uint                _workers;           // Number of workers.
-  Monitor*                  _monitor;           // Notification of changes.
-  SynchronizedGCTaskQueue*  _queue;             // Queue of tasks.
-  GCTaskThread**            _thread;            // Array of worker threads.
-  uint                      _created_workers;   // Number of workers created.
-  uint                      _active_workers;    // Number of active workers.
-  uint                      _busy_workers;      // Number of busy workers.
-  uint                      _blocking_worker;   // The worker that's blocking.
-  bool*                     _resource_flag;     // Array of flag per threads.
-  uint                      _delivered_tasks;   // Count of delivered tasks.
-  uint                      _completed_tasks;   // Count of completed tasks.
-  uint                      _barriers;          // Count of barrier tasks.
-  uint                      _emptied_queue;     // Times we emptied the queue.
-  NoopGCTask*               _noop_task;         // The NoopGCTask instance.
-  WaitHelper                _wait_helper;       // Used by inactive worker
-  volatile uint             _idle_workers;      // Number of idled workers
-  uint*                     _processor_assignment; // Worker to cpu mappings. May
-                                                   // be used lazily
-public:
-  // Factory create and destroy methods.
-  static GCTaskManager* create(uint workers) {
-    return new GCTaskManager(workers);
-  }
-  static void destroy(GCTaskManager* that) {
-    if (that != NULL) {
-      delete that;
-    }
-  }
-  // Accessors.
-  uint busy_workers() const {
-    return _busy_workers;
-  }
-  volatile uint idle_workers() const {
-    return _idle_workers;
-  }
-  //     Pun between Monitor* and Mutex*
-  Monitor* monitor() const {
-    return _monitor;
-  }
-  Monitor * lock() const {
-    return _monitor;
-  }
-  WaitHelper* wait_helper() {
-    return &_wait_helper;
-  }
-  // Methods.
-  //     Add the argument task to be run.
-  void add_task(GCTask* task);
-  //     Add a list of tasks.  Removes task from the argument list.
-  void add_list(GCTaskQueue* list);
-  //     Claim a task for argument worker.
-  GCTask* get_task(uint which);
-  //     Note the completion of a task by the argument worker.
-  void note_completion(uint which);
-  //     Is the queue blocked from handing out new tasks?
-  bool is_blocked() const {
-    return (blocking_worker() != sentinel_worker());
-  }
-  //     Request that all workers release their resources.
-  void release_all_resources();
-  //     Ask if a particular worker should release its resources.
-  bool should_release_resources(uint which); // Predicate.
-  //     Note the release of resources by the argument worker.
-  void note_release(uint which);
-  //     Create IdleGCTasks for inactive workers and start workers
-  void task_idle_workers();
-  //     Release the workers in IdleGCTasks
-  void release_idle_workers();
-  // Constants.
-  //     A sentinel worker identifier.
-  static uint sentinel_worker() {
-    return (uint) -1;                   // Why isn't there a max_uint?
-  }
-
-  //     Execute the task queue and wait for the completion.
-  void execute_and_wait(GCTaskQueue* list);
-
-  void print_task_time_stamps();
-  void print_threads_on(outputStream* st);
-  void threads_do(ThreadClosure* tc);
-
-protected:
-  // Constructors.  Clients use factory, but there might be subclasses.
-  //     Create a GCTaskManager with the appropriate number of workers.
-  GCTaskManager(uint workers);
-  //     Make virtual if necessary.
-  ~GCTaskManager();
-  // Accessors.
-  uint workers() const {
-    return _workers;
-  }
-  uint update_active_workers(uint v) {
-    assert(v <= _workers, "Trying to set more workers active than there are");
-    _active_workers = MIN2(v, _workers);
-    assert(v != 0, "Trying to set active workers to 0");
-    _active_workers = MAX2(1U, _active_workers);
-    return _active_workers;
-  }
-  // Sets the number of threads that will be used in a collection
-  void set_active_gang();
-
-  SynchronizedGCTaskQueue* queue() const {
-    return _queue;
-  }
-  NoopGCTask* noop_task() const {
-    return _noop_task;
-  }
-  //     Bounds-checking per-thread data accessors.
-  GCTaskThread* thread(uint which);
-  void set_thread(uint which, GCTaskThread* value);
-  bool resource_flag(uint which);
-  void set_resource_flag(uint which, bool value);
-  // Modifier methods with some semantics.
-  //     Is any worker blocking handing out new tasks?
-  uint blocking_worker() const {
-    return _blocking_worker;
-  }
-  void set_blocking_worker(uint value) {
-    _blocking_worker = value;
-  }
-  void set_unblocked() {
-    set_blocking_worker(sentinel_worker());
-  }
-  //     Count of busy workers.
-  void reset_busy_workers() {
-    _busy_workers = 0;
-  }
-  uint increment_busy_workers();
-  uint decrement_busy_workers();
-  //     Count of tasks delivered to workers.
-  uint delivered_tasks() const {
-    return _delivered_tasks;
-  }
-  void increment_delivered_tasks() {
-    _delivered_tasks += 1;
-  }
-  void reset_delivered_tasks() {
-    _delivered_tasks = 0;
-  }
-  //     Count of tasks completed by workers.
-  uint completed_tasks() const {
-    return _completed_tasks;
-  }
-  void increment_completed_tasks() {
-    _completed_tasks += 1;
-  }
-  void reset_completed_tasks() {
-    _completed_tasks = 0;
-  }
-  //     Count of barrier tasks completed.
-  uint barriers() const {
-    return _barriers;
-  }
-  void increment_barriers() {
-    _barriers += 1;
-  }
-  void reset_barriers() {
-    _barriers = 0;
-  }
-  //     Count of how many times the queue has emptied.
-  uint emptied_queue() const {
-    return _emptied_queue;
-  }
-  void increment_emptied_queue() {
-    _emptied_queue += 1;
-  }
-  void reset_emptied_queue() {
-    _emptied_queue = 0;
-  }
-  void increment_idle_workers() {
-    _idle_workers++;
-  }
-  void decrement_idle_workers() {
-    _idle_workers--;
-  }
-  // Other methods.
-  void initialize();
-
- public:
-  // Return true if all workers are currently active.
-  bool all_workers_active() { return workers() == active_workers(); }
-  uint active_workers() const {
-    return _active_workers;
-  }
-  uint created_workers() const {
-    return _created_workers;
-  }
-  // Create a GC worker and install into GCTaskManager
-  GCTaskThread* install_worker(uint worker_id);
-  // Add GC workers as needed.
-  void add_workers(bool initializing);
-  // Base name (without worker id #) of threads.
-  const char* group_name();
-};
-
-//
-// Some exemplary GCTasks.
-//
-
-// A noop task that does nothing,
-// except take us around the GCTaskThread loop.
-class NoopGCTask : public GCTask {
-public:
-  // Factory create and destroy methods.
-  static NoopGCTask* create_on_c_heap();
-  static void destroy(NoopGCTask* that);
-
-  virtual char* name() { return (char *)"noop task"; }
-  // Methods from GCTask.
-  void do_it(GCTaskManager* manager, uint which) {
-    // Nothing to do.
-  }
-protected:
-  // Constructor.
-  NoopGCTask();
-  // Destructor-like method.
-  void destruct();
-};
-
-// A WaitForBarrierGCTask is a GCTask
-// with a method you can call to wait until
-// the BarrierGCTask is done.
-class WaitForBarrierGCTask : public GCTask {
-  friend class GCTaskManager;
-  friend class IdleGCTask;
-private:
-  // Instance state.
-  WaitHelper    _wait_helper;
-  WaitForBarrierGCTask();
-public:
-  virtual char* name() { return (char *) "waitfor-barrier-task"; }
-
-  // Factory create and destroy methods.
-  static WaitForBarrierGCTask* create();
-  static void destroy(WaitForBarrierGCTask* that);
-  // Methods.
-  void     do_it(GCTaskManager* manager, uint which);
-protected:
-  // Destructor-like method.
-  void destruct();
-
-  // Methods.
-  //     Wait for this to be the only task running.
-  void do_it_internal(GCTaskManager* manager, uint which);
-
-  void wait_for(bool reset) {
-    _wait_helper.wait_for(reset);
-  }
-};
-
-// Task that is used to idle a GC task when fewer than
-// the maximum workers are wanted.
-class IdleGCTask : public GCTask {
-  const bool    _is_c_heap_obj;            // Was allocated on the heap.
- public:
-  bool is_c_heap_obj() {
-    return _is_c_heap_obj;
-  }
-  // Factory create and destroy methods.
-  static IdleGCTask* create();
-  static IdleGCTask* create_on_c_heap();
-  static void destroy(IdleGCTask* that);
-
-  virtual char* name() { return (char *)"idle task"; }
-  // Methods from GCTask.
-  virtual void do_it(GCTaskManager* manager, uint which);
-protected:
-  // Constructor.
-  IdleGCTask(bool on_c_heap) :
-    GCTask(GCTask::Kind::idle_task),
-    _is_c_heap_obj(on_c_heap) {
-    // Nothing to do.
-  }
-  // Destructor-like method.
-  void destruct();
-};
-
-class MonitorSupply : public AllStatic {
-private:
-  // State.
-  //     Control multi-threaded access.
-  static Mutex*                   _lock;
-  //     The list of available Monitor*'s.
-  static GrowableArray<Monitor*>* _freelist;
-public:
-  // Reserve a Monitor*.
-  static Monitor* reserve();
-  // Release a Monitor*.
-  static void release(Monitor* instance);
-private:
-  // Accessors.
-  static Mutex* lock() {
-    return _lock;
-  }
-  static GrowableArray<Monitor*>* freelist() {
-    return _freelist;
-  }
-};
-
-#endif // SHARE_GC_PARALLEL_GCTASKMANAGER_HPP
--- a/src/hotspot/share/gc/parallel/gcTaskThread.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
-#include "gc/parallel/gcTaskThread.hpp"
-#include "gc/shared/gcId.hpp"
-#include "logging/log.hpp"
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/handles.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/os.hpp"
-#include "runtime/thread.hpp"
-
-GCTaskThread::GCTaskThread(GCTaskManager* manager,
-                           uint           which,
-                           uint           processor_id) :
-  _manager(manager),
-  _processor_id(processor_id),
-  _time_stamps(NULL),
-  _time_stamp_index(0)
-{
-  set_id(which);
-  set_name("%s#%d", manager->group_name(), which);
-}
-
-GCTaskThread::~GCTaskThread() {
-  if (_time_stamps != NULL) {
-    FREE_C_HEAP_ARRAY(GCTaskTimeStamp, _time_stamps);
-  }
-}
-
-void GCTaskThread::add_task_timestamp(const char* name, jlong t_entry, jlong t_exit) {
-  if (_time_stamp_index < GCTaskTimeStampEntries) {
-    GCTaskTimeStamp* time_stamp = time_stamp_at(_time_stamp_index);
-    time_stamp->set_name(name);
-    time_stamp->set_entry_time(t_entry);
-    time_stamp->set_exit_time(t_exit);
-  } else {
-    if (_time_stamp_index ==  GCTaskTimeStampEntries) {
-      log_warning(gc, task, time)("GC-thread %u: Too many timestamps, ignoring future ones. "
-                                  "Increase GCTaskTimeStampEntries to get more info.",
-                                  id());
-    }
-    // Let _time_stamp_index keep counting to give the user an idea about how many
-    // are needed.
-  }
-  _time_stamp_index++;
-}
-
-GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) {
-  assert(index < GCTaskTimeStampEntries, "Precondition");
-  if (_time_stamps == NULL) {
-    // We allocate the _time_stamps array lazily since logging can be enabled dynamically
-    GCTaskTimeStamp* time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries, mtGC);
-    if (!Atomic::replace_if_null(time_stamps, &_time_stamps)) {
-      // Someone already setup the time stamps
-      FREE_C_HEAP_ARRAY(GCTaskTimeStamp, time_stamps);
-    }
-  }
-  return &(_time_stamps[index]);
-}
-
-void GCTaskThread::print_task_time_stamps() {
-  assert(log_is_enabled(Debug, gc, task, time), "Sanity");
-
-  // Since _time_stamps is now lazily allocated we need to check that it
-  // has in fact been allocated when calling this function.
-  if (_time_stamps != NULL) {
-    log_debug(gc, task, time)("GC-Thread %u entries: %d%s", id(),
-                              _time_stamp_index,
-                              _time_stamp_index >= GCTaskTimeStampEntries ? " (overflow)" : "");
-    const uint max_index = MIN2(_time_stamp_index, GCTaskTimeStampEntries);
-    for (uint i = 0; i < max_index; i++) {
-      GCTaskTimeStamp* time_stamp = time_stamp_at(i);
-      log_debug(gc, task, time)("\t[ %s " JLONG_FORMAT " " JLONG_FORMAT " ]",
-                                time_stamp->name(),
-                                time_stamp->entry_time(),
-                                time_stamp->exit_time());
-    }
-
-    // Reset after dumping the data
-    _time_stamp_index = 0;
-  }
-}
-
-// GC workers get tasks from the GCTaskManager and execute
-// them in this method.  If there are no tasks to execute,
-// the GC workers wait in the GCTaskManager's get_task()
-// for tasks to be enqueued for execution.
-
-void GCTaskThread::run() {
-  // Bind yourself to your processor.
-  if (processor_id() != GCTaskManager::sentinel_worker()) {
-    log_trace(gc, task, thread)("GCTaskThread::run: binding to processor %u", processor_id());
-    if (!os::bind_to_processor(processor_id())) {
-      DEBUG_ONLY(
-        log_warning(gc)("Couldn't bind GCTaskThread %u to processor %u",
-                        which(), processor_id());
-      )
-    }
-  }
-  // Part of thread setup.
-  // ??? Are these set up once here to make subsequent ones fast?
-  HandleMark   hm_outer;
-  ResourceMark rm_outer;
-
-  TimeStamp timer;
-
-  for (;/* ever */;) {
-    // These are so we can flush the resources allocated in the inner loop.
-    HandleMark   hm_inner;
-    ResourceMark rm_inner;
-    for (; /* break */; ) {
-      // This will block until there is a task to be gotten.
-      GCTask* task = manager()->get_task(which());
-      GCIdMark gc_id_mark(task->gc_id());
-      // Record if this is an idle task for later use.
-      bool is_idle_task = task->is_idle_task();
-      // In case the update is costly
-      if (log_is_enabled(Debug, gc, task, time)) {
-        timer.update();
-      }
-
-      jlong entry_time = timer.ticks();
-      char* name = task->name();
-
-      // If this is the barrier task, it can be destroyed
-      // by the GC task manager once the do_it() executes.
-      task->do_it(manager(), which());
-
-      // Use the saved value of is_idle_task because references
-      // using "task" are not reliable for the barrier task.
-      if (!is_idle_task) {
-        manager()->note_completion(which());
-
-        if (log_is_enabled(Debug, gc, task, time)) {
-          timer.update();
-          add_task_timestamp(name, entry_time, timer.ticks());
-        }
-      } else {
-        // idle tasks complete outside the normal accounting
-        // so that a task can complete without waiting for idle tasks.
-        // They have to be terminated separately.
-        IdleGCTask::destroy((IdleGCTask*)task);
-      }
-
-      // Check if we should release our inner resources.
-      if (manager()->should_release_resources(which())) {
-        manager()->note_release(which());
-        break;
-      }
-    }
-  }
-}
--- a/src/hotspot/share/gc/parallel/gcTaskThread.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_GC_PARALLEL_GCTASKTHREAD_HPP
-#define SHARE_GC_PARALLEL_GCTASKTHREAD_HPP
-
-#include "runtime/thread.hpp"
-
-// Forward declarations of classes defined here.
-class GCTaskThread;
-class GCTaskTimeStamp;
-
-// Declarations of classes referenced in this file via pointer.
-class GCTaskManager;
-
-class GCTaskThread : public WorkerThread {
-  friend class GCTaskManager;
-private:
-  // Instance state.
-  GCTaskManager* _manager;              // Manager for worker.
-  const uint     _processor_id;         // Which processor the worker is on.
-
-  GCTaskTimeStamp* _time_stamps;
-  uint _time_stamp_index;
-
-  GCTaskTimeStamp* time_stamp_at(uint index);
-  void add_task_timestamp(const char* name, jlong t_entry, jlong t_exit);
-
-  // Factory create and destroy methods.
-  static GCTaskThread* create(GCTaskManager* manager,
-                              uint           which,
-                              uint           processor_id) {
-    return new GCTaskThread(manager, which, processor_id);
-  }
- public:
-
-  static void destroy(GCTaskThread* manager) {
-    if (manager != NULL) {
-      delete manager;
-    }
-  }
-  // Methods from Thread.
-  bool is_GC_task_thread() const {
-    return true;
-  }
-  virtual void run();
-
-  void print_task_time_stamps();
-
-protected:
-  // Constructor.  Clients use factory, but there could be subclasses.
-  GCTaskThread(GCTaskManager* manager, uint which, uint processor_id);
-  // Destructor: virtual destructor because of virtual methods.
-  virtual ~GCTaskThread();
-  // Accessors.
-  GCTaskManager* manager() const {
-    return _manager;
-  }
-  uint which() const {
-    return id();
-  }
-  uint processor_id() const {
-    return _processor_id;
-  }
-};
-
-class GCTaskTimeStamp : public CHeapObj<mtGC>
-{
- private:
-  jlong  _entry_time;
-  jlong  _exit_time;
-  const char*  _name;
-
- public:
-  jlong entry_time()              { return _entry_time; }
-  jlong exit_time()               { return _exit_time; }
-  const char* name() const        { return _name; }
-
-  void set_entry_time(jlong time) { _entry_time = time; }
-  void set_exit_time(jlong time)  { _exit_time = time; }
-  void set_name(const char* name) { _name = name; }
-};
-
-#endif // SHARE_GC_PARALLEL_GCTASKTHREAD_HPP
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -28,7 +28,6 @@
 #include "gc/parallel/adjoiningGenerationsForHeteroHeap.hpp"
 #include "gc/parallel/adjoiningVirtualSpaces.hpp"
 #include "gc/parallel/parallelArguments.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/objectStartArray.inline.hpp"
 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
@@ -59,7 +58,6 @@
 PSOldGen*    ParallelScavengeHeap::_old_gen = NULL;
 PSAdaptiveSizePolicy* ParallelScavengeHeap::_size_policy = NULL;
 PSGCAdaptivePolicyCounters* ParallelScavengeHeap::_gc_policy_counters = NULL;
-GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
 
 jint ParallelScavengeHeap::initialize() {
   const size_t reserved_heap_size = ParallelArguments::heap_reserved_size_bytes();
@@ -116,9 +114,6 @@
   _gc_policy_counters =
     new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 2, _size_policy);
 
-  // Set up the GCTaskManager
-  _gc_task_manager = GCTaskManager::create(ParallelGCThreads);
-
   if (UseParallelOldGC && !PSParallelCompact::initialize()) {
     return JNI_ENOMEM;
   }
@@ -605,11 +600,11 @@
 }
 
 void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const {
-  PSScavenge::gc_task_manager()->threads_do(tc);
+  ParallelScavengeHeap::heap()->workers().threads_do(tc);
 }
 
 void ParallelScavengeHeap::print_gc_threads_on(outputStream* st) const {
-  PSScavenge::gc_task_manager()->print_threads_on(st);
+  ParallelScavengeHeap::heap()->workers().print_worker_threads_on(st);
 }
 
 void ParallelScavengeHeap::print_tracing_info() const {
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -45,7 +45,6 @@
 
 class AdjoiningGenerations;
 class GCHeapSummary;
-class GCTaskManager;
 class MemoryManager;
 class MemoryPool;
 class PSAdaptiveSizePolicy;
@@ -69,9 +68,6 @@
   AdjoiningGenerations* _gens;
   unsigned int _death_march_count;
 
-  // The task manager
-  static GCTaskManager* _gc_task_manager;
-
   GCMemoryManager* _young_manager;
   GCMemoryManager* _old_manager;
 
@@ -136,8 +132,6 @@
 
   static ParallelScavengeHeap* heap();
 
-  static GCTaskManager* const gc_task_manager() { return _gc_task_manager; }
-
   CardTableBarrierSet* barrier_set();
   PSCardTable* card_table();
 
--- a/src/hotspot/share/gc/parallel/parallel_globals.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,12 +62,6 @@
           "limiter (a number between 0-100)")                               \
           range(0, 100)                                                     \
                                                                             \
-  develop(bool, TraceGCTaskManager, false,                                  \
-          "Trace actions of the GC task manager")                           \
-                                                                            \
-  develop(bool, TraceGCTaskQueue, false,                                    \
-          "Trace actions of the GC task queues")                            \
-                                                                            \
   develop(bool, TraceParallelOldGCMarkingPhase, false,                      \
           "Trace marking phase in ParallelOldGC")                           \
                                                                             \
--- a/src/hotspot/share/gc/parallel/psCardTable.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psCardTable.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/objectStartArray.inline.hpp"
 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/psCardTable.hpp"
--- a/src/hotspot/share/gc/parallel/psCardTable.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psCardTable.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -31,7 +31,6 @@
 class MutableSpace;
 class ObjectStartArray;
 class PSPromotionManager;
-class GCTaskQueue;
 
 class PSCardTable: public CardTable {
  private:
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
 
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/objectStartArray.hpp"
 #include "gc/parallel/parMarkBitMap.inline.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
@@ -68,12 +67,12 @@
 }
 
 void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
-  assert(PSParallelCompact::gc_task_manager() != NULL,
+  assert(ParallelScavengeHeap::heap() != NULL,
     "Needed for initialization");
 
   _mark_bitmap = mbm;
 
-  uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
+  uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
 
   assert(_manager_array == NULL, "Attempt to initialize twice");
   _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC);
@@ -100,12 +99,12 @@
   _manager_array[parallel_gc_threads] = new ParCompactionManager();
   guarantee(_manager_array[parallel_gc_threads] != NULL,
     "Could not create ParCompactionManager");
-  assert(PSParallelCompact::gc_task_manager()->workers() != 0,
+  assert(ParallelScavengeHeap::heap()->workers().total_workers() != 0,
     "Not initialized?");
 }
 
 void ParCompactionManager::reset_all_bitmap_query_caches() {
-  uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
+  uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
   for (uint i=0; i<=parallel_gc_threads; i++) {
     _manager_array[i]->reset_bitmap_query_cache();
   }
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -43,7 +43,6 @@
   friend class CompactionWithStealingTask;
   friend class UpdateAndFillClosure;
   friend class RefProcTaskExecutor;
-  friend class IdleGCTask;
   friend class PCRefProcTask;
   friend class MarkFromRootsTask;
   friend class UpdateDensePrefixAndCompactionTask;
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -30,7 +30,6 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/parMarkBitMap.inline.hpp"
@@ -1018,9 +1017,6 @@
   DEBUG_ONLY(mark_bitmap()->verify_clear();)
   DEBUG_ONLY(summary_data().verify_clear();)
 
-  // Have worker threads release resources the next time they run a task.
-  gc_task_manager()->release_all_resources();
-
   ParCompactionManager::reset_all_bitmap_query_caches();
 }
 
@@ -1785,7 +1781,7 @@
 
   // Get the compaction manager reserved for the VM thread.
   ParCompactionManager* const vmthread_cm =
-    ParCompactionManager::manager_array(gc_task_manager()->workers());
+    ParCompactionManager::manager_array(ParallelScavengeHeap::heap()->workers().total_workers());
 
   {
     ResourceMark rm;
@@ -1797,10 +1793,6 @@
                                         Threads::number_of_non_daemon_threads());
     ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
 
-    // Set the number of GC threads to be used in this collection
-    gc_task_manager()->set_active_gang();
-    gc_task_manager()->task_idle_workers();
-
     GCTraceCPUTime tcpu;
     GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause, true);
 
@@ -1936,7 +1928,6 @@
     // Track memory usage and detect low memory
     MemoryService::track_memory_usage();
     heap->update_counters();
-    gc_task_manager()->release_idle_workers();
 
     heap->post_full_gc_dump(&_gc_timer);
   }
@@ -1975,7 +1966,6 @@
   log_debug(gc, task, time)("VM-Thread " JLONG_FORMAT " " JLONG_FORMAT " " JLONG_FORMAT,
                          marking_start.ticks(), compaction_start.ticks(),
                          collection_exit.ticks());
-  gc_task_manager()->print_task_time_stamps();
 
 #ifdef TRACESPINNING
   ParallelTaskTerminator::print_termination_counts();
@@ -1999,7 +1989,7 @@
   assert(young_gen->virtual_space()->alignment() ==
          old_gen->virtual_space()->alignment(), "alignments do not match");
 
-  // We also return false when it's a heterogenous heap because old generation cannot absorb data from eden
+  // We also return false when it's a heterogeneous heap because old generation cannot absorb data from eden
   // when it is allocated on different memory (example, nv-dimm) than young.
   if (!(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary) ||
       ParallelArguments::is_heterogeneous_heap()) {
@@ -2080,12 +2070,6 @@
   return true;
 }
 
-GCTaskManager* const PSParallelCompact::gc_task_manager() {
-  assert(ParallelScavengeHeap::gc_task_manager() != NULL,
-    "shouldn't return NULL");
-  return ParallelScavengeHeap::gc_task_manager();
-}
-
 class PCAddThreadRootsMarkingTaskClosure : public ThreadClosure {
 private:
   uint _worker_id;
@@ -2264,10 +2248,7 @@
   GCTraceTime(Info, gc, phases) tm("Marking Phase", &_gc_timer);
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  uint parallel_gc_threads = heap->gc_task_manager()->workers();
-  uint active_gc_threads = heap->gc_task_manager()->active_workers();
-  TaskQueueSetSuper* qset = ParCompactionManager::stack_array();
-  TaskTerminator terminator(active_gc_threads, qset);
+  uint active_gc_threads = ParallelScavengeHeap::heap()->workers().active_workers();
 
   PCMarkAndPushClosure mark_and_push_closure(cm);
   ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -40,8 +40,7 @@
 class ParCompactionManager;
 class ParallelTaskTerminator;
 class PSParallelCompact;
-class GCTaskManager;
-class GCTaskQueue;
+class PreGCValues;
 class MoveAndUpdateClosure;
 class RefProcTaskExecutor;
 class ParallelOldTracer;
@@ -1114,9 +1113,6 @@
   static unsigned int total_invocations() { return _total_invocations; }
   static CollectorCounters* counters()    { return _counters; }
 
-  // Used to add tasks
-  static GCTaskManager* const gc_task_manager();
-
   // Marking support
   static inline bool mark_obj(oop obj);
   static inline bool is_marked(oop obj);
--- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -24,7 +24,6 @@
 
 #include "precompiled.hpp"
 #include "classfile/javaClasses.inline.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/mutableSpace.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "gc/parallel/psOldGen.hpp"
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -27,7 +27,6 @@
 #include "classfile/classLoaderDataGraph.hpp"
 #include "classfile/stringTable.hpp"
 #include "code/codeCache.hpp"
-#include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
 #include "gc/parallel/psClosure.inline.hpp"
@@ -500,15 +499,6 @@
                                         Threads::number_of_non_daemon_threads());
     ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
 
-    // Release all previously held resources
-    gc_task_manager()->release_all_resources();
-
-    // Set the number of GC threads to be used in this collection
-    gc_task_manager()->set_active_gang();
-    gc_task_manager()->task_idle_workers();
-
-    assert(active_workers == gc_task_manager()->active_workers(), "sanity, taskmanager and workgang ought to agree");
-
     PSPromotionManager::pre_scavenge();
 
     // We'll use the promotion manager again later.
@@ -728,8 +718,6 @@
     // Track memory usage and detect low memory
     MemoryService::track_memory_usage();
     heap->update_counters();
-
-    gc_task_manager()->release_idle_workers();
   }
 
   if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
@@ -745,7 +733,6 @@
   log_debug(gc, task, time)("VM-Thread " JLONG_FORMAT " " JLONG_FORMAT " " JLONG_FORMAT,
                             scavenge_entry.ticks(), scavenge_midpoint.ticks(),
                             scavenge_exit.ticks());
-  gc_task_manager()->print_task_time_stamps();
 
 #ifdef TRACESPINNING
   ParallelTaskTerminator::print_termination_counts();
@@ -823,13 +810,6 @@
   return result;
 }
 
-  // Used to add tasks
-GCTaskManager* const PSScavenge::gc_task_manager() {
-  assert(ParallelScavengeHeap::gc_task_manager() != NULL,
-   "shouldn't return NULL");
-  return ParallelScavengeHeap::gc_task_manager();
-}
-
 // Adaptive size policy support.  When the young generation/old generation
 // boundary moves, _young_generation_boundary must be reset
 void PSScavenge::set_young_generation_boundary(HeapWord* v) {
--- a/src/hotspot/share/gc/parallel/psScavenge.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/gc/parallel/psScavenge.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -33,8 +33,6 @@
 #include "oops/oop.hpp"
 #include "utilities/stack.hpp"
 
-class GCTaskManager;
-class GCTaskQueue;
 class OopStack;
 class ReferenceProcessor;
 class ParallelScavengeHeap;
@@ -111,8 +109,6 @@
     assert(_ref_processor != NULL, "Sanity");
     return _ref_processor;
   }
-  // Used to add tasks
-  static GCTaskManager* const gc_task_manager();
   // The promotion managers tell us if they encountered overflow
   static void set_survivor_overflow(bool state) {
     _survivor_overflow = state;
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 16 09:18:38 2019 +0200
@@ -126,8 +126,6 @@
 Mutex*   OldSets_lock                 = NULL;
 Monitor* RootRegionScan_lock          = NULL;
 
-Monitor* GCTaskManager_lock           = NULL;
-
 Mutex*   Management_lock              = NULL;
 Monitor* Service_lock                 = NULL;
 Monitor* PeriodicTask_lock            = NULL;
--- a/src/hotspot/share/runtime/thread.hpp	Fri Aug 16 09:18:35 2019 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Fri Aug 16 09:18:38 2019 +0200
@@ -83,7 +83,6 @@
 class DeoptResourceMark;
 class jvmtiDeferredLocalVariableSet;
 
-class GCTaskQueue;
 class ThreadClosure;
 class ICRefillVerifier;
 class IdealGraphPrinter;
@@ -108,7 +107,6 @@
 //       - ConcurrentGCThread
 //       - WorkerThread
 //         - GangWorker
-//         - GCTaskThread
 //     - WatcherThread
 //     - JfrThreadSampler
 //