diff options
Diffstat (limited to 'src/cs')
-rw-r--r-- | src/cs/cortex.rs | 20 | ||||
-rw-r--r-- | src/cs/dummy.rs | 18 | ||||
-rw-r--r-- | src/cs/mod.rs | 38 |
3 files changed, 76 insertions, 0 deletions
diff --git a/src/cs/cortex.rs b/src/cs/cortex.rs new file mode 100644 index 0000000..cc97a12 --- /dev/null +++ b/src/cs/cortex.rs @@ -0,0 +1,20 @@ +use super::CriticalSection; + +use cortex_m::interrupt; + +pub struct Locker {} + +impl Locker { + pub const fn new() -> Self { + Self {} + } +} + +impl CriticalSection for Locker { + fn with_lock<F, R>(&self, f: F) -> R + where + F: FnOnce() -> R, + { + interrupt::free(|_cs| f()) + } +} diff --git a/src/cs/dummy.rs b/src/cs/dummy.rs new file mode 100644 index 0000000..86f4e90 --- /dev/null +++ b/src/cs/dummy.rs @@ -0,0 +1,18 @@ +use super::CriticalSection; + +pub struct Locker {} + +impl Locker { + pub const fn new() -> Self { + Self {} + } +} + +impl CriticalSection for Locker { + fn with_lock<F, R>(&self, f: F) -> R + where + F: FnOnce() -> R, + { + f() + } +} diff --git a/src/cs/mod.rs b/src/cs/mod.rs new file mode 100644 index 0000000..8f97b6e --- /dev/null +++ b/src/cs/mod.rs @@ -0,0 +1,38 @@ +//! Critical Section support. +//! +//! Types that implement the `CriticalSection` trait can be used to +//! create critical sections to prevent data races between interrupt +//! and non-interrupt contexts. +//! +//! # Note +//! +//! Critical sections are only acquired for updating a +//! `HandlerTable`'s entries. They are *not* used when calling into a +//! closure. This is because the expected implementation of critical +//! sections turns off interrupts entirely. Given that interrupts are +//! off, it is impossible to call an ISR, and thus no data race can +//! occur. Additionally, because critcal sections are only enforced on +//! updates, deadlock is impossible between updating a `HandlerTable` +//! entry and calling into it. +//! +//! However, if you are going to implement your own `CriticalSection`, +//! you need to be aware of this limitation and its rationale to avoid +//! getting into trouble. + +/// Generic trait which supplies the ability to create a critical +/// section. +pub trait CriticalSection { + /// Execute `f` within a critical section. + fn with_lock<F, R>(&self, f: F) -> R + where + F: FnOnce() -> R; +} + +#[cfg_attr(any(all(target_arch = "arm", target_os = "none")), path = "cortex.rs")] +#[cfg_attr( + not(any(all(target_arch = "arm", target_os = "none"))), + path = "dummy.rs" +)] +mod csimpl; + +pub use csimpl::Locker; |