Skip to content
10 changes: 8 additions & 2 deletions src/hotspot/share/prims/jvmtiExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,16 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
}

JvmtiThreadState*
JvmtiExport::get_jvmti_thread_state(JavaThread *thread) {
JvmtiExport::get_jvmti_thread_state(JavaThread *thread, bool allow_suspend) {
assert(thread == JavaThread::current(), "must be current thread");
if (thread->is_vthread_mounted() && thread->jvmti_thread_state() == nullptr) {
JvmtiEventController::thread_started(thread);
if (allow_suspend && thread->is_suspended()) {
// Suspend here if thread_started got a suspend request during its execution.
// Within thread_started we could block on a VM mutex and pick up a suspend
// request from debug agent which we need to honor before proceeding.
ThreadBlockInVM tbivm(thread, true /* allow suspend */);
}
}
return thread->jvmti_thread_state();
}
Expand Down Expand Up @@ -2628,7 +2634,7 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na
// jvmti thread state.
// The collector and/or state might be null if JvmtiDynamicCodeEventCollector
// has been initialized while JVMTI_EVENT_DYNAMIC_CODE_GENERATED was disabled.
JvmtiThreadState *state = get_jvmti_thread_state(thread);
JvmtiThreadState *state = get_jvmti_thread_state(thread, false /* allow_suspend */);
if (state != nullptr) {
JvmtiDynamicCodeEventCollector *collector = state->get_dynamic_code_event_collector();
if (collector != nullptr) {
Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/share/prims/jvmtiExport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,11 @@ class JvmtiExport : public AllStatic {
// If the jvmti_thread_state is absent and any thread filtered event
// is enabled globally then it is created.
// Otherwise, the thread->jvmti_thread_state() is returned.
static JvmtiThreadState* get_jvmti_thread_state(JavaThread *thread);
// The 'allow_suspend' parameter is passed as 'true' by default which work for almost all call sites.
// It means that a suspend point need to be organized by this function for virtual threads if the call
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// It means that a suspend point need to be organized by this function for virtual threads if the call
// It means that a suspend point needs to be organized by this function for virtual threads if the call

// to jvmtiEventController::thread_started hits a safepoint and gets a new suspend request.
// The 'allow_suspend' parameter must be passed as 'false' if thread is holding a VM lock.
static JvmtiThreadState* get_jvmti_thread_state(JavaThread *thread, bool allow_suspend = true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a detailed comment on what the allow_suspend parameter means and when it should be true and false.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, thanks! Will add a comment.


// single stepping management methods
static void at_single_stepping_point(JavaThread *thread, Method* method, address location) NOT_JVMTI_RETURN;
Expand Down