diff -r 4ebc2e2fb97c -r 71c04702a3d5 src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp --- /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. + } + } +}