On Tue, Sep 15, 2015 at 2:33 PM, Mark Thomas <ma...@apache.org> wrote:

> On 15/09/2015 21:51, Yilong Li wrote:
> > On Tue, Sep 15, 2015 at 1:09 PM, Mark Thomas <ma...@apache.org> wrote:
> >
> >> On 15/09/2015 20:42, Caldarale, Charles R wrote:
> >>>> From: Mark Thomas [mailto:ma...@apache.org]
> >>>> Subject: Re: RV-Predict bugs
> >>>
> >>>> Putting it into my own words to check my understanding:
> >>>
> >>>> - The two reads in T2 may be re-ordered because, in T2, there is
> nothing
> >>>>   that requires a happens-before relationship between the two reads
> >>>
> >>> Depends on what was really meant by the ??? notation.  If it were
> >> another reference to st_200, then the example ignores the potential
> write
> >> to st_200.
> >>>
> >>>> - If T2 was executing in isolation the order of the reads wouldn't
> >>>>   matter
> >>>
> >>> Correct, assuming there is no write in T2's control flow.
> >>>
> >>>> - However, T1 is writing.
> >>>
> >>>> So if the writes
> >>>
> >>> I'll assume you meant "reads" there.
> >>
> >> I'd did. Thanks.
> >>
> >>>> in T2 are re-ordered and the write from T1 takes place between them
> the
> >> T2
> >>>> read for the line 'st_200 == null' could return a non-null value for
> >> st_200
> >>>> (the value after the write from T1) while the read for the line
> 'return
> >>>> st_200;' could return null (the value from before the write in T1).
> >>>
> >>> No - that would violate program order (intra-thread semantics).  The
> >> compiler cannot legally move the read for "return st_200" to a point
> before
> >> the potential write to st_200.  The CPU can speculatively read for the
> >> return value, but must discard such speculation if a write were to occur
> >> (or use store forwarding to update the read).
> >>
> >> Thanks for sticking with me on this. I'm finding it hugely helpful. I
> >> think I need a few more references to make things clearer so I'm going
> >> to restate the problem.
> >>
> >> st_200 is non-volatile
> >>
> >> L1 if (st_200 == null ) {
> >> L2    st_200 = sm.getString("sc.200");
> >> L3 }
> >> L4 return st_200;
> >>
> >> Ln=Line n
> >> Tx=Thread x
> >> Rn=Read at line n
> >> Wn=Write at line n
> >>
> >> So T2 has two reads, T2R1 and T2R4.
> >> Depending on the value read for T2R1 there may be a write at T2W2.
> >> If there is a write there is a happens before relationship between T2R1
> >> and T2R4.
> >>
> >> Consider the following sequence
> >>
> >> T2R4 (out of order read returns null)
> >> T1R1 (returns null)
> >> T1W2 (writes non-null value)
> >> T1R4 (reads new non-null value)
> >> T2R1 (reads new non-null value)
> >>
> >> Because T2R1 reads a non-null value there is no write in T2.
> >> Therefore there is no happens-before relationship between T2R1 and T2R4
> >> because there is no intervening write in that thread (the write happens
> >> in T1).
> >> Therefore the re-ordering is allowed to happen.
> >> And we get the unexpected result.
> >>
> >> Or
> >>
> >> The write at T1W2 is sufficient to enforce the happens before
> >> relationship between T2R1 and T2R4. In which case what is the point of
> >> volatile? What do I gain by using it?
> >>
> >
> > Again, as I mentioned in my previous message, I am afraid this is not the
> > correct way to use HB relationship. To make things more clear, I steal
> this
> > transformation from Jeremy Manson's article I sent before:
>
> That doesn't help my improve my understanding at all.
>
> What I'm looking for is an explanation - ideally using my example above
> - of exactly how T2R4 can return null while T2R1 reads a non-null value.
> "Because the JMM says it can" is not a sufficient explanation.  I
> believe that the JMM says it can but I don't understand how this can
> actually happen. What I am looking for is the explanation of how. Your
> message at 16.59 (UTC) was heading in the right direction but the
> explanation skipped over the crucial part.
>

Fine. Let's do your example:
T2R4 (out of order read returns null)
T1R1 (returns null)
T1W2 (writes non-null value)
T1R4 (reads new non-null value)
T2R1 (reads new non-null value)

First of all, when reasoning with JMM, you should not move T2R4 to the
front. This is forbidden by the intra-thread semantics so I move it back to
the bottom:
T1R1 (returns null)
T1W2 (writes non-null value)
T1R4 (reads new non-null value)
T2R1 (reads new non-null value)
T2R4 (out of order read returns null)

Intra-thread semantics ensures the following HB order:
T1R1 < T2W2 < T1R4
T2R1 < T2R4

T2R4 is allowed to read null because 1) T2R4 is not ordered before the
write of null (let's call it INIT) by JVM during object initialization; and
2) there is no intervening write w' such that INIT < w' < T2R4. You see,
T1W2 is *not* an intervening write because there is no HB order between
T1W2 & T2R4.

Let me know if it is still not clear enough.

Yilong


> Providing the explanation of how is the difference between:
> a) a bug being theoretically valid based on the JMM but a practically
> never going to happen because JVMs aren't written that way
> vs.
> b) a bug that can happen with current JVMs.
>
> We care a lot more about b) than we do a). And we may choose to not to
> care at all about a).
>
> Assuming the answer is b) then there is potentially a wider benefit if a
> clear explanation of the why can be provided since that is the sort of
> thing that makes it a lot easier to convince people there is a real
> problem they need to fix.
>
> Mark
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: dev-h...@tomcat.apache.org
>
>

Reply via email to