RFR: 8364343: Virtual Thread transition management needs to be independent of JVM TI [v4]

Patricio Chilano Mateo pchilanomate at openjdk.org
Tue Nov 25 19:58:53 UTC 2025


On Fri, 21 Nov 2025 00:42:32 GMT, David Holmes <dholmes at openjdk.org> wrote:

>> Patricio Chilano Mateo has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Rename VM methods for endFirstTransition/startFinalTransition
>
> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 277:
> 
>> 275: 
>> 276:   // Start of the critical region. Prevent future memory
>> 277:   // operations to be ordered before we read the transition flag.
> 
> Does this refer to `java_lang_Thread::is_in_VTMS_transition(_vthread())`? If so perhaps that should internally perform the `load_acquire`?

Yes, but that would also call for doing the same with `JavaThread::_is_in_VTMS_transition` for the `VTMS_transition_disable_for_all` case, and also have the pairing release stores by the virtual thread in `end_transition` on those same addresses, otherwise it would be confusing. And same with the other side, i.e doing load_acquire by the virtual thread of `_VTMS_transition_disable_count` and `_global_start_transition_disable_count` on `start_transition` and release store by the disabler when enabling transitions again. But I wanted to avoid unnecessary barriers in the virtual thread transition side, so I kept them as plain load/stores with separate memory barriers when necessary.

> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 307:
> 
>> 305:   // Block while some mount/unmount transitions are in progress.
>> 306:   // Debug version fails and prints diagnostic information.
>> 307:   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
> 
> This looks very odd, having an assignment in the loop condition check and no actual loop-update expression.

Yes, from what I see this same construct is used in many places. Seems this is valid because a pointer used in a boolean context evaluates to false if nullptr and true if non-null. :)

> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 316:
> 
>> 314:   // operations to be ordered before we read the transition flags.
>> 315:   // This matches the release fence in end_transition().
>> 316:   OrderAccess::acquire();
> 
> Surely the use of the iterator already provides the necessary ordering guarantee here as well. ?

We still need it because we need to prevent reordering of loads from the critical section with loads of `jt->is_in_VTMS_transition()`.

> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 327:
> 
>> 325:   // End of the critical section. Prevent previous memory operations to
>> 326:   // be ordered after we clear the clear the disable transition flag.
>> 327:   // This matches the equivalent acquire fence in start_transition().
> 
> Suggestion:
> 
>   // This pairs with the acquire in start_transition().
> 
> I just realized you are using "fence" to describe release and acquire memory barrier semantics. Given we have an operation `fence` I find this confusing for the reader - especially when we also have a `release_store_fence` operation which might be confused with "release fence".

Right, I changed it now to use the terms acquire and release barrier respectively.

> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 370:
> 
>> 368:   assert(VTMSTransition_lock->owned_by_self() || SafepointSynchronize::is_at_safepoint(), "Must be locked");
>> 369:   assert(_global_start_transition_disable_count >= 0, "");
>> 370:   AtomicAccess::store(&_global_start_transition_disable_count, _global_start_transition_disable_count + 1);
> 
> Suggestion:
> 
>   AtomicAccess::inc(&_global_start_transition_disable_count);

I’d prefer to leave it as a plain store to avoid the unnecessary extra fence.

> src/hotspot/share/runtime/mountUnmountDisabler.cpp line 376:
> 
>> 374:   assert(VTMSTransition_lock->owned_by_self() || SafepointSynchronize::is_at_safepoint(), "Must be locked");
>> 375:   assert(_global_start_transition_disable_count > 0, "");
>> 376:   AtomicAccess::store(&_global_start_transition_disable_count, _global_start_transition_disable_count - 1);
> 
> Suggestion:
> 
>   AtomicAccess::dec(&_global_start_transition_disable_count);

Same here.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561208616
PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561210899
PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561216984
PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561219344
PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561219842
PR Review Comment: https://git.openjdk.org/jdk/pull/28361#discussion_r2561220292


More information about the graal-dev mailing list