[jmm-dev] VarHandle.safepoint() methods
Andrew Haley
aph at redhat.com
Thu Jan 5 09:35:18 UTC 2017
On 04/01/17 21:47, David Holmes wrote:
> Hi Andrew,
>
> On 5/01/2017 4:04 AM, Andrew Haley wrote:
>> This is a proposal for a new VarHandle method, but it also is an
>> extension to the Java Memory Model, so I'm starting the discussion
>> here.
>>
>> My intention is to provide an efficient way to handle the case where a
>> field has reads which outnumber writes by several orders of magnitude.
>> Once a field has been successfully modified, no thread may observe a
>> stale value. Writes to a field are expected to be very rare, and can
>> be expensive.
>>
>> It provides a secure and fast way to do something like a volatile
>> access but without any memory fences (or even any restrictions on
>> memory reordering) on the reader side.
>>
>> I propose two new VarHandle methods:
>>
>> Object getSafepoint()
>>
>> Returns the value of a variable, with memory semantics of reading as
>> if the variable was declared non-volatile, except that this load
>> shall not be reordered with a preceding safepoint.
>
> I'm no compiler guy but I would think, given the compiler has no idea
> what may lead to a safepoint, that this would have to preclude any
> reordering of any kind around the load.
We have a pretty good idea what needs to be done to the compiler to
make this work. It's not easy, but neither is it impossible.
>> static void safepoint()
>>
>> Wait for a safepoint. When this method returns, every thread in the
>> JVM shall have executed a safepoint. Ensures that loads and stores
>> before the safepoint will not be reordered with loads and stores
>> after the safepoint.
>>
>> [Note that VarHandle.safepoint() does not specify whether the VM
>> safepoints immediately or the thread waits for a safepoint which would
>> occur anyway.]
>
> So you're relying on the existence of a global synchronization point
> (aka "safepoint") in the VM and then using that to achieve "global
> synchronization" without having to do any work in the common case.
Yes.
> As an API I find that somewhat ill-defined. I would not want to see VM
> safepoints enshrined in a user-level API. Nor would I want to see a
> distinct global synchronization mechanism.
Well, the global synchronization mechanism exists already in most
JVMs, and there's not much chance of it going away. All this does
is expose it.
> In terms of implementation the existing VM safepoint mechanism has no
> means to "wait for a safepoint", but could trivially request one. I'll
> also note that we're always looking at ways to remove the need for
> global safepoints in the VM, so a request may be essential - though when
> using GuaranteedSafepointInterval a sleep of that duration would ensure
> a global safepoint has occurred.
Sure. I was thinking of a version of VarHandle.safepoint() which took a
timeout: if a safepoint didn't arrive after N seconds, force one.
>> A mechanism like this is needed in order to implement
>> MappedByteBuffer.unmap() securely and efficiently, but I think this
>> mechanism is sufficiently useful that it should be exposed as an API.
>
> I'm unclear how you deal with detecting the buffer has been unmapped
> since the call to buf() in buf().get() ? Are you also requiring that no
> safepoint can occur in that interval?
Yes, exactly. The compiler knows that there is no safepoint in that
interval.
>> From an implementation point of view, getSafepoint() is a plain read
>> except that a JIT compiler cannot reorder it with a safepoint.
>> getSafepoint() can be hoisted out of loops and doesn't inhibit
>> vectorization, so the overhead of getSafepoint() can be made extremely
>> low, and hopefully almost zero.
>
> How does a JIT know what may lead to a safepoint?
I don't know what you mean by this question. It already knows this.
> How can you hoist out of a loop if there is a safepoint check on
> each loop iteration?
You can't, but not all loops have safepoints.
Andrew.
More information about the jmm-dev
mailing list