diff --git a/jcl/src/java.base/share/classes/java/lang/Object.java b/jcl/src/java.base/share/classes/java/lang/Object.java index e30dd5ff71a..79714c17803 100644 --- a/jcl/src/java.base/share/classes/java/lang/Object.java +++ b/jcl/src/java.base/share/classes/java/lang/Object.java @@ -22,9 +22,9 @@ */ package java.lang; -/*[IF JAVA_SPEC_VERSION >= 19]*/ +/*[IF (JAVA_SPEC_VERSION >= 19) & (JAVA_SPEC_VERSION < 24)]*/ import jdk.internal.misc.Blocker; -/*[ENDIF] JAVA_SPEC_VERSION >= 19 */ +/*[ENDIF] (JAVA_SPEC_VERSION >= 19) & (JAVA_SPEC_VERSION < 24) */ /** * Object is the root of the java class hierarchy. All non-base types @@ -283,7 +283,7 @@ public final void wait(long time, int frac) throws InterruptedException { } finally { Blocker.end(blockerRC); } -/*[ELSE] JAVA_SPEC_VERSION < 23 */ +/*[ELSEIF JAVA_SPEC_VERSION < 24] */ if (!Thread.currentThread().isVirtual()) { waitImpl(time, frac); } else { @@ -294,6 +294,21 @@ public final void wait(long time, int frac) throws InterruptedException { Blocker.end(blocking); } } +/*[ELSE] JAVA_SPEC_VERSION < 24 */ + if ((time < 0) || (frac < 0)) { + throw new IllegalArgumentException("timeout value is negative"); + } + if (!Thread.currentThread().isVirtual()) { + waitImpl(time, frac); + } else { + try { + waitImpl(time, frac); + } catch (InterruptedException e) { + // Clear virtual thread's interrupt status + Thread.currentThread().getAndClearInterrupt(); + throw e; + } + } /*[ENDIF] JAVA_SPEC_VERSION < 19 */ } diff --git a/jcl/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java b/jcl/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java index 94c22a59364..46c3d57c1f3 100644 --- a/jcl/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java +++ b/jcl/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/ +/*[INCLUDE-IF (JAVA_SPEC_VERSION >= 21) & (JAVA_SPEC_VERSION < 24)]*/ /* * Copyright IBM Corp. and others 2023 * diff --git a/jcl/src/java.base/share/classes/java/lang/ref/Reference.java b/jcl/src/java.base/share/classes/java/lang/ref/Reference.java index b53ddf6b544..38e051a7a80 100644 --- a/jcl/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/jcl/src/java.base/share/classes/java/lang/ref/Reference.java @@ -96,9 +96,11 @@ public void runFinalization() { /*[ENDIF] JAVA_SPEC_VERSION >= 11 */ /*[IF JAVA_SPEC_VERSION >= 19]*/ + /*[IF JAVA_SPEC_VERSION < 24] */ public ReferenceQueue newNativeReferenceQueue() { return new NativeReferenceQueue<>(); } + /*[ENDIF] JAVA_SPEC_VERSION < 24 */ public void startThreads() { throw new UnsupportedOperationException(); diff --git a/jcl/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java b/jcl/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java index 35622747d5a..9e554764578 100644 --- a/jcl/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java +++ b/jcl/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java @@ -28,6 +28,11 @@ import sun.misc.Cleaner; /*[ENDIF] JAVA_SPEC_VERSION >= 9 */ +/*[IF JAVA_SPEC_VERSION >= 24]*/ +import jdk.internal.vm.Continuation; + +/*[ENDIF] JAVA_SPEC_VERSION >= 24*/ + /*[IF CRIU_SUPPORT]*/ import openj9.internal.criu.NotCheckpointSafe; /*[ENDIF] CRIU_SUPPORT */ @@ -89,6 +94,14 @@ public Reference poll () { if(empty) { return null; } + + /*[IF JAVA_SPEC_VERSION >= 24]*/ + boolean isVirtual = false; + if (Thread.currentThread().isVirtual()) { + isVirtual = true; + Continuation.pin(); + } + /*[ENDIF] JAVA_SPEC_VERSION >= 24*/ synchronized(this) { if(empty) { return null; @@ -104,6 +117,11 @@ public Reference poll () { empty = true; } } + /*[IF JAVA_SPEC_VERSION >= 24]*/ + if (isVirtual) { + Continuation.unpin(); + } + /*[ENDIF] JAVA_SPEC_VERSION >= 24*/ return ref; } diff --git a/runtime/j9vm/exports.cmake b/runtime/j9vm/exports.cmake index 8a370c8344e..8181b0e2fef 100644 --- a/runtime/j9vm/exports.cmake +++ b/runtime/j9vm/exports.cmake @@ -468,6 +468,8 @@ if(NOT JAVA_SPEC_VERSION LESS 24) jvm_add_exports(jvm JVM_IsContainerized JVM_IsStaticallyLinked + JVM_VirtualThreadPinnedEvent + JVM_TakeVirtualThreadListToUnblock ) endif() diff --git a/runtime/j9vm/j9vmnatives.xml b/runtime/j9vm/j9vmnatives.xml index 1e610420cdc..54d710e0a61 100644 --- a/runtime/j9vm/j9vmnatives.xml +++ b/runtime/j9vm/j9vmnatives.xml @@ -482,5 +482,9 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex + + + + diff --git a/runtime/j9vm/javanextvmi.cpp b/runtime/j9vm/javanextvmi.cpp index 92491ed655d..e11aa852c23 100644 --- a/runtime/j9vm/javanextvmi.cpp +++ b/runtime/j9vm/javanextvmi.cpp @@ -799,6 +799,20 @@ JVM_IsStaticallyLinked(void) /* OpenJDK removed static builds using --enable-static-build. */ return JNI_FALSE; } + +JNIEXPORT void JNICALL +JVM_VirtualThreadPinnedEvent(JNIEnv* env, jclass clazz, jstring op) +{ + // TODO: emit JFR Event + return; +} + +JNIEXPORT jobject JNICALL +JVM_TakeVirtualThreadListToUnblock(JNIEnv* env, jclass ignored) +{ + // TODO: return the unblocked list + return NULL; +} #endif /* JAVA_SPEC_VERSION >= 24 */ } /* extern "C" */ diff --git a/runtime/jvmti/jvmtiHelpers.cpp b/runtime/jvmti/jvmtiHelpers.cpp index 7b3c1476779..e226771e9a6 100644 --- a/runtime/jvmti/jvmtiHelpers.cpp +++ b/runtime/jvmti/jvmtiHelpers.cpp @@ -900,16 +900,33 @@ getVirtualThreadState(J9VMThread *currentThread, jthread thread) case JVMTI_VTHREAD_STATE_UNPARKED: case JVMTI_VTHREAD_STATE_YIELDING: case JVMTI_VTHREAD_STATE_YIELDED: +#if JAVA_SPEC_VERSION >= 24 + case JVMTI_VTHREAD_STATE_UNBLOCKED: + case JVMTI_VTHREAD_STATE_WAITING: + case JVMTI_VTHREAD_STATE_TIMED_WAITING: +#endif /* JAVA_SPEC_VERSION >= 24 */ rc = JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE; break; case JVMTI_VTHREAD_STATE_PINNED: case JVMTI_VTHREAD_STATE_PARKED: +#if JAVA_SPEC_VERSION >= 24 + case JVMTI_VTHREAD_STATE_WAIT: +#endif /* JAVA_SPEC_VERSION >= 24 */ rc = JVMTI_JAVA_LANG_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_PARKED; break; case JVMTI_VTHREAD_STATE_TIMED_PINNED: case JVMTI_VTHREAD_STATE_TIMED_PARKED: +#if JAVA_SPEC_VERSION >= 24 + case JVMTI_VTHREAD_STATE_TIMED_WAIT: +#endif /* JAVA_SPEC_VERSION >= 24 */ rc = JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING | JVMTI_THREAD_STATE_PARKED; break; +#if JAVA_SPEC_VERSION >= 24 + case JVMTI_VTHREAD_STATE_BLOCKING: + case JVMTI_VTHREAD_STATE_BLOCKED: + rc = JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED; + break; +#endif /* JAVA_SPEC_VERSION >= 24 */ case JVMTI_VTHREAD_STATE_TERMINATED: rc = JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED; break; diff --git a/runtime/oti/jvmtiInternal.h b/runtime/oti/jvmtiInternal.h index 32473d0ec68..cb181005067 100644 --- a/runtime/oti/jvmtiInternal.h +++ b/runtime/oti/jvmtiInternal.h @@ -587,6 +587,15 @@ typedef struct jvmtiGcp_translation { #define JVMTI_VTHREAD_STATE_UNPARKED 9 #define JVMTI_VTHREAD_STATE_YIELDING 10 #define JVMTI_VTHREAD_STATE_YIELDED 11 +#if JAVA_SPEC_VERSION >= 24 +#define JVMTI_VTHREAD_STATE_BLOCKING 12 +#define JVMTI_VTHREAD_STATE_BLOCKED 13 +#define JVMTI_VTHREAD_STATE_UNBLOCKED 14 +#define JVMTI_VTHREAD_STATE_WAITING 15 +#define JVMTI_VTHREAD_STATE_WAIT 16 +#define JVMTI_VTHREAD_STATE_TIMED_WAITING 17 +#define JVMTI_VTHREAD_STATE_TIMED_WAIT 18 +#endif /* JAVA_SPEC_VERSION >= 24 */ #define JVMTI_VTHREAD_STATE_TERMINATED 99 #define JVMTI_VTHREAD_STATE_SUSPENDED (1 << 8) #endif /* JAVA_SPEC_VERSION >= 19 */ diff --git a/runtime/redirector/forwarders.m4 b/runtime/redirector/forwarders.m4 index 726db1066a0..8084405565f 100644 --- a/runtime/redirector/forwarders.m4 +++ b/runtime/redirector/forwarders.m4 @@ -446,3 +446,7 @@ _IF([JAVA_SPEC_VERSION >= 24], [_X(JVM_IsContainerized, JNICALL, false, jboolean, void)]) _IF([JAVA_SPEC_VERSION >= 24], [_X(JVM_IsStaticallyLinked, JNICALL, false, jboolean, void)]) +_IF([JAVA_SPEC_VERSION >= 24], + [_X(JVM_VirtualThreadPinnedEvent, JNICALL, false, void, JNIEnv* env, jclass clazz, jstring op)]) +_IF([JAVA_SPEC_VERSION >= 24], + [_X(JVM_TakeVirtualThreadListToUnblock, JNICALL, false, jobject, JNIEnv* env, jclass ignored)])