On Sep 30, 2024, at 17:33, Jonas Oberhauser <jonas.oberhauser@xxxxxxxxxxxxxxx> wrote: > > > > Am 9/30/2024 um 11:27 AM schrieb Alan Huang: >> 2024年9月30日 17:15,Alan Huang <mmpgouride@xxxxxxxxx> 写道: >>> >>> 2024年9月30日 16:57,Jonas Oberhauser <jonas.oberhauser@xxxxxxxxxxxxxxx> 写道: >>>> >>>> >>>> >>>> Am 9/29/2024 um 12:26 AM schrieb Alan Huang: >>>>> 2024年9月28日 23:55,Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx> wrote: >>>>>> >>>>>> The motivation for introducing ptr_eq() is indeed because the >>>>>> compiler barrier is not sufficient to prevent the compiler from >>>>>> using one pointer instead of the other. >>>>> barrier_data(&b) prevents that. >>>> >>>> I don't think one barrier_data can garantuee preventing this, because right after doing the comparison, the compiler still could do b=a. >>>> >>>> In that case you would be guaranteed to use the value in b, but that value is not the value loaded into b originally but rather the value loaded into a, and hence your address dependency goes to the wrong load still. >>> >>> After barrier_data(&b), *b will be loaded from memory, you mean even if *b is loaded from memory, the address dependency goes to the wrong load still? >> Sorry, *b should b. > > That's exactly what I meant to say. In my understanding, it can happen like this: > > a = READ_ONCE(*p); > ... > b = READ_ONCE(*p); > if (a == b) { > b = a; // inserted by compiler > > barrier_data(&b); > > foo(*b); // compiler definitely use the current value in b > } > > > > In the end, the address dependency is from the first load, and the CPU can speculatively (with register renaming, forwarding etc) execute > > a = READ_ONCE(*p); > b2 = a; // speculatively > tmp = load *b2 // speculatively > b1 = READ_ONCE(*p); > if (a == b1) { // confirmed > foo(tmp); > } I get it now, thanks for the explanation. > > > best wishes, > jonas >