[cpp-threads] RE: Memory model formalism, again
Boehm, Hans
hans.boehm at hp.com
Thu Dec 15 22:02:35 GMT 2005
> From: Jeremy Manson [mailto:jmanson at cs.purdue.edu]
>
> Hi Hans,
>
> Thanks for including me on this - I don't know how helpful I
> will be, as
> I don't really have access to information about what the requirements
> for the C++ MM are. But I'm happy to look at it.
>
> Boehm, Hans wrote:
> > 1) (I think this is roughly a reuse of something Peter suggested a
> > long time ago in a different context.) We define an atomic
> store in a
> > given thread to depend on an (earlier in thread ordering)
> atomic load
> > if by altering only the value seen by that load, the store
> (i.e. the
> > value, location, or existence) is altered. (This is
> informal, but I
> > think unambiguous and easily formalizable. It is independent of
> > compiler dependence analysis, or the hardware's notion of
> dependence.)
>
> This is a little tricky, although perhaps not terminally so.
> It looks
> as if you are going for a model where you are given an
> execution E, and
> then validate its correctness. To do so, you need to, for
> every atomic
> load, generate an execution E' where that atomic load sees another
> value. How do you generate E'?
>
> The issue here is that you need E and E' to be as similar as
> possible,
> and you need a way to make sure that the atomic load in E'
> corresponds
> to the atomic load in E. If you don't do this, it can cause
> problems.
> Here's an artificial example:
>
> Thread 1:
> r1 = read input from keyboard
> if (r1 == 1)
> r2 = v;
> w = 42;
> else {
> r2 = v;
> if (r2 == 42)
> w = 42;
> }
>
> Thread 2:
> r3 = w;
> if (r3 == 42)
> v = 42;
>
> If, in E, r1 == 0, but in all E' your method generates, r1 ==
> 1, you can
> claim that w = 42 is not dependent on r2 = v.
>
> This is a fairly stupid example (it's late and I don't feel
> like working
> out a better one :) ), but you should see where I am going. An
> iterative formulation (as per the JMM's commit sets) seems to work.
Thanks for the response.
I agree that this is a bit tricky, but I would also argue that it's not
terminally so, as you put it. I would define actions as including the
(position of) the corresponding source statement. You can then also
talk about valid executions of a single thread. (I do this in
http://www.hpl.hp.com/techreports/2005/HPL-2005-217.html, and I think
you may want to anyway to make intra-thread constraints explicit. It's
admittedly more complicated here, since in the tech report I carefully
talk only about sequentially consistent executions.) In this context I
think you can talk about single-thread executions that differ only in
the value returned by a single, potentially inter-thread, load.
The result still seems considerably simpler to me than the iterative
formulation. And there seems to be a non-misleading informal version of
the statement, which is probably want we want in the standard.
>
> As for the rest, I can't really evaluate it without knowing
> what are and
> are not acceptable outcomes for atomics. I would urge you to look at
> Causality Test Case 17, though, as I suspect that your intent would
> disallow it, and I am not sure you want to do that (although
> maybe you
> do, given that we are talking about atomics).
That's an interesting example to look at.
Let's reinterpret all loads and stores in test case 17 of
http://www.cs.umd.edu/~pugh/java/memoryModel/CausalityTestCases.html as
atomic and unordered operations.
Adding some line numbers, we get
Initially, x = y = 0
Thread 1:
1: r3 = x
2: if (r3 != 42)
3: x = 42
4: r1 = x
5: y = r1
Thread 2:
6: r2 = y
7: x = r2
Can r1 = r2 = r3 = 42? (r3 is the interesting one.)
By my posted rules, 1 happens-before 3, 4 happens-before 5, and 6
happens-before 7. For the outcome to occur,
1 would have to see 7, 4 would have to see 3, and 6 would have to see 5.
Thus 7 hb 1 hb 3 hb 4 hb 5 hb 6 hb 7, and we have a cycle. Thus this is
indeed disallowed. This means we can't do constant propagation on
thread 1 and transform it to
Thread 1':
1: r3 = x
2: if (r3 != 42)
3: x = 42
5: y = 42
Given our current context, I wouldn't be far less upset about that than
in the Java context. I doubt anyone does constant propagations through
volatile stores and loads now, which would be the closest analog.
But I think we can actually arrange to get the other answer, assuming we
want it. If we say that the fact that a load sees a store induces a hb
relationship only across threads, not within a thread, then we no longer
have 3 hb 4, and I think the questionable outcome becomes allowable. I
think that has the right effect of allowing intra-thread analysis by not
enforcing implicit intra-thread visibility orders, and it's probably
what I should have said. But it would be good to think about this more.
>
> Jeremy
>
>
>
More information about the cpp-threads
mailing list