--- /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.
+ }
+ }
+}