Skip to content

Commit

Permalink
Test changes + JFR Updates + Library code changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pchilano committed Oct 17, 2024
1 parent 21c3353 commit 9baaff9
Show file tree
Hide file tree
Showing 70 changed files with 3,585 additions and 1,273 deletions.
3 changes: 3 additions & 0 deletions src/hotspot/share/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,9 @@ JVM_VirtualThreadHideFrames(JNIEnv* env, jclass clazz, jboolean hide);
JNIEXPORT void JNICALL
JVM_VirtualThreadDisableSuspend(JNIEnv* env, jclass clazz, jboolean enter);

JNIEXPORT void JNICALL
JVM_VirtualThreadPinnedEvent(jint reasonCode, jstring reasonString);

JNIEXPORT jobject JNICALL
JVM_TakeVirtualThreadListToUnblock(JNIEnv* env, jclass ignored);

Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/jfr/metadata/metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@
<Field type="ulong" name="id" label="Continuation ID" />
</Event>

<Event name="VirtualThreadPinned" category="Java Virtual Machine, Runtime" label="Virtual Thread Pinned" thread="true" stackTrace="true" startTime="false">
<Field type="string" name="pinnedReason" label="Pinned Reason" />
<Field type="Thread" name="carrierThread" label="Carrier Thread" />
</Event>

<Event name="ReservedStackActivation" category="Java Virtual Machine, Runtime" label="Reserved Stack Activation"
description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack" thread="true" stackTrace="true"
startTime="false">
Expand Down
16 changes: 16 additions & 0 deletions src/hotspot/share/oops/instanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,22 @@ void InstanceKlass::initialize_impl(TRAPS) {
}
wait = true;
jt->set_class_to_be_initialized(this);

#if INCLUDE_JFR
ContinuationEntry* ce = jt->last_continuation();
if (ce != nullptr && ce->is_virtual_thread()) {
EventVirtualThreadPinned e;
if (e.should_commit()) {
ResourceMark rm(jt);
char reason[256];
jio_snprintf(reason, sizeof reason, "Waiting for initialization of klass %s", external_name());
e.set_pinnedReason(reason);
e.set_carrierThread(JFR_JVM_THREAD_ID(THREAD));
e.commit();
}
}
#endif

ol.wait_uninterruptibly(jt);
jt->set_class_to_be_initialized(nullptr);
}
Expand Down
14 changes: 14 additions & 0 deletions src/hotspot/share/prims/jvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3979,6 +3979,20 @@ JVM_ENTRY(void, JVM_VirtualThreadDisableSuspend(JNIEnv* env, jclass clazz, jbool
#endif
JVM_END

JVM_ENTRY_NO_ENV(void, JVM_VirtualThreadPinnedEvent(jint reasonCode, jstring reasonString))
#if INCLUDE_JFR
EventVirtualThreadPinned e;
if (e.should_commit()) {
ResourceMark rm(THREAD);
// ignore reason code for now
const char *reason = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reasonString));
e.set_pinnedReason(reason);
e.set_carrierThread(JFR_JVM_THREAD_ID(THREAD));
e.commit();
}
#endif
JVM_END

JVM_ENTRY(jobject, JVM_TakeVirtualThreadListToUnblock(JNIEnv* env, jclass ignored))
ParkEvent* parkEvent = ObjectMonitor::vthread_unparker_ParkEvent();
assert(parkEvent != nullptr, "not initialized");
Expand Down
25 changes: 24 additions & 1 deletion src/hotspot/share/runtime/objectMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ OopStorage* ObjectMonitor::_oop_storage = nullptr;
OopHandle ObjectMonitor::_vthread_cxq_head;
ParkEvent* ObjectMonitor::_vthread_unparker_ParkEvent = nullptr;

static void post_virtual_thread_pinned_event(JavaThread* current, const char* reason) {
EventVirtualThreadPinned e;
if (e.should_commit()) {
e.set_pinnedReason(reason);
e.set_carrierThread(JFR_JVM_THREAD_ID(current));
e.commit();
}
}

// -----------------------------------------------------------------------------
// Theory of operations -- Monitors lists, thread residency, etc:
//
Expand Down Expand Up @@ -519,6 +528,11 @@ void ObjectMonitor::enter_with_contention_mark(JavaThread *current, ObjectMonito
(!acquired && !current->preemption_cancelled() && state == java_lang_VirtualThread::BLOCKING), "invariant");
return;
}
if (result == freeze_pinned_native) {
post_virtual_thread_pinned_event(current, "Native frame or <clinit> on stack");
} else if (result == freeze_unsupported) {
post_virtual_thread_pinned_event(current, "Native frame or <clinit> or monitors on stack");
}
}

OSThreadContendState osts(current->osthread());
Expand Down Expand Up @@ -1676,6 +1690,16 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
current->set_current_waiting_monitor(nullptr);
return;
}
if (result == freeze_pinned_native || result == freeze_unsupported) {
const Klass* monitor_klass = object()->klass();
if (!is_excluded(monitor_klass)) {
if (result == freeze_pinned_native) {
post_virtual_thread_pinned_event(current,"Native frame or <clinit> on stack");
} else if (result == freeze_unsupported) {
post_virtual_thread_pinned_event(current, "Native frame or <clinit> or monitors on stack");
}
}
}
}

// create a node to be put into the queue
Expand Down Expand Up @@ -1857,7 +1881,6 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
// Monitor notify has precedence over thread interrupt.
}


