Skip to content

Commit

Permalink
interrupt: Defer mask until just before branch
Browse files Browse the repository at this point in the history
This does not change the code generation, but in the actual generated
code the mask is deferred until just before the branch, like this.
Since there has been some misleading discussion about this in the past,
we will use code that more closely matches the generated code.
  • Loading branch information
taiki-e committed Oct 17, 2022
1 parent e2245ac commit 18961fa
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/imp/interrupt/armv4t.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ pub(super) fn disable() -> State {
/// Restores the previous interrupt state.
#[inline]
#[instruction_set(arm::a32)]
pub(super) unsafe fn restore(State(prev): State) {
pub(super) unsafe fn restore(State(cpsr): State) {
// SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`,
unsafe {
// Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled.
asm!("msr cpsr_c, {0}", in(reg) prev, options(nostack));
asm!("msr cpsr_c, {0}", in(reg) cpsr, options(nostack));
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/imp/interrupt/armv6m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use core::arch::asm;
pub(super) use core::sync::atomic;

#[derive(Clone, Copy)]
pub(super) struct WasEnabled(bool);
pub(super) struct State(u32);

/// Disables interrupts and returns the previous interrupt state.
#[inline]
pub(super) fn disable() -> WasEnabled {
pub(super) fn disable() -> State {
let r: u32;
// SAFETY: reading the priority mask register and disabling interrupts are safe.
// (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions)
Expand All @@ -23,13 +23,13 @@ pub(super) fn disable() -> WasEnabled {
options(nostack, preserves_flags),
);
}
WasEnabled(r & 0x1 == 0)
State(r)
}

/// Restores the previous interrupt state.
#[inline]
pub(super) unsafe fn restore(WasEnabled(was_enabled): WasEnabled) {
if was_enabled {
pub(super) unsafe fn restore(State(r): State) {
if r & 0x1 == 0 {
// SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`,
// and we've checked that interrupts were enabled before disabling interrupts.
unsafe {
Expand Down
12 changes: 6 additions & 6 deletions src/imp/interrupt/msp430.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use core::arch::asm;
pub(super) use super::super::msp430 as atomic;

#[derive(Clone, Copy)]
pub(super) struct WasEnabled(bool);
pub(super) struct State(u16);

/// Disables interrupts and returns the previous interrupt state.
#[inline]
pub(super) fn disable() -> WasEnabled {
pub(super) fn disable() -> State {
let r: u16;
// SAFETY: reading the status register and disabling interrupts are safe.
// (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions)
Expand All @@ -31,14 +31,14 @@ pub(super) fn disable() -> WasEnabled {
llvm_asm!("dint { nop" ::: "memory" : "volatile");
}
}
// GIE (global interrupt enable) bit (1 << 3)
WasEnabled(r & 0x8 != 0)
State(r)
}

/// Restores the previous interrupt state.
#[inline]
pub(super) unsafe fn restore(WasEnabled(was_enabled): WasEnabled) {
if was_enabled {
pub(super) unsafe fn restore(State(r): State) {
// GIE (global interrupt enable) bit (1 << 3)
if r & 0x8 != 0 {
// SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`,
// and we've checked that interrupts were enabled before disabling interrupts.
unsafe {
Expand Down

0 comments on commit 18961fa

Please sign in to comment.