Skip to content

Commit 13b1ebb

Browse files
author
Serguei Spitsyn
committedFeb 14, 2023
8298853: JvmtiVTMSTransitionDisabler should support disabling one virtual thread transitions
Reviewed-by: pchilanomate, lmesnik
1 parent abbeb7e commit 13b1ebb

8 files changed

+182
-69
lines changed
 

‎src/hotspot/share/classfile/javaClasses.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,8 @@ int java_lang_Thread::_contextClassLoader_offset;
15161516
int java_lang_Thread::_inheritedAccessControlContext_offset;
15171517
int java_lang_Thread::_eetop_offset;
15181518
int java_lang_Thread::_jvmti_thread_state_offset;
1519+
int java_lang_Thread::_jvmti_VTMS_transition_disable_count_offset;
1520+
int java_lang_Thread::_jvmti_is_in_VTMS_transition_offset;
15191521
int java_lang_Thread::_interrupted_offset;
15201522
int java_lang_Thread::_tid_offset;
15211523
int java_lang_Thread::_continuation_offset;
@@ -1566,6 +1568,31 @@ void java_lang_Thread::set_jvmti_thread_state(oop java_thread, JvmtiThreadState*
15661568
java_thread->address_field_put(_jvmti_thread_state_offset, (address)state);
15671569
}
15681570