// Consider:
// If the lock is cool (cxq == null && succ == null) and we're on an MP system
// then instead of transferring a thread from the WaitSet to the EntryList
Expand Down
80 changes: 57 additions & 23 deletions src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import jdk.internal.misc.Blocker;

import static sun.nio.ch.EPoll.EPOLLIN;
import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
Expand Down Expand Up @@ -105,36 +104,71 @@ protected int doSelect(Consumer<SelectionKey> action, long timeout)
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin(blocking);

do {
long startTime = timedPoll ? System.nanoTime() : 0;
boolean attempted = Blocker.begin(blocking);
try {
if (Thread.currentThread().isVirtual()) {
numEntries = (timedPoll)
? timedPoll(TimeUnit.MILLISECONDS.toNanos(to))
: untimedPoll(blocking);
} else {
try {
begin(blocking);
do {
long startTime = timedPoll ? System.nanoTime() : 0;
numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, to);
} finally {
Blocker.end(attempted);
}
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= (int) TimeUnit.NANOSECONDS.toMillis(adjust);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= (int) TimeUnit.NANOSECONDS.toMillis(adjust);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
}
}
}
} while (numEntries == IOStatus.INTERRUPTED);
assert IOStatus.check(numEntries);

} finally {
end(blocking);
} while (numEntries == IOStatus.INTERRUPTED);
} finally {
end(blocking);
}
}
assert IOStatus.check(numEntries);

processDeregisterQueue();
return processEvents(numEntries, action);
}

/**
* If blocking, parks the current virtual thread until a file descriptor is polled
* or the thread is interrupted.
*/
private int untimedPoll(boolean block) throws IOException {
int numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, 0);
if (block) {
while (numEntries == 0 && !Thread.currentThread().isInterrupted()) {
Poller.pollSelector(epfd, 0);
numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, 0);
}
}
return numEntries;
}

/**
* Parks the current virtual thread until a file descriptor is polled, or the thread
* is interrupted, for up to the specified waiting time.
*/
private int timedPoll(long nanos) throws IOException {
long startNanos = System.nanoTime();
int numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, 0);
while (numEntries == 0 && !Thread.currentThread().isInterrupted()) {
long remainingNanos = nanos - (System.nanoTime() - startNanos);
if (remainingNanos <= 0) {
// timeout
break;
}
Poller.pollSelector(epfd, remainingNanos);
numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, 0);
}
return numEntries;
}

/**
* Process changes to the interest ops.
*/
Expand Down
80 changes: 57 additions & 23 deletions src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import jdk.internal.misc.Blocker;

import static sun.nio.ch.KQueue.EVFILT_READ;
import static sun.nio.ch.KQueue.EVFILT_WRITE;
Expand Down Expand Up @@ -109,36 +108,71 @@ protected int doSelect(Consumer<SelectionKey> action, long timeout)
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin(blocking);

do {
long startTime = timedPoll ? System.nanoTime() : 0;
boolean attempted = Blocker.begin(blocking);
try {
if (Thread.currentThread().isVirtual()) {
numEntries = (timedPoll)
? timedPoll(TimeUnit.MILLISECONDS.toNanos(to))
: untimedPoll(blocking);
} else {
try {
begin(blocking);
do {
long startTime = timedPoll ? System.nanoTime() : 0;
numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, to);
} finally {
Blocker.end(attempted);
}
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= TimeUnit.NANOSECONDS.toMillis(adjust);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= TimeUnit.NANOSECONDS.toMillis(adjust);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
}
}
}
} while (numEntries == IOStatus.INTERRUPTED);
assert IOStatus.check(numEntries);

} finally {
end(blocking);
} while (numEntries == IOStatus.INTERRUPTED);
} finally {
end(blocking);
}
}
assert IOStatus.check(numEntries);

processDeregisterQueue();
return processEvents(numEntries, action);
}

/**
* If blocking, parks the current virtual thread until a file descriptor is polled
* or the thread is interrupted.
*/
private int untimedPoll(boolean block) throws IOException {
int numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, 0);
if (block) {
while (numEntries == 0 && !Thread.currentThread().isInterrupted()) {
Poller.pollSelector(kqfd, 0);
numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, 0);
}
}
return numEntries;
}

/**
* Parks the current virtual thread until a file descriptor is polled, or the thread
* is interrupted, for up to the specified waiting time.
*/
private int timedPoll(long nanos) throws IOException {
long startNanos = System.nanoTime();
int numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, 0);
while (numEntries == 0 && !Thread.currentThread().isInterrupted()) {
long remainingNanos = nanos - (System.nanoTime() - startNanos);
if (remainingNanos <= 0) {
// timeout
break;
}
Poller.pollSelector(kqfd, remainingNanos);
numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, 0);
}
return numEntries;
}

/**
* Process changes to the interest ops.
*/
Expand Down
12 changes: 2 additions & 10 deletions src/java.base/share/classes/java/io/ByteArrayOutputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,8 @@ public void writeBytes(byte[] b) {
* @throws NullPointerException if {@code out} is {@code null}.
* @throws IOException if an I/O error occurs.
*/
public void writeTo(OutputStream out) throws IOException {
if (Thread.currentThread().isVirtual()) {
byte[] bytes;
synchronized (this) {
bytes = Arrays.copyOf(buf, count);
}
out.write(bytes);
} else synchronized (this) {
out.write(buf, 0, count);
}
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}

/**
Expand Down
Loading

0 comments on commit 9baaff9

Please sign in to comment.