From cd4f2db97961699522873aed48ff7ca306d8a525 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 4 Mar 2024 09:09:38 -0800 Subject: [PATCH] Add optional backend for `critical-section` (#191) This is similar to the single-threaded bare metal implementations in `cortex-m` and `riscv`. In theory there could be a race condition in `acquire` if an interrupt occurs between the `read` and `write`, and the interrupt disables `IME`. But it's probably not sensible to have an interrupt disable interrupts, so I don't think it's necessarily to complicate things with inline assembly using `swp`. --- Cargo.toml | 1 + src/critical_section.rs | 18 ++++++++++++++++++ src/lib.rs | 2 ++ 3 files changed, 21 insertions(+) create mode 100644 src/critical_section.rs diff --git a/Cargo.toml b/Cargo.toml index 50099796..1ede30bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ track_caller = [] voladdress = "1.3.0" bitfrob = "1" bracer = "0.1.2" +critical-section = { version = "1.1.2", features = ["restore-state-bool"], optional = true } [profile.dev] opt-level = 3 diff --git a/src/critical_section.rs b/src/critical_section.rs new file mode 100644 index 00000000..9bcb7b1a --- /dev/null +++ b/src/critical_section.rs @@ -0,0 +1,18 @@ +use critical_section::{set_impl, Impl, RawRestoreState}; + +use crate::mmio::IME; + +struct GbaCriticalSection; +set_impl!(GbaCriticalSection); + +unsafe impl Impl for GbaCriticalSection { + unsafe fn acquire() -> RawRestoreState { + let restore = IME.read(); + IME.write(false); + restore + } + + unsafe fn release(restore: RawRestoreState) { + IME.write(restore); + } +} diff --git a/src/lib.rs b/src/lib.rs index 5a2c1094..4cd643c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,8 @@ mod macros; pub mod asm_runtime; pub mod bios; pub mod builtin_art; +#[cfg(feature = "critical-section")] +mod critical_section; pub mod dma; pub mod fixed; pub mod gba_cell;