< prev index next > src/hotspot/share/runtime/continuation.cpp
Print this page
#include "precompiled.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "oops/method.inline.hpp"
+ #include "oops/oop.inline.hpp"
+ #include "prims/jvmtiThreadState.inline.hpp"
#include "runtime/continuation.hpp"
#include "runtime/continuationEntry.inline.hpp"
#include "runtime/continuationHelper.inline.hpp"
#include "runtime/continuationJavaClasses.inline.hpp"
#include "runtime/continuationWrapper.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaThread.inline.hpp"
+ #include "runtime/jniHandles.inline.hpp"
#include "runtime/osThread.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/vframe_hp.hpp"
// defined in continuationFreezeThaw.cpp
THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "pin underflow");
}
}
JVM_END
+ #ifdef LOOM_MONITOR_SUPPORT
+
+ #if INCLUDE_JVMTI
+ class JvmtiUnmountBeginMark : public StackObj {
+ Handle _vthread;
+ JavaThread* _target;
+ int _preempt_result;
+
+ public:
+ JvmtiUnmountBeginMark(JavaThread* t) :
+ _vthread(t, t->vthread()), _target(t), _preempt_result(freeze_pinned_native) {
+ assert(!_target->is_in_any_VTMS_transition(), "must be");
+
+ if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
+ JvmtiVTMSTransitionDisabler::start_VTMS_transition((jthread)_vthread.raw_value(), /* is_mount */ false);
+ } else {
+ _target->set_is_in_VTMS_transition(true);
+ java_lang_Thread::set_is_in_VTMS_transition(_vthread(), true);
+ }
+ }
+ ~JvmtiUnmountBeginMark() {
+ assert(!_target->is_suspended(), "must be");
+
+ assert(_target->is_in_VTMS_transition(), "must be");
+ assert(java_lang_Thread::is_in_VTMS_transition(_vthread()), "must be");
+
+ // Read it again since for late binding agents the flag could have
+ // been set while blocked in the allocation path during freeze.
+ bool jvmti_present = JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events();
+
+ if (_preempt_result != freeze_ok) {
+ // Undo transition
+ if (jvmti_present) {
+ JvmtiVTMSTransitionDisabler::finish_VTMS_transition((jthread)_vthread.raw_value(), false);
+ } else {
+ _target->set_is_in_VTMS_transition(false);
+ java_lang_Thread::set_is_in_VTMS_transition(_vthread(), false);
+ }
+ } else {
+ if (jvmti_present) {
+ _target->rebind_to_jvmti_thread_state_of(_target->threadObj());
+ if (JvmtiExport::should_post_vthread_mount()) {
+ _target->set_pending_jvmti_unmount_event(true);
+ }
+ }
+ }
+ }
+ void set_preempt_result(int res) { _preempt_result = res; }
+ };
+
+ static bool is_safe_vthread_to_preempt_for_jvmti(JavaThread* target, oop vthread) {
+ assert(!target->has_pending_popframe(), "should be true; no support for vthreads yet");
+ JvmtiThreadState* state = target->jvmti_thread_state();
+ assert(state == nullptr || !state->is_earlyret_pending(), "should be true; no support for vthreads yet");
+
+ if (target->is_in_any_VTMS_transition()) {
+ // We caught target at the end of a mount transition (is_in_VTMS_transition()) or at the
+ // beginning or end of a temporary switch to carrier thread (is_in_tmp_VTMS_transition()).
+ return false;
+ }
+ return true;
+ }
+ #endif // INCLUDE_JVMTI
+
+ static bool is_safe_vthread_to_preempt(JavaThread* target, oop vthread) {
+ if (!java_lang_VirtualThread::is_instance(vthread) || // inside transition
+ java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition
+ return false;
+ }
+ return JVMTI_ONLY(is_safe_vthread_to_preempt_for_jvmti(target, vthread)) NOT_JVMTI(true);
+ }
+
+ typedef int (*FreezeContFnT)(JavaThread*, intptr_t*, int);
+
+ int Continuation::try_preempt(JavaThread* target, oop continuation, int preempt_kind) {
+ assert(target == JavaThread::current(), "no support for external preemption");
+ assert(target->has_last_Java_frame(), "");
+ assert(!target->preempting(), "");
+ assert(target->last_continuation() != nullptr, "");
+ assert(target->last_continuation()->cont_oop(target) == continuation, "");
+ assert(!is_continuation_preempted(continuation), "");
+ assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), "");
+ assert(!target->has_pending_exception(), "");
+ assert(!target->is_suspended() JVMTI_ONLY(|| target->is_disable_suspend()) || target->obj_locker_count() > 0, "");
+
+ if (LockingMode == LM_LEGACY) {
+ return freeze_unsupported;
+ }
+
+ if (preempt_kind == freeze_on_monitorenter && !target->is_on_monitorenter()) {
+ return freeze_pinned_native;
+ }
+
+ if (is_continuation_done(continuation)) {
+ return freeze_not_mounted;
+ }
+
+ // Continuation is mounted and it's not done so check if it's safe to preempt.
+ if (!is_safe_vthread_to_preempt(target, target->vthread())) {
+ return freeze_pinned_native;
+ }
+
+ JVMTI_ONLY(JvmtiUnmountBeginMark jubm(target);)
+ target->set_preempting(true);
+ int res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp(), preempt_kind);
+ log_trace(continuations, preempt)("try_preempt: %d", res);
+ JVMTI_ONLY(jubm.set_preempt_result(res);)
+ if (res != freeze_ok) {
+ target->set_preempting(false);
+ }
+ return res;
+ }
+ #endif // LOOM_MONITOR_SUPPORT
+
+ bool Continuation::is_continuation_preempted(oop cont) {
+ return jdk_internal_vm_Continuation::is_preempted(cont);
+ }
+
+ bool Continuation::is_continuation_done(oop cont) {
+ return jdk_internal_vm_Continuation::done(cont);
+ }
+
#ifndef PRODUCT
static jlong java_tid(JavaThread* thread) {
return java_lang_Thread::thread_id(thread->threadObj());
}
#endif
< prev index next >