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

Re: [RFC] LKMM: Add volatile_if()

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2021-06-06 18:11:23
Also in: linux-arch, lkml

On Sun, Jun 6, 2021 at 4:56 AM Segher Boessenkool
[off-list ref] 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.

              Linus
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help