On Wed, 12 May 2021 08:04:47 GMT, Robbin Ehn <r...@openjdk.org> wrote:

>> Please consider this change which removes the manual transitions to blocked.
>> This adds a preprocess template/functor which is executed in the destructor 
>> of 'ThreadBlockInVM' if we are going to do any processing.
>> This gives us a way to backout of the object/raw monitor before suspend or 
>> other processing, such as a safepoint.
>> 
>> The object monitor code could be straight forward changed to use this 
>> instead of manual transitions.
>> 
>> Raw monitors on the other hand are a bit more complicated due to 'implicit' 
>> rules (consequences of the specs).
>> Added a comment in hpp trying to explain it; we cannot simply transition 
>> with a raw monitor held.
>> This caused the change in the destructor ~ThreadInVMfromNative() (this 
>> specific change have also been tested in unrelated exploration of 
>> transition), now this RAII does the same as we do when going to native from 
>> Java, just setting the state.
>> Since we are going from an unsafe state, in VM, to a safe state, in native, 
>> we do not need to check the poll.
>> That made it possible to careful use ThreadInVMfromNative in raw monitors.
>> 
>> I also remove the early CAS in raw_enter.
>> We lock a lock to do a CAS, in the uncontended case means CAS on lock then 
>> CAS raw monitor.
>> Now we instead do a transitions, in the uncontended case means fence, CAS 
>> raw monitor, fence.
>> (multiple fence (CAS is also a fence) very close to each other have little 
>> additional performance impact on contemporary hardware)
>> 
>> Passes t1-t7 and manual stressing relevant test groups.
>
> Robbin Ehn has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fixes for Dan

Hi Robbin,

Sorry for the delay in getting through this.

Overall approach looks good. I have a few queries below and some requested 
naming changes to make things clearer.

Thanks,
David

src/hotspot/share/prims/jvmtiRawMonitor.hpp line 48:

> 46: // The rules are:
> 47: // - We must never safepoint poll if raw monitor is owned.
> 48: // - We may safepoint poll before it is owned and after it has been 
> released.

I'm not sure exactly what this is trying to say because user code can acquire a 
RawMonitor, then call into Java while holding the RawMonitor. That external use 
of RawMonitors should never cause any deadlock with the VMThread of course.

src/hotspot/share/prims/jvmtiRawMonitor.hpp line 96:

> 94:    protected:
> 95:     JvmtiRawMonitor* _rm;
> 96:     bool _rm_exit;

If this signifies the monitor exited then please name it `_rm_exited`.

src/hotspot/share/runtime/interfaceSupport.inline.hpp line 207:

> 205:     assert(_thread->thread_state() == _thread_in_vm, "coming from wrong 
> thread state");
> 206:     assert(!_thread->has_last_Java_frame() || 
> _thread->frame_anchor()->walkable(), "Unwalkable stack in vm->native 
> transition");
> 207:     _thread->set_thread_state(_thread_in_native);

After doing a heavyweight transition for many many years I find it somewhat 
disconcerting to suddenly be told it is not necessary. If we are _thread_in_vm 
and so unsafe, then no handshake/safepoint can have been processed, so there is 
nothing to check. Makes sense. But how long has that been true? Could we have 
simplified this years ago or it is a result of other changes?

src/hotspot/share/runtime/interfaceSupport.inline.hpp line 277:

> 275: class ThreadBlockInVM {
> 276:   InFlightMutexRelease _ifmr;
> 277:   ThreadBlockInVMPreprocess<InFlightMutexRelease> _tbivmpp;

Why delegate to the TBIVMPP instead of extending it?

src/hotspot/share/runtime/objectMonitor.cpp line 435:

> 433:         EnterI(current);
> 434:       }
> 435:       if (!eos.om_op_done()) {

I find this API too generic. I'd much rather see:

if (!eos.exited()) {
  assert ...
  break;
}

src/hotspot/share/runtime/objectMonitor.hpp line 309:

> 307:    protected:
> 308:     ObjectMonitor* _om;
> 309:     bool _om_op_done;

Please rename to _exited - we know what the "op" is so no need to use generic 
terminology.

src/hotspot/share/runtime/objectMonitor.hpp line 313:

> 311:     ExitOnSuspend(ObjectMonitor* om) : _om(om), _om_op_done(false) {}
> 312:     void operator()(JavaThread* current);
> 313:     bool om_op_done() { return _om_op_done; }

please rename to exited()

src/hotspot/share/runtime/objectMonitor.hpp line 315:

> 313:     bool om_op_done() { return _om_op_done; }
> 314:   };
> 315:   class ClearSuccOnSuspend : public ExitOnSuspend {

I don't see why there is any relationship between these two. You don't 
clear-succ and exit.

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

Changes requested by dholmes (Reviewer).

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

Reply via email to