RFR (S) 8182397: Race in field updates when creating ArrayKlasses can lead to crash

Andrew Haley aph at redhat.com
Thu Jul 27 08:58:58 UTC 2017

On 25/07/17 19:13, Erik Österlund wrote:
>> On 25 Jul 2017, at 18:57, Andrew Haley <aph at redhat.com> wrote:
>> On 25/07/17 14:41, Erik Österlund wrote:
>>> On 2017-07-25 14:42, Andrew Haley wrote:
>>>> On 25/07/17 12:13, Erik Österlund wrote:
>>>>> For example, take this example pseudo code for performing what I refer
>>>>> to as a stable load between two fields modified concurrently with
>>>>> potential ABA issues:
>>>>> loop {
>>>>>    x_start = load_relaxed(field_A)
>>>>>    y = load_consume(field_B)
>>>>>    x = load_consume(field_A)
>>>>>    if (x_start == x) break;
>>>>> }
>>>>> // use x->foo
>>>> I don't understand this pseudocode.  What is the base address for field_A
>>>> and field_B ?
>>> field_A and field_B could be two different registers pointing at 
>>> different addresses - i.e. they are arbitrary pointers. The key in this 
>>> example is that field_A is reloaded, and then we compare if the reloaded 
>>> value is equal to the original value (with a possible ABA problem), and 
>>> stop the loop then. But the original and reloaded value could reside in 
>>> different registers, and when we continue using x->foo afterwards, the 
>>> compiler could elect to use either one of the two registers as base 
>>> pointers in the dereference - either the one from the reloaded value of 
>>> field_A or for the original value, as they are equal to each other.
>> OK, I see what you're getting at.  Compilers have to be pretty
>> smart to make consume work properly.
> Precisely.

I've been thinking about this some more, and I think this example does
not have a problem after all.

loop {
   x_start = load_relaxed(field_A)
   y = load_consume(field_B)
   x = load_consume(field_A)
   if (x_start == x) break;

// use x->foo

It is true that if the compiler uses x_start instead of x to load
x->foo then there is no data dependency between the load of x and the
use of x->foo.  However, this does not matter, because the load of
x->foo is *control dependent* on load_consume(field_A), and this is
enough to keep things in order.

Sure, this would fail on some mis-specified architecture which
recognizes data dependencies but not control dependencies, but that's
their problem and they'll have to use load acquire until their
hardware spec is fixed.

Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671

More information about the hotspot-dev mailing list