~ThreadInVMForHandshake() should call handle_special_runtime_exit_condition()

Daniel D. Daugherty daniel.daugherty at oracle.com
Thu May 9 23:11:06 UTC 2019


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