-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(interrupts): replace compiler fences with potentially-synchronizing assembly #440
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than some minor formatting, looks good to me. I trust @RalfJung that this will do the right thing w.r.t. compiler memory ordering (although I do wish we just had a way to say "volatile" like in C).
Not sure what you mean? We have Generally I'm not an expert on the concrete implementation of inline assembly, I just know how to deal with it in the abstract, in theory. But I think rust-lang/reference#1413 documents what you need? |
Oh I was referring to GCC's Thanks for the pointers. |
Oh you meant asm-block |
…ng assembly Compiler fences only synchronize with atomic instructions. When creating a thread-local critical section, we need to prevent reordering of any reads and writes across interrupt toggles, not just atomic ones. To achieve this, we omit `nomem` from `asm!`. Since then, the assembly might potentially perform synchronizing operations such as acquiring or releasing a lock, the compiler won't move any reads and writes through these assembly blocks. Signed-off-by: Martin Kröning <[email protected]>
`IF` from `EFLAGS` must not be restored upon exiting the asm block. https://doc.rust-lang.org/stable/reference/inline-assembly.html#rules-for-inline-assembly Signed-off-by: Martin Kröning <[email protected]>
010568a
to
745e7fc
Compare
I adjusted the formatting. 👍 |
The previous implementation using compiler fences was already correct (modulo a small bug: the fence should have been after the |
That only synchronizes with atomic operations, though. This PR specifically aims to prevent any reordering through these assembly blocks. |
The |
But the compiler does not analyze what's inside the And even if both |
Yeah I don't see how a |
Follow up on #436.
I am sorry to open this discussion again, but the previous PR is not sufficient to prevent unexpected behavior.
Compiler fences only synchronize with atomic instructions. When creating a thread-local critical section, we need to prevent reordering of any reads and writes across interrupt toggles, not just atomic ones. To achieve this, we omit
nomem
fromasm!
. Since then, the assembly might potentially perform synchronizing operations such as acquiring or releasing a lock, the compiler won't move any reads and writes through these assembly blocks.See mkroening/interrupt-ref-cell#5 (comment).
As an unrelated optimization, I also added
preserves_flags
here, sinceIF
fromEFLAGS
must not be restored upon exiting theasm
block when specifyingperserves_flags
: Rules for inline assembly—Inline assembly—The Rust Reference