On Sat, Sep 28, 2024 at 11:55:22AM -0400, Mathieu Desnoyers wrote: > On 2024-09-28 17:49, Alan Stern wrote: > > On Sat, Sep 28, 2024 at 11:32:18AM -0400, Mathieu Desnoyers wrote: > > > On 2024-09-28 16:49, Alan Stern wrote: > > > > On Sat, Sep 28, 2024 at 09:51:27AM -0400, Mathieu Desnoyers wrote: > > > > > equality, which does not preserve address dependencies and allows the > > > > > following misordering speculations: > > > > > > > > > > - If @b is a constant, the compiler can issue the loads which depend > > > > > on @a before loading @a. > > > > > - If @b is a register populated by a prior load, weakly-ordered > > > > > CPUs can speculate loads which depend on @a before loading @a. > > > > > > > > It shouldn't matter whether @a and @b are constants, registers, or > > > > anything else. All that matters is that the compiler uses the wrong > > > > one, which allows weakly ordered CPUs to speculate loads you wouldn't > > > > expect it to, based on the source code alone. > > > > > > I only partially agree here. > > > > > > On weakly-ordered architectures, indeed we don't care whether the > > > issue is caused by the compiler reordering the code (constant) > > > or the CPU speculating the load (registers). > > > > > > However, on strongly-ordered architectures, AFAIU, only the constant > > > case is problematic (compiler reordering the dependent load), because > > > > I thought you were trying to prevent the compiler from using one pointer > > instead of the other, not trying to prevent it from reordering anything. > > Isn't this the point the documentation wants to get across when it says > > that comparing pointers can be dangerous? > > 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. > > But it turns out that ptr_eq() is also a good tool to prevent the > compiler from reordering loads in case where the comparison is > done against a constant. Isn't that the same thing? A constant pointer like &x is still a pointer. What you want to do is compare p with &x without allowing the compiler to then replace *p with *&x (or just x). > > Isn't it true that on strongly ordered CPUs, a compiler barrier is > > sufficient to prevent the rcu_dereference() problem? So the whole idea > > behind ptr_eq() is that it prevents the problem on all CPUs. > > Correct. But given that we have ptr_eq(), it's good to show how it > equally prevents the compiler from reordering address-dependent loads > (comparison with constant) *and* prevents the compiler from using > one pointer rather than the other (comparison between two non-constant > pointers) which affects speculation on weakly-ordered CPUs. I don't see how these two things differ from each other. In the comparison-with-a-constant case, how is the compiler reordering anything? Isn't it just using the constant address rather than the loaded pointer and thereby breaking the address dependency? Alan stern