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 JavaThread* _target;
63 int _preempt_result;
64
65 public:
66 JvmtiUnmountBeginMark(JavaThread* t) :
67 _target(t), _preempt_result(freeze_pinned_native) {
68 assert(!_target->is_in_any_VTMS_transition(), "must be");
69
70 if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
71 JvmtiVTMSTransitionDisabler::start_VTMS_transition(JNIHandles::make_local(_target->vthread()), /* is_mount */ false);
72 } else {
73 _target->set_is_in_VTMS_transition(true);
74 java_lang_Thread::set_is_in_VTMS_transition(_target->vthread(), true);
75 }
76 }
77 ~JvmtiUnmountBeginMark() {
78 assert(!_target->is_suspended(), "must be");
79
80 assert(_target->is_in_VTMS_transition(), "must be");
81 assert(java_lang_Thread::is_in_VTMS_transition(_target->vthread()), "must be");
82
83 // Read it again since for late binding agents the flag could have
84 // been set while blocked in the allocation path during freeze.
85 bool jvmti_present = JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events();
86
87 if (_preempt_result != freeze_ok) {
88 // Undo transition
89 if (jvmti_present) {
90 JvmtiVTMSTransitionDisabler::finish_VTMS_transition(JNIHandles::make_local(_target->vthread()), false);
91 } else {
92 _target->set_is_in_VTMS_transition(false);
93 java_lang_Thread::set_is_in_VTMS_transition(_target->vthread(), false);
94 }
95 } else {
96 if (jvmti_present) {
97 _target->rebind_to_jvmti_thread_state_of(_target->threadObj());
98 _target->set_jvmti_unmount_event_pending(true);
99 }
100 }
101 }
102 void set_preempt_result(int res) { _preempt_result = res; }
103 };
104
105 static bool is_safe_vthread_to_preempt_for_jvmti(JavaThread* target, oop vthread) {
106 assert(!target->has_pending_popframe(), "should be true; no support for vthreads yet");
107 JvmtiThreadState* state = target->jvmti_thread_state();
108 assert(state == nullptr || !state->is_earlyret_pending(), "should be true; no support for vthreads yet");
109
110 if (target->is_in_any_VTMS_transition()) {
111 // We caught target at the end of a mount transition (is_in_VTMS_transition()) or at the
112 // beginning or end of a temporary switch to carrier thread (is_in_tmp_VTMS_transition()).
113 return false;
114 }
115 return true;
116 }
117 #endif
118
119 static bool is_safe_vthread_to_preempt(JavaThread* target, oop vthread) {
120 if (!java_lang_VirtualThread::is_instance(vthread) || // inside transition
121 java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition
122 return false;
123 }
124 return JVMTI_ONLY(is_safe_vthread_to_preempt_for_jvmti(target, vthread)) NOT_JVMTI(true);
125 }
126
127 typedef int (*FreezeContFnT)(JavaThread*, intptr_t*);
128
129 int Continuation::try_preempt(JavaThread* target, oop continuation, bool set_state_yielding) {
130 assert(target->is_on_monitorenter(), "must be");
131 assert(target->has_last_Java_frame(), "must be");
132 assert(!target->preempting(), "must be");
133 assert(!target->is_suspended() || target->is_disable_suspend(), "must be");
134 assert(!target->has_pending_exception(), "must be");
135 assert(target->last_continuation() != nullptr, "must be");
136 assert(target->last_continuation()->cont_oop(target) == continuation, "must be");
137 assert(!is_continuation_preempted(continuation), "shouldn't be");
138 assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), "must be");
139
140 if (!VM_Version::supports_cont_preemption()) {
141 return unsupported;
142 }
143
144 if (is_continuation_done(continuation)) {
145 return freeze_not_mounted;
146 }
147
148 // Continuation is mounted and it's not done so check if it's safe to preempt.
149 if (!is_safe_vthread_to_preempt(target, target->vthread())) {
150 return freeze_pinned_native;
151 }
152
153 #if INCLUDE_JVMTI
154 JvmtiUnmountBeginMark jubm(target);
155 #endif
156 target->set_preempting(true);
157 int res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp());
158 log_trace(continuations, preempt)("try_preempt: %d", res);
159 JVMTI_ONLY(jubm.set_preempt_result(res);)
160 if (res != freeze_ok) {
161 target->set_preempting(false);
162 } else if (set_state_yielding) {
163 java_lang_VirtualThread::set_state(target->vthread(), java_lang_VirtualThread::YIELDING);
164 }
165 return res;
166 }
167
168 bool Continuation::is_continuation_preempted(oop cont) {
169 return jdk_internal_vm_Continuation::is_preempted(cont);
170 }
171
172 bool Continuation::is_continuation_done(oop cont) {
173 return jdk_internal_vm_Continuation::done(cont);
174 }
175
176 #ifndef PRODUCT
177 static jlong java_tid(JavaThread* thread) {
178 return java_lang_Thread::thread_id(thread->threadObj());
179 }
180 #endif
181
182 ContinuationEntry* Continuation::get_continuation_entry_for_continuation(JavaThread* thread, oop continuation) {
183 if (thread == nullptr || continuation == nullptr) {
184 return nullptr;
185 }
186
187 for (ContinuationEntry* entry = thread->last_continuation(); entry != nullptr; entry = entry->parent()) {
188 if (continuation == entry->cont_oop(thread)) {
189 return entry;
190 }
191 }
192 return nullptr;
193 }
194
195 static bool is_on_stack(JavaThread* thread, const ContinuationEntry* entry) {
|