~ThreadInVMForHandshake() should call handle_special_runtime_exit_condition()
David Holmes
david.holmes at oracle.com
Fri May 10 00:05:33 UTC 2019
Hi Dan,
Many thanks for doing that detailed walkthrough! I also tried to verify
the conditions of the _thread_state as they are not what was originally
proposed. But once I saw the recursion I called it a night! The
recursion here makes me very nervous (it's preexisting of course) - this
stuff is hard enough to reason about with only one level of nesting. :(
There's no regression test as this was not seen in the wild only
hypothesised:
http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2019-May/034144.html
Thanks,
David
On 10/05/2019 9:11 am, Daniel D. Daugherty wrote:
> Richard,
>
> Very nice catch!
>
>
> On 5/9/19 6:05 AM, Reingruber, Richard wrote:
>> Hi,
>>
>> could I please get reviews and sponsoring for
>>
>> Webrev: http://cr.openjdk.java.net/~rrich/webrevs/2019/8223572/webrev.1/
>
> src/hotspot/share/runtime/interfaceSupport.inline.hpp
> Verified that your new conditional block for calling
> handle_special_runtime_exit_condition() and the
> conditions for the parameter match the code at the
> end of SafepointSynchronize::block(JavaThread *thread).
>
> I had to walk through the target thread call sequence:
>
> SafepointSynchronize::handle_polling_page_exception(JavaThread *thread)
> thread->safepoint_state()->handle_polling_page_exception
> SafepointMechanism::block_if_requested(thread())
> SafepointMechanism::block_if_requested_slow(thread)
> SafepointMechanism::block_or_handshake()
> // not a global poll
> thread->handshake_process_by_self()
> _handshake.process_by_self(this)
> process_self_inner(thread)
> ThreadInVMForHandshake tivm(thread)
> : make_walkable()
> : set _thread_in_vm
> _semaphore.wait_with_safepoint_check(thread)
> : ThreadBlockInVM tbivm
> : make_walkable()
> : trans(_thread_in_vm, _thread_blocked)
> : _impl.wait()
> : <VM_thread signals>
> : <VM_ThreadSuspend on target thread>
> : ~ThreadBlockInVM
> : trans(_thread_blocked, _thread_in_vm)
> : : transition(_thread, from, to)
> : : set _thread_blocked+1
> : : SafepointMechanism::block_if_requested(thread)
> : : :
> SafepointMechanism::block_if_requested_slow(thread)
> : : : SafepointMechanism::block_or_handshake()
> : : : if (global_poll()) {
> : : : SafepointSynchronize::block(thread)
> : : : make_walkable()
> : : : set _thread_blocked
> : : : _wait_barrier->wait()
> : : : // wait is notified when the
> safepoint is over
> : : : restore _thread_blocked+1 //
> _thread_blocked_trans
> : : : skip the call to
> handle_special_runtime_exit_condition()
> : : : because state == _thread_blocked_trans
> : : // return all the way back to transition()
> : : set _thread_in_vm
> ~ThreadInVMForHandshake
> transition_back()
> set _thread_in_vm_trans
> SafepointMechanism::block_if_requested()
> set _original_state
> // Now we return all the way back to handle_polling_page_exception().
> // If we came from a _thread_in_Java state, then we just returned to
> // that state without self suspending.
> // The fix adds this:
> if (_original_state != _thread_blocked_trans &&
> _original_state != _thread_in_vm_trans &&
> _thread->has_special_runtime_exit_condition()) {
> _thread->handle_special_runtime_exit_condition(
> !_thread->is_at_poll_safepoint() &&
> (_original_state != _thread_in_native_trans));
>
> And handle_special_runtime_exit_condition() does this:
>
> bool do_self_suspend = is_external_suspend_with_lock();
> if (do_self_suspend && (!AllowJNIEnvProxy || this ==
> JavaThread::current())) {
> frame_anchor()->make_walkable(this);
> java_suspend_self_with_safepoint_check();
> }
>
> Okay. Now I grok where the bug is and how your fix handles it.
> Thumbs up on the fix itself!
>
> You don't mention how you tested this fix. You also don't say
> whether you have a test that reproduces this issue.
>
> Obviously, we also need to hear from Robbin on this thread.
>
> Dan
>
>> Bug: https://bugs.openjdk.java.net/browse/JDK-8223572
>>
>> A java thread T can continue executing bytecodes after it was
>> suspended using the vm operation
>> VM_ThreadSuspend. This can happen in
>> HandshakeState::process_self_inner() when T becomes safepoint
>> safe calling _semaphore.wait_with_safepoint_check(thread).
>>
>> Fix: poll has_special_runtime_exit_condition() and conditionally call
>> handle_special_runtime_exit_condition() as it is done in
>> SafepointSynchronize::block(), too.
>>
>> Thanks, Richard.
>>
>> PS: see also mail thread
>> https://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2019-May/034144.html
>>
>
More information about the hotspot-runtime-dev
mailing list