Merge pull request #137 from lulf/generic-critical-section

Allow signals to be used when building for std
This commit is contained in:
Dario Nieuwenhuis 2021-04-12 13:45:34 +02:00 committed by GitHub
commit 75337fdf39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 4 deletions

View File

@ -26,3 +26,5 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
embassy-traits = { version = "0.1.0", path = "../embassy-traits"} embassy-traits = { version = "0.1.0", path = "../embassy-traits"}
atomic-polyfill = { version = "0.1.1" } atomic-polyfill = { version = "0.1.1" }
# Workaround https://github.com/japaric/cast.rs/pull/27
cast = { version = "=0.2.3", default-features = false }

View File

@ -0,0 +1,30 @@
pub use cs::{critical_section, CriticalSection};
#[cfg(feature = "std")]
mod cs {
static INIT: std::sync::Once = std::sync::Once::new();
static mut BKL: Option<std::sync::Mutex<()>> = None;
pub type CriticalSection = std::sync::MutexGuard<'static, ()>;
pub fn critical_section<F, R>(f: F) -> R
where
F: FnOnce(&CriticalSection) -> R,
{
INIT.call_once(|| unsafe {
BKL.replace(std::sync::Mutex::new(()));
});
let guard = unsafe { BKL.as_ref().unwrap().lock().unwrap() };
f(&guard)
}
}
#[cfg(not(feature = "std"))]
mod cs {
pub use cortex_m::interrupt::CriticalSection;
pub fn critical_section<F, R>(f: F) -> R
where
F: FnOnce(&CriticalSection) -> R,
{
cortex_m::interrupt::free(f)
}
}

View File

@ -5,6 +5,7 @@ mod mutex;
mod on_drop; mod on_drop;
mod portal; mod portal;
mod signal; mod signal;
mod critical_section;
#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] #[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
mod waker; mod waker;
@ -16,6 +17,7 @@ pub use on_drop::*;
pub use portal::*; pub use portal::*;
pub use signal::*; pub use signal::*;
pub use waker::*; pub use waker::*;
pub use critical_section::*;
pub trait PeripheralBorrow { pub trait PeripheralBorrow {
type Target; type Target;

View File

@ -11,6 +11,7 @@ use ptr::NonNull;
use crate::executor; use crate::executor;
use crate::fmt::panic; use crate::fmt::panic;
use crate::interrupt::{Interrupt, InterruptExt}; use crate::interrupt::{Interrupt, InterruptExt};
use crate::util::critical_section::critical_section;
/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. /// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks.
/// ///
@ -37,7 +38,7 @@ impl<T: Send> Signal<T> {
/// Mark this Signal as completed. /// Mark this Signal as completed.
pub fn signal(&self, val: T) { pub fn signal(&self, val: T) {
cortex_m::interrupt::free(|_| unsafe { critical_section(|_| unsafe {
let state = &mut *self.state.get(); let state = &mut *self.state.get();
if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) {
waker.wake(); waker.wake();
@ -46,14 +47,14 @@ impl<T: Send> Signal<T> {
} }
pub fn reset(&self) { pub fn reset(&self) {
cortex_m::interrupt::free(|_| unsafe { critical_section(|_| unsafe {
let state = &mut *self.state.get(); let state = &mut *self.state.get();
*state = State::None *state = State::None
}) })
} }
pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
cortex_m::interrupt::free(|_| unsafe { critical_section(|_| unsafe {
let state = &mut *self.state.get(); let state = &mut *self.state.get();
match state { match state {
State::None => { State::None => {
@ -77,7 +78,7 @@ impl<T: Send> Signal<T> {
/// non-blocking method to check whether this signal has been signaled. /// non-blocking method to check whether this signal has been signaled.
pub fn signaled(&self) -> bool { pub fn signaled(&self) -> bool {
cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) critical_section(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
} }
} }