Skip to content

Commit f47e3f0

Browse files
committed
Add pinning checks to blocking operations
co-author: Ravali Yatham <rayatha1@in.ibm.com> Signed-off-by: Tobi Ajila <atobia@ca.ibm.com>
1 parent aeb79a4 commit f47e3f0

2 files changed

Lines changed: 108 additions & 101 deletions

File tree

runtime/vm/BytecodeInterpreter.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,11 +1207,12 @@ class INTERPRETER_CLASS
12071207
enterObjectMonitor(REGISTER_ARGS_LIST, j9object_t obj)
12081208
{
12091209
UDATA rc = (UDATA)obj;
1210+
bool pinningSupportEnabled = J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION);
12101211
if (!VM_ObjectMonitor::inlineFastObjectMonitorEnter(_currentThread, obj)) {
12111212
rc = objectMonitorEnterNonBlocking(_currentThread, obj);
12121213
if (J9_OBJECT_MONITOR_BLOCKING == rc) {
12131214
#if JAVA_SPEC_VERSION >= 24
1214-
if (VM_ContinuationHelpers::isYieldableVirtualThread(_currentThread)) {
1215+
if (pinningSupportEnabled && VM_ContinuationHelpers::isYieldableVirtualThread(_currentThread)) {
12151216
/* Try to yield the virtual thread if it will be blocked. */
12161217
updateVMStruct(REGISTER_ARGS);
12171218
rc = preparePinnedVirtualThreadForUnmount(_currentThread, obj, false);
@@ -1225,7 +1226,7 @@ class INTERPRETER_CLASS
12251226
}
12261227
}
12271228
#if JAVA_SPEC_VERSION >= 24
1228-
if (rc == (UDATA)obj) {
1229+
if (pinningSupportEnabled && (rc == (UDATA)obj)) {
12291230
J9VMContinuation *continuation = _currentThread->currentContinuation;
12301231
if (NULL != continuation) {
12311232
if (J9_ARE_ALL_BITS_SET(continuation->runtimeFlags, J9VM_CONTINUATION_RUNTIMEFLAG_JVMTI_CONTENDED_MONITOR_ENTER_RECORDED)) {

runtime/vm/monhelpers.c

Lines changed: 105 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
7171
lock = J9_LOAD_LOCKWORD(vmStruct, lockEA);
7272

7373
if (J9_FLATLOCK_OWNER(lock) == vmStruct) {
74+
#if JAVA_SPEC_VERSION >= 24
75+
J9JavaVM *vm = vmStruct->javaVM;
76+
#endif /* JAVA_SPEC_VERSION >= 24 */
7477
/* The current thread owns the monitor, and it's a flat lock. */
7578
UDATA count = (UDATA)lock & OBJECT_HEADER_LOCK_BITS_MASK;
7679
/*
@@ -96,133 +99,136 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
9699
#endif /* if !(defined(AIXPPC) || defined(LINUXPPC)) */
97100
#endif /* ifndef J9VM_THR_LOCK_RESERVATION */
98101
#if JAVA_SPEC_VERSION >= 24
99-
if (OBJECT_HEADER_LOCK_FLC == count) {
100-
/* FLC set, non-recursive. */
101-
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
102-
103-
if (NULL == objectMonitor) {
104-
/* Out of memory - impossible? */
105-
monitorExitWriteBarrier();
106-
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
107-
} else {
108-
omrthread_monitor_t monitor = objectMonitor->monitor;
109-
J9JavaVM *vm = vmStruct->javaVM;
102+
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION) {
103+
if (OBJECT_HEADER_LOCK_FLC == count) {
104+
/* FLC set, non-recursive. */
105+
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
106+
107+
if (NULL == objectMonitor) {
108+
/* Out of memory - impossible? */
109+
monitorExitWriteBarrier();
110+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
111+
} else {
112+
omrthread_monitor_t monitor = objectMonitor->monitor;
110113

111-
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);
114+
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);
112115

113-
omrthread_monitor_exit(monitor);
116+
omrthread_monitor_exit(monitor);
114117

115-
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
116-
&& (0 != objectMonitor->virtualThreadWaitCount)
118+
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
119+
&& (0 != objectMonitor->virtualThreadWaitCount)
120+
) {
121+
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
122+
}
123+
}
124+
} else {
125+
j9objectmonitor_t newLock = 0;
126+
BOOLEAN casSuccess = FALSE;
127+
if (0x00 == count) {
128+
/* Just release the flatlock. */
129+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
130+
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
117131
) {
118-
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
132+
/* Learning state case. */
133+
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
134+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
135+
/* Lock is in Learning state but unowned.
136+
* (if it were owned it would have been caught by the first Learning state check)
137+
*/
138+
goto done;
139+
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
140+
/* Just decrement the flatlock recursion count. */
141+
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
142+
#ifdef J9VM_THR_LOCK_RESERVATION
143+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
144+
/* Lock is reserved but unowned.
145+
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
146+
*/
147+
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
148+
goto done;
149+
#endif /* J9VM_THR_LOCK_RESERVATION */
150+
}
151+
152+
monitorExitWriteBarrier();
153+
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
154+
casSuccess = (lock == compareAndSwapU32((uint32_t *)lockEA, (uint32_t)lock, (uint32_t)newLock));
155+
} else {
156+
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
157+
}
158+
159+
if (!casSuccess) {
160+
/* Another thread has attempted to get the lock and may have update the FLC flag. */
161+
goto restart;
119162
}
120163
}
121-
} else {
122-
j9objectmonitor_t newLock = 0;
123-
BOOLEAN casSuccess = FALSE;
164+
} else
165+
#endif /* JAVA_SPEC_VERSION >= 24 */
166+
{
124167
if (0x00 == count) {
125168
/* Just release the flatlock. */
169+
monitorExitWriteBarrier();
170+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
126171
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
127172
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
128173
) {
129174
/* Learning state case. */
130-
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
175+
BOOLEAN casSuccess = FALSE;
176+
177+
if (1 == J9_FLATLOCK_COUNT(lock)) {
178+
/* If RC field is 1, this fully unlocks the object so a write barrier is needed. */
179+
monitorExitWriteBarrier();
180+
}
181+
182+
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
183+
casSuccess = (lock == compareAndSwapU32((uint32_t*)lockEA, (uint32_t)lock,
184+
(uint32_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
185+
} else {
186+
casSuccess = (lock == compareAndSwapUDATA((uintptr_t*)lockEA, (uintptr_t)lock,
187+
(uintptr_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
188+
}
189+
190+
if (!casSuccess) {
191+
/*
192+
* Another thread has attempted to get the lock and atomically changed the state to Flat.
193+
* Start over and read the new lockword. The lock can not go back to Learning so this will
194+
* only happen once.
195+
*/
196+
goto restart;
197+
}
131198
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
132199
/* Lock is in Learning state but unowned.
133-
* (if it were owned it would have been caught by the first Learning state check)
134-
*/
200+
* (if it were owned it would have been caught by the first Learning state check)
201+
*/
202+
Trc_VM_objectMonitorExit_Exit_LearningStateUnowned(vmStruct, lock, object);
135203
goto done;
136204
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
137205
/* Just decrement the flatlock recursion count. */
138-
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
206+
lock -= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
207+
J9_STORE_LOCKWORD(vmStruct, lockEA, lock);
139208
#ifdef J9VM_THR_LOCK_RESERVATION
140209
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
141210
/* Lock is reserved but unowned.
142-
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
143-
*/
211+
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
212+
*/
144213
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
145214
goto done;
146215
#endif /* J9VM_THR_LOCK_RESERVATION */
147-
}
148-
149-
monitorExitWriteBarrier();
150-
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
151-
casSuccess = (lock == compareAndSwapU32((uint32_t *)lockEA, (uint32_t)lock, (uint32_t)newLock));
152216
} else {
153-
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
154-
}
217+
/* FLC set, non-recursive. */
218+
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
155219

156-
if (!casSuccess) {
157-
/* Another thread has attempted to get the lock and may have update the FLC flag. */
158-
goto restart;
220+
if (NULL == objectMonitor) {
221+
/* Out of memory - impossible? */
222+
monitorExitWriteBarrier();
223+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
224+
} else {
225+
omrthread_monitor_t monitor = objectMonitor->monitor;
226+
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vmStruct->javaVM->hookInterface, vmStruct, monitor);
227+
omrthread_monitor_exit(monitor);
228+
}
159229
}
160230
}
161-
#else /* JAVA_SPEC_VERSION >= 24 */
162-
if (0x00 == count) {
163-
/* Just release the flatlock. */
164-
monitorExitWriteBarrier();
165-
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
166-
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
167-
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
168-
) {
169-
/* Learning state case. */
170-
BOOLEAN casSuccess = FALSE;
171-
172-
if (1 == J9_FLATLOCK_COUNT(lock)) {
173-
/* If RC field is 1, this fully unlocks the object so a write barrier is needed. */
174-
monitorExitWriteBarrier();
175-
}
176-
177-
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
178-
casSuccess = (lock == compareAndSwapU32((uint32_t*)lockEA, (uint32_t)lock,
179-
(uint32_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
180-
} else {
181-
casSuccess = (lock == compareAndSwapUDATA((uintptr_t*)lockEA, (uintptr_t)lock,
182-
(uintptr_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
183-
}
184231

185-
if (!casSuccess) {
186-
/*
187-
* Another thread has attempted to get the lock and atomically changed the state to Flat.
188-
* Start over and read the new lockword. The lock can not go back to Learning so this will
189-
* only happen once.
190-
*/
191-
goto restart;
192-
}
193-
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
194-
/* Lock is in Learning state but unowned.
195-
* (if it were owned it would have been caught by the first Learning state check)
196-
*/
197-
Trc_VM_objectMonitorExit_Exit_LearningStateUnowned(vmStruct, lock, object);
198-
goto done;
199-
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
200-
/* Just decrement the flatlock recursion count. */
201-
lock -= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
202-
J9_STORE_LOCKWORD(vmStruct, lockEA, lock);
203-
#ifdef J9VM_THR_LOCK_RESERVATION
204-
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
205-
/* Lock is reserved but unowned.
206-
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
207-
*/
208-
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
209-
goto done;
210-
#endif /* J9VM_THR_LOCK_RESERVATION */
211-
} else {
212-
/* FLC set, non-recursive. */
213-
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
214-
215-
if (NULL == objectMonitor) {
216-
/* Out of memory - impossible? */
217-
monitorExitWriteBarrier();
218-
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
219-
} else {
220-
omrthread_monitor_t monitor = objectMonitor->monitor;
221-
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vmStruct->javaVM->hookInterface, vmStruct, monitor);
222-
omrthread_monitor_exit(monitor);
223-
}
224-
}
225-
#endif /* JAVA_SPEC_VERSION >= 24 */
226232
Trc_VM_objectMonitorExit_Exit_FCBSet(vmStruct);
227233
rc = 0;
228234
goto done;

0 commit comments

Comments
 (0)