1571+
int java_lang_Thread::VTMS_transition_disable_count(oop java_thread) {
1572+
return java_thread->int_field(_jvmti_VTMS_transition_disable_count_offset);
1573+
}
1574+
1575+
void java_lang_Thread::inc_VTMS_transition_disable_count(oop java_thread) {
1576+
assert(JvmtiVTMSTransition_lock->owned_by_self(), "Must be locked");
1577+
int val = VTMS_transition_disable_count(java_thread);
1578+
java_thread->int_field_put(_jvmti_VTMS_transition_disable_count_offset, val + 1);
1579+
}
1580+
1581+
void java_lang_Thread::dec_VTMS_transition_disable_count(oop java_thread) {
1582+
assert(JvmtiVTMSTransition_lock->owned_by_self(), "Must be locked");
1583+
int val = VTMS_transition_disable_count(java_thread);
1584+
assert(val > 0, "VTMS_transition_disable_count should never be negative");
1585+
java_thread->int_field_put(_jvmti_VTMS_transition_disable_count_offset, val - 1);
1586+
}
1587+
1588+
bool java_lang_Thread::is_in_VTMS_transition(oop java_thread) {
1589+
return java_thread->bool_field_volatile(_jvmti_is_in_VTMS_transition_offset);
1590+
}
1591+
1592+
void java_lang_Thread::set_is_in_VTMS_transition(oop java_thread, bool val) {
1593+
java_thread->bool_field_put_volatile(_jvmti_is_in_VTMS_transition_offset, val);
1594+
}
1595+
15691596
void java_lang_Thread::clear_scopedValueBindings(oop java_thread) {
15701597
assert(java_thread != nullptr, "need a java_lang_Thread pointer here");
15711598
java_thread->obj_field_put(_scopedValueBindings_offset, nullptr);

‎src/hotspot/share/classfile/javaClasses.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ class java_lang_Class : AllStatic {
334334

335335
#define THREAD_INJECTED_FIELDS(macro) \
336336
macro(java_lang_Thread, jvmti_thread_state, intptr_signature, false) \
337+
macro(java_lang_Thread, jvmti_VTMS_transition_disable_count, int_signature, false) \
338+
macro(java_lang_Thread, jvmti_is_in_VTMS_transition, bool_signature, false) \
337339
JFR_ONLY(macro(java_lang_Thread, jfr_epoch, short_signature, false))
338340

339341
class java_lang_Thread : AllStatic {
@@ -347,6 +349,8 @@ class java_lang_Thread : AllStatic {
347349
static int _inheritedAccessControlContext_offset;
348350
static int _eetop_offset;
349351
static int _jvmti_thread_state_offset;
352+
static int _jvmti_VTMS_transition_disable_count_offset;
353+
static int _jvmti_is_in_VTMS_transition_offset;
350354
static int _interrupted_offset;
351355
static int _tid_offset;
352356
static int _continuation_offset;
@@ -396,6 +400,11 @@ class java_lang_Thread : AllStatic {
396400

397401
static JvmtiThreadState* jvmti_thread_state(oop java_thread);
398402
static void set_jvmti_thread_state(oop java_thread, JvmtiThreadState* state);
403+
static int VTMS_transition_disable_count(oop java_thread);
404+
static void inc_VTMS_transition_disable_count(oop java_thread);
405+
static void dec_VTMS_transition_disable_count(oop java_thread);
406+
static bool is_in_VTMS_transition(oop java_thread);
407+
static void set_is_in_VTMS_transition(oop java_thread, bool val);
399408

400409
// Clear all scoped value bindings on error
401410
static void clear_scopedValueBindings(oop java_thread);

‎src/hotspot/share/classfile/vmSymbols.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@
520520
template(java_lang_Boolean_signature, "Ljava/lang/Boolean;") \
521521
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
522522
template(jvmti_thread_state_name, "jvmti_thread_state") \
523+
template(jvmti_VTMS_transition_disable_count_name, "jvmti_VTMS_transition_disable_count") \
524+
template(jvmti_is_in_VTMS_transition_name, "jvmti_is_in_VTMS_transition") \
523525
template(module_entry_name, "module_entry") \
524526
template(resolved_references_name, "<resolved_references>") \
525527
template(init_lock_name, "<init_lock>") \

‎src/hotspot/share/prims/jvmtiEnv.cpp

+26-26
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ jvmtiError
149149
JvmtiEnv::SetThreadLocalStorage(jthread thread, const void* data) {
150150
JavaThread* current = JavaThread::current();
151151
JvmtiThreadState* state = nullptr;
152-
JvmtiVTMSTransitionDisabler disabler;
152+
JvmtiVTMSTransitionDisabler disabler(thread);
153153
ThreadsListHandle tlh(current);
154154

155155
JavaThread* java_thread = nullptr;
@@ -202,7 +202,7 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) {
202202
VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread)
203203
debug_only(VMNativeEntryWrapper __vew;)
204204

205-
JvmtiVTMSTransitionDisabler disabler;
205+
JvmtiVTMSTransitionDisabler disabler(thread);
206206
ThreadsListHandle tlh(current_thread);
207207

208208
JavaThread* java_thread = nullptr;
@@ -575,7 +575,7 @@ JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, j
575575
if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
576576
record_class_file_load_hook_enabled();
577577
}
578-
JvmtiVTMSTransitionDisabler disabler;
578+
JvmtiVTMSTransitionDisabler disabler(event_thread);
579579

580580
if (event_thread == nullptr) {
581581
// Can be called at Agent_OnLoad() time with event_thread == nullptr
@@ -856,7 +856,7 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
856856
jvmtiError
857857
JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) {
858858
JavaThread* current_thread = JavaThread::current();
859-
JvmtiVTMSTransitionDisabler disabler;
859+
JvmtiVTMSTransitionDisabler disabler(thread);
860860
ThreadsListHandle tlh(current_thread);
861861

862862
JavaThread* java_thread = nullptr;
@@ -1181,7 +1181,7 @@ jvmtiError
11811181
JvmtiEnv::StopThread(jthread thread, jobject exception) {
11821182
JavaThread* current_thread = JavaThread::current();
11831183

1184-
JvmtiVTMSTransitionDisabler disabler;
1184+
JvmtiVTMSTransitionDisabler disabler(thread);
11851185
ThreadsListHandle tlh(current_thread);
11861186
JavaThread* java_thread = nullptr;
11871187
oop thread_oop = nullptr;
@@ -1213,7 +1213,7 @@ JvmtiEnv::InterruptThread(jthread thread) {
12131213
JavaThread* current_thread = JavaThread::current();
12141214
HandleMark hm(current_thread);
12151215

1216-
JvmtiVTMSTransitionDisabler disabler;
1216+
JvmtiVTMSTransitionDisabler disabler(thread);
12171217
ThreadsListHandle tlh(current_thread);
12181218

12191219
JavaThread* java_thread = nullptr;
@@ -1258,7 +1258,7 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
12581258
JavaThread* java_thread = nullptr;
12591259
oop thread_oop = nullptr;
12601260

1261-
JvmtiVTMSTransitionDisabler disabler;
1261+
JvmtiVTMSTransitionDisabler disabler(thread);
12621262
ThreadsListHandle tlh(current_thread);
12631263

12641264
// if thread is null the current thread is used
@@ -1358,7 +1358,7 @@ JvmtiEnv::GetOwnedMonitorInfo(jthread thread, jint* owned_monitor_count_ptr, job
13581358
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
13591359
new (mtServiceability) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, mtServiceability);
13601360

1361-
JvmtiVTMSTransitionDisabler disabler;
1361+
JvmtiVTMSTransitionDisabler disabler(thread);
13621362
ThreadsListHandle tlh(calling_thread);
13631363

13641364
JavaThread* java_thread = nullptr;
@@ -1431,7 +1431,7 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(jthread thread, jint* monitor_info_count
14311431
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
14321432
new (mtServiceability) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, mtServiceability);
14331433

1434-
JvmtiVTMSTransitionDisabler disabler;
1434+
JvmtiVTMSTransitionDisabler disabler(thread);
14351435
ThreadsListHandle tlh(calling_thread);
14361436

14371437
JavaThread* java_thread = nullptr;
@@ -1501,7 +1501,7 @@ JvmtiEnv::GetCurrentContendedMonitor(jthread thread, jobject* monitor_ptr) {
15011501
JavaThread* calling_thread = JavaThread::current();
15021502
HandleMark hm(calling_thread);
15031503

1504-
JvmtiVTMSTransitionDisabler disabler;
1504+
JvmtiVTMSTransitionDisabler disabler(thread);
15051505
ThreadsListHandle tlh(calling_thread);
15061506

15071507
JavaThread* java_thread = nullptr;
@@ -1715,7 +1715,7 @@ JvmtiEnv::GetStackTrace(jthread thread, jint start_depth, jint max_frame_count,
17151715
JavaThread* current_thread = JavaThread::current();
17161716
HandleMark hm(current_thread);
17171717

1718-
JvmtiVTMSTransitionDisabler disabler;
1718+
JvmtiVTMSTransitionDisabler disabler(thread);
17191719
ThreadsListHandle tlh(current_thread);
17201720

17211721
JavaThread* java_thread = nullptr;
@@ -1833,7 +1833,7 @@ JvmtiEnv::GetFrameCount(jthread thread, jint* count_ptr) {
18331833
JavaThread* current_thread = JavaThread::current();
18341834
HandleMark hm(current_thread);
18351835

1836-
JvmtiVTMSTransitionDisabler disabler;
1836+
JvmtiVTMSTransitionDisabler disabler(thread);
18371837
ThreadsListHandle tlh(current_thread);
18381838

18391839
JavaThread* java_thread = nullptr;
@@ -1877,7 +1877,7 @@ JvmtiEnv::PopFrame(jthread thread) {
18771877
if (thread == nullptr) {
18781878
return JVMTI_ERROR_INVALID_THREAD;
18791879
}
1880-
JvmtiVTMSTransitionDisabler disabler;
1880+
JvmtiVTMSTransitionDisabler disabler(thread);
18811881
ThreadsListHandle tlh(current_thread);
18821882

18831883
JavaThread* java_thread = nullptr;
@@ -1925,7 +1925,7 @@ JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jl
19251925
JavaThread* current_thread = JavaThread::current();
19261926
HandleMark hm(current_thread);
19271927

1928-
JvmtiVTMSTransitionDisabler disabler;
1928+
JvmtiVTMSTransitionDisabler disabler(thread);
19291929
ThreadsListHandle tlh(current_thread);
19301930

19311931
JavaThread* java_thread = nullptr;
@@ -1965,7 +1965,7 @@ JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jl
19651965
jvmtiError
19661966
JvmtiEnv::NotifyFramePop(jthread thread, jint depth) {
19671967
ResourceMark rm;
1968-
JvmtiVTMSTransitionDisabler disabler;
1968+
JvmtiVTMSTransitionDisabler disabler(thread);
19691969
ThreadsListHandle tlh;
19701970

19711971
JavaThread* java_thread = nullptr;
@@ -2243,7 +2243,7 @@ JvmtiEnv::GetLocalObject(jthread thread, jint depth, jint slot, jobject* value_p
22432243
// doit_prologue(), but after doit() is finished with it.
22442244
ResourceMark rm(current_thread);
22452245
HandleMark hm(current_thread);
2246-
JvmtiVTMSTransitionDisabler disabler;
2246+
JvmtiVTMSTransitionDisabler disabler(thread);
22472247
ThreadsListHandle tlh(current_thread);
22482248

22492249
JavaThread* java_thread = nullptr;
@@ -2284,7 +2284,7 @@ JvmtiEnv::GetLocalInstance(jthread thread, jint depth, jobject* value_ptr){
22842284
// doit_prologue(), but after doit() is finished with it.
22852285
ResourceMark rm(current_thread);
22862286
HandleMark hm(current_thread);
2287-
JvmtiVTMSTransitionDisabler disabler;
2287+
JvmtiVTMSTransitionDisabler disabler(thread);
22882288
ThreadsListHandle tlh(current_thread);
22892289

22902290
JavaThread* java_thread = nullptr;
@@ -2326,7 +2326,7 @@ JvmtiEnv::GetLocalInt(jthread thread, jint depth, jint slot, jint* value_ptr) {
23262326
// doit_prologue(), but after doit() is finished with it.
23272327
ResourceMark rm(current_thread);
23282328
HandleMark hm(current_thread);
2329-
JvmtiVTMSTransitionDisabler disabler;
2329+
JvmtiVTMSTransitionDisabler disabler(thread);
23302330
ThreadsListHandle tlh(current_thread);
23312331

23322332
JavaThread* java_thread = nullptr;
@@ -2368,7 +2368,7 @@ JvmtiEnv::GetLocalLong(jthread thread, jint depth, jint slot, jlong* value_ptr)
23682368
// doit_prologue(), but after doit() is finished with it.
23692369
ResourceMark rm(current_thread);
23702370
HandleMark hm(current_thread);
2371-
JvmtiVTMSTransitionDisabler disabler;
2371+
JvmtiVTMSTransitionDisabler disabler(thread);
23722372
ThreadsListHandle tlh(current_thread);
23732373

23742374
JavaThread* java_thread = nullptr;
@@ -2410,7 +2410,7 @@ JvmtiEnv::GetLocalFloat(jthread thread, jint depth, jint slot, jfloat* value_ptr
24102410
// doit_prologue(), but after doit() is finished with it.
24112411
ResourceMark rm(current_thread);
24122412
HandleMark hm(current_thread);
2413-
JvmtiVTMSTransitionDisabler disabler;
2413+
JvmtiVTMSTransitionDisabler disabler(thread);
24142414
ThreadsListHandle tlh(current_thread);
24152415

24162416
JavaThread* java_thread = nullptr;
@@ -2452,7 +2452,7 @@ JvmtiEnv::GetLocalDouble(jthread thread, jint depth, jint slot, jdouble* value_p
24522452
// doit_prologue(), but after doit() is finished with it.
24532453
ResourceMark rm(current_thread);
24542454
HandleMark hm(current_thread);
2455-
JvmtiVTMSTransitionDisabler disabler;
2455+
JvmtiVTMSTransitionDisabler disabler(thread);
24562456
ThreadsListHandle tlh(current_thread);
24572457

24582458
JavaThread* java_thread = nullptr;
@@ -2493,7 +2493,7 @@ JvmtiEnv::SetLocalObject(jthread thread, jint depth, jint slot, jobject value) {
24932493
// doit_prologue(), but after doit() is finished with it.
24942494
ResourceMark rm(current_thread);
24952495
HandleMark hm(current_thread);
2496-
JvmtiVTMSTransitionDisabler disabler;
2496+
JvmtiVTMSTransitionDisabler disabler(thread);
24972497
ThreadsListHandle tlh(current_thread);
24982498

24992499
JavaThread* java_thread = nullptr;
@@ -2530,7 +2530,7 @@ JvmtiEnv::SetLocalInt(jthread thread, jint depth, jint slot, jint value) {
25302530
// doit_prologue(), but after doit() is finished with it.
25312531
ResourceMark rm(current_thread);
25322532
HandleMark hm(current_thread);
2533-
JvmtiVTMSTransitionDisabler disabler;
2533+
JvmtiVTMSTransitionDisabler disabler(thread);
25342534
ThreadsListHandle tlh(current_thread);
25352535

25362536
JavaThread* java_thread = nullptr;
@@ -2567,7 +2567,7 @@ JvmtiEnv::SetLocalLong(jthread thread, jint depth, jint slot, jlong value) {
25672567
// doit_prologue(), but after doit() is finished with it.
25682568
ResourceMark rm(current_thread);
25692569
HandleMark hm(current_thread);
2570-
JvmtiVTMSTransitionDisabler disabler;
2570+
JvmtiVTMSTransitionDisabler disabler(thread);
25712571
ThreadsListHandle tlh(current_thread);
25722572

25732573
JavaThread* java_thread = nullptr;
@@ -2604,7 +2604,7 @@ JvmtiEnv::SetLocalFloat(jthread thread, jint depth, jint slot, jfloat value) {
26042604
// doit_prologue(), but after doit() is finished with it.
26052605
ResourceMark rm(current_thread);
26062606
HandleMark hm(current_thread);
2607-
JvmtiVTMSTransitionDisabler disabler;
2607+
JvmtiVTMSTransitionDisabler disabler(thread);
26082608
ThreadsListHandle tlh(current_thread);
26092609

26102610
JavaThread* java_thread = nullptr;
@@ -2641,7 +2641,7 @@ JvmtiEnv::SetLocalDouble(jthread thread, jint depth, jint slot, jdouble value) {
26412641
// doit_prologue(), but after doit() is finished with it.
26422642
ResourceMark rm(current_thread);
26432643
HandleMark hm(current_thread);
2644-
JvmtiVTMSTransitionDisabler disabler;
2644+
JvmtiVTMSTransitionDisabler disabler(thread);
26452645
ThreadsListHandle tlh(current_thread);
26462646

26472647
JavaThread* java_thread = nullptr;

‎src/hotspot/share/prims/jvmtiEnvBase.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ JvmtiEnvBase::check_and_skip_hidden_frames(oop vthread, javaVFrame* jvf) {
680680
// nothing to skip
681681
return jvf;
682682
}
683-
jvf = check_and_skip_hidden_frames(state->is_in_VTMS_transition(), jvf);
683+
jvf = check_and_skip_hidden_frames(java_lang_Thread::is_in_VTMS_transition(vthread), jvf);
684684
return jvf;
685685
}
686686

@@ -1912,7 +1912,7 @@ JvmtiEnvBase::force_early_return(jthread thread, jvalue value, TosState tos) {
19121912
JavaThread* current_thread = JavaThread::current();
19131913
HandleMark hm(current_thread);
19141914

1915-
JvmtiVTMSTransitionDisabler disabler;
1915+
JvmtiVTMSTransitionDisabler disabler(thread);
19161916
ThreadsListHandle tlh(current_thread);
19171917

19181918
JavaThread* java_thread = nullptr;

‎src/hotspot/share/prims/jvmtiEnvThreadState.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,6 @@ void JvmtiEnvThreadState::reset_current_location(jvmtiEvent event_type, bool ena
376376
JavaThread* thread = get_thread_or_saved();
377377

378378
oop thread_oop = jvmti_thread_state()->get_thread_oop();
379-
assert(!jvmti_thread_state()->is_in_VTMS_transition(), "sanity check");
380379

381380
if (thread == nullptr && event_type == JVMTI_EVENT_SINGLE_STEP && is_virtual()) {
382381
// Handle the unmounted virtual thread case.

‎src/hotspot/share/prims/jvmtiThreadState.cpp

+104-29
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ JvmtiThreadState::JvmtiThreadState(JavaThread* thread, oop thread_oop)
8282
_earlyret_tos = ilgl;
8383
_earlyret_value.j = 0L;
8484
_earlyret_oop = nullptr;
85-
8685
_jvmti_event_queue = nullptr;
87-
_is_in_VTMS_transition = false;
8886
_is_virtual = false;
8987

9088
_thread_oop_h = OopHandle(JvmtiExport::jvmti_oop_storage(), thread_oop);
@@ -218,8 +216,11 @@ JvmtiThreadState::periodic_clean_up() {
218216
// VTMS transitions cannot be disabled while this counter is positive.
219217
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_count = 0;
220218

221-
// VTMS transitions is disabled while this counter is positive
222-
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_count = 0;
219+
// VTMS transitions for one virtual thread are disabled while it is positive
220+
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_for_one_count = 0;
221+
222+
// VTMs transitions for all virtual threads are disabled while it is positive
223+
volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_for_all_count = 0;
223224

224225
// There is an active suspender or resumer.
225226
volatile bool JvmtiVTMSTransitionDisabler::_SR_mode = false;
@@ -228,8 +229,9 @@ volatile bool JvmtiVTMSTransitionDisabler::_SR_mode = false;
228229
#ifdef ASSERT
229230
void
230231
JvmtiVTMSTransitionDisabler::print_info() {
231-
log_error(jvmti)("_VTMS_transition_disable_count: %d _VTMS_transition_count: %d\n\n",
232-
_VTMS_transition_disable_count, _VTMS_transition_count);
232+
log_error(jvmti)("_VTMS_transition_count: %d\n", _VTMS_transition_count);
233+
log_error(jvmti)("_VTMS_transition_disable_for_one_count: %d\n", _VTMS_transition_disable_for_one_count);
234+
log_error(jvmti)("_VTMS_transition_disable_for_all_count: %d\n\n", _VTMS_transition_disable_for_all_count);
233235
int attempts = 10000;
234236
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *java_thread = jtiwh.next(); ) {
235237
ResourceMark rm;
@@ -240,15 +242,35 @@ JvmtiVTMSTransitionDisabler::print_info() {
240242
}
241243
#endif
242244

243-
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR) {
245+
// disable VTMS transitions for one virtual thread
246+
// no-op if thread is non-NULL and not a virtual thread
247+
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(jthread thread)
248+
: _is_SR(false), _thread(thread)
249+
{
244250
if (!Continuations::enabled()) {
245251
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
246252
}
247253
if (Thread::current_or_null() == nullptr) {
248254
return; // Detached thread, can be a call from Agent_OnLoad.
249255
}
250-
_is_SR = is_SR;
251-
disable_VTMS_transitions();
256+
if (_thread != nullptr) {
257+
VTMS_transition_disable_for_one(); // disable VTMS transitions for one virtual thread
258+
} else {
259+
VTMS_transition_disable_for_all(); // disable VTMS transitions for all virtual threads
260+
}
261+
}
262+
263+
// disable VTMS transitions for all virtual threads
264+
JvmtiVTMSTransitionDisabler::JvmtiVTMSTransitionDisabler(bool is_SR)
265+
: _is_SR(is_SR), _thread(nullptr)
266+
{
267+
if (!Continuations::enabled()) {
268+
return; // JvmtiVTMSTransitionDisabler is no-op without virtual threads
269+
}
270+
if (Thread::current_or_null() == nullptr) {
271+
return; // Detached thread, can be a call from Agent_OnLoad.
272+
}
273+
VTMS_transition_disable_for_all();
252274
}
253275

254276
JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
@@ -258,11 +280,43 @@ JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
258280
if (Thread::current_or_null() == nullptr) {
259281
return; // Detached thread, can be a call from Agent_OnLoad.
260282
}
261-
enable_VTMS_transitions();
283+
if (_thread != nullptr) {
284+
VTMS_transition_enable_for_one(); // enable VTMS transitions for one virtual thread
285+
} else {
286+
VTMS_transition_enable_for_all(); // enable VTMS transitions for all virtual threads
287+
}
262288
}
263289

290+
// disable VTMS transitions for one virtual thread
264291
void
265-
JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
292+
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_one() {
293+
assert(_thread != NULL, "sanity check");
294+
JavaThread* thread = JavaThread::current();
295+
HandleMark hm(thread);
296+
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
297+
if (!java_lang_VirtualThread::is_instance(vth())) {
298+
return; // no-op if _thread is not a virtual thread
299+
}
300+
ThreadBlockInVM tbivm(thread);
301+
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
302+
303+
while (_SR_mode) { // suspender or resumer is a JvmtiVTMSTransitionDisabler monopolist
304+
ml.wait(10); // wait while there is an active suspender or resumer
305+
}
306+
Atomic::inc(&_VTMS_transition_disable_for_one_count);
307+
java_lang_Thread::inc_VTMS_transition_disable_count(vth());
308+
309+
while (java_lang_Thread::is_in_VTMS_transition(vth())) {
310+
ml.wait(10); // wait while the virtual thread is in transition
311+
}
312+
#ifdef ASSERT
313+
thread->set_is_VTMS_transition_disabler(true);
314+
#endif
315+
}
316+
317+
// disable VTMS transitions for all virtual threads
318+
void
319+
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_all() {
266320
JavaThread* thread = JavaThread::current();
267321
int attempts = 50000;
268322
{
@@ -276,11 +330,11 @@ JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
276330
}
277331
if (_is_SR) {
278332
_SR_mode = true;
279-
while (_VTMS_transition_disable_count > 0) {
333+
while (_VTMS_transition_disable_for_all_count > 0) {
280334
ml.wait(10); // Wait while there is any active jvmtiVTMSTransitionDisabler.
281335
}
282336
}
283-
Atomic::inc(&_VTMS_transition_disable_count);
337+
Atomic::inc(&_VTMS_transition_disable_for_all_count);
284338

285339
// Block while some mount/unmount transitions are in progress.
286340
// Debug version fails and prints diagnostic information.
@@ -300,23 +354,44 @@ JvmtiVTMSTransitionDisabler::disable_VTMS_transitions() {
300354
#ifdef ASSERT
301355
if (attempts == 0) {
302356
print_info();
303-
fatal("stuck in JvmtiVTMSTransitionDisabler::disable_VTMS_transitions");
357+
fatal("stuck in JvmtiVTMSTransitionDisabler::VTMS_transition_disable");
304358
}
305359
#endif
306360
}
307361

362+
// enable VTMS transitions for one virtual thread
363+
void
364+
JvmtiVTMSTransitionDisabler::VTMS_transition_enable_for_one() {
365+
JavaThread* thread = JavaThread::current();
366+
HandleMark hm(thread);
367+
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
368+
if (!java_lang_VirtualThread::is_instance(vth())) {
369+
return; // no-op if _thread is not a virtual thread
370+
}
371+
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
372+
java_lang_Thread::dec_VTMS_transition_disable_count(vth());
373+
Atomic::dec(&_VTMS_transition_disable_for_one_count);
374+
if (_VTMS_transition_disable_for_one_count == 0 || _is_SR) {
375+
ml.notify_all();
376+
}
377+
#ifdef ASSERT
378+
thread->set_is_VTMS_transition_disabler(false);
379+
#endif
380+
}
381+
382+
// enable VTMS transitions for all virtual threads
308383
void
309-
JvmtiVTMSTransitionDisabler::enable_VTMS_transitions() {
384+
JvmtiVTMSTransitionDisabler::VTMS_transition_enable_for_all() {
310385
JavaThread* current = JavaThread::current();
311386
{
312387
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
313-
assert(_VTMS_transition_disable_count > 0, "VTMS_transition sanity check");
388+
assert(_VTMS_transition_disable_for_all_count > 0, "VTMS_transition sanity check");
314389

315390
if (_is_SR) { // Disabler is suspender or resumer.
316391
_SR_mode = false;
317392
}
318-
Atomic::dec(&_VTMS_transition_disable_count);
319-
if (_VTMS_transition_disable_count == 0 || _is_SR) {
393+
Atomic::dec(&_VTMS_transition_disable_for_all_count);
394+
if (_VTMS_transition_disable_for_all_count == 0 || _is_SR) {
320395
ml.notify_all();
321396
}
322397
#ifdef ASSERT
@@ -335,25 +410,30 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
335410
// Avoid using MonitorLocker on performance critical path, use
336411
// two-level synchronization with lock-free operations on counters.
337412
Atomic::inc(&_VTMS_transition_count); // Try to enter VTMS transition section optmistically.
413+
java_lang_Thread::set_is_in_VTMS_transition(vth(), true);
338414

339415
// Do not allow suspends inside VTMS transitions.
340416
// Block while transitions are disabled or there are suspend requests.
341417
int64_t thread_id = java_lang_Thread::thread_id(vth()); // Cannot use oops while blocked.
342-
if (_VTMS_transition_disable_count > 0 ||
418+
419+
if (_VTMS_transition_disable_for_all_count > 0 ||
420+
java_lang_Thread::VTMS_transition_disable_count(vth()) > 0 ||
343421
thread->is_suspended() ||
344422
JvmtiVTSuspender::is_vthread_suspended(thread_id)
345423
) {
346424
// Slow path: undo unsuccessful optimistic counter incrementation.
347425
// It can cause an extra waiting cycle for VTMS transition disablers.
348426
Atomic::dec(&_VTMS_transition_count);
427+
java_lang_Thread::set_is_in_VTMS_transition(vth(), false);
349428

350429
while (true) {
351430
ThreadBlockInVM tbivm(thread);
352431
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
353432

354433
// Do not allow suspends inside VTMS transitions.
355434
// Block while transitions are disabled or there are suspend requests.
356-
if (_VTMS_transition_disable_count > 0 ||
435+
if (_VTMS_transition_disable_for_all_count > 0 ||
436+
java_lang_Thread::VTMS_transition_disable_count(vth()) > 0 ||
357437
thread->is_suspended() ||
358438
JvmtiVTSuspender::is_vthread_suspended(thread_id)
359439
) {
@@ -365,6 +445,7 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
365445
continue; // ~ThreadBlockInVM has handshake-based suspend point.
366446
}
367447
Atomic::inc(&_VTMS_transition_count);
448+
java_lang_Thread::set_is_in_VTMS_transition(vth(), true);
368449
break;
369450
}
370451
}
@@ -379,10 +460,6 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun
379460
// Enter VTMS transition section.
380461
assert(!thread->is_in_VTMS_transition(), "VTMS_transition sanity check");
381462
thread->set_is_in_VTMS_transition(true);
382-
JvmtiThreadState* vstate = java_lang_Thread::jvmti_thread_state(vth());
383-
if (vstate != nullptr) {
384-
vstate->set_is_in_VTMS_transition(true);
385-
}
386463
}
387464

388465
void
@@ -393,15 +470,13 @@ JvmtiVTMSTransitionDisabler::finish_VTMS_transition(jthread vthread, bool is_mou
393470
thread->set_is_in_VTMS_transition(false);
394471
oop vt = JNIHandles::resolve_external_guard(vthread);
395472
int64_t thread_id = java_lang_Thread::thread_id(vt);
396-
JvmtiThreadState* vstate = java_lang_Thread::jvmti_thread_state(vt);
397-
if (vstate != nullptr) {
398-
vstate->set_is_in_VTMS_transition(false);
399-
}
473+
java_lang_Thread::set_is_in_VTMS_transition(vt, false);
400474

401475
Atomic::dec(&_VTMS_transition_count);
402476

403477
// Unblock waiting VTMS transition disablers.
404-
if (_VTMS_transition_disable_count > 0) {
478+
if (_VTMS_transition_disable_for_one_count > 0 ||
479+
_VTMS_transition_disable_for_all_count > 0) {
405480
MonitorLocker ml(JvmtiVTMSTransition_lock, Mutex::_no_safepoint_check_flag);
406481
ml.notify_all();
407482
}

‎src/hotspot/share/prims/jvmtiThreadState.hpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,24 @@ class JvmtiEnvThreadStateIterator : public StackObj {
7979
//
8080
class JvmtiVTMSTransitionDisabler {
8181
private:
82-
static volatile bool _SR_mode; // there is an active suspender or resumer
83-
static volatile int _VTMS_transition_count; // current number of VTMS transitions
84-
static volatile int _VTMS_transition_disable_count; // VTMS transitions are disabled while it is non-zero
82+
static volatile int _VTMS_transition_disable_for_one_count; // transitions for one virtual thread are disabled while it is positive
83+
static volatile int _VTMS_transition_disable_for_all_count; // transitions for all virtual threads are disabled while it is positive
84+
static volatile bool _SR_mode; // there is an active suspender or resumer
85+
static volatile int _VTMS_transition_count; // current number of VTMS transitions
8586

86-
bool _is_SR; // is suspender or resumer
87-
88-
void disable_VTMS_transitions();
89-
void enable_VTMS_transitions();
87+
bool _is_SR; // is suspender or resumer
88+
jthread _thread; // virtual thread to disable transitions for, no-op if it is a platform thread
9089

9190
DEBUG_ONLY(static void print_info();)
91+
void VTMS_transition_disable_for_one();
92+
void VTMS_transition_disable_for_all();
93+
void VTMS_transition_enable_for_one();
94+
void VTMS_transition_enable_for_all();
95+
9296
public:
9397
// parameter is_SR: suspender or resumer
9498
JvmtiVTMSTransitionDisabler(bool is_SR = false);
99+
JvmtiVTMSTransitionDisabler(jthread thread);
95100
~JvmtiVTMSTransitionDisabler();
96101

97102
static void start_VTMS_transition(jthread vthread, bool is_mount);
@@ -153,7 +158,6 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
153158
OopHandle _thread_oop_h;
154159
// Jvmti Events that cannot be posted in their current context.
155160
JvmtiDeferredEventQueue* _jvmti_event_queue;
156-
bool _is_in_VTMS_transition; // saved JavaThread.is_in_VTMS_transition()
157161
bool _is_virtual; // state belongs to a virtual thread
158162
bool _hide_single_stepping;
159163
bool _pending_interp_only_mode;
@@ -270,9 +274,6 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
270274
void set_thread(JavaThread* thread);
271275
oop get_thread_oop();
272276

273-
// The JavaThread is_in_VTMS_transition() bit saved at unmount to restore at mount.
274-
inline bool is_in_VTMS_transition() { return _is_in_VTMS_transition; }
275-
inline void set_is_in_VTMS_transition(bool val) { _is_in_VTMS_transition = val; }
276277
inline bool is_virtual() { return _is_virtual; } // the _thread is virtual
277278

278279
inline bool is_exception_detected() { return _exception_state == ES_DETECTED; }

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Feb 14, 2023

@openjdk-notifier[bot]
Please sign in to comment.