8298853: JvmtiVTMSTransitionDisabler should support disabling one virtual thread transitions
Reviewed-by: pchilanomate, lmesnik
This commit is contained in:
parent
abbeb7e4d2
commit
13b1ebba27
@ -1516,6 +1516,8 @@ int java_lang_Thread::_contextClassLoader_offset;
|
||||
int java_lang_Thread::_inheritedAccessControlContext_offset;
|
||||
int java_lang_Thread::_eetop_offset;
|
||||
int java_lang_Thread::_jvmti_thread_state_offset;
|
||||
int java_lang_Thread::_jvmti_VTMS_transition_disable_count_offset;
|
||||
int java_lang_Thread::_jvmti_is_in_VTMS_transition_offset;
|
||||
int java_lang_Thread::_interrupted_offset;
|
||||
int java_lang_Thread::_tid_offset;
|
||||
int java_lang_Thread::_continuation_offset;
|
||||
@ -1566,6 +1568,31 @@ void java_lang_Thread::set_jvmti_thread_state(oop java_thread, JvmtiThreadState*
|
||||
java_thread->address_field_put(_jvmti_thread_state_offset, (address)state);
|
||||
}
|
||||
|
||||
int java_lang_Thread::VTMS_transition_disable_count(oop java_thread) {
|
||||
return java_thread->int_field(_jvmti_VTMS_transition_disable_count_offset);
|
||||
}
|
||||
|
||||
void java_lang_Thread::inc_VTMS_transition_disable_count(oop java_thread) {
|
||||
assert(JvmtiVTMSTransition_lock->owned_by_self(), "Must be locked");
|
||||
int val = VTMS_transition_disable_count(java_thread);
|
||||
java_thread->int_field_put(_jvmti_VTMS_transition_disable_count_offset, val + 1);
|
||||
}
|
||||
|
||||
void java_lang_Thread::dec_VTMS_transition_disable_count(oop java_thread) {
|
||||
assert(JvmtiVTMSTransition_lock->owned_by_self(), "Must be locked");
|
||||
int val = VTMS_transition_disable_count(java_thread);
|
||||
assert(val > 0, "VTMS_transition_disable_count should never be negative");
|
||||
java_thread->int_field_put(_jvmti_VTMS_transition_disable_count_offset, val - 1);
|
||||
}
|
||||
|
||||
bool java_lang_Thread::is_in_VTMS_transition(oop java_thread) {
|
||||
return java_thread->bool_field_volatile(_jvmti_is_in_VTMS_transition_offset);
|
||||
}
|
||||
|
||||
void java_lang_Thread::set_is_in_VTMS_transition(oop java_thread, bool val) {
|
||||
java_thread->bool_field_put_volatile(_jvmti_is_in_VTMS_transition_offset, val);
|
||||
}
|
||||
|
||||
void java_lang_Thread::clear_scopedValueBindings(oop java_thread) {
|
||||
assert(java_thread != nullptr, "need a java_lang_Thread pointer here");
|
||||
java_thread->obj_field_put(_scopedValueBindings_offset, nullptr);
|
||||
|
@ -334,6 +334,8 @@ class java_lang_Class : AllStatic {
|
||||
|
||||
#define THREAD_INJECTED_FIELDS(macro) \
|
||||
macro(java_lang_Thread, jvmti_thread_state, intptr_signature, false) \
|
||||
macro(java_lang_Thread, jvmti_VTMS_transition_disable_count, int_signature, false) \
|
||||
macro(java_lang_Thread, jvmti_is_in_VTMS_transition, bool_signature, false) \
|
||||
JFR_ONLY(macro(java_lang_Thread, jfr_epoch, short_signature, false))
|
||||
|
||||
class java_lang_Thread : AllStatic {
|
||||
@ -347,6 +349,8 @@ class java_lang_Thread : AllStatic {
|
||||
static int _inheritedAccessControlContext_offset;
|
||||
static int _eetop_offset;
|
||||
static int _jvmti_thread_state_offset;
|
||||
static int _jvmti_VTMS_transition_disable_count_offset;
|
||||
static int _jvmti_is_in_VTMS_transition_offset;
|
||||
static int _interrupted_offset;
|
||||
static int _tid_offset;
|
||||
static int _continuation_offset;
|
||||
@ -396,6 +400,11 @@ class java_lang_Thread : AllStatic {
|
||||
|
||||
static JvmtiThreadState* jvmti_thread_state(oop java_thread);
|
||||
static void set_jvmti_thread_state(oop java_thread, JvmtiThreadState* state);
|
||||
static int VTMS_transition_disable_count(oop java_thread);
|
||||
static void inc_VTMS_transition_disable_count(oop java_thread);
|
||||
static void dec_VTMS_transition_disable_count(oop java_thread);
|
||||
static bool is_in_VTMS_transition(oop java_thread);
|
||||
static void set_is_in_VTMS_transition(oop java_thread, bool val);
|
||||
|
||||
// Clear all scoped value bindings on error
|
||||
static void clear_scopedValueBindings(oop java_thread);
|
||||
|
@ -520,6 +520,8 @@
|
||||
template(java_lang_Boolean_signature, "Ljava/lang/Boolean;") \
|
||||
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
|
||||
template(jvmti_thread_state_name, "jvmti_thread_state") \
|
||||
template(jvmti_VTMS_transition_disable_count_name, "jvmti_VTMS_transition_disable_count") \
|
||||
template(jvmti_is_in_VTMS_transition_name, "jvmti_is_in_VTMS_transition") \
|
||||
template(module_entry_name, "module_entry") \
|
||||
template(resolved_references_name, "<resolved_references>") \
|
||||
template(init_lock_name, "<init_lock>") \
|
||||
|
@ -149,7 +149,7 @@ jvmtiError
|
||||
JvmtiEnv::SetThreadLocalStorage(jthread thread, const void* data) {
|
||||
JavaThread* current = JavaThread::current();
|
||||
JvmtiThreadState* state = nullptr;
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -202,7 +202,7 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) {
|
||||
VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread)
|
||||
debug_only(VMNativeEntryWrapper __vew;)
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -575,7 +575,7 @@ JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, j
|
||||
if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
|
||||
record_class_file_load_hook_enabled();
|
||||
}
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(event_thread);
|
||||
|
||||
if (event_thread == nullptr) {
|
||||
// Can be called at Agent_OnLoad() time with event_thread == nullptr
|
||||
@ -856,7 +856,7 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
|
||||
jvmtiError
|
||||
JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) {
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1181,7 +1181,7 @@ jvmtiError
|
||||
JvmtiEnv::StopThread(jthread thread, jobject exception) {
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
JavaThread* java_thread = nullptr;
|
||||
oop thread_oop = nullptr;
|
||||
@ -1213,7 +1213,7 @@ JvmtiEnv::InterruptThread(jthread thread) {
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
HandleMark hm(current_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1258,7 +1258,7 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
|
||||
JavaThread* java_thread = nullptr;
|
||||
oop thread_oop = nullptr;
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
// if thread is null the current thread is used
|
||||
@ -1358,7 +1358,7 @@ JvmtiEnv::GetOwnedMonitorInfo(jthread thread, jint* owned_monitor_count_ptr, job
|
||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
||||
new (mtServiceability) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, mtServiceability);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(calling_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1431,7 +1431,7 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(jthread thread, jint* monitor_info_count
|
||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
||||
new (mtServiceability) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, mtServiceability);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(calling_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1501,7 +1501,7 @@ JvmtiEnv::GetCurrentContendedMonitor(jthread thread, jobject* monitor_ptr) {
|
||||
JavaThread* calling_thread = JavaThread::current();
|
||||
HandleMark hm(calling_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(calling_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1715,7 +1715,7 @@ JvmtiEnv::GetStackTrace(jthread thread, jint start_depth, jint max_frame_count,
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
HandleMark hm(current_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1833,7 +1833,7 @@ JvmtiEnv::GetFrameCount(jthread thread, jint* count_ptr) {
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
HandleMark hm(current_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1877,7 +1877,7 @@ JvmtiEnv::PopFrame(jthread thread) {
|
||||
if (thread == nullptr) {
|
||||
return JVMTI_ERROR_INVALID_THREAD;
|
||||
}
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1925,7 +1925,7 @@ JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jl
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
HandleMark hm(current_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -1965,7 +1965,7 @@ JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jl
|
||||
jvmtiError
|
||||
JvmtiEnv::NotifyFramePop(jthread thread, jint depth) {
|
||||
ResourceMark rm;
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh;
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2243,7 +2243,7 @@ JvmtiEnv::GetLocalObject(jthread thread, jint depth, jint slot, jobject* value_p
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2284,7 +2284,7 @@ JvmtiEnv::GetLocalInstance(jthread thread, jint depth, jobject* value_ptr){
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2326,7 +2326,7 @@ JvmtiEnv::GetLocalInt(jthread thread, jint depth, jint slot, jint* value_ptr) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2368,7 +2368,7 @@ JvmtiEnv::GetLocalLong(jthread thread, jint depth, jint slot, jlong* value_ptr)
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2410,7 +2410,7 @@ JvmtiEnv::GetLocalFloat(jthread thread, jint depth, jint slot, jfloat* value_ptr
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2452,7 +2452,7 @@ JvmtiEnv::GetLocalDouble(jthread thread, jint depth, jint slot, jdouble* value_p
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2493,7 +2493,7 @@ JvmtiEnv::SetLocalObject(jthread thread, jint depth, jint slot, jobject value) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2530,7 +2530,7 @@ JvmtiEnv::SetLocalInt(jthread thread, jint depth, jint slot, jint value) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2567,7 +2567,7 @@ JvmtiEnv::SetLocalLong(jthread thread, jint depth, jint slot, jlong value) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2604,7 +2604,7 @@ JvmtiEnv::SetLocalFloat(jthread thread, jint depth, jint slot, jfloat value) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
@ -2641,7 +2641,7 @@ JvmtiEnv::SetLocalDouble(jthread thread, jint depth, jint slot, jdouble value) {
|
||||
// doit_prologue(), but after doit() is finished with it.
|
||||
ResourceMark rm(current_thread);
|
||||
HandleMark hm(current_thread);
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
|
@ -680,7 +680,7 @@ JvmtiEnvBase::check_and_skip_hidden_frames(oop vthread, javaVFrame* jvf) {
|
||||
// nothing to skip
|
||||
return jvf;
|
||||
}
|
||||
jvf = check_and_skip_hidden_frames(state->is_in_VTMS_transition(), jvf);
|
||||
jvf = check_and_skip_hidden_frames(java_lang_Thread::is_in_VTMS_transition(vthread), jvf);
|
||||
return jvf;
|
||||
}
|
||||
|
||||
@ -1912,7 +1912,7 @@ JvmtiEnvBase::force_early_return(jthread thread, jvalue value, TosState tos) {
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
HandleMark hm(current_thread);
|
||||
|
||||
JvmtiVTMSTransitionDisabler disabler;
|
||||
JvmtiVTMSTransitionDisabler disabler(thread);
|
||||
ThreadsListHandle tlh(current_thread);
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
|
@ -376,7 +376,6 @@ void JvmtiEnvThreadState::reset_current_location(jvmtiEvent event_type, bool ena
|
||||
JavaThread* thread = get_thread_or_saved();
|
||||
|
||||
oop thread_oop = jvmti_thread_state()->get_thread_oop();
|
||||
assert(!jvmti_thread_state()->is_in_VTMS_transition(), "sanity check");
|
||||
|
||||
if (thread == nullptr && event_type == JVMTI_EVENT_SINGLE_STEP && is_virtual()) {
|
||||
// Handle the unmounted virtual thread case.
|
||||
|
@ -82,9 +82,7 @@ JvmtiThreadState::JvmtiThreadState(JavaThread* thread, oop thread_oop)
|
||||
_earlyret_tos = ilgl;
|
||||
_earlyret_value.j = 0L;
|
||||
_earlyret_oop = nullptr;
|
||||
|
||||
_jvmti_event_queue = nullptr;
|
||||
_is_in_VTMS_transition = false;
|
||||
_is_virtual = false;
|
||||
|
||||
_thread_oop_h = OopHandle(JvmtiExport::jvmti_oop_storage(), thread_oop);
|
||||
@ -218,8 +216,11 @@ JvmtiThreadState::periodic_clean_up() {
|
||||
// VTMS transitions cannot be disabled while this counter is positive.
|
||||
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_count = 0;
|
||||
|
||||
// VTMS transitions is disabled while this counter is positive
|
||||
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_count = 0;
|
||||
// VTMS transitions for one virtual thread are disabled while it is positive
|
||||
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_for_one_count = 0;
|
||||
|
||||
// VTMs transitions for all virtual threads are disabled while it is positive
|
||||
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_for_all_count = 0;
|
||||
|
||||
// There is an active suspender or resumer.
|
||||
volatile bool JvmtiVTMSTransitionDisabler::_SR_mode = false;
|
||||
@ -228,8 +229,9 @@ volatile bool JvmtiVTMSTransitionDisabler::_SR_mode = false;
|
||||
#ifdef ASSERT
|
||||
void
|
||||
JvmtiVTMSTransitionDisabler::print_info() {
|
||||
log_error(jvmti)("_VTMS_transition_disable_count: %d _VTMS_transition_count: %d\n\n",
|
||||
_VTMS_transition_disable_count, _VTMS_transition_count);
|
||||
log_error(jvmti)("_VTMS_transition_count: %d\n", _VTMS_transition_count);
|
||||
log_error(jvmti)("_VTMS_transition_disable_for_one_count: %d\n", _VTMS_transition_disable_for_one_count);
|
||||
log_error(jvmti)("_VTMS_transition_disable_for_all_count: %d\n\n", _VTMS_transition_disable_for_all_count);
|
||||
int attempts = 10000;
|
||||
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *java_thread = jtiwh.next(); ) {
|
||||
ResourceMark rm;
|
||||
@ -240,15 +242,35 @@ JvmtiVTMSTransitionDisabler::print_info() {
|
||||
}
|
||||
#endif
|
||||
|
||||
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR) {
|
||||
// disable VTMS transitions for one virtual thread
|
||||
// no-op if thread is non-NULL and not a virtual thread
|
||||
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
|
||||
: _is_SR(false), _thread(thread)
|
||||
{
|
||||
if (!Continuations::enabled()) {
|
||||
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
|
||||
}
|
||||
if (Thread::current_or_null() == nullptr) {
|
||||
return; // Detached thread, can be a call from Agent_OnLoad.
|
||||
}
|
||||
_is_SR = is_SR;
|
||||
disable_VTMS_transitions();
|
||||
if (_thread != nullptr) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// disable VTMS transitions for all virtual threads
|
||||
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR)
|
||||
: _is_SR(is_SR), _thread(nullptr)
|
||||
{
|
||||
if (!Continuations::enabled()) {
|
||||
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
|
||||
}
|
||||
if (Thread::current_or_null() == nullptr) {
|
||||
return; // Detached thread, can be a call from Agent_OnLoad.
|
||||
}
|
||||
VTMS_transition_disable_for_all();
|
||||
}
|
||||
|
||||
JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
|
||||
@ -258,11 +280,43 @@ JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
|
||||
if (Thread::current_or_null() == nullptr) {
|
||||
return; // Detached thread, can be a call from Agent_OnLoad.
|
||||
}
|
||||
enable_VTMS_transitions();
|
||||
if (_thread != nullptr) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// disable VTMS transitions for one virtual thread
|
||||
void
|
||||
JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
|
||||
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_one() {
|
||||
assert(_thread != NULL, "sanity check");
|
||||
JavaThread* thread = JavaThread::current();
|
||||
HandleMark hm(thread);
|
||||
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
|
||||
if (!java_lang_VirtualThread::is_instance(vth())) {
|
||||
return; // no-op if _thread is not a virtual thread
|
||||
}
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
while (_SR_mode) { // suspender or resumer is a JvmtiVTMSTransitionDisabler monopolist
|
||||
ml.wait(10); // wait while there is an active suspender or resumer
|
||||
}
|
||||
Atomic::inc(&_VTMS_transition_disable_for_one_count);
|
||||
java_lang_Thread::inc_VTMS_transition_disable_count(vth());
|
||||
|
||||
while (java_lang_Thread::is_in_VTMS_transition(vth())) {
|
||||
ml.wait(10); // wait while the virtual thread is in transition
|
||||
}
|
||||
#ifdef ASSERT
|
||||
thread->set_is_VTMS_transition_disabler(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// disable VTMS transitions for all virtual threads
|
||||
void
|
||||
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_all() {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
int attempts = 50000;
|
||||
{
|
||||
@ -276,11 +330,11 @@ JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
|
||||
}
|
||||
if (_is_SR) {
|
||||
_SR_mode = true;
|
||||
while (_VTMS_transition_disable_count > 0) {
|
||||
while (_VTMS_transition_disable_for_all_count > 0) {
|
||||
ml.wait(10); // Wait while there is any active jvmtiVTMSTransitionDisabler.
|
||||
}
|
||||
}
|
||||
Atomic::inc(&_VTMS_transition_disable_count);
|
||||
Atomic::inc(&_VTMS_transition_disable_for_all_count);
|
||||
|
||||
// Block while some mount/unmount transitions are in progress.
|
||||
// Debug version fails and prints diagnostic information.
|
||||
@ -300,23 +354,44 @@ JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
|
||||
#ifdef ASSERT
|
||||
if (attempts == 0) {
|
||||
print_info();
|
||||
fatal("stuck in JvmtiVTMSTransitionDisabler::disable_VTMS_transitions");
|
||||
fatal("stuck in JvmtiVTMSTransitionDisabler::VTMS_transition_disable");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// enable VTMS transitions for one virtual thread
|
||||
void
|
||||
JvmtiVTMSTransitionDisabler::enable_VTMS_transitions() {
|
||||
JvmtiVTMSTransitionDisabler::VTMS_transition_enable_for_one() {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
HandleMark hm(thread);
|
||||
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
|
||||
if (!java_lang_VirtualThread::is_instance(vth())) {
|
||||
return; // no-op if _thread is not a virtual thread
|
||||
}
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
|
||||
java_lang_Thread::dec_VTMS_transition_disable_count(vth());
|
||||
Atomic::dec(&_VTMS_transition_disable_for_one_count);
|
||||
if (_VTMS_transition_disable_for_one_count == 0 || _is_SR) {
|
||||
ml.notify_all();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
thread->set_is_VTMS_transition_disabler(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// enable VTMS transitions for all virtual threads
|
||||
void
|
||||
JvmtiVTMSTransitionDisabler::VTMS_transition_enable_for_all() {
|
||||
JavaThread* current = JavaThread::current();
|
||||
{
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
|
||||
assert(_VTMS_transition_disable_count > 0, "VTMS_transition sanity check");
|
||||
assert(_VTMS_transition_disable_for_all_count > 0, "VTMS_transition sanity check");
|
||||
|
||||
if (_is_SR) { // Disabler is suspender or resumer.
|
||||
_SR_mode = false;
|
||||
}
|
||||
Atomic::dec(&_VTMS_transition_disable_count);
|
||||
if (_VTMS_transition_disable_count == 0 || _is_SR) {
|
||||
Atomic::dec(&_VTMS_transition_disable_for_all_count);
|
||||
if (_VTMS_transition_disable_for_all_count == 0 || _is_SR) {
|
||||
ml.notify_all();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
@ -335,17 +410,21 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
|
||||
// Avoid using MonitorLocker on performance critical path, use
|
||||
// two-level synchronization with lock-free operations on counters.
|
||||
Atomic::inc(&_VTMS_transition_count); // Try to enter VTMS transition section optmistically.
|
||||
java_lang_Thread::set_is_in_VTMS_transition(vth(), true);
|
||||
|
||||
// Do not allow suspends inside VTMS transitions.
|
||||
// Block while transitions are disabled or there are suspend requests.
|
||||
int64_t thread_id = java_lang_Thread::thread_id(vth()); // Cannot use oops while blocked.
|
||||
if (_VTMS_transition_disable_count > 0 ||
|
||||
|
||||
if (_VTMS_transition_disable_for_all_count > 0 ||
|
||||
java_lang_Thread::VTMS_transition_disable_count(vth()) > 0 ||
|
||||
thread->is_suspended() ||
|
||||
JvmtiVTSuspender::is_vthread_suspended(thread_id)
|
||||
) {
|
||||
// Slow path: undo unsuccessful optimistic counter incrementation.
|
||||
// It can cause an extra waiting cycle for VTMS transition disablers.
|
||||
Atomic::dec(&_VTMS_transition_count);
|
||||
java_lang_Thread::set_is_in_VTMS_transition(vth(), false);
|
||||
|
||||
while (true) {
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
@ -353,7 +432,8 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
|
||||
|
||||
// Do not allow suspends inside VTMS transitions.
|
||||
// Block while transitions are disabled or there are suspend requests.
|
||||
if (_VTMS_transition_disable_count > 0 ||
|
||||
if (_VTMS_transition_disable_for_all_count > 0 ||
|
||||
java_lang_Thread::VTMS_transition_disable_count(vth()) > 0 ||
|
||||
thread->is_suspended() ||
|
||||
JvmtiVTSuspender::is_vthread_suspended(thread_id)
|
||||
) {
|
||||
@ -365,6 +445,7 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
|
||||
continue; // ~ThreadBlockInVM has handshake-based suspend point.
|
||||
}
|
||||
Atomic::inc(&_VTMS_transition_count);
|
||||
java_lang_Thread::set_is_in_VTMS_transition(vth(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -379,10 +460,6 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
|
||||
// Enter VTMS transition section.
|
||||
assert(!thread->is_in_VTMS_transition(), "VTMS_transition sanity check");
|
||||
thread->set_is_in_VTMS_transition(true);
|
||||
JvmtiThreadState* vstate = java_lang_Thread::jvmti_thread_state(vth());
|
||||
if (vstate != nullptr) {
|
||||
vstate->set_is_in_VTMS_transition(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -393,15 +470,13 @@ JvmtiVTMSTransitionDisabler::finish_VTMS_transition(jthread vthread, bool is_mou
|
||||
thread->set_is_in_VTMS_transition(false);
|
||||
oop vt = JNIHandles::resolve_external_guard(vthread);
|
||||
int64_t thread_id = java_lang_Thread::thread_id(vt);
|
||||
JvmtiThreadState* vstate = java_lang_Thread::jvmti_thread_state(vt);
|
||||
if (vstate != nullptr) {
|
||||
vstate->set_is_in_VTMS_transition(false);
|
||||
}
|
||||
java_lang_Thread::set_is_in_VTMS_transition(vt, false);
|
||||
|
||||
Atomic::dec(&_VTMS_transition_count);
|
||||
|
||||
// Unblock waiting VTMS transition disablers.
|
||||
if (_VTMS_transition_disable_count > 0) {
|
||||
if (_VTMS_transition_disable_for_one_count > 0 ||
|
||||
_VTMS_transition_disable_for_all_count > 0) {
|
||||
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
|
||||
ml.notify_all();
|
||||
}
|
||||
|
@ -79,19 +79,24 @@ class JvmtiEnvThreadStateIterator : public StackObj {
|
||||
//
|
||||
class JvmtiVTMSTransitionDisabler {
|
||||
private:
|
||||
static volatile bool _SR_mode; // there is an active suspender or resumer
|
||||
static volatile int _VTMS_transition_count; // current number of VTMS transitions
|
||||
static volatile int _VTMS_transition_disable_count; // VTMS transitions are disabled while it is non-zero
|
||||
static volatile int _VTMS_transition_disable_for_one_count; // transitions for one virtual thread are disabled while it is positive
|
||||
static volatile int _VTMS_transition_disable_for_all_count; // transitions for all virtual threads are disabled while it is positive
|
||||
static volatile bool _SR_mode; // there is an active suspender or resumer
|
||||
static volatile int _VTMS_transition_count; // current number of VTMS transitions
|
||||
|
||||
bool _is_SR; // is suspender or resumer
|
||||
|
||||
void disable_VTMS_transitions();
|
||||
void enable_VTMS_transitions();
|
||||
bool _is_SR; // is suspender or resumer
|
||||
jthread _thread; // virtual thread to disable transitions for, no-op if it is a platform thread
|
||||
|
||||
DEBUG_ONLY(static void print_info();)
|
||||
void VTMS_transition_disable_for_one();
|
||||
void VTMS_transition_disable_for_all();
|
||||
void VTMS_transition_enable_for_one();
|
||||
void VTMS_transition_enable_for_all();
|
||||
|
||||
public:
|
||||
// parameter is_SR: suspender or resumer
|
||||
JvmtiVTMSTransitionDisabler(bool is_SR = false);
|
||||
JvmtiVTMSTransitionDisabler(jthread thread);
|
||||
~JvmtiVTMSTransitionDisabler();
|
||||
|
||||
static void start_VTMS_transition(jthread vthread, bool is_mount);
|
||||
@ -153,7 +158,6 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
|
||||
OopHandle _thread_oop_h;
|
||||
// Jvmti Events that cannot be posted in their current context.
|
||||
JvmtiDeferredEventQueue* _jvmti_event_queue;
|
||||
bool _is_in_VTMS_transition; // saved JavaThread.is_in_VTMS_transition()
|
||||
bool _is_virtual; // state belongs to a virtual thread
|
||||
bool _hide_single_stepping;
|
||||
bool _pending_interp_only_mode;
|
||||
@ -270,9 +274,6 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
|
||||
void set_thread(JavaThread* thread);
|
||||
oop get_thread_oop();
|
||||
|
||||
// The JavaThread is_in_VTMS_transition() bit saved at unmount to restore at mount.
|
||||
inline bool is_in_VTMS_transition() { return _is_in_VTMS_transition; }
|
||||
inline void set_is_in_VTMS_transition(bool val) { _is_in_VTMS_transition = val; }
|
||||
inline bool is_virtual() { return _is_virtual; } // the _thread is virtual
|
||||
|
||||
inline bool is_exception_detected() { return _exception_state == ES_DETECTED; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user