555: Use cortex-m only on cortex-m archs. r=Dirbaio a=Dirbaio

Without this, build fails for iOS.

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
bors[bot] 2021-12-23 12:57:55 +00:00 committed by GitHub
commit 7561fa1934
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 70 deletions

View File

@ -29,7 +29,6 @@ executor-agnostic = []
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }
cortex-m = "0.7.3"
futures = { version = "0.3.17", default-features = false, features = [ "cfg-target-has-atomic", "unstable" ] } futures = { version = "0.3.17", default-features = false, features = [ "cfg-target-has-atomic", "unstable" ] }
pin-project = { version = "1.0.8", default-features = false } pin-project = { version = "1.0.8", default-features = false }
embassy-macros = { version = "0.1.0", path = "../embassy-macros"} embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
@ -38,12 +37,28 @@ atomic-polyfill = "0.1.5"
critical-section = "0.2.5" critical-section = "0.2.5"
embedded-hal = "0.2.6" embedded-hal = "0.2.6"
heapless = "0.7.5" heapless = "0.7.5"
cfg-if = "1.0.0"
# WASM dependencies # WASM dependencies
wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true } wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true }
js-sys = { version = "0.3", optional = true } js-sys = { version = "0.3", optional = true }
wasm-timer = { version = "0.2.5", optional = true } wasm-timer = { version = "0.2.5", optional = true }
[target."thumbv6m-none-eabi".dependencies]
cortex-m = "0.7.3"
[target."thumbv7m-none-eabi".dependencies]
cortex-m = "0.7.3"
[target."thumbv7em-none-eabi".dependencies]
cortex-m = "0.7.3"
[target."thumbv7em-none-eabihf".dependencies]
cortex-m = "0.7.3"
[target."thumbv8m.base-none-eabi".dependencies]
cortex-m = "0.7.3"
[target."thumbv8m.main-none-eabi".dependencies]
cortex-m = "0.7.3"
[target."thumbv8m.main-none-eabihf".dependencies]
cortex-m = "0.7.3"
[dev-dependencies] [dev-dependencies]
embassy = { path = ".", features = ["executor-agnostic"] } embassy = { path = ".", features = ["executor-agnostic"] }
futures-executor = { version = "0.3.17", features = [ "thread-pool" ] } futures-executor = { version = "0.3.17", features = [ "thread-pool" ] }

View File

@ -1,19 +1,20 @@
use super::{CriticalSectionMutex, Mutex, NoopMutex, ThreadModeMutex};
pub trait MutexKind { pub trait MutexKind {
type Mutex<T>: Mutex<Data = T>; type Mutex<T>: super::Mutex<Data = T>;
} }
pub enum CriticalSection {} pub enum CriticalSection {}
impl MutexKind for CriticalSection { impl MutexKind for CriticalSection {
type Mutex<T> = CriticalSectionMutex<T>; type Mutex<T> = super::CriticalSectionMutex<T>;
} }
#[cfg(any(cortex_m, feature = "std"))]
pub enum ThreadMode {} pub enum ThreadMode {}
#[cfg(any(cortex_m, feature = "std"))]
impl MutexKind for ThreadMode { impl MutexKind for ThreadMode {
type Mutex<T> = ThreadModeMutex<T>; type Mutex<T> = super::ThreadModeMutex<T>;
} }
pub enum Noop {} pub enum Noop {}
impl MutexKind for Noop { impl MutexKind for Noop {
type Mutex<T> = NoopMutex<T>; type Mutex<T> = super::NoopMutex<T>;
} }

View File

@ -62,77 +62,84 @@ impl<T> Mutex for CriticalSectionMutex<T> {
} }
} }
/// A "mutex" that only allows borrowing from thread mode. #[cfg(any(cortex_m, feature = "std"))]
/// pub use thread_mode_mutex::*;
/// # Safety #[cfg(any(cortex_m, feature = "std"))]
/// mod thread_mode_mutex {
/// **This Mutex is only safe on single-core systems.** use super::*;
///
/// On multi-core systems, a `ThreadModeMutex` **is not sufficient** to ensure exclusive access.
pub struct ThreadModeMutex<T> {
inner: UnsafeCell<T>,
}
// NOTE: ThreadModeMutex only allows borrowing from one execution context ever: thread mode. /// A "mutex" that only allows borrowing from thread mode.
// Therefore it cannot be used to send non-sendable stuff between execution contexts, so it can ///
// be Send+Sync even if T is not Send (unlike CriticalSectionMutex) /// # Safety
unsafe impl<T> Sync for ThreadModeMutex<T> {} ///
unsafe impl<T> Send for ThreadModeMutex<T> {} /// **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>,
}
impl<T> ThreadModeMutex<T> { // NOTE: ThreadModeMutex only allows borrowing from one execution context ever: thread mode.
/// Creates a new mutex // Therefore it cannot be used to send non-sendable stuff between execution contexts, so it can
pub const fn new(value: T) -> Self { // be Send+Sync even if T is not Send (unlike CriticalSectionMutex)
ThreadModeMutex { unsafe impl<T> Sync for ThreadModeMutex<T> {}
inner: UnsafeCell::new(value), 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),
}
}
/// Borrows the data
pub fn borrow(&self) -> &T {
assert!(
in_thread_mode(),
"ThreadModeMutex can only be borrowed from thread mode."
);
unsafe { &*self.inner.get() }
} }
} }
/// Borrows the data impl<T> Mutex for ThreadModeMutex<T> {
pub fn borrow(&self) -> &T { type Data = T;
assert!(
in_thread_mode(),
"ThreadModeMutex can only be borrowed from thread mode."
);
unsafe { &*self.inner.get() }
}
}
impl<T> Mutex for ThreadModeMutex<T> { fn new(data: T) -> Self {
type Data = T; Self::new(data)
}
fn new(data: T) -> Self { fn lock<R>(&self, f: impl FnOnce(&Self::Data) -> R) -> R {
Self::new(data) f(self.borrow())
}
} }
fn lock<R>(&self, f: impl FnOnce(&Self::Data) -> R) -> R { impl<T> Drop for ThreadModeMutex<T> {
f(self.borrow()) fn drop(&mut self) {
// Only allow dropping from thread mode. Dropping calls drop on the inner `T`, so
// `drop` needs the same guarantees as `lock`. `ThreadModeMutex<T>` is Send even if
// T isn't, so without this check a user could create a ThreadModeMutex in thread mode,
// send it to interrupt context and drop it there, which would "send" a T even if T is not Send.
assert!(
in_thread_mode(),
"ThreadModeMutex can only be dropped from thread mode."
);
// Drop of the inner `T` happens after this.
}
} }
}
impl<T> Drop for ThreadModeMutex<T> { pub fn in_thread_mode() -> bool {
fn drop(&mut self) { #[cfg(feature = "std")]
// Only allow dropping from thread mode. Dropping calls drop on the inner `T`, so return Some("main") == std::thread::current().name();
// `drop` needs the same guarantees as `lock`. `ThreadModeMutex<T>` is Send even if
// T isn't, so without this check a user could create a ThreadModeMutex in thread mode,
// send it to interrupt context and drop it there, which would "send" a T even if T is not Send.
assert!(
in_thread_mode(),
"ThreadModeMutex can only be dropped from thread mode."
);
// Drop of the inner `T` happens after this. #[cfg(not(feature = "std"))]
return cortex_m::peripheral::SCB::vect_active()
== cortex_m::peripheral::scb::VectActive::ThreadMode;
} }
} }
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;
}
/// A "mutex" that does nothing and cannot be shared between threads. /// A "mutex" that does nothing and cannot be shared between threads.
pub struct NoopMutex<T> { pub struct NoopMutex<T> {
inner: T, inner: T,

View File

@ -2,12 +2,25 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#[cfg_attr(feature = "std", path = "arch/std.rs")] cfg_if::cfg_if! {
#[cfg_attr(feature = "wasm", path = "arch/wasm.rs")] if #[cfg(cortex_m)] {
#[cfg_attr(not(any(feature = "std", feature = "wasm")), path = "arch/arm.rs")] #[path="arch/cortex_m.rs"]
mod arch; mod arch;
pub mod raw; pub use arch::*;
mod spawner; }
else if #[cfg(feature="wasm")] {
#[path="arch/wasm.rs"]
mod arch;
pub use arch::*;
}
else if #[cfg(feature="std")] {
#[path="arch/std.rs"]
mod arch;
pub use arch::*;
}
}
pub use arch::*; pub mod raw;
mod spawner;
pub use spawner::*; pub use spawner::*;

View File

@ -13,6 +13,7 @@ pub mod channel;
pub mod waitqueue; pub mod waitqueue;
pub mod executor; pub mod executor;
#[cfg(cortex_m)]
pub mod interrupt; pub mod interrupt;
pub mod io; pub mod io;
#[cfg(feature = "time")] #[cfg(feature = "time")]