[jmm-dev] State of play with modeling relaxed memory

Alan Jeffrey ajeffrey at bell-labs.com
Mon Mar 17 17:39:22 UTC 2014


The rule would be something like the following...

s satisfies constrains whenever, for any valid permutation of s, and an 
action a in that permutation, the previous action is compatible with a.

This depends on a notion of compatibility of actions, which would be 
something like (W x=v) is incompatible with (C x:V) whenever v not in V.

This definition (together with the old one) seems to allow TC1 and TC8 
but not TC9 or TC 18. It doesn't allow thin-air reads.

The main annoyance I've spotted so far is that it doesn't validate an 
optimization which replaces a read by the value last written by the same 
thread, for example:

Thread 1: r1=x; x=2; r3=x; if(r3==2){ y=1; }
Thread 2: r2=y; x=r2;

The execution where r1==r2==1 isn't allowed because the constraint 
action (C x:{2}) isn't compatible with the visible write action (W x=1) 
from thread 2. Really you should be able to optimize (x=2; r3=x; P) to 
(x=2; r3=2; P), which would allow the y to be reordered.

This could probably be patched, but at the cost of extra complexity to 
the model.

A.

On 03/17/2014 12:06 PM, Doug Lea wrote:
> On 03/17/2014 10:59 AM, Alan Jeffrey wrote:
>> The way I can imagine rescuing the Mazurkeiwicz trace semantics is by
>> introducing something like constraint actions (C x:V) which constrains
>> x to only
>> have values from V. The semantics of read would then be:
>>
>>    sum_V (C x:V) . sum_(v in V) (R x=v) . P
>>
>> The requirements for a valid execution would then include that for any
>> constraint action (C x:V) and any visible write action (W x=w), we
>> have w in V.
>
> Have you thought about the rules for resolving constraints?
> On the one hand, you'd like some self-referentialness.
> On the other hand: cycles.
>
> -Doug
>
>> Such a model should support TC1 since the semantics of thread 1 would be:
>>
>>    sum_V (C x:V) . Q_V
>>
>> where:
>>
>>    Q_V = sum(v in V) (R x=v) . P_v
>>    P_+n = (W y=1)
>>    P_-n = 0
>>
>> In particular:
>>
>>    Q_{0,1}
>>      = sum(v in {0,1}) (R x=v) . P_v
>>      = sum(v in {0,1}) (R x=v) . (W y=1)
>>      = (W y=1) . sum(v in {0,1}) (R x=v)
>>
>> which allows the write action to move before the read, and the rest is
>> routine.
>>
>> James and I sketched out such a model, but abandoned it because it was
>> looking
>> pretty cumbersome with its additional constraint actions. It might be
>> worth
>> rescuing if the alternatives are looking just as inelegant though.
>>
>> A.
>>
>> On 03/15/2014 01:23 PM, Doug Lea wrote:
>>> On 03/12/2014 10:19 AM, Alan Jeffrey wrote:
>>>> Ah yes, I owe the world a status report...
>>>>
>>>> I looked into modeling relaxed memory using Mazurkeiwicz traces, that
>>>> is strings
>>>> of actions up to appropriate reorderings. My main result here is
>>>> negative, in
>>>> that you can build a model of memory, and get it to support
>>>> speculative write,
>>>> in that:
>>>>
>>>>                r=x; y=1  ==  y=1; r=x
>>>>    if(b){y=1;}else{y=1;} == y=1
>>>>
>>>> The justification for speculative write is:
>>>>
>>>>    sum_i a_i . b . P  ==  b . sum_i a_i . P
>>>>
>>>> when b is independent of every a_i. The problem with this model is
>>>> that it only
>>>> supports a speculative write w when every branch performs w. In
>>>> particular, it
>>>> doesn't support causality test case 1:
>>>>
>>>>    thread 1: r1 = x; if (r1 >= 0) { y = 1; }
>>>>    thread 2: r2 = y; x = r2;
>>>>
>>>> The trace semantics of thread 1 is:
>>>>
>>>>    P = sum_v (R x=v) . P_v
>>>>
>>>> where
>>>>
>>>>    P_+n = (W y=1)
>>>>    P_-n = 0
>>>>
>>>> Since some P_v doesn't perform (W y=1), P can't perform (W y=1) before
>>>> (R x=v).
>>>>
>>>> So, assuming that TC1 (and similar examples) still stands, I don't see
>>>> how to
>>>> get a Mazurkeiwicz trace model to fly.
>>>
>>> Where TC1 is from
>>> http://www.cs.umd.edu/~pugh/java/memoryModel/unifiedProposal/testcases.html
>>>
>>>
>>> The "human" rationale given for allowing r1 == r2 == 1 is that,
>>> via whole program analysis, a compiler could determine that
>>> x and y are always non-negative. Given this, TC1 acts as:
>>>    thread 1: r1 = x; y = 1;
>>>    thread 2: r2 = y; x = r2;
>>> which seems unchallenging.
>>>
>>> You'd think that any memory model that handled this sort of case
>>> would explicitly incorporate/allow the global analysis that led to
>>> its rationale. RAO does so. It's surprising that the JSR133
>>> model doesn't, but we don't think this generalizes completely.
>>>
>>> So, it is not clear to me that you've shown a fatal flaw in Mazurkeiwicz
>>> trace based mechanics per se.
>>>
>>> -Doug
>>>
>>
>


More information about the jmm-dev mailing list