mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8316682: serviceability/jvmti/vthread/SelfSuspendDisablerTest timed out
Reviewed-by: lmesnik, pchilanomate
This commit is contained in:
parent
bed5114e3a
commit
9a23f721c7
@ -988,6 +988,10 @@ JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvm
|
||||
self_tobj = Handle(current, thread_oop);
|
||||
continue; // self suspend after all other suspends
|
||||
}
|
||||
if (java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
|
||||
java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
|
||||
}
|
||||
results[i] = suspend_thread(thread_oop, java_thread, /* single_suspend */ true);
|
||||
}
|
||||
}
|
||||
@ -1114,6 +1118,10 @@ JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmt
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
|
||||
java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
|
||||
}
|
||||
results[i] = resume_thread(thread_oop, java_thread, /* single_resume */ true);
|
||||
}
|
||||
// per-thread resume results returned via results parameter
|
||||
|
||||
@ -1398,8 +1398,7 @@ JvmtiEnvBase::is_vthread_suspended(oop vt_oop, JavaThread* jt) {
|
||||
bool suspended = false;
|
||||
if (java_lang_VirtualThread::is_instance(vt_oop)) {
|
||||
suspended = JvmtiVTSuspender::is_vthread_suspended(vt_oop);
|
||||
}
|
||||
if (vt_oop->is_a(vmClasses::BoundVirtualThread_klass())) {
|
||||
} else if (vt_oop->is_a(vmClasses::BoundVirtualThread_klass())) {
|
||||
suspended = jt->is_suspended();
|
||||
}
|
||||
return suspended;
|
||||
@ -1757,57 +1756,46 @@ JvmtiEnvBase::suspend_thread(oop thread_oop, JavaThread* java_thread, bool singl
|
||||
Handle thread_h(current, thread_oop);
|
||||
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h());
|
||||
|
||||
if (is_virtual) {
|
||||
if (single_suspend) {
|
||||
if (JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
|
||||
return JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
}
|
||||
JvmtiVTSuspender::register_vthread_suspend(thread_h());
|
||||
// Check if virtual thread is mounted and there is a java_thread.
|
||||
// A non-null java_thread is always passed in the !single_suspend case.
|
||||
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_h());
|
||||
java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
|
||||
// Unmounted vthread case.
|
||||
|
||||
if (is_virtual && java_thread == nullptr) {
|
||||
assert(single_suspend, "sanity check");
|
||||
if (JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
|
||||
return JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
}
|
||||
// The java_thread can be still blocked in VTMS transition after a previous JVMTI resume call.
|
||||
// There is no need to suspend the java_thread in this case. After vthread unblocking,
|
||||
// it will check for ext_suspend request and suspend itself if necessary.
|
||||
if (java_thread == nullptr || java_thread->is_suspended()) {
|
||||
// We are done if the virtual thread is unmounted or
|
||||
// the java_thread is externally suspended.
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
// The virtual thread is mounted: suspend the java_thread.
|
||||
JvmtiVTSuspender::register_vthread_suspend(thread_h());
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
// Platform thread or mounted vthread cases.
|
||||
|
||||
assert(java_thread != nullptr, "sanity check");
|
||||
assert(!java_thread->is_in_VTMS_transition(), "sanity check");
|
||||
|
||||
// Don't allow hidden thread suspend request.
|
||||
if (java_thread->is_hidden_from_external_view()) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
|
||||
|
||||
// A case of non-virtual thread.
|
||||
if (!is_virtual) {
|
||||
// Thread.suspend() is used in some tests. It sets jt->is_suspended() only.
|
||||
if (java_thread->is_carrier_thread_suspended() ||
|
||||
(!is_thread_carrying && java_thread->is_suspended())) {
|
||||
return JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
}
|
||||
java_thread->set_carrier_thread_suspended();
|
||||
}
|
||||
assert(!java_thread->is_in_VTMS_transition(), "sanity check");
|
||||
|
||||
assert(!single_suspend || (!is_virtual && java_thread->is_carrier_thread_suspended()) ||
|
||||
(is_virtual && JvmtiVTSuspender::is_vthread_suspended(thread_h())),
|
||||
"sanity check");
|
||||
|
||||
// An attempt to handshake-suspend a thread carrying a virtual thread will result in
|
||||
// suspension of mounted virtual thread. So, we just mark it as suspended
|
||||
// and it will be actually suspended at virtual thread unmount transition.
|
||||
if (!is_thread_carrying) {
|
||||
bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
|
||||
if (is_thread_carrying) {
|
||||
return java_thread->set_carrier_thread_suspended() ? JVMTI_ERROR_NONE : JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
} else {
|
||||
// Platform thread (not carrying vthread) or mounted vthread cases.
|
||||
assert(thread_h() != nullptr, "sanity check");
|
||||
assert(single_suspend || thread_h()->is_a(vmClasses::BaseVirtualThread_klass()),
|
||||
"SuspendAllVirtualThreads should never suspend non-virtual threads");
|
||||
// Case of mounted virtual or attached carrier thread.
|
||||
if (!java_thread->java_suspend()) {
|
||||
|
||||
// Ideally we would just need to check java_thread->is_suspended(), but we have to
|
||||
// consider the case of trying to suspend a thread that was previously suspended while
|
||||
// carrying a vthread but has already unmounted it.
|
||||
if (java_thread->is_suspended() || (!is_virtual && java_thread->is_carrier_thread_suspended())) {
|
||||
return JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
}
|
||||
if (!java_thread->java_suspend(is_virtual && single_suspend)) {
|
||||
// Thread is already suspended or in process of exiting.
|
||||
if (java_thread->is_exiting()) {
|
||||
// The thread was in the process of exiting.
|
||||
@ -1815,8 +1803,8 @@ JvmtiEnvBase::suspend_thread(oop thread_oop, JavaThread* java_thread, bool singl
|
||||
}
|
||||
return JVMTI_ERROR_THREAD_SUSPENDED;
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
// java_thread - protected by ThreadsListHandle
|
||||
@ -1827,54 +1815,51 @@ JvmtiEnvBase::resume_thread(oop thread_oop, JavaThread* java_thread, bool single
|
||||
Handle thread_h(current, thread_oop);
|
||||
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h());
|
||||
|
||||
if (is_virtual) {
|
||||
if (single_resume) {
|
||||
if (!JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
|
||||
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
}
|
||||
JvmtiVTSuspender::register_vthread_resume(thread_h());
|
||||
// Check if virtual thread is mounted and there is a java_thread.
|
||||
// A non-null java_thread is always passed in the !single_resume case.
|
||||
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_h());
|
||||
java_thread = carrier_thread == nullptr ? nullptr : java_lang_Thread::thread(carrier_thread);
|
||||
// Unmounted vthread case.
|
||||
|
||||
if (is_virtual && java_thread == nullptr) {
|
||||
assert(single_resume, "sanity check");
|
||||
if (!JvmtiVTSuspender::is_vthread_suspended(thread_h())) {
|
||||
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
}
|
||||
// The java_thread can be still blocked in VTMS transition after a previous JVMTI suspend call.
|
||||
// There is no need to resume the java_thread in this case. After vthread unblocking,
|
||||
// it will check for is_vthread_suspended request and remain resumed if necessary.
|
||||
if (java_thread == nullptr || !java_thread->is_suspended()) {
|
||||
// We are done if the virtual thread is unmounted or
|
||||
// the java_thread is not externally suspended.
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
// The virtual thread is mounted and java_thread is supended: resume the java_thread.
|
||||
JvmtiVTSuspender::register_vthread_resume(thread_h());
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
// Platform thread or mounted vthread cases.
|
||||
|
||||
assert(java_thread != nullptr, "sanity check");
|
||||
assert(!java_thread->is_in_VTMS_transition(), "sanity check");
|
||||
|
||||
// Don't allow hidden thread resume request.
|
||||
if (java_thread->is_hidden_from_external_view()) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool is_thread_carrying = is_thread_carrying_vthread(java_thread, thread_h());
|
||||
if (is_thread_carrying) {
|
||||
return java_thread->clear_carrier_thread_suspended() ? JVMTI_ERROR_NONE : JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
} else {
|
||||
// Platform thread (not carrying vthread) or mounted vthread cases.
|
||||
|
||||
// A case of a non-virtual thread.
|
||||
if (!is_virtual) {
|
||||
if (!java_thread->is_carrier_thread_suspended() &&
|
||||
(is_thread_carrying || !java_thread->is_suspended())) {
|
||||
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
}
|
||||
java_thread->clear_carrier_thread_suspended();
|
||||
}
|
||||
assert(!java_thread->is_in_VTMS_transition(), "sanity check");
|
||||
|
||||
if (!is_thread_carrying) {
|
||||
assert(thread_h() != nullptr, "sanity check");
|
||||
assert(single_resume || thread_h()->is_a(vmClasses::BaseVirtualThread_klass()),
|
||||
"ResumeAllVirtualThreads should never resume non-virtual threads");
|
||||
if (java_thread->is_suspended()) {
|
||||
if (!java_thread->java_resume()) {
|
||||
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
}
|
||||
|
||||
// Ideally we would not have to check this but we have to consider the case
|
||||
// of trying to resume a thread that was previously suspended while carrying
|
||||
// a vthread but has already unmounted it.
|
||||
if (!is_virtual && java_thread->is_carrier_thread_suspended()) {
|
||||
bool res = java_thread->clear_carrier_thread_suspended();
|
||||
assert(res, "resume operations running concurrently?");
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
if (!java_thread->java_resume(is_virtual && single_resume)) {
|
||||
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
ResourceTracker::ResourceTracker(JvmtiEnv* env) {
|
||||
|
||||
@ -658,7 +658,7 @@ vframe *VM_GetOrSetLocal::get_vframe() {
|
||||
|
||||
javaVFrame *VM_GetOrSetLocal::get_java_vframe() {
|
||||
vframe* vf = get_vframe();
|
||||
if (!(_self || _thread->is_carrier_thread_suspended())) {
|
||||
if (!_self && !_thread->is_suspended() && !_thread->is_carrier_thread_suspended()) {
|
||||
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -254,7 +254,10 @@ JvmtiVTMSTransitionDisabler::print_info() {
|
||||
// disable VTMS transitions for one virtual thread
|
||||
// disable VTMS transitions for all threads if thread is nullptr or a platform thread
|
||||
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
|
||||
: _is_SR(false), _thread(thread)
|
||||
: _is_SR(false),
|
||||
_is_virtual(false),
|
||||
_is_self(false),
|
||||
_thread(thread)
|
||||
{
|
||||
if (!Continuations::enabled()) {
|
||||
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
|
||||
@ -262,21 +265,26 @@ JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
|
||||
if (Thread::current_or_null() == nullptr) {
|
||||
return; // Detached thread, can be a call from Agent_OnLoad.
|
||||
}
|
||||
JavaThread* current = JavaThread::current();
|
||||
oop thread_oop = JNIHandles::resolve_external_guard(thread);
|
||||
_is_virtual = java_lang_VirtualThread::is_instance(thread_oop);
|
||||
|
||||
if (thread == nullptr ||
|
||||
(!_is_virtual && thread_oop == current->threadObj()) ||
|
||||
(_is_virtual && thread_oop == current->vthread())) {
|
||||
_is_self = true;
|
||||
return; // no need for current thread to disable and enable transitions for itself
|
||||
}
|
||||
if (!sync_protocol_enabled_permanently()) {
|
||||
JvmtiVTMSTransitionDisabler::inc_sync_protocol_enabled_count();
|
||||
}
|
||||
oop thread_oop = JNIHandles::resolve_external_guard(thread);
|
||||
|
||||
// Target can be virtual or platform thread.
|
||||
// If target is a platform thread then we have to disable VTMS transitions for all threads.
|
||||
// It is by several reasons:
|
||||
// - carrier threads can mount virtual threads which may cause incorrect behavior
|
||||
// - there is no mechanism to disable transitions for a specific carrier thread yet
|
||||
if (!java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
_thread = nullptr; // target is a platform thread, switch to disabling VTMS transitions for all threads
|
||||
}
|
||||
|
||||
if (_thread != nullptr) {
|
||||
if (_is_virtual) {
|
||||
VTMS_transition_disable_for_one(); // disable VTMS transitions for one virtual thread
|
||||
} else {
|
||||
VTMS_transition_disable_for_all(); // disable VTMS transitions for all virtual threads
|
||||
@ -285,7 +293,10 @@ JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
|
||||
|
||||
// disable VTMS transitions for all virtual threads
|
||||
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR)
|
||||
: _is_SR(is_SR), _thread(nullptr)
|
||||
: _is_SR(is_SR),
|
||||
_is_virtual(false),
|
||||
_is_self(false),
|
||||
_thread(nullptr)
|
||||
{
|
||||
if (!Continuations::enabled()) {
|
||||
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
|
||||
@ -309,7 +320,10 @@ JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
|
||||
if (Thread::current_or_null() == nullptr) {
|
||||
return; // Detached thread, can be a call from Agent_OnLoad.
|
||||
}
|
||||
if (_thread != nullptr) {
|
||||
if (_is_self) {
|
||||
return; // no need for current thread to disable and enable transitions for itself
|
||||
}
|
||||
if (_is_virtual) {
|
||||
VTMS_transition_enable_for_one(); // enable VTMS transitions for one virtual thread
|
||||
} else {
|
||||
VTMS_transition_enable_for_all(); // enable VTMS transitions for all virtual threads
|
||||
@ -684,7 +698,7 @@ JvmtiVTSuspender::_not_suspended_list = new VirtualThreadList();
|
||||
|
||||
void
|
||||
JvmtiVTSuspender::register_all_vthreads_suspend() {
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock);
|
||||
MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
_SR_mode = SR_all;
|
||||
_suspended_list->invalidate();
|
||||
@ -693,7 +707,7 @@ JvmtiVTSuspender::register_all_vthreads_suspend() {
|
||||
|
||||
void
|
||||
JvmtiVTSuspender::register_all_vthreads_resume() {
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock);
|
||||
MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
_SR_mode = SR_none;
|
||||
_suspended_list->invalidate();
|
||||
@ -703,7 +717,7 @@ JvmtiVTSuspender::register_all_vthreads_resume() {
|
||||
void
|
||||
JvmtiVTSuspender::register_vthread_suspend(oop vt) {
|
||||
int64_t id = java_lang_Thread::thread_id(vt);
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock);
|
||||
MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
if (_SR_mode == SR_all) {
|
||||
assert(_not_suspended_list->contains(id),
|
||||
@ -720,7 +734,7 @@ JvmtiVTSuspender::register_vthread_suspend(oop vt) {
|
||||
void
|
||||
JvmtiVTSuspender::register_vthread_resume(oop vt) {
|
||||
int64_t id = java_lang_Thread::thread_id(vt);
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock);
|
||||
MutexLocker ml(JvmtiVThreadSuspend_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
if (_SR_mode == SR_all) {
|
||||
assert(!_not_suspended_list->contains(id),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2025, 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
|
||||
@ -86,6 +86,8 @@ class JvmtiVTMSTransitionDisabler {
|
||||
static volatile bool _sync_protocol_enabled_permanently; // seen a suspender: JvmtiVTMSTransitionDisabler protocol is enabled permanently
|
||||
|
||||
bool _is_SR; // is suspender or resumer
|
||||
bool _is_virtual; // target thread is virtual
|
||||
bool _is_self; // JvmtiVTMSTransitionDisabler is a no-op for current platform, carrier or virtual thread
|
||||
jthread _thread; // virtual thread to disable transitions for, no-op if it is a platform thread
|
||||
|
||||
DEBUG_ONLY(static void print_info();)
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/jvmtiThreadState.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/handshake.hpp"
|
||||
@ -729,7 +730,7 @@ class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure {
|
||||
virtual bool is_suspend() { return true; }
|
||||
};
|
||||
|
||||
bool HandshakeState::suspend_with_handshake() {
|
||||
bool HandshakeState::suspend_with_handshake(bool register_vthread_SR) {
|
||||
assert(_handshakee->threadObj() != nullptr, "cannot suspend with a null threadObj");
|
||||
if (_handshakee->is_exiting()) {
|
||||
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " exiting", p2i(_handshakee));
|
||||
@ -744,7 +745,7 @@ bool HandshakeState::suspend_with_handshake() {
|
||||
// Target is going to wake up and leave suspension.
|
||||
// Let's just stop the thread from doing that.
|
||||
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " re-suspended", p2i(_handshakee));
|
||||
set_suspended(true);
|
||||
set_suspended(true, register_vthread_SR);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -752,7 +753,7 @@ bool HandshakeState::suspend_with_handshake() {
|
||||
assert(!is_suspended(), "cannot be suspended without a suspend request");
|
||||
// Thread is safe, so it must execute the request, thus we can count it as suspended
|
||||
// from this point.
|
||||
set_suspended(true);
|
||||
set_suspended(true, register_vthread_SR);
|
||||
set_async_suspend_handshake(true);
|
||||
log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended, arming ThreadSuspension", p2i(_handshakee));
|
||||
ThreadSelfSuspensionHandshake* ts = new ThreadSelfSuspensionHandshake();
|
||||
@ -762,17 +763,19 @@ bool HandshakeState::suspend_with_handshake() {
|
||||
|
||||
// This is the closure that synchronously honors the suspend request.
|
||||
class SuspendThreadHandshake : public HandshakeClosure {
|
||||
bool _register_vthread_SR;
|
||||
bool _did_suspend;
|
||||
public:
|
||||
SuspendThreadHandshake() : HandshakeClosure("SuspendThread"), _did_suspend(false) {}
|
||||
SuspendThreadHandshake(bool register_vthread_SR) : HandshakeClosure("SuspendThread"),
|
||||
_register_vthread_SR(register_vthread_SR), _did_suspend(false) {}
|
||||
void do_thread(Thread* thr) {
|
||||
JavaThread* target = JavaThread::cast(thr);
|
||||
_did_suspend = target->handshake_state()->suspend_with_handshake();
|
||||
_did_suspend = target->handshake_state()->suspend_with_handshake(_register_vthread_SR);
|
||||
}
|
||||
bool did_suspend() { return _did_suspend; }
|
||||
};
|
||||
|
||||
bool HandshakeState::suspend() {
|
||||
bool HandshakeState::suspend(bool register_vthread_SR) {
|
||||
JVMTI_ONLY(assert(!_handshakee->is_in_VTMS_transition(), "no suspend allowed in VTMS transition");)
|
||||
JavaThread* self = JavaThread::current();
|
||||
if (_handshakee == self) {
|
||||
@ -780,31 +783,42 @@ bool HandshakeState::suspend() {
|
||||
// and just suspend directly
|
||||
ThreadBlockInVM tbivm(self);
|
||||
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
|
||||
set_suspended(true);
|
||||
set_suspended(true, register_vthread_SR);
|
||||
do_self_suspend();
|
||||
return true;
|
||||
} else {
|
||||
SuspendThreadHandshake st;
|
||||
SuspendThreadHandshake st(register_vthread_SR);
|
||||
Handshake::execute(&st, _handshakee);
|
||||
return st.did_suspend();
|
||||
}
|
||||
}
|
||||
|
||||
bool HandshakeState::resume() {
|
||||
if (!is_suspended()) {
|
||||
return false;
|
||||
}
|
||||
bool HandshakeState::resume(bool register_vthread_SR) {
|
||||
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (!is_suspended()) {
|
||||
assert(!_handshakee->is_suspended(), "cannot be suspended without a suspend request");
|
||||
return false;
|
||||
}
|
||||
// Resume the thread.
|
||||
set_suspended(false);
|
||||
set_suspended(false, register_vthread_SR);
|
||||
_lock.notify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandshakeState::set_suspended(bool is_suspend, bool register_vthread_SR) {
|
||||
#if INCLUDE_JVMTI
|
||||
if (register_vthread_SR) {
|
||||
assert(_handshakee->is_vthread_mounted(), "sanity check");
|
||||
if (is_suspend) {
|
||||
JvmtiVTSuspender::register_vthread_suspend(_handshakee->vthread());
|
||||
} else {
|
||||
JvmtiVTSuspender::register_vthread_resume(_handshakee->vthread());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Atomic::store(&_suspended, is_suspend);
|
||||
}
|
||||
|
||||
void HandshakeState::handle_unsafe_access_error() {
|
||||
if (is_suspended()) {
|
||||
// A suspend handshake was added to the queue after the
|
||||
|
||||
@ -173,18 +173,18 @@ class HandshakeState {
|
||||
bool _async_suspend_handshake;
|
||||
|
||||
// Called from the suspend handshake.
|
||||
bool suspend_with_handshake();
|
||||
bool suspend_with_handshake(bool register_vthread_SR);
|
||||
// Called from the async handshake (the trap)
|
||||
// to stop a thread from continuing execution when suspended.
|
||||
void do_self_suspend();
|
||||
|
||||
bool is_suspended() { return Atomic::load(&_suspended); }
|
||||
void set_suspended(bool to) { return Atomic::store(&_suspended, to); }
|
||||
void set_suspended(bool to, bool register_vthread_SR);
|
||||
bool has_async_suspend_handshake() { return _async_suspend_handshake; }
|
||||
void set_async_suspend_handshake(bool to) { _async_suspend_handshake = to; }
|
||||
|
||||
bool suspend();
|
||||
bool resume();
|
||||
bool suspend(bool register_vthread_SR);
|
||||
bool resume(bool register_vthread_SR);
|
||||
};
|
||||
|
||||
#endif // SHARE_RUNTIME_HANDSHAKE_HPP
|
||||
|
||||
@ -1193,7 +1193,7 @@ void JavaThread::set_is_VTMS_transition_disabler(bool val) {
|
||||
// - Target thread will not execute any new bytecode.
|
||||
// - Target thread will not enter any new monitors.
|
||||
//
|
||||
bool JavaThread::java_suspend() {
|
||||
bool JavaThread::java_suspend(bool register_vthread_SR) {
|
||||
#if INCLUDE_JVMTI
|
||||
// Suspending a JavaThread in VTMS transition or disabling VTMS transitions can cause deadlocks.
|
||||
assert(!is_in_VTMS_transition(), "no suspend allowed in VTMS transition");
|
||||
@ -1202,13 +1202,13 @@ bool JavaThread::java_suspend() {
|
||||
|
||||
guarantee(Thread::is_JavaThread_protected(/* target */ this),
|
||||
"target JavaThread is not protected in calling context.");
|
||||
return this->handshake_state()->suspend();
|
||||
return this->handshake_state()->suspend(register_vthread_SR);
|
||||
}
|
||||
|
||||
bool JavaThread::java_resume() {
|
||||
bool JavaThread::java_resume(bool register_vthread_SR) {
|
||||
guarantee(Thread::is_JavaThread_protected_by_TLH(/* target */ this),
|
||||
"missing ThreadsListHandle in calling context.");
|
||||
return this->handshake_state()->resume();
|
||||
return this->handshake_state()->resume(register_vthread_SR);
|
||||
}
|
||||
|
||||
// Wait for another thread to perform object reallocation and relocking on behalf of
|
||||
|
||||
@ -698,8 +698,8 @@ private:
|
||||
|
||||
// Suspend/resume support for JavaThread
|
||||
// higher-level suspension/resume logic called by the public APIs
|
||||
bool java_suspend();
|
||||
bool java_resume();
|
||||
bool java_suspend(bool register_vthread_SR);
|
||||
bool java_resume(bool register_vthread_SR);
|
||||
bool is_suspended() { return _handshake.is_suspended(); }
|
||||
|
||||
// Check for async exception in addition to safepoint.
|
||||
@ -710,11 +710,11 @@ private:
|
||||
void wait_for_object_deoptimization();
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
inline void set_carrier_thread_suspended();
|
||||
inline void clear_carrier_thread_suspended();
|
||||
inline bool set_carrier_thread_suspended();
|
||||
inline bool clear_carrier_thread_suspended();
|
||||
|
||||
bool is_carrier_thread_suspended() const {
|
||||
return _carrier_thread_suspended;
|
||||
return Atomic::load(&_carrier_thread_suspended);
|
||||
}
|
||||
|
||||
bool is_in_VTMS_transition() const { return _is_in_VTMS_transition; }
|
||||
|
||||
@ -71,11 +71,11 @@ inline void JavaThread::clear_obj_deopt_flag() {
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
inline void JavaThread::set_carrier_thread_suspended() {
|
||||
_carrier_thread_suspended = true;
|
||||
inline bool JavaThread::set_carrier_thread_suspended() {
|
||||
return Atomic::cmpxchg(&_carrier_thread_suspended, false, true) == false;
|
||||
}
|
||||
inline void JavaThread::clear_carrier_thread_suspended() {
|
||||
_carrier_thread_suspended = false;
|
||||
inline bool JavaThread::clear_carrier_thread_suspended() {
|
||||
return Atomic::cmpxchg(&_carrier_thread_suspended, true, false) == true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@ Monitor* JNICritical_lock = nullptr;
|
||||
Mutex* JvmtiThreadState_lock = nullptr;
|
||||
Monitor* EscapeBarrier_lock = nullptr;
|
||||
Monitor* JvmtiVTMSTransition_lock = nullptr;
|
||||
Mutex* JvmtiVThreadSuspend_lock = nullptr;
|
||||
Monitor* Heap_lock = nullptr;
|
||||
#if INCLUDE_PARALLELGC
|
||||
Mutex* PSOldGenExpand_lock = nullptr;
|
||||
@ -260,6 +261,7 @@ void mutex_init() {
|
||||
MUTEX_DEFN(DirectivesStack_lock , PaddedMutex , nosafepoint);
|
||||
|
||||
MUTEX_DEFN(JvmtiVTMSTransition_lock , PaddedMonitor, safepoint); // used for Virtual Thread Mount State transition management
|
||||
MUTEX_DEFN(JvmtiVThreadSuspend_lock , PaddedMutex, nosafepoint-1);
|
||||
MUTEX_DEFN(EscapeBarrier_lock , PaddedMonitor, nosafepoint); // Used to synchronize object reallocation/relocking triggered by JVMTI
|
||||
MUTEX_DEFN(Management_lock , PaddedMutex , safepoint); // used for JVM management
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ extern Monitor* JNICritical_lock; // a lock used while synchroniz
|
||||
extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data
|
||||
extern Monitor* EscapeBarrier_lock; // a lock to sync reallocating and relocking objects because of JVMTI access
|
||||
extern Monitor* JvmtiVTMSTransition_lock; // a lock for Virtual Thread Mount State transition (VTMS transition) management
|
||||
extern Mutex* JvmtiVThreadSuspend_lock; // a lock for virtual threads suspension
|
||||
extern Monitor* Heap_lock; // a lock on the heap
|
||||
#if INCLUDE_PARALLELGC
|
||||
extern Mutex* PSOldGenExpand_lock; // a lock on expanding the heap
|
||||
|
||||
@ -108,7 +108,6 @@ gc/shenandoah/TestEvilSyncBug.java#generational 8345501 generic-all
|
||||
# :hotspot_runtime
|
||||
|
||||
runtime/jni/terminatedThread/TestTerminatedThread.java 8317789 aix-ppc64
|
||||
runtime/handshake/HandshakeSuspendExitTest.java 8294313 generic-all
|
||||
runtime/Monitor/SyncOnValueBasedClassTest.java 8340995 linux-s390x
|
||||
runtime/os/TestTracePageSizes.java#no-options 8267460 linux-aarch64
|
||||
runtime/os/TestTracePageSizes.java#explicit-large-page-size 8267460 linux-aarch64
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user