src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp
changeset 47216 71c04702a3d5
parent 46384 dacebddcdea0
child 54623 1126f0607c70
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017, 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/shared/concurrentGCPhaseManager.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/thread.hpp"
+
+#define assert_ConcurrentGC_thread() \
+  assert(Thread::current()->is_ConcurrentGC_thread(), "precondition")
+
+#define assert_not_enter_unconstrained(phase) \
+  assert((phase) != UNCONSTRAINED_PHASE, "Cannot enter \"unconstrained\" phase")
+
+#define assert_manager_is_tos(manager, stack, kind)  \
+  assert((manager) == (stack)->_top, kind " manager is not top of stack")
+
+ConcurrentGCPhaseManager::Stack::Stack() :
+  _requested_phase(UNCONSTRAINED_PHASE),
+  _top(NULL)
+{ }
+
+ConcurrentGCPhaseManager::ConcurrentGCPhaseManager(int phase, Stack* stack) :
+  _phase(phase),
+  _active(true),
+  _prev(NULL),
+  _stack(stack)
+{
+  assert_ConcurrentGC_thread();
+  assert_not_enter_unconstrained(phase);
+  assert(stack != NULL, "precondition");
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  if (stack->_top != NULL) {
+    assert(stack->_top->_active, "precondition");
+    _prev = stack->_top;
+  }
+  stack->_top = this;
+  ml.notify_all();
+}
+
+ConcurrentGCPhaseManager::~ConcurrentGCPhaseManager() {
+  assert_ConcurrentGC_thread();
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  assert_manager_is_tos(this, _stack, "This");
+  wait_when_requested_impl();
+  _stack->_top = _prev;
+  ml.notify_all();
+}
+
+bool ConcurrentGCPhaseManager::is_requested() const {
+  assert_ConcurrentGC_thread();
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  assert_manager_is_tos(this, _stack, "This");
+  return _active && (_stack->_requested_phase == _phase);
+}
+
+bool ConcurrentGCPhaseManager::wait_when_requested_impl() const {
+  assert_ConcurrentGC_thread();
+  assert_lock_strong(CGCPhaseManager_lock);
+  bool waited = false;
+  while (_active && (_stack->_requested_phase == _phase)) {
+    waited = true;
+    CGCPhaseManager_lock->wait(Mutex::_no_safepoint_check_flag);
+  }
+  return waited;
+}
+
+bool ConcurrentGCPhaseManager::wait_when_requested() const {
+  assert_ConcurrentGC_thread();
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  assert_manager_is_tos(this, _stack, "This");
+  return wait_when_requested_impl();
+}
+
+void ConcurrentGCPhaseManager::set_phase(int phase, bool force) {
+  assert_ConcurrentGC_thread();
+  assert_not_enter_unconstrained(phase);
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  assert_manager_is_tos(this, _stack, "This");
+  if (!force) wait_when_requested_impl();
+  _phase = phase;
+  ml.notify_all();
+}
+
+void ConcurrentGCPhaseManager::deactivate() {
+  assert_ConcurrentGC_thread();
+  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  assert_manager_is_tos(this, _stack, "This");
+  _active = false;
+  ml.notify_all();
+}
+
+bool ConcurrentGCPhaseManager::wait_for_phase(int phase, Stack* stack) {
+  assert(Thread::current()->is_Java_thread(), "precondition");
+  assert(stack != NULL, "precondition");
+  MonitorLockerEx ml(CGCPhaseManager_lock);
+  // Update request and notify service of change.
+  if (stack->_requested_phase != phase) {
+    stack->_requested_phase = phase;
+    ml.notify_all();
+  }
+
+  if (phase == UNCONSTRAINED_PHASE) {
+    return true;
+  }
+
+  // Wait until phase or IDLE is active.
+  while (true) {
+    bool idle = false;
+    for (ConcurrentGCPhaseManager* manager = stack->_top;
+         manager != NULL;
+         manager = manager->_prev) {
+      if (manager->_phase == phase) {
+        return true;            // phase is active.
+      } else if (manager->_phase == IDLE_PHASE) {
+        idle = true;            // Note idle active, continue search for phase.
+      }
+    }
+    if (idle) {
+      return false;             // idle is active and phase is not.
+    } else {
+      ml.wait();                // Wait for phase change.
+    }
+  }
+}