Thread (121 messages) 121 messages, 13 authors, 2021-09-24

Re: [RFC] LKMM: Add volatile_if()

From: Alan Stern <stern@rowland.harvard.edu>
Date: 2021-06-06 18:23:10
Also in: linux-arch, lkml

On Sun, Jun 06, 2021 at 11:04:49AM -0700, Linus Torvalds wrote:
On Sun, Jun 6, 2021 at 4:56 AM Segher Boessenkool
[off-list ref] wrote:
quoted
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.
quoted
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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help