RFR: 8266557: assert(SafepointMechanism::local_poll_armed(_handshakee)) failed: Must be [v3]

Daniel D.Daugherty dcubed at openjdk.java.net
Thu Jun 3 16:11:48 UTC 2021


On Wed, 2 Jun 2021 09:20:11 GMT, Robbin Ehn <rehn at openjdk.org> wrote:

>> src/hotspot/share/runtime/handshake.cpp line 429:
>> 
>>> 427:   assert(_handshakee == Thread::current(), "Must be called by self");
>>> 428:   assert(_lock.owned_by_self(), "Lock must be held");
>>> 429:   return _queue.peek();
>> 
>> `get_op_for_self()` name does not match the `peek()` operation.
>> The new name should be `peek_op_for_self()`.
>
> The method retrieves the next operation to be executed, hence 'get'.
> That the method uses a queue which provides a pop() and peek() is an implementation, there is no value for the user of  get_op_for_self() to know how this is done?

Agreed there is no value in that distinction. I was having trouble getting my head
wrapped around what the code was trying to do.

>> src/hotspot/share/runtime/handshake.cpp line 445:
>> 
>>> 443:   assert(_handshakee != Thread::current(), "Must not be called by self");
>>> 444:   assert(_lock.owned_by_self(), "Lock must be held");
>>> 445:   return _queue.peek(non_self_queue_filter);
>> 
>> `get_op()` name does not match the peek() operation.
>> The new name should be `peek_op()`.
>
> The method retrieves the next operation to be executed, hence 'get'.
> That the method uses a queue which provides a pop() and peek() is an implementation, there is no value for the user of  get_op_for_self() to know how this is done?

Agreed.

>> src/hotspot/share/runtime/handshake.cpp line 452:
>> 
>>> 450:   MatchOp mo(op);
>>> 451:   HandshakeOperation* ret = _queue.pop(mo);
>>> 452:   assert(ret == op, "OP missing from queue");
>> 
>> Perhaps this for the assert() mesg:
>> `  assert(ret == op, "popped op must match requested op.");
>> 
>> Also, I would name this one `pop_op()` instead of `remove_op()`.
>
> Changed assert.
> 
> In the handshake code we need two operation get operation and remove operation.
> They happen to be implemented with peek and pop.
> So from the user perspective he wants to remove an operation and thus uses the remove method.
> Since we do not want any return from this method, renaming it pop and not return anything is just confusing, isn't it?

Agreed.

>> src/hotspot/share/runtime/handshake.cpp line 483:
>> 
>>> 481:         HandleMark hm(_handshakee);
>>> 482:         PreserveExceptionMark pem(_handshakee);
>>> 483:         op->do_handshake(_handshakee); // acquire, op removed after
>> 
>> Why `acquire`? Perhaps:
>> `// peek and handshake with op; op removed after`
>
> It's mean do_handshake provide acquire thus op is removed after.

Ok.

>> src/hotspot/share/runtime/handshake.cpp line 489:
>> 
>>> 487:         // The destructor ~PreserveExceptionMark touches the exception oop so it must not be executed,
>>> 488:         // since a safepoint may be in-progress when returning from the async handshake.
>>> 489:         op->do_handshake(_handshakee); // acquire, op removed after
>> 
>> Why acquire? Perhaps:
>> // peek and handshake with op; op removed after
>
> It's mean do_handshake provide acquire thus op is removed after.

Ok.

>> src/hotspot/share/runtime/handshake.cpp line 583:
>> 
>>> 581: 
>>> 582:   set_active_handshaker(current_thread);
>>> 583:   op->do_handshake(_handshakee); // acquire, op removed after
>> 
>> Why acquire? Perhaps:
>> // peek and handshake with op; op removed after
>
> It's mean do_handshake provide acquire thus op is removed after.

Ok.

>> src/hotspot/share/utilities/filterQueue.inline.hpp line 127:
>> 
>>> 125:   do {
>>> 126:     if (match_func(cur->_data)) {
>>> 127:       match = cur;
>> 
>> Hmmm.... I was expecting a break after this match.
>> Is there a reason to continue the loop?
>> 
>> But now I'm realizing that I'm confused since this is called `peek()`, but
>> it's not really peeking at the head of the queue. It is searching the entire
>> queue for a match.
>
> It is a FIFO queue, which provides inserts at the end (push) and retrieves at the front of the queue (pop/peek).
> Push inserts at tail and pop/peek looks at head. (maybe these should be named differently to reflect this better, but that is another PR :) )
> 
> To provide lock-free inserts the queue only have a tail pointer.
> This enabled us to do concurrent inserts with other inserts and/or another serialized operation, such as peek.
> To get to the front of the queue we must always walk until the end.
> 
> This means peek is peeking at the head (with a filter).
> Conceptually we generate a queue from that filter and from that virtual queue we peek at it's head.
> 
> Tail->A1->A2->A3->A4->A5
> Filter = even
> Virtual tail->A2->A4
> Virtual head = A4
> 
> To get to A4 we walk and apply the filter, the last match will be the head we are looking to peek at.

So it's not just find _a_ match. It is find the _last_ match. OK.

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

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


More information about the hotspot-runtime-dev mailing list