9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/vmSymbols.hpp"
27 #include "gc/shared/barrierSetNMethod.hpp"
28 #include "oops/method.inline.hpp"
29 #include "runtime/continuation.hpp"
30 #include "runtime/continuationEntry.inline.hpp"
31 #include "runtime/continuationHelper.inline.hpp"
32 #include "runtime/continuationJavaClasses.inline.hpp"
33 #include "runtime/continuationWrapper.inline.hpp"
34 #include "runtime/interfaceSupport.inline.hpp"
35 #include "runtime/javaThread.inline.hpp"
36 #include "runtime/osThread.hpp"
37 #include "runtime/vframe.inline.hpp"
38 #include "runtime/vframe_hp.hpp"
39
40 // defined in continuationFreezeThaw.cpp
41 extern "C" jint JNICALL CONT_isPinned0(JNIEnv* env, jobject cont_scope);
42
43 JVM_ENTRY(void, CONT_pin(JNIEnv* env, jclass cls)) {
44 if (!Continuation::pin(JavaThread::thread_from_jni_environment(env))) {
45 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "pin overflow");
46 }
47 }
48 JVM_END
49
50 JVM_ENTRY(void, CONT_unpin(JNIEnv* env, jclass cls)) {
51 if (!Continuation::unpin(JavaThread::thread_from_jni_environment(env))) {
52 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "pin underflow");
53 }
54 }
55 JVM_END
56
57 #ifndef PRODUCT
58 static jlong java_tid(JavaThread* thread) {
59 return java_lang_Thread::thread_id(thread->threadObj());
60 }
61 #endif
62
63 ContinuationEntry* Continuation::get_continuation_entry_for_continuation(JavaThread* thread, oop continuation) {
64 if (thread == nullptr || continuation == nullptr) {
65 return nullptr;
66 }
67
68 for (ContinuationEntry* entry = thread->last_continuation(); entry != nullptr; entry = entry->parent()) {
69 if (continuation == entry->cont_oop(thread)) {
70 return entry;
71 }
72 }
73 return nullptr;
74 }
75
76 static bool is_on_stack(JavaThread* thread, const ContinuationEntry* entry) {
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/vmSymbols.hpp"
27 #include "gc/shared/barrierSetNMethod.hpp"
28 #include "oops/method.inline.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "prims/jvmtiThreadState.inline.hpp"
31 #include "runtime/continuation.hpp"
32 #include "runtime/continuationEntry.inline.hpp"
33 #include "runtime/continuationHelper.inline.hpp"
34 #include "runtime/continuationJavaClasses.inline.hpp"
35 #include "runtime/continuationWrapper.inline.hpp"
36 #include "runtime/interfaceSupport.inline.hpp"
37 #include "runtime/javaThread.inline.hpp"
38 #include "runtime/jniHandles.inline.hpp"
39 #include "runtime/osThread.hpp"
40 #include "runtime/vframe.inline.hpp"
41 #include "runtime/vframe_hp.hpp"
42
43 // defined in continuationFreezeThaw.cpp
44 extern "C" jint JNICALL CONT_isPinned0(JNIEnv* env, jobject cont_scope);
45
46 JVM_ENTRY(void, CONT_pin(JNIEnv* env, jclass cls)) {
47 if (!Continuation::pin(JavaThread::thread_from_jni_environment(env))) {
48 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "pin overflow");
49 }
50 }
51 JVM_END
52
53 JVM_ENTRY(void, CONT_unpin(JNIEnv* env, jclass cls)) {
54 if (!Continuation::unpin(JavaThread::thread_from_jni_environment(env))) {
55 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "pin underflow");
56 }
57 }
58 JVM_END
59
60 #if INCLUDE_JVMTI
61 class JvmtiUnmountBeginMark : public StackObj {
62 Handle _vthread;
63 JavaThread* _target;
64 int _preempt_result;
65
66 public:
67 JvmtiUnmountBeginMark(JavaThread* t) :
68 _vthread(t, t->vthread()), _target(t), _preempt_result(freeze_pinned_native) {
69 assert(!_target->is_in_any_VTMS_transition(), "must be");
70
71 if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
72 JvmtiVTMSTransitionDisabler::start_VTMS_transition((jthread)_vthread.raw_value(), /* is_mount */ false);
73 } else {
74 _target->set_is_in_VTMS_transition(true);
75 java_lang_Thread::set_is_in_VTMS_transition(_vthread(), true);
76 }
77 }
78 ~JvmtiUnmountBeginMark() {
79 assert(!_target->is_suspended(), "must be");
80
81 assert(_target->is_in_VTMS_transition(), "must be");
82 assert(java_lang_Thread::is_in_VTMS_transition(_vthread()), "must be");
83
84 // Read it again since for late binding agents the flag could have
85 // been set while blocked in the allocation path during freeze.
86 bool jvmti_present = JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events();
87
88 if (_preempt_result != freeze_ok) {
89 // Undo transition
90 if (jvmti_present) {
91 JvmtiVTMSTransitionDisabler::finish_VTMS_transition((jthread)_vthread.raw_value(), false);
92 } else {
93 _target->set_is_in_VTMS_transition(false);
94 java_lang_Thread::set_is_in_VTMS_transition(_vthread(), false);
95 }
96 } else {
97 if (jvmti_present) {
98 _target->rebind_to_jvmti_thread_state_of(_target->threadObj());
99 if (JvmtiExport::should_post_vthread_mount()) {
100 _target->set_pending_jvmti_unmount_event(true);
101 }
102 }
103 }
104 }
105 void set_preempt_result(int res) { _preempt_result = res; }
106 };
107
108 static bool is_safe_vthread_to_preempt_for_jvmti(JavaThread* target, oop vthread) {
109 assert(!target->has_pending_popframe(), "should be true; no support for vthreads yet");
110 JvmtiThreadState* state = target->jvmti_thread_state();
111 assert(state == nullptr || !state->is_earlyret_pending(), "should be true; no support for vthreads yet");
112
113 if (target->is_in_any_VTMS_transition()) {
114 // We caught target at the end of a mount transition (is_in_VTMS_transition()) or at the
115 // beginning or end of a temporary switch to carrier thread (is_in_tmp_VTMS_transition()).
116 return false;
117 }
118 return true;
119 }
120 #endif
121
122 static bool is_safe_vthread_to_preempt(JavaThread* target, oop vthread) {
123 if (!java_lang_VirtualThread::is_instance(vthread) || // inside transition
124 java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition
125 return false;
126 }
127 return JVMTI_ONLY(is_safe_vthread_to_preempt_for_jvmti(target, vthread)) NOT_JVMTI(true);
128 }
129
130 typedef int (*FreezeContFnT)(JavaThread*, intptr_t*, int);
131
132 int Continuation::try_preempt(JavaThread* target, oop continuation, int preempt_kind) {
133 assert(target == JavaThread::current(), "no support for external preemption");
134 assert((preempt_kind == freeze_on_monitorenter && target->is_on_monitorenter()) ||
135 (preempt_kind == freeze_on_wait && target->current_waiting_monitor() != nullptr), "");
136 assert(target->has_last_Java_frame(), "");
137 assert(!target->preempting(), "");
138 assert(target->last_continuation() != nullptr, "");
139 assert(target->last_continuation()->cont_oop(target) == continuation, "");
140 assert(!is_continuation_preempted(continuation), "");
141 assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), "");
142 assert(!target->has_pending_exception(), "");
143 assert(!target->is_suspended() || target->is_disable_suspend(), "");
144
145 if (!VM_Version::supports_cont_preemption()) {
146 return unsupported;
147 }
148
149 if (is_continuation_done(continuation)) {
150 return freeze_not_mounted;
151 }
152
153 // Continuation is mounted and it's not done so check if it's safe to preempt.
154 if (!is_safe_vthread_to_preempt(target, target->vthread())) {
155 return freeze_pinned_native;
156 }
157
158 JVMTI_ONLY(JvmtiUnmountBeginMark jubm(target);)
159 target->set_preempting(true);
160 int res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp(), preempt_kind);
161 log_trace(continuations, preempt)("try_preempt: %d", res);
162 JVMTI_ONLY(jubm.set_preempt_result(res);)
163 if (res != freeze_ok) {
164 target->set_preempting(false);
165 }
166 return res;
167 }
168
169 bool Continuation::is_continuation_preempted(oop cont) {
170 return jdk_internal_vm_Continuation::is_preempted(cont);
171 }
172
173 bool Continuation::is_continuation_done(oop cont) {
174 return jdk_internal_vm_Continuation::done(cont);
175 }
176
177 #ifndef PRODUCT
178 static jlong java_tid(JavaThread* thread) {
179 return java_lang_Thread::thread_id(thread->threadObj());
180 }
181 #endif
182
183 ContinuationEntry* Continuation::get_continuation_entry_for_continuation(JavaThread* thread, oop continuation) {
184 if (thread == nullptr || continuation == nullptr) {
185 return nullptr;
186 }
187
188 for (ContinuationEntry* entry = thread->last_continuation(); entry != nullptr; entry = entry->parent()) {
189 if (continuation == entry->cont_oop(thread)) {
190 return entry;
191 }
192 }
193 return nullptr;
194 }
195
196 static bool is_on_stack(JavaThread* thread, const ContinuationEntry* entry) {
|