Add CriticalSectionMutex, ThreadModeMutex.

This commit is contained in:
Dario Nieuwenhuis 2021-01-11 10:38:43 +01:00
parent 877fc0321a
commit c91882a72c
2 changed files with 77 additions and 0 deletions

View file

@ -1,11 +1,13 @@
mod drop_bomb;
mod forever;
mod mutex;
mod portal;
mod signal;
mod waker;
pub use drop_bomb::*;
pub use forever::*;
pub use mutex::*;
pub use portal::*;
pub use signal::*;
pub use waker::*;

75
embassy/src/util/mutex.rs Normal file
View file

@ -0,0 +1,75 @@
use core::cell::UnsafeCell;
use cortex_m::interrupt::CriticalSection;
use crate::fmt::{assert, panic, *};
/// A "mutex" based on critical sections
///
/// # Safety
///
/// **This Mutex is only safe on single-core systems.**
///
/// On multi-core systems, a `CriticalSection` **is not sufficient** to ensure exclusive access.
pub struct CriticalSectionMutex<T> {
inner: UnsafeCell<T>,
}
unsafe impl<T> Sync for CriticalSectionMutex<T> {}
unsafe impl<T> Send for CriticalSectionMutex<T> {}
impl<T> CriticalSectionMutex<T> {
/// Creates a new mutex
pub const fn new(value: T) -> Self {
CriticalSectionMutex {
inner: UnsafeCell::new(value),
}
}
}
impl<T> CriticalSectionMutex<T> {
/// Borrows the data for the duration of the critical section
pub fn borrow<'cs>(&'cs self, _cs: &'cs CriticalSection) -> &'cs T {
unsafe { &*self.inner.get() }
}
}
/// A "mutex" that only allows borrowing from thread mode.
///
/// # Safety
///
/// **This Mutex is only safe on single-core systems.**
///
/// On multi-core systems, a `ThreadModeMutex` **is not sufficient** to ensure exclusive access.
pub struct ThreadModeMutex<T> {
inner: UnsafeCell<T>,
}
unsafe impl<T> Sync for ThreadModeMutex<T> {}
unsafe impl<T> Send for ThreadModeMutex<T> {}
impl<T> ThreadModeMutex<T> {
/// Creates a new mutex
pub const fn new(value: T) -> Self {
ThreadModeMutex {
inner: UnsafeCell::new(value),
}
}
}
impl<T> ThreadModeMutex<T> {
/// Borrows the data
pub fn borrow(&self) -> &T {
assert!(
in_thread_mode(),
"ThreadModeMutex can only be borrowed from thread mode."
);
unsafe { &*self.inner.get() }
}
}
pub fn in_thread_mode() -> bool {
#[cfg(feature = "std")]
return Some("main") == std::thread::current().name();
#[cfg(not(feature = "std"))]
return cortex_m::peripheral::SCB::vect_active()
== cortex_m::peripheral::scb::VectActive::ThreadMode;
}