atomicity for value types

John Rose john.r.rose at
Mon Jan 13 22:03:35 UTC 2020

On Jan 13, 2020, at 1:44 PM, Tobi Ajila <Tobi_Ajila at> wrote:
> Hi John
> Given that inline types can be flattened there is a possibility that data races will occur in places where users were not expecting it before. So your `__AlwaysAtomic` modifier is a necessary tool as the existing spec will only enforce atomicity for 32bit primitives and references. I just want to confirm if the intention of the __AlwaysAtomic bit on an inline class is only to ensure atomic reads and writes of inline types and that there are no happens-before ordering expectations as there are with the existing volatile modifier on fields.

Confirmed; thanks for taking the time to raise the question clearly.

It really isn’t “always volatile”; that would be a different and much less
useful feature.

> For example:
> ```
> __AlwaysAtomic inline class Long256 { long v1, v2, v3 ,v4; … }
> class Example {
> Long256 bigLong;
> int x;
> int y;
> void method() {
> Long256 newLong = new Long256(1, 2, 3, 4);
> x = 1;
> //compiler is still free to re-order write to bigLong with respect
> //to writes to x and y, but the write to bigLong must be done atomically
> bigLong = newLong;
> y = 2;
> }
> }
> ```
> Does this match your expectations?

Yes, it does.

> The reason I ask is because of the "Protection is “as if” each field were volatile" wording in your previous note. Does this only speak to the atomicity properties of the volatile modifier? Or do you intend further constraints?

No further constraints beyond simple atomicity of the individual
load or store.  In particular no new ordering constraints with other
loads or stores.

The only special atomicity properties of volatile I’m appealing to
are those which apply to long and double.  Those are the properties
I am seeking to extend to value types, both those marked “volatile”
at the use site of the type, and those marked “alwaysatomic” at the
declaration site of the type.

But now that you ask… there are *old* ordering constraints which
are relevant.

I expect, because an inline type’s fields are always final, that
storing an inline value containing a pointer to a new object will
safely publish that new object.  This rule in the JMM may need
to be clarified.  In effect, if an inline object contains a pointer,
storing it should include a previous store-store ordering
constraint, or some other implementation of the JMM
“freeze” operation at the end of the inline’s constructor.

Make sense?

— John

P.S.  After writing unit tests for “alwaysatomic” I found tearing
race conditions in HotSpot which were wrong for all inline types,
and not just “alwaysatomic”.  In particular, if the JVM ever secretly
buffers a value onto the heap, it should issue a store-store barrier
before publishing the secret reference.  This may happen, for example,
when an inline value is stored in an Object variable.  I’m mentioning
this in case you have a similar issue in J9.  We had enough complicated
paths in the HotSpot prototype that in some cases the store-store
barrier was not being emitted, causing wrong execution.

See also this thread about surprise tearing, and why it’s wrong:

More information about the valhalla-spec-observers mailing list