-
Notifications
You must be signed in to change notification settings - Fork 148
fix(interrupts): replace compiler fences with potentially-synchronizing assembly #440
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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 <martin.kroening@eonerc.rwth-aachen.de>
`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 <martin.kroening@eonerc.rwth-aachen.de>
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