Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support using threadStatus field in JVM native #21043

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 43 additions & 11 deletions jcl/src/java.base/share/classes/java/lang/Thread.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,15 @@ private static final class TidLock {
*/
private volatile boolean deadInterrupt;
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
private volatile boolean started; // If !isAlive(), tells if Thread died already or hasn't even started
private String name; // The Thread's name
private int priority = NORM_PRIORITY; // The Thread's current priority
private volatile boolean started; // If !isAlive(), tells if Thread died already or hasn't even started
private String name; // The Thread's name
private int priority = NORM_PRIORITY; // The Thread's current priority
private boolean isDaemon; // Tells if the Thread is a daemon thread or not.
private volatile int threadStatus; // The Thread's state.
fengxue-IS marked this conversation as resolved.
Show resolved Hide resolved
gacholio marked this conversation as resolved.
Show resolved Hide resolved

ThreadGroup group; // A Thread belongs to exactly one ThreadGroup
ThreadGroup group; // A Thread belongs to exactly one ThreadGroup
private Runnable runnable; // Target (optional) runnable object
private boolean stopCalled = false; // Used by the VM
private boolean stopCalled = false; // Used by the VM
/*[PR 1FENTZW]*/
private ClassLoader contextClassLoader; // Used to find classes and resources in this Thread
ThreadLocal.ThreadLocalMap threadLocals;
Expand Down Expand Up @@ -1488,6 +1489,39 @@ public static enum State {
*/
TERMINATED }

/**
* Returns the translation from a J9VMThread state to a Thread::State.
*
* @param status thread status value set by VM.
* @return this thread's state.
fengxue-IS marked this conversation as resolved.
Show resolved Hide resolved
*
* @see State
*/
private State translateJ9VMThreadStateToThreadState(int status) {
switch (status) {
case 1: // J9VMTHREAD_STATE_RUNNING
return State.RUNNABLE;
case 2: // J9VMTHREAD_STATE_BLOCKED
return State.BLOCKED;
case 4: // J9VMTHREAD_STATE_WAITING
case 0x80: // J9VMTHREAD_STATE_PARKED
return State.WAITING;
case 8: // J9VMTHREAD_STATE_SLEEPING
case 64: // J9VMTHREAD_STATE_WAITING_TIMED
case 0x100: // J9VMTHREAD_STATE_PARKED_TIMED
return State.TIMED_WAITING;
case 32: // J9VMTHREAD_STATE_DEAD
return State.TERMINATED;
default:
synchronized (lock) {
if (threadRef == NO_REF) {
return State.TERMINATED;
}
return State.values()[getStateImpl(threadRef)];
}
}
}

/**
* Returns the current Thread state.
*
Expand All @@ -1496,15 +1530,13 @@ public static enum State {
* @see State
*/
public State getState() {
synchronized(lock) {
if (started) {
if (threadRef == NO_REF) {
if (isDead()) {
return State.TERMINATED;
}
return State.NEW;
return State.TERMINATED;
fengxue-IS marked this conversation as resolved.
Show resolved Hide resolved
}
return State.values()[getStateImpl(threadRef)];
return translateJ9VMThreadStateToThreadState(threadStatus);
}
return State.NEW;
}

private native int getStateImpl(long threadRef);
Expand Down
25 changes: 25 additions & 0 deletions runtime/oti/VMHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2275,6 +2275,31 @@ class VM_VMHelpers
targetThread->privateFlags2 |= J9_PRIVATE_FLAGS2_REENTER_INTERPRETER;
indicateAsyncMessagePending(targetThread);
}


static U_64
setThreadState(J9VMThread *currentThread, U_64 state)
{
U_64 oldState = 0;
#if JAVA_SPEC_VERSION >= 19
j9object_t receiverObject = currentThread->carrierThreadObject;
if (NULL != receiverObject) {
/* Platform threads must have a non-null FieldHolder object. */
j9object_t threadHolder = J9VMJAVALANGTHREAD_HOLDER(currentThread, receiverObject);
if (NULL != threadHolder) {
oldState = J9VMJAVALANGTHREADFIELDHOLDER_THREADSTATUS(currentThread, threadHolder);
J9VMJAVALANGTHREADFIELDHOLDER_SET_THREADSTATUS(currentThread, threadHolder, state);
}
}
#else /* JAVA_SPEC_VERSION >= 19 */
j9object_t receiverObject = currentThread->threadObject;
if (NULL != receiverObject) {
oldState = J9VMJAVALANGTHREAD_THREADSTATUS(currentThread, receiverObject);
J9VMJAVALANGTHREAD_SET_THREADSTATUS(currentThread, receiverObject, state);
}
#endif /* JAVA_SPEC_VERSION >= 19 */
return oldState;
}
};

#endif /* VMHELPERS_HPP_ */
1 change: 1 addition & 0 deletions runtime/oti/vmconstantpool.xml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
<fieldref class="java/lang/Thread" name="priority" signature="I" versions="8-18"/>
<fieldref class="java/lang/Thread" name="isDaemon" signature="Z" versions="8-18"/>
<fieldref class="java/lang/Thread" name="group" signature="Ljava/lang/ThreadGroup;" versions="8-18"/>
<fieldref class="java/lang/Thread" name="threadStatus" signature="I" versions="8-18"/>

<fieldref class="java/lang/VirtualThread" name="state" signature="I" versions="19-"/>
<fieldref class="java/lang/VirtualThread" name="carrierThread" signature="Ljava/lang/Thread;" versions="19-"/>
Expand Down
7 changes: 7 additions & 0 deletions runtime/vm/ObjectMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ objectMonitorEnterBlocking(J9VMThread *currentThread)
IDATA waitTime = 1;
if (J9_EVENT_IS_HOOKED(vm->hookInterface, J9HOOK_VM_MONITOR_CONTENDED_ENTER)) {
bool frameBuilt = saveBlockingEnterObject(currentThread);
/* Set j.l.Thread status to BLOCKED. */
VM_VMHelpers::setThreadState(currentThread, J9VMTHREAD_STATE_BLOCKED);
VM_VMAccess::setPublicFlags(currentThread, J9_PUBLIC_FLAGS_THREAD_BLOCKED);
ALWAYS_TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_ENTER(vm->hookInterface, currentThread, monitor);
restoreBlockingEnterObject(currentThread, frameBuilt);
Expand All @@ -185,6 +187,8 @@ objectMonitorEnterBlocking(J9VMThread *currentThread)
goto releasedAccess;
}
restart:
/* Set j.l.Thread status to BLOCKED. */
VM_VMHelpers::setThreadState(currentThread, J9VMTHREAD_STATE_BLOCKED);
internalReleaseVMAccessSetStatus(currentThread, J9_PUBLIC_FLAGS_THREAD_BLOCKED);
releasedAccess:
omrthread_monitor_enter_using_threadId(monitor, osThread);
Expand Down Expand Up @@ -285,6 +289,9 @@ objectMonitorEnterBlocking(J9VMThread *currentThread)
}
done:
clearEventFlag(currentThread, J9_PUBLIC_FLAGS_THREAD_BLOCKED);
/* Set j.l.Thread status to RUNNING state. */
VM_VMHelpers::setThreadState(currentThread, J9VMTHREAD_STATE_RUNNING);

/* Clear the SUPPRESS_CONTENDED_EXITS bit in the monitor saying that CONTENDED EXIT can be sent again */
((J9ThreadMonitor*)monitor)->flags &= ~(UDATA)J9THREAD_MONITOR_SUPPRESS_CONTENDED_EXIT;
VM_AtomicSupport::subtract(&monitor->pinCount, 1);
Expand Down
8 changes: 8 additions & 0 deletions runtime/vm/callin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,14 @@ initializeAttachedThreadImpl(J9VMThread *currentThread, const char *name, j9obje
currentThread->returnValue2 = (UDATA)J9VMJAVALANGTHREAD_INIT_METHOD(vm);
c_cInterpreter(currentThread);
J9VMJAVALANGTHREAD_SET_STARTED(currentThread, initializee->threadObject, JNI_TRUE);
#if JAVA_SPEC_VERSION >= 19
j9object_t threadHolder = J9VMJAVALANGTHREAD_HOLDER(currentThread, initializee->threadObject);
if (NULL != threadHolder) {
J9VMJAVALANGTHREADFIELDHOLDER_SET_THREADSTATUS(currentThread, threadHolder, J9VMTHREAD_STATE_RUNNING);
}
#else /* JAVA_SPEC_VERSION >= 19 */
J9VMJAVALANGTHREAD_SET_THREADSTATUS(currentThread, initializee->threadObject, J9VMTHREAD_STATE_RUNNING);
#endif /* JAVA_SPEC_VERSION >= 19 */
}
}
done:
Expand Down
10 changes: 10 additions & 0 deletions runtime/vm/threadhelp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,16 @@ monitorWaitImpl(J9VMThread *vmThread, j9object_t object, I_64 millis, I_32 nanos
#endif
J9VMTHREAD_SET_BLOCKINGENTEROBJECT(vmThread, vmThread, object);
object = NULL;
/* Set j.l.Thread status to WAITING. */
U_64 oldState = J9_ARE_ANY_BITS_SET(thrstate, J9_PUBLIC_FLAGS_THREAD_TIMED)
? VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_WAITING_TIMED)
: VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_WAITING);
internalReleaseVMAccessSetStatus(vmThread, thrstate);
rc = timeCompensationHelper(vmThread,
interruptable ? HELPER_TYPE_MONITOR_WAIT_INTERRUPTABLE : HELPER_TYPE_MONITOR_WAIT_TIMED, monitor, millis, nanos);
internalAcquireVMAccessClearStatus(vmThread, thrstate);
/* Set j.l.Thread status to oldState. */
VM_VMHelpers::setThreadState(vmThread, oldState);
J9VMTHREAD_SET_BLOCKINGENTEROBJECT(vmThread, vmThread, NULL);
omrthread_monitor_unpin(monitor, vmThread->osThread);
TRIGGER_J9HOOK_VM_MONITOR_WAITED(javaVM->hookInterface, vmThread, monitor, millis, nanos, rc, startTicks, (UDATA) monitor, VM_VMHelpers::currentClass(monitorClass));
Expand Down Expand Up @@ -179,9 +185,13 @@ threadSleepImpl(J9VMThread *vmThread, I_64 millis, I_32 nanos)
#endif
if (0 == rc) {
TRIGGER_J9HOOK_VM_SLEEP(javaVM->hookInterface, vmThread, millis, nanos);
/* Set j.l.Thread status to SLEEPING. */
U_64 oldState = VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_SLEEPING);
internalReleaseVMAccessSetStatus(vmThread, J9_PUBLIC_FLAGS_THREAD_SLEEPING);
rc = timeCompensationHelper(vmThread, HELPER_TYPE_THREAD_SLEEP, NULL, millis, nanos);
internalAcquireVMAccessClearStatus(vmThread, J9_PUBLIC_FLAGS_THREAD_SLEEPING);
/* Set j.l.Thread status to oldState. */
VM_VMHelpers::setThreadState(vmThread, oldState);
TRIGGER_J9HOOK_VM_SLEPT(javaVM->hookInterface, vmThread, millis, nanos, startTicks);
}

Expand Down
6 changes: 6 additions & 0 deletions runtime/vm/threadpark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ threadParkImpl(J9VMThread *vmThread, BOOLEAN timeoutIsEpochRelative, I_64 timeou
/* vmThread->threadObject != NULL because vmThread must be the current thread */
J9VMTHREAD_SET_BLOCKINGENTEROBJECT(vmThread, vmThread, J9VMJAVALANGTHREAD_PARKBLOCKER(vmThread, vmThread->threadObject));
TRIGGER_J9HOOK_VM_PARK(vm->hookInterface, vmThread, millis, nanos);
/* Set j.l.Thread status to WAITING. */
U_64 oldState = J9_ARE_ANY_BITS_SET(thrstate, J9_PUBLIC_FLAGS_THREAD_TIMED)
? VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_WAITING_TIMED)
: VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_WAITING);
internalReleaseVMAccessSetStatus(vmThread, thrstate);

while (1) {
Expand All @@ -116,6 +120,8 @@ threadParkImpl(J9VMThread *vmThread, BOOLEAN timeoutIsEpochRelative, I_64 timeou
}

internalAcquireVMAccessClearStatus(vmThread, thrstate);
/* Set j.l.Thread status to oldState. */
VM_VMHelpers::setThreadState(vmThread, oldState);
TRIGGER_J9HOOK_VM_UNPARKED(vm->hookInterface, vmThread, millis, nanos, startTicks, (UDATA) parkedAddress, VM_VMHelpers::currentClass(parkedClass));
J9VMTHREAD_SET_BLOCKINGENTEROBJECT(vmThread, vmThread, NULL);
}
Expand Down
6 changes: 6 additions & 0 deletions runtime/vm/vmthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "ut_j9vm.h"
#include "vm_internal.h"
#include "vmaccess.h"
#include "VMHelpers.hpp"
#include "vmhook_internal.h"

#include "HeapIteratorAPI.h"
Expand Down Expand Up @@ -459,6 +460,8 @@ void threadCleanup(J9VMThread * vmThread, UDATA forkedByVM)
/* Safe to call this whether handleUncaughtException clears the exception or not */
internalExceptionDescribe(vmThread);
}
/* Set j.l.Thread status to TERMINATED. */
VM_VMHelpers::setThreadState(vmThread, J9VMTHREAD_STATE_DEAD);
releaseVMAccess(vmThread);

/* Mark this thread as dead */
Expand Down Expand Up @@ -2010,6 +2013,9 @@ startJavaThreadInternal(J9VMThread * currentThread, UDATA privateFlags, UDATA os
}
J9VMJAVALANGTHREAD_SET_THREADREF(currentThread, threadObject, newThread);

/* Set j.l.Thread status to RUNNABLE. */
VM_VMHelpers::setThreadState(currentThread, J9VMTHREAD_STATE_RUNNING);

#if (JAVA_SPEC_VERSION >= 14)
/* If thread was interrupted before start, make sure interrupt flag is set for running thread. */
if (J9VMJAVALANGTHREAD_DEADINTERRUPT(currentThread, threadObject)) {
Expand Down