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