Skip to content

Commit 928522a

Browse files
committed
Add pinning checks to blocking operations
Signed-off-by: Tobi Ajila <atobia@ca.ibm.com>
1 parent aeb79a4 commit 928522a

2 files changed

Lines changed: 106 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: 103 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -96,133 +96,137 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
9696
#endif /* if !(defined(AIXPPC) || defined(LINUXPPC)) */
9797
#endif /* ifndef J9VM_THR_LOCK_RESERVATION */
9898
#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;
99+
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION) {
100+
if (OBJECT_HEADER_LOCK_FLC == count) {
101+
/* FLC set, non-recursive. */
102+
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
103+
104+
if (NULL == objectMonitor) {
105+
/* Out of memory - impossible? */
106+
monitorExitWriteBarrier();
107+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
108+
} else {
109+
omrthread_monitor_t monitor = objectMonitor->monitor;
110+
J9JavaVM *vm = vmStruct->javaVM;
110111

111-
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);
112+
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);
112113

113-
omrthread_monitor_exit(monitor);
114+
omrthread_monitor_exit(monitor);
114115

115-
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
116-
&& (0 != objectMonitor->virtualThreadWaitCount)
116+
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
117+
&& (0 != objectMonitor->virtualThreadWaitCount)
118+
) {
119+
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
120+
}
121+
}
122+
} else {
123+
j9objectmonitor_t newLock = 0;
124+
BOOLEAN casSuccess = FALSE;
125+
if (0x00 == count) {
126+
/* Just release the flatlock. */
127+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
128+
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
117129
) {
118-
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
130+
/* Learning state case. */
131+
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
132+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
133+
/* Lock is in Learning state but unowned.
134+
* (if it were owned it would have been caught by the first Learning state check)
135+
*/
136+
goto done;
137+
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
138+
/* Just decrement the flatlock recursion count. */
139+
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
140+
#ifdef J9VM_THR_LOCK_RESERVATION
141+
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
142+
/* Lock is reserved but unowned.
143+
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
144+
*/
145+
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
146+
goto done;
147+
#endif /* J9VM_THR_LOCK_RESERVATION */
148+
}
149+
150+
monitorExitWriteBarrier();
151+
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
152+
casSuccess = (lock == compareAndSwapU32((uint32_t *)lockEA, (uint32_t)lock, (uint32_t)newLock));
153+
} else {
154+
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
155+
}
156+
157+
if (!casSuccess) {
158+
/* Another thread has attempted to get the lock and may have update the FLC flag. */
159+
goto restart;
119160
}
120161
}
121-
} else {
122-
j9objectmonitor_t newLock = 0;
123-
BOOLEAN casSuccess = FALSE;
162+
} else
163+
#endif
164+
{
124165
if (0x00 == count) {
125166
/* Just release the flatlock. */
167+
monitorExitWriteBarrier();
168+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
126169
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
127170
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
128171
) {
129172
/* Learning state case. */
130-
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
173+
BOOLEAN casSuccess = FALSE;
174+
175+
if (1 == J9_FLATLOCK_COUNT(lock)) {
176+
/* If RC field is 1, this fully unlocks the object so a write barrier is needed. */
177+
monitorExitWriteBarrier();
178+
}
179+
180+
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
181+
casSuccess = (lock == compareAndSwapU32((uint32_t*)lockEA, (uint32_t)lock,
182+
(uint32_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
183+
} else {
184+
casSuccess = (lock == compareAndSwapUDATA((uintptr_t*)lockEA, (uintptr_t)lock,
185+
(uintptr_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
186+
}
187+
188+
if (!casSuccess) {
189+
/*
190+
* Another thread has attempted to get the lock and atomically changed the state to Flat.
191+
* Start over and read the new lockword. The lock can not go back to Learning so this will
192+
* only happen once.
193+
*/
194+
goto restart;
195+
}
131196
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
132197
/* Lock is in Learning state but unowned.
133-
* (if it were owned it would have been caught by the first Learning state check)
134-
*/
198+
* (if it were owned it would have been caught by the first Learning state check)
199+
*/
200+
Trc_VM_objectMonitorExit_Exit_LearningStateUnowned(vmStruct, lock, object);
135201
goto done;
136202
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
137203
/* Just decrement the flatlock recursion count. */
138-
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
204+
lock -= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
205+
J9_STORE_LOCKWORD(vmStruct, lockEA, lock);
139206
#ifdef J9VM_THR_LOCK_RESERVATION
140207
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
141208
/* Lock is reserved but unowned.
142-
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
143-
*/
209+
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
210+
*/
144211
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
145212
goto done;
146213
#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));
152214
} else {
153-
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
154-
}
215+
/* FLC set, non-recursive. */
216+
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);
155217

156-
if (!casSuccess) {
157-
/* Another thread has attempted to get the lock and may have update the FLC flag. */
158-
goto restart;
218+
if (NULL == objectMonitor) {
219+
/* Out of memory - impossible? */
220+
monitorExitWriteBarrier();
221+
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
222+
} else {
223+
omrthread_monitor_t monitor = objectMonitor->monitor;
224+
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vmStruct->javaVM->hookInterface, vmStruct, monitor);
225+
omrthread_monitor_exit(monitor);
226+
}
159227
}
160228
}
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-
}
184-
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);
214229

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 */
226230
Trc_VM_objectMonitorExit_Exit_FCBSet(vmStruct);
227231
rc = 0;
228232
goto done;

0 commit comments

Comments
 (0)