RFR: 8254264: Remove redundant cross_modify_fence()

Patricio Chilano patricio.chilano.mateo at oracle.com
Fri Oct 16 18:33:17 UTC 2020


Hi David,

On 10/16/20 1:58 AM, David Holmes wrote:
> 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?
I'm not sure of that. But we added these fences for the case where the 
code got patched during a safepoint. Maybe Robbin knows the answer.  : )

>> 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. 
Only with ThreadToNativeFromVM, because we switch to native and then 
call has_special_runtime_exit_condition(). Which by the way, I don't see 
why we need to make that call since we are going from vm->native. We 
don't deliver async exceptions and we don't need to check for suspend 
since we are going to native. If we remove that call we can remove that 
conditional in java_suspend_self_with_safepoint_check() and always call 
SafepointMechanism::process_if_requested().

> 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.)
Exactly.

> \So long story short: this all looks good to me. :)
Thanks David!


Patricio
> 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