On Thu, 17 Sep 2020 12:07:15 GMT, Robbin Ehn <r...@openjdk.org> wrote:

>> This patch implements asynchronous handshake, which changes how handshakes 
>> works by default. Asynchronous handshakes
>> are target only executed, which they may never be executed. (target may 
>> block on socket for the rest of VM lifetime)
>> Since we have several use-cases for them we can have many handshake pending. 
>> (should be very rare) To be able handle an
>> arbitrary amount of handshakes this patch adds a per JavaThread queue and 
>> heap allocated HandshakeOperations. It's a
>> singly linked list where you push/insert to the end and pop/get from the 
>> front. Inserts are done via CAS on first
>> pointer, no lock needed. Pops are done while holding the per handshake state 
>> lock, and when working on the first
>> pointer also CAS.  The thread grabbing the handshake state lock for a 
>> JavaThread will pop and execute all handshake
>> operations matching the filter. The JavaThread itself uses no filter and any 
>> other thread uses the filter of everything
>> except asynchronous handshakes. In this initial change-set there is no need 
>> to do any other filtering. If needed
>> filtering can easily be exposed as a virtual method on the HandshakeClosure, 
>> but note that filtering causes handshake
>> operation to be done out-order. Since the filter determins who execute the 
>> operation and not the invoked method, there
>> is now only one method to call when handshaking one thread.  Some comments 
>> about the changes:
>> - HandshakeClosure uses ThreadClosure, since it neat to use the same closure 
>> for both alla JavThreads do and Handshake
>>   all threads. With heap allocating it cannot extends StackObj. I tested 
>> several ways to fix this, but those very much
>>   worse then this.
>> 
>> - I added a is_handshake_safe_for for checking if it's current thread is 
>> operating on itself or the handshaker of that
>>   thread.
>> 
>> - Simplified JVM TI with a JvmtiHandshakeClosure and also made them not 
>> needing a JavaThread when executing as a
>>   handshaker on a JavaThread, e.g. VM Thread can execute the handshake 
>> operation.
>> 
>> - Added WB testing method.
>> 
>> - Removed VM_HandshakeOneThread, the VM thread uses the same call path as 
>> direct handshakes did.
>> 
>> - Changed the handshake semaphores to mutex to be able to handle deadlocks 
>> with lock ranking.
>> 
>> - VM_HandshakeAllThreadsis still a VM operation, since we do support half of 
>> the threads being handshaked before a
>>   safepoint and half of them after, in many handshake all operations.
>> 
>> - ThreadInVMForHandshake do not need to do a fenced transistion since this 
>> is always a transistion from unsafe to unsafe.
>> 
>> - Added NoSafepointVerifyer, we are thinking about supporting safepoints 
>> inside handshake, but it's not needed at the
>>   moment. To make sure that gets well tested if added the 
>> NoSafepointVerifyer will raise eyebrows.
>> 
>> - Added ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id()); 
>> due to lock rank.
>> 
>> - Added filtered queue and gtest for it.
>> 
>> Passes multiple t1-8 runs.
>> Been through some pre-reviwing.
>
> Robbin Ehn has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fixed double checks
>   Added NSV
>   ProcessResult to enum
>   Fixed logging
>   Moved _active_handshaker to private

Changes look good, thanks for fixing! I added some comments on the changes.

src/hotspot/share/runtime/handshake.cpp line 464:

> 462:
> 463: const char* executioner_name(Thread* current_thread, Thread* handshakee, 
> bool current_is_requester) {
> 464:   if (current_thread == handshakee) return "self(JavaThread)";

I think we can remove this line since executioner_name() is only called by the 
handshaker.

src/hotspot/share/runtime/handshake.cpp line 508:

> 506:       assert(op->_target == NULL || _handshakee == op->_target, "Wrong 
> thread");
> 507:       log_trace(handshake)("Processing handshake " INTPTR_FORMAT " by 
> %s", p2i(op),
> 508:                            executioner_name(current_thread, _handshakee, 
> op == match_op));

With the above change we could even avoid factoring the code into 
executioner_name() and just do:
log_trace(handshake)("Processing handshake " INTPTR_FORMAT " by %s%s", p2i(op),
                                         op == match_op ? "handshaker" : 
"cooperative",
                                         current_thread->is_VM_thread() ? "(VM 
Thread)" : "(JavaThread)");

src/hotspot/share/prims/jvmtiEnvBase.cpp line 908:

> 906: #endif
> 907:   Thread* current_thread = Thread::current();
> 908:   assert(current_thread == java_thread ||

One extra check here.

src/hotspot/share/prims/jvmtiEnvBase.cpp line 1164:

> 1162: #ifdef ASSERT
> 1163:   Thread *current_thread = Thread::current();
> 1164:   assert(current_thread == thr ||

One extra check here.

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

PR: https://git.openjdk.java.net/jdk/pull/151

Reply via email to