Skip to content

Commit f1f9fee

Browse files
authored
Merge pull request #22404 from fengxue-IS/054-22068
(v0.54.0) Add -XX:[+|-]UnblockerTimedWait option
2 parents 25c9689 + ad167a7 commit f1f9fee

File tree

5 files changed

+71
-22
lines changed

5 files changed

+71
-22
lines changed

runtime/oti/ContinuationHelpers.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#include "j9.h"
2626
#include "j9consts.h"
2727
#include "j9vmconstantpool.h"
28+
#if JAVA_SPEC_VERSION >= 24
29+
#include "thrtypes.h"
30+
#endif /* JAVA_SPEC_VERSION >= 24 */
2831
#include "VMHelpers.hpp"
2932

3033
/* These should match the error code values in enum Pinned within class Continuation. */
@@ -462,6 +465,33 @@ class VM_ContinuationHelpers {
462465
/* Virtual can only be in one list at a time. */
463466
return !(foundInBlockedContinuationList && foundInMonitorList);
464467
}
468+
469+
static VMINLINE bool
470+
isBlockingMonitorUnowned(J9VMThread *currentThread, j9object_t vThreadObject)
471+
{
472+
bool result = false;
473+
j9object_t continuationObject = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, vThreadObject);
474+
j9object_t blockingObject = J9VMJDKINTERNALVMCONTINUATION_BLOCKER(currentThread, continuationObject);
475+
476+
/* blockingObject must be non-null. */
477+
if (NULL != blockingObject) {
478+
j9objectmonitor_t *lockEA = VM_ObjectMonitor::inlineGetLockAddress(currentThread, blockingObject);
479+
if (NULL != lockEA) {
480+
j9objectmonitor_t lock = J9_LOAD_LOCKWORD(currentThread, lockEA);
481+
482+
if (J9_LOCK_IS_INFLATED(lock)) {
483+
omrthread_monitor_t monitor = J9_INFLLOCK_MONITOR(lock);
484+
if (0 == monitor->count) {
485+
result = true;
486+
}
487+
} else if (!J9_LOCK_IS_FLATLOCKED(lock)) {
488+
result = true;
489+
}
490+
}
491+
}
492+
493+
return result;
494+
}
465495
#endif /* JAVA_SPEC_VERSION >= 24 */
466496
};
467497

runtime/oti/j9nonbuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6526,6 +6526,7 @@ typedef struct J9JavaVM {
65266526
J9VMContinuation *blockedContinuations;
65276527
omrthread_monitor_t blockedVirtualThreadsMutex;
65286528
BOOLEAN pendingBlockedVirtualThreadsNotify;
6529+
I_64 unblockerWaitTime;
65296530
#endif /* JAVA_SPEC_VERSION >= 24 */
65306531
} J9JavaVM;
65316532

runtime/oti/jvminit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ enum INIT_STAGE {
476476
/* Option to toggle on/off the feature to yield pinned virtual threads. */
477477
#define VMOPT_XXYIELDPINNEDVIRTUALTHREADS "-XX:+YieldPinnedVirtualThreads"
478478
#define VMOPT_XXNOYIELDPINNEDVIRTUALTHREADS "-XX:-YieldPinnedVirtualThreads"
479+
480+
/* Option to set timed wait on unblocker thread. */
481+
#define VMOPT_XXUNBLOCKERTHREADWAITTIME_EQUALS "-XX:UnblockerThreadWaitTime="
479482
#endif /* JAVA_SPEC_VERSION >= 24 */
480483

481484
/* Option to turn on exception on synchronization on instances of value-based classes */

runtime/vm/ContinuationHelpers.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
#include "j9protos.h"
2525
#include "j9vmnls.h"
2626
#include "objhelp.h"
27-
#if JAVA_SPEC_VERSION >= 24
28-
#include "thrtypes.h"
29-
#endif /* JAVA_SPEC_VERSION >= 24 */
3027
#include "ut_j9vm.h"
3128
#include "vm_api.h"
3229
#include "AtomicSupport.hpp"
@@ -1191,7 +1188,7 @@ waitForSignal(J9VMThread *currentThread)
11911188
*/
11921189
omrthread_monitor_enter(vm->blockedVirtualThreadsMutex);
11931190
if (!vm->pendingBlockedVirtualThreadsNotify) {
1194-
omrthread_monitor_wait_interruptable(vm->blockedVirtualThreadsMutex, 0, 0);
1191+
omrthread_monitor_wait_interruptable(vm->blockedVirtualThreadsMutex, vm->unblockerWaitTime, 0);
11951192
}
11961193
vm->pendingBlockedVirtualThreadsNotify = FALSE;
11971194
omrthread_monitor_exit(vm->blockedVirtualThreadsMutex);
@@ -1245,18 +1242,18 @@ takeVirtualThreadListToUnblock(J9VMThread *currentThread)
12451242
switch (state) {
12461243
case JAVA_LANG_VIRTUALTHREAD_BLOCKING:
12471244
{
1248-
omrthread_monitor_t monitor = syncObjectMonitor->monitor;
1249-
/* For BLOCKING and BLOCKED states, VirtualThread.blockPermit will allow
1245+
/* For BLOCKING state, VirtualThread.blockPermit will allow
12501246
* VirtualThread.afterYield() to reschedule the thread.
12511247
*
12521248
* Set blockPermit only if the monitor's blocker object is available.
12531249
*
1254-
* All blocking/waiting monitors have to be inflated. If the monitor has not been inflated,
1250+
* All blocking monitors have to be inflated. If the monitor has not been inflated,
12551251
* then the owner has not yet released the flat lock.
1252+
*
1253+
* There is a special case where the FLC bit maybe overwritten by fast exit code,
1254+
* so also unblock thread if the blocking object has a unowned flatlock.
12561255
*/
1257-
if (J9_ARE_ANY_BITS_SET(((J9ThreadMonitor *)monitor)->flags, J9THREAD_MONITOR_INFLATED)
1258-
&& (0 == monitor->count)
1259-
) {
1256+
if (VM_ContinuationHelpers::isBlockingMonitorUnowned(currentThread, current->vthread)) {
12601257
J9VMJAVALANGVIRTUALTHREAD_SET_BLOCKPERMIT(currentThread, current->vthread, JNI_TRUE);
12611258
}
12621259
previous = current;
@@ -1284,9 +1281,9 @@ takeVirtualThreadListToUnblock(J9VMThread *currentThread)
12841281
) {
12851282
Assert_VM_true(syncObjectMonitor->virtualThreadWaitCount > 0);
12861283
omrthread_monitor_t monitor = syncObjectMonitor->monitor;
1287-
/* All blocking/waiting monitors have to be inflated. If the monitor has not been inflated,
1288-
* then the owner has not yet released the flat lock.
1289-
*/
1284+
/* All waiting monitors have to be inflated. If the monitor has not been inflated,
1285+
* then wait call have not been done correctly.
1286+
*/
12901287
if (J9_ARE_ANY_BITS_SET(((J9ThreadMonitor *)monitor)->flags, J9THREAD_MONITOR_INFLATED)
12911288
&& (0 == monitor->count)
12921289
) {
@@ -1299,18 +1296,16 @@ takeVirtualThreadListToUnblock(J9VMThread *currentThread)
12991296
case JAVA_LANG_VIRTUALTHREAD_BLOCKED:
13001297
{
13011298
Assert_VM_true(syncObjectMonitor->virtualThreadWaitCount > 0);
1302-
omrthread_monitor_t monitor = syncObjectMonitor->monitor;
1303-
/* For BLOCKING and BLOCKED states, VirtualThread.blockPermit will allow
1304-
* VirtualThread.afterYield() to reschedule the thread.
1299+
/* For BLOCKED state, set VirtualThread.onWaitingList and
1300+
* add vthread to the unblock list so unblocker can reschedule.
13051301
*
1306-
* Set blockPermit only if the monitor's blocker object is available.
1307-
*
1308-
* All blocking/waiting monitors have to be inflated. If the monitor has not been inflated,
1302+
* All blocked monitors have to be inflated. If the monitor has not been inflated,
13091303
* then the owner has not yet released the flat lock.
1304+
*
1305+
* There is a special case where the FLC bit maybe overwritten by fast exit code,
1306+
* so also unblock thread if the blocking object has a unowned flatlock.
13101307
*/
1311-
if (J9_ARE_ANY_BITS_SET(((J9ThreadMonitor *)monitor)->flags, J9THREAD_MONITOR_INFLATED)
1312-
&& (0 == monitor->count)
1313-
) {
1308+
if (VM_ContinuationHelpers::isBlockingMonitorUnowned(currentThread, current->vthread)) {
13141309
unblocked = true;
13151310
syncObjectMonitor->virtualThreadWaitCount -= 1;
13161311
J9VMJAVALANGVIRTUALTHREAD_SET_ONWAITINGLIST(currentThread, current->vthread, JNI_TRUE);

runtime/vm/jvminit.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4379,6 +4379,26 @@ processVMArgsFromFirstToLast(J9JavaVM * vm)
43794379
vm->extendedRuntimeFlags3 &= ~J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION;
43804380
}
43814381
}
4382+
{
4383+
IDATA argIndex = FIND_AND_CONSUME_VMARG(STARTSWITH_MATCH, VMOPT_XXUNBLOCKERTHREADWAITTIME_EQUALS, NULL);
4384+
if (argIndex >= 0) {
4385+
UDATA value = 0;
4386+
char *optname = VMOPT_XXUNBLOCKERTHREADWAITTIME_EQUALS;
4387+
4388+
IDATA parseError = GET_INTEGER_VALUE(argIndex, optname, value);
4389+
if (OPTION_OK != parseError) {
4390+
PORT_ACCESS_FROM_JAVAVM(vm);
4391+
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_VM_INVALID_CMD_LINE_OPT, VMOPT_XXUNBLOCKERTHREADWAITTIME_EQUALS);
4392+
return JNI_ERR;
4393+
}
4394+
4395+
vm->unblockerWaitTime = value;
4396+
} else {
4397+
#define DEFAULT_UNBLOCKER_WAIT_TIME 64
4398+
/* Enable timed wait on unblocker thread by default to 64ms. */
4399+
vm->unblockerWaitTime = DEFAULT_UNBLOCKER_WAIT_TIME;
4400+
}
4401+
}
43824402
#endif /* JAVA_SPEC_VERSION >= 24 */
43834403

43844404
{

0 commit comments

Comments
 (0)