RFR: 8254264: Remove redundant cross_modify_fence()
David Holmes
david.holmes at oracle.com
Fri Oct 16 04:58:41 UTC 2020
Hi Patricio,
On 16/10/2020 4:09 am, Patricio Chilano wrote:
> Hi David,
>
> On 10/15/20 5:22 AM, David Holmes wrote:
>> Hi Patricio,
>>
>> On 15/10/2020 1:20 am, Patricio Chilano Mateo wrote:
>>> Hi all,
>>>
>>> Please review the following patch that removes some uneeded uses of
>>> cross_modify_fence() in common code, in particular
>>> from ~ThreadBlockInVM(), ~ThreadBlockInVMWithDeadlockCheck() and
>>> java_suspend_self_with_safepoint_check(). These fences
>>> were added before each JavaThread had to disarm itself (8230594).
>>> After a safepoint/handshake each JavaThread will
>>> always call SafepointMechanism::process_if_requested_slow() when
>>> transitioning out of the safe state and will execute a
>>> cross_modify_fence(). Tested with mach5 tiers1-7.
>>
>> As you have already done the analysis, could you show the exact call
>> sequences that allow for the removal of the code as described? I'm
>> trying to verify what you've stated but trying to reverse engineer the
>> calling sequences is painful. :)
> So, before each JavaThread had to disarm itself you could have the
> following sequence:
>
> - JT T creates ThreadBlockInVM object and then blocks (usually in
> park()/wait())
> - VMThread arms T for a safepoint operation. Since T is in
> _thread_blocked state it's safe so safepoint starts.
> - Once safepoint operation is done VMThread disarms T
> - T wakes up and executes ~ThreadBlockInVM(). Since the poll word/page
> is not armed it just continues execution. If we didn't have that
> cross_modify_fence() in ~ThreadBlockInVM() we can transition back to
> java later without executing the fence instruction.
And just to be clear any action that changes code such that a
cross-modify-fence is needed by other threads, has to perform a global
safepoint/handshake?
> Same sequence with ~ThreadBlockInVMWithDeadlockCheck and
> java_suspend_self_with_safepoint_check(). So when transitioning out of
> the _thread_blocked state a JT wouldn't know if a safepoint happened so
> we had that fence there unconditionally.
>
> Today disarming of the poll word/page is done by each JT, so if a
> safepoint happened while the JT was blocked the poll word/page will
> remain armed. The JT when transitioning out of the _thread_blocked will
> call SafepointMechanism::process_if_requested() (in
> ~TBIVM/~TBIVMWDC/java_suspend_self_with_safepoint_check()), will go
> through process_if_requested_slow() to check if it needs to process some
> operation and at the end will execute a cross_modify_fence().
Okay so ...
~ThreadBlockInVM()
-> trans(_thread_blocked, _thread_in_vm);
--> transition(...);
---> SafepointMechanism::process_if_requested(thread)
-----> if (!local_poll_armed(thread)) { // <- It is armed
return;
}
process_if_requested_slow(thread); => OK
~ThreadBlockInVMWithDeadlockCheck()
-> if (SafepointMechanism::should_process(_thread)) { // True as poll armed
release_mutex();
SafepointMechanism::process_if_requested(_thread);
------> if (!local_poll_armed(thread)) { // <- It is armed
return;
}
process_if_requested_slow(thread); => OK
JavaThread::java_suspend_self_with_safepoint_check()
-> if (state != _thread_in_native) {
SafepointMechanism::process_if_requested(this); => OK
}
Those cases are all good as you stated.
So my only uncertainty now is the _thread_in_native case for suspension.
But how can we be _thread_in_native at the time we call
java_suspend_self_with_safepoint_check? When we call from
check_safepoint_and_suspend_for_native_trans we are in
_thread_in_native_trans. So that leaves
handle_special_runtime_exit_condition, which is called from:
- JavaCallWrapper::JavaCallWrapper
- thread must be _thread_in_vm here
- SafepointSynchronize::block
- can't be _thread_in_native (fatal error)
- ~ThreadInVMfromJava()
- thread must be _thread_in_Java
- ThreadToNativeFromVM
- thread must be _thread_in_vm
- ~ThreadInVMfromJavaNoAsyncException
- thread must be _thread_in_vm
So as far as I can see we can never be _thread_in_native when calling
JavaThread::java_suspend_self_with_safepoint_check. So it seems I don't
have to worry about that case after all :) (and in any case when leaving
_thread_in_native we will call
check_safepoint_and_suspend_for_native_trans so we'd get to the
cross-modify-fence via that route.)
So long story short: this all looks good to me. :)
Thanks,
David
-----
>
> Patricio
>> Thanks,
>> David
>>
>>> Thanks,
>>> Patricio
>>>
>>> -------------
>>>
>>> Commit messages:
>>> - v1
>>>
>>> Changes: https://git.openjdk.java.net/jdk/pull/655/files
>>> Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=655&range=00
>>> Issue: https://bugs.openjdk.java.net/browse/JDK-8254264
>>> Stats: 5 lines in 2 files changed: 0 ins; 5 del; 0 mod
>>> Patch: https://git.openjdk.java.net/jdk/pull/655.diff
>>> Fetch: git fetch https://git.openjdk.java.net/jdk
>>> pull/655/head:pull/655
>>>
>>> PR: https://git.openjdk.java.net/jdk/pull/655
>>>
>
More information about the hotspot-runtime-dev
mailing list