Skip to content

Commit e3ab047

Browse files
authored
fix(interrupts): replace compiler fences with potentially-synchronizing assembly (#440)
* fix(interrupts): replace compiler fences with potentially-synchronizing 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]> * fix(interrupts): add `preserves_flags` option `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]> --------- Signed-off-by: Martin Kröning <[email protected]>
1 parent 9d1e486 commit e3ab047

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

src/instructions/interrupts.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Enabling and disabling interrupts
22
33
use core::arch::asm;
4-
use core::sync::atomic::{compiler_fence, Ordering};
54

65
/// Returns whether interrupts are enabled.
76
#[inline]
@@ -16,10 +15,10 @@ pub fn are_enabled() -> bool {
1615
/// This is a wrapper around the `sti` instruction.
1716
#[inline]
1817
pub fn enable() {
19-
// Prevent earlier writes to be moved beyond this point
20-
compiler_fence(Ordering::Release);
18+
// Omit `nomem` to imitate a lock release. Otherwise, the compiler
19+
// is free to move reads and writes through this asm block.
2120
unsafe {
22-
asm!("sti", options(nomem, nostack));
21+
asm!("sti", options(preserves_flags, nostack));
2322
}
2423
}
2524

@@ -28,10 +27,10 @@ pub fn enable() {
2827
/// This is a wrapper around the `cli` instruction.
2928
#[inline]
3029
pub fn disable() {
31-
// Prevent future writes to be moved before this point.
32-
compiler_fence(Ordering::Acquire);
30+
// Omit `nomem` to imitate a lock acquire. Otherwise, the compiler
31+
// is free to move reads and writes through this asm block.
3332
unsafe {
34-
asm!("cli", options(nomem, nostack));
33+
asm!("cli", options(preserves_flags, nostack));
3534
}
3635
}
3736

0 commit comments

Comments
 (0)