@@ -220,6 +220,7 @@ synchronizeWithConcurrentGCScan(J9VMThread *currentThread, j9object_t continuati
220
220
BOOLEAN
221
221
enterContinuation (J9VMThread *currentThread, j9object_t continuationObject)
222
222
{
223
+ J9JavaVM *vm = currentThread->javaVM ;
223
224
BOOLEAN result = TRUE ;
224
225
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF (currentThread, continuationObject);
225
226
ContinuationState volatile *continuationStatePtr = VM_ContinuationHelpers::getContinuationStateAddress (currentThread, continuationObject);
@@ -232,7 +233,7 @@ enterContinuation(J9VMThread *currentThread, j9object_t continuationObject)
232
233
/* Directly return result if the create code failed, exception is already set. */
233
234
return result;
234
235
}
235
- currentThread-> javaVM ->memoryManagerFunctions ->continuationObjectStarted (currentThread, continuationObject);
236
+ vm ->memoryManagerFunctions ->continuationObjectStarted (currentThread, continuationObject);
236
237
237
238
continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF (currentThread, continuationObject);
238
239
#if JAVA_SPEC_VERSION >= 24
@@ -241,6 +242,33 @@ enterContinuation(J9VMThread *currentThread, j9object_t continuationObject)
241
242
}
242
243
Assert_VM_notNull (continuation);
243
244
245
+ #if JAVA_SPEC_VERSION >= 24
246
+ if (NULL != continuation->nextWaitingContinuation ) {
247
+ /* Continuation is still in a blocked list. This can happen with TIMED_WAIT.
248
+ * It must be removed from the waiting list.
249
+ */
250
+ bool foundInBlockedContinuationList = false ;
251
+ bool foundInMonitorList = false ;
252
+
253
+ omrthread_monitor_enter (vm->blockedVirtualThreadsMutex );
254
+
255
+ foundInBlockedContinuationList = VM_ContinuationHelpers::removeContinuationFromList (
256
+ &vm->blockedContinuations , continuation);
257
+
258
+ foundInMonitorList = VM_ContinuationHelpers::removeContinuationFromList (
259
+ &continuation->objectWaitMonitor ->waitingContinuations , continuation);
260
+
261
+ omrthread_monitor_exit (vm->blockedVirtualThreadsMutex );
262
+
263
+ Assert_VM_true (foundInMonitorList || foundInMonitorList);
264
+
265
+ /* Virtual can only be in one list at a time. */
266
+ Assert_VM_false (foundInBlockedContinuationList && foundInMonitorList);
267
+
268
+ continuation->objectWaitMonitor = NULL ;
269
+ }
270
+ #endif /* JAVA_SPEC_VERSION >= 24 */
271
+
244
272
/* let GC know we are mounting, so they don't need to scan us, or if there is already ongoing scan wait till it's complete. */
245
273
continuationObject = synchronizeWithConcurrentGCScan (currentThread, continuationObject, continuationStatePtr);
246
274
@@ -816,6 +844,7 @@ preparePinnedVirtualThreadForUnmount(J9VMThread *currentThread, j9object_t syncO
816
844
j9objectmonitor_t lock = 0 ;
817
845
j9object_t continuationObj = NULL ;
818
846
UDATA monitorCount = 0 ;
847
+ J9JavaVM *vm = currentThread->javaVM ;
819
848
820
849
if (NULL != syncObj) {
821
850
enterVThreadTransitionCritical (currentThread, (jobject)¤tThread->threadObject );
@@ -829,7 +858,7 @@ preparePinnedVirtualThreadForUnmount(J9VMThread *currentThread, j9object_t syncO
829
858
830
859
if (syncObj != object) {
831
860
if (!LN_HAS_LOCKWORD (currentThread, object)) {
832
- objectMonitor = monitorTablePeek (currentThread-> javaVM , object);
861
+ objectMonitor = monitorTablePeek (vm , object);
833
862
if (NULL != objectMonitor) {
834
863
lock = J9_LOAD_LOCKWORD (currentThread, &objectMonitor->alternateLockword );
835
864
} else {
@@ -863,7 +892,7 @@ preparePinnedVirtualThreadForUnmount(J9VMThread *currentThread, j9object_t syncO
863
892
864
893
if (syncObj != object) {
865
894
if (!LN_HAS_LOCKWORD (currentThread, object)) {
866
- objectMonitor = monitorTablePeek (currentThread-> javaVM , object);
895
+ objectMonitor = monitorTablePeek (vm , object);
867
896
if (NULL != objectMonitor) {
868
897
lock = J9_LOAD_LOCKWORD (currentThread, &objectMonitor->alternateLockword );
869
898
} else {
@@ -892,7 +921,7 @@ preparePinnedVirtualThreadForUnmount(J9VMThread *currentThread, j9object_t syncO
892
921
893
922
if (NULL != syncObj) {
894
923
if (!LN_HAS_LOCKWORD (currentThread, syncObj)) {
895
- syncObjectMonitor = monitorTablePeek (currentThread-> javaVM , syncObj);
924
+ syncObjectMonitor = monitorTablePeek (vm , syncObj);
896
925
if (NULL != syncObjectMonitor) {
897
926
lock = J9_LOAD_LOCKWORD (currentThread, &syncObjectMonitor->alternateLockword );
898
927
} else {
@@ -930,10 +959,11 @@ preparePinnedVirtualThreadForUnmount(J9VMThread *currentThread, j9object_t syncO
930
959
931
960
/* Add Continuation struct to the monitor's waiting list. */
932
961
omrthread_monitor_exit (monitor);
933
- omrthread_monitor_enter (currentThread-> javaVM ->blockedVirtualThreadsMutex );
962
+ omrthread_monitor_enter (vm ->blockedVirtualThreadsMutex );
934
963
currentThread->currentContinuation ->nextWaitingContinuation = syncObjectMonitor->waitingContinuations ;
935
964
syncObjectMonitor->waitingContinuations = currentThread->currentContinuation ;
936
- omrthread_monitor_exit (currentThread->javaVM ->blockedVirtualThreadsMutex );
965
+ currentThread->currentContinuation ->objectWaitMonitor = syncObjectMonitor;
966
+ omrthread_monitor_exit (vm->blockedVirtualThreadsMutex );
937
967
} else {
938
968
syncObjectMonitor->virtualThreadWaitCount += 1 ;
939
969
}
@@ -971,33 +1001,32 @@ takeVirtualThreadListToUnblock(J9VMThread *currentThread)
971
1001
while (NULL == unblockedList) {
972
1002
if (NULL != vm->blockedContinuations ) {
973
1003
restart:
974
- J9VMContinuation *listHead = vm->blockedContinuations ;
1004
+ J9VMContinuation *previous = NULL ;
1005
+ J9VMContinuation *current = vm->blockedContinuations ;
975
1006
J9VMContinuation *next = NULL ;
976
- vm->blockedContinuations = NULL ;
977
- while (NULL != listHead) {
1007
+ while (NULL != current) {
978
1008
bool unblocked = false ;
979
- next = listHead-> nextWaitingContinuation ;
980
- U_32 state = J9VMJAVALANGVIRTUALTHREAD_STATE (currentThread, listHead-> vthread ) ;
1009
+ U_32 state = J9VMJAVALANGVIRTUALTHREAD_STATE (currentThread, current-> vthread ) ;
1010
+ next = current-> nextWaitingContinuation ;
981
1011
/* Skip vthreads that are still in transition. */
982
1012
switch (state) {
983
1013
case JAVA_LANG_VIRTUALTHREAD_BLOCKING:
984
1014
case JAVA_LANG_VIRTUALTHREAD_WAITING:
985
1015
case JAVA_LANG_VIRTUALTHREAD_TIMED_WAITING:
986
- listHead->nextWaitingContinuation = vm->blockedContinuations ;
987
- vm->blockedContinuations = listHead;
988
- listHead = next;
1016
+ previous = current;
1017
+ current = next;
989
1018
continue ;
990
1019
case JAVA_LANG_VIRTUALTHREAD_WAIT:
991
1020
case JAVA_LANG_VIRTUALTHREAD_TIMED_WAIT:
992
- J9VMJAVALANGVIRTUALTHREAD_SET_STATE (currentThread, listHead ->vthread , JAVA_LANG_VIRTUALTHREAD_BLOCKED);
1021
+ J9VMJAVALANGVIRTUALTHREAD_SET_STATE (currentThread, current ->vthread , JAVA_LANG_VIRTUALTHREAD_BLOCKED);
993
1022
/* FALLTHROUGH */
994
1023
default :
995
1024
break ;
996
1025
}
997
- if (J9VMJAVALANGVIRTUALTHREAD_ONWAITINGLIST (currentThread, listHead ->vthread )) {
1026
+ if (J9VMJAVALANGVIRTUALTHREAD_ONWAITINGLIST (currentThread, current ->vthread )) {
998
1027
unblocked = true ;
999
1028
} else {
1000
- j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT (currentThread, listHead ->vthread );
1029
+ j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT (currentThread, current ->vthread );
1001
1030
j9object_t syncObject = J9VMJDKINTERNALVMCONTINUATION_BLOCKER (currentThread, continuationObj);
1002
1031
J9ObjectMonitor *syncObjectMonitor = NULL ;
1003
1032
j9objectmonitor_t lock = 0 ;
@@ -1016,18 +1045,29 @@ takeVirtualThreadListToUnblock(J9VMThread *currentThread)
1016
1045
if (syncObjectMonitor->virtualThreadWaitCount >= 1 ) {
1017
1046
syncObjectMonitor->virtualThreadWaitCount -= 1 ;
1018
1047
}
1019
- J9VMJAVALANGVIRTUALTHREAD_SET_ONWAITINGLIST (currentThread, listHead ->vthread , JNI_TRUE);
1048
+ J9VMJAVALANGVIRTUALTHREAD_SET_ONWAITINGLIST (currentThread, current ->vthread , JNI_TRUE);
1020
1049
}
1021
1050
}
1022
1051
1023
1052
if (unblocked) {
1024
- J9VMJAVALANGVIRTUALTHREAD_SET_NEXT (currentThread, listHead->vthread , unblockedList);
1025
- unblockedList = listHead->vthread ;
1053
+ /* Add to Java unblock list. */
1054
+ J9VMJAVALANGVIRTUALTHREAD_SET_NEXT (currentThread, current->vthread , unblockedList);
1055
+ unblockedList = current->vthread ;
1056
+
1057
+ /* Remove from native blocking list. */
1058
+ current->nextWaitingContinuation = NULL ;
1059
+
1060
+ if (NULL == previous) {
1061
+ vm->blockedContinuations = next;
1062
+ } else {
1063
+ previous->nextWaitingContinuation = next;
1064
+ }
1026
1065
} else {
1027
- listHead-> nextWaitingContinuation = vm-> blockedContinuations ;
1028
- vm-> blockedContinuations = listHead ;
1066
+ /* Keep in native blocking list. */
1067
+ previous = current ;
1029
1068
}
1030
- listHead = next;
1069
+
1070
+ current = next;
1031
1071
}
1032
1072
if (NULL == unblockedList) {
1033
1073
vmFuncs->internalExitVMToJNI (currentThread);
0 commit comments