Skip to content

Commit

Permalink
Support critical_section
Browse files Browse the repository at this point in the history
Currently untested
  • Loading branch information
kevin-vigor authored and berkus committed Nov 8, 2024
1 parent 7c817f5 commit a44b821
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ exclude = [

[dependencies]
tock-registers = { version = "0.9.0", default-features = false } # Use it as interface-only library.
critical-section = "1.1.2"

[features]
critical-section-single-core = ["critical-section/restore-state-bool"]

24 changes: 24 additions & 0 deletions src/critical_section.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use critical_section::{set_impl, Impl, RawRestoreState};

use crate::interrupt;

struct SingleCoreCriticalSection;
set_impl!(SingleCoreCriticalSection);

unsafe impl Impl for SingleCoreCriticalSection {
unsafe fn acquire() -> RawRestoreState {
let was_active = interrupt::enabled();
// NOTE: Fence guarantees are provided by interrupt::disable(), which performs a `compiler_fence(SeqCst)`.
interrupt::disable();
was_active
}

unsafe fn release(was_active: RawRestoreState) {
// Only re-enable interrupts if they were enabled before the critical section.
if was_active {
// NOTE: Fence guarantees are provided by interrupt::enable(), which performs a
// `compiler_fence(SeqCst)`.
interrupt::enable()
}
}
}
37 changes: 37 additions & 0 deletions src/interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Interrupts

#[cfg(target_arch = "aarch64")]
use crate::registers::{Readable, Writeable, DAIF};
#[cfg(target_arch = "aarch64")]
use core::sync::atomic::{compiler_fence, Ordering};

/// Disables all interrupts in the current core.
#[cfg(target_arch = "aarch64")]
#[inline]
pub fn disable() {
compiler_fence(Ordering::SeqCst);
DAIF.write(DAIF::I::Masked + DAIF::F::Masked);
compiler_fence(Ordering::SeqCst);
}

/// Enables all the interrupts in the current core.
///
/// # Safety
///
/// - Do not call this function inside a critical section.
#[cfg(target_arch = "aarch64")]
#[inline]
pub unsafe fn enable() {
compiler_fence(Ordering::SeqCst);
DAIF.write(DAIF::I::Unmasked + DAIF::F::Unmasked);
compiler_fence(Ordering::SeqCst);
}

#[cfg(target_arch = "aarch64")]
#[inline]
pub unsafe fn enabled() -> bool {
if DAIF.read(DAIF::I) == 0 || DAIF.read(DAIF::F) == 0 {
return true;
}
false
}
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,15 @@
#![no_std]

pub mod asm;
pub mod interrupt;
pub mod registers;

#[cfg(all(target_arch = "aarch64", feature = "critical-section-single-core"))]
mod critical_section;

/// Used to reexport items for use in macros. Do not use directly.
/// Not covered by semver guarantees.
#[doc(hidden)]
pub mod _export {
pub use critical_section;
}

0 comments on commit a44b821

Please sign in to comment.