Re: [RFC] LKMM: Add volatile_if()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jun 06, 2021 at 11:04:49AM -0700, Linus Torvalds wrote:
> On Sun, Jun 6, 2021 at 4:56 AM Segher Boessenkool
> <segher@xxxxxxxxxxxxxxxxxxx> wrote:
> >
> > And that is a simple fact, since the same assembler code (at the same
> > spot in the program) will do the same thing no matter how that ended up
> > there.
> 
> The thing is, that's exactl;y what gcc violates.
> 
> The example - you may not have been cc'd personally on that one - was
> something like
> 
>     if (READ_ONCE(a)) {
>         barrier();
>         WRITE_ONCE(b,1);
>    } else {
>         barrier();
>         WRITE_ONCE(b, 1);
>     }
> 
> and currently because gcc thinks "same exact code", it will actually
> optimize this to (pseudo-asm):
> 
>     LD A
>     "empty asm"
>     ST $1,B
> 
> which is very much NOT equivalent to
> 
>     LD A
>     BEQ over
>     "empty asm"
>     ST $1,B
>     JMP join
> 
> over:
>     "empty asm"
>     ST $1,B
> 
> join:
> 
> and that's the whole point of the barriers.
> 
> It's not equivalent exactly because of memory ordering. In the first
> case, there is no ordering on weak architectures. In the second case,
> there is always an ordering, because of CPU consistency guarantees.
> 
> And no, gcc doesn't understand about memory ordering. But that's
> exactly why we use inline asms.
> 
> > And the compiler always is allowed to duplicate, join, delete, you name
> > it, inline assembler code.  The only thing that it cares about is
> > semantics of the code, just like for any other code.
> 
> See, but it VIOLATES the semantics of the code.
> 
> You can't join those two empty asm's (and then remove the branch),
> because the semantics of the code really aren't the same any more if
> you do. Truly.

To be fair, the same argument applies even without the asm code.  The 
compiler will translate

     if (READ_ONCE(a))
         WRITE_ONCE(b, 1);
     else
         WRITE_ONCE(b, 1);

to

     LD A
     ST $1,B

intstead of

     LD A
     BEQ over
     ST $1,B
     JMP join
 
 over:
     ST $1,B
 
 join:

And these two are different for the same memory ordering reasons as 
above.

Alan



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux