RFR: 7143664: Clean up OrderAccess implementations and usage

David Holmes david.holmes at oracle.com
Mon Feb 9 07:14:23 UTC 2015

On 29/01/2015 8:48 AM, David Holmes wrote:
> Updated webrev:
> http://cr.openjdk.java.net/~dholmes/7143664/webrev.v2/

First let me say that Erik and I had a lot of offline discussions about 
this since he first proposed his reworking. My initial concern was 
ensuring the model changes were appropriate as this is a complex area 
and there can be different views of how things can/should be expressed. 
As per the bug report I was aware of a number of issues with the 
existing expression of semantics, but Erik showed me things were even 
worse than I had thought :)

Basically the definitions of stand-alone release() and acquire() as they 
currently are in orderAccess.hpp are somewhat broken. "release" 
semantics must establish a barrier between accesses prior to the 
release() and a specific store after the release - hence release_store() 
and similarly for acquire() and a preceding load, hence load_acquire(). 
The general definitions of acquire() and release() as one-way movement 
barriers don't provide useful semantics - in part because regardless of 
which way you move things once everything is on the same side of the 
barrier you can't tell in which direction they moved. :)

Further, those general definitions would imply that release_store() and 
release();store are semantically very different - but they are currently 
implemented (as are things like release_store_fence) as if semantically 
the same.

And finally, while orderAccess.hpp suggests that release() can be 
implemented by a storeStore|loadStore barrier, there is code throughout 
the VM that expects it is exactly a storeStore|storeload barrier. (And 
similarly for acquire). C1 for example explicitly defines:

membar_acquire := LoadLoad + LoadStore
membar_release := LoadStore + StoreStore
membar         := StoreLoad (aka fence)

and if I then look at where "release" is used in the codebase they all 
seem incorrect based on "release" semantics, but correct if you expect 
release() to mean LoadStore|StoreStore (and in most cases you would then 
actually use a release_store).

So the changes Erik proposes to ensure that release() and acquire() are 
defined with respect to that subsequent-store or preceding-load, bring 
expectations in the code back into alignment. It means release(); store 
is the same as release_store() semantically, and the latter is a means 
for optimizing when you place the barrier and the store directly 
together - where often you can't because the actual store/load may be 
buried within other accessor methods eg:

java_lang_Thread::set_xxx(threadobj, value);

We can fix that by adding set_with_release/load_with_acquire, or passing 
in barrier enums C++11 style, but that is a lot of rework.

On the implementation side I'm a template novice and was originally 
skeptical about the technique, but having implemented it for a couple of 
platforms I'm now a fan - even if I couldn't walk you through the exact 
behaviour of the template specialization code :)

So on to the actual review comments ...



Minor nit: I would prefer the term "bound" rather than "joined" when 
referring to load_acquire and store_release.

In the implementation table I think "sparc" should be "sparc TSO".

I still think we need to say something about C++ volatile and about 
compiler barriers in general.



No comment



No comment (this just removes stale/unused terminology)



No comments - ppc64 folk need to review these.



In OrderAccess::fence doesn't the existing asm already act as a compiler 
barrier; and on uniprocessor we need neither compiler nor hardware 
barriers; so isn't the compiler_barrier() redundant?



No comments - The Zero folk will need to approve this change in terminology.



No comments.



You've removed the GNU_SOURCE ifdefs which means the new code has to be 
tested using gcc on Solaris. We don't officially support that platform 
so I have no way to verify these particular changes.



I think it makes sense to use the same code here as the linux x86 
version. But as above can't verify this for gcc on Solaris; also query 
about need for compiler_barrier() in fence().


Same comment about fence() and compiler_barrier() :)

Do you have a reference to the MSVC volatile semantics?

Not clear about the 32-bit versus 64-bit changes - mainly because I 
don't know why they were different in the first place.

Why are windows release_store_fence specializations different to linux 
x86 versions?

Not clear about your change to the float version of release_store_fence:
a) do we need to change it?
b) given what we changed it to isn't that the default ?


General comment: copyright dates need updating in most, if not all, files.


More information about the hotspot-dev mailing list