mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 18:14:38 +02:00
146 lines
4.8 KiB
C++
146 lines
4.8 KiB
C++
/*
|
|
* 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.
|
|
}
|
|
}
|
|
}
|