diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs index 355a0f08..6c1300ae 100644 --- a/embassy-executor/src/arch/cortex_m.rs +++ b/embassy-executor/src/arch/cortex_m.rs @@ -11,27 +11,22 @@ mod thread { use crate::thread::ThreadContext; #[export_name = "__thread_mode_pender"] - fn __thread_mode_pender(_core_id: OpaqueThreadContext) { + fn __thread_mode_pender(_context: OpaqueThreadContext) { unsafe { core::arch::asm!("sev") } } /// TODO // Name pending #[derive(Default)] // Default enables Executor::new - pub struct CortexMThreadContext; + pub struct Context; - impl ThreadContext for CortexMThreadContext { + impl ThreadContext for Context { #[cfg(feature = "thread-context")] fn context(&self) -> OpaqueThreadContext { // Enabling thread-context is not incorrect, just wasteful. OpaqueThreadContext(0) } - #[cfg(not(feature = "thread-context"))] - fn context(&self) -> OpaqueThreadContext { - OpaqueThreadContext(()) - } - fn wait(&mut self) { unsafe { core::arch::asm!("wfe") } } @@ -39,7 +34,7 @@ mod thread { /// TODO // Type alias for backwards compatibility - pub type Executor = crate::thread::ThreadModeExecutor; + pub type Executor = crate::thread::ThreadModeExecutor; } // None of this has to be public, I guess? diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs index c4e772e3..08720400 100644 --- a/embassy-executor/src/arch/riscv32.rs +++ b/embassy-executor/src/arch/riscv32.rs @@ -17,27 +17,22 @@ mod thread { static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); #[export_name = "__thread_mode_pender"] - fn __thread_mode_pender(_core_id: OpaqueThreadContext) { + fn __thread_mode_pender(_context: OpaqueThreadContext) { SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); } /// TODO // Name pending #[derive(Default)] // Default enables Executor::new - pub struct RiscVThreadContext; + pub struct Context; - impl ThreadContext for RiscVThreadContext { + impl ThreadContext for Context { #[cfg(feature = "thread-context")] fn context(&self) -> OpaqueThreadContext { // Enabling thread-context is not incorrect, just wasteful. OpaqueThreadContext(0) } - #[cfg(not(feature = "thread-context"))] - fn context(&self) -> OpaqueThreadContext { - OpaqueThreadContext(()) - } - fn wait(&mut self) { // We do not care about race conditions between the load and store operations, // interrupts will only set this value to true. @@ -60,5 +55,5 @@ mod thread { /// TODO // Type alias for backwards compatibility - pub type Executor = crate::thread::ThreadModeExecutor; + pub type Executor = crate::thread::ThreadModeExecutor; } diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs index b08974a0..2731e275 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -18,11 +18,11 @@ mod thread { /// TODO // Name pending - pub struct StdThreadCtx { + pub struct Context { signaler: &'static Signaler, } - impl Default for StdThreadCtx { + impl Default for Context { fn default() -> Self { Self { signaler: &*Box::leak(Box::new(Signaler::new())), @@ -30,7 +30,7 @@ mod thread { } } - impl ThreadContext for StdThreadCtx { + impl ThreadContext for Context { fn context(&self) -> OpaqueThreadContext { OpaqueThreadContext(self.signaler as *const _ as usize) } @@ -41,8 +41,8 @@ mod thread { } #[export_name = "__thread_mode_pender"] - fn __thread_mode_pender(core_id: OpaqueThreadContext) { - let signaler: &'static Signaler = unsafe { std::mem::transmute(core_id) }; + fn __thread_mode_pender(context: OpaqueThreadContext) { + let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; signaler.signal() } @@ -76,5 +76,5 @@ mod thread { /// TODO // Type alias for backwards compatibility - pub type Executor = crate::thread::ThreadModeExecutor; + pub type Executor = crate::thread::ThreadModeExecutor; } diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs index 1097bff8..54c84202 100644 --- a/embassy-executor/src/arch/xtensa.rs +++ b/embassy-executor/src/arch/xtensa.rs @@ -15,27 +15,22 @@ mod thread { static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); #[export_name = "__thread_mode_pender"] - fn __thread_mode_pender(_core_id: OpaqueThreadContext) { + fn __thread_mode_pender(_context: OpaqueThreadContext) { SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); } /// TODO // Name pending #[derive(Default)] // Default enables Executor::new - pub struct XtensaThreadContext; + pub struct Context; - impl ThreadContext for XtensaThreadContext { + impl ThreadContext for Context { #[cfg(feature = "thread-context")] fn context(&self) -> OpaqueThreadContext { // Enabling thread-context is not incorrect, just wasteful. OpaqueThreadContext(0) } - #[cfg(not(feature = "thread-context"))] - fn context(&self) -> OpaqueThreadContext { - OpaqueThreadContext(()) - } - fn wait(&mut self) { unsafe { // Manual critical section implementation that only masks interrupts handlers. @@ -66,5 +61,5 @@ mod thread { /// TODO // Type alias for backwards compatibility - pub type Executor = crate::thread::ThreadModeExecutor; + pub type Executor = crate::thread::ThreadModeExecutor; } diff --git a/embassy-executor/src/interrupt.rs b/embassy-executor/src/interrupt.rs index c1084ea7..6f310651 100644 --- a/embassy-executor/src/interrupt.rs +++ b/embassy-executor/src/interrupt.rs @@ -7,13 +7,17 @@ use atomic_polyfill::{AtomicBool, Ordering}; use crate::raw::{self, OpaqueInterruptContext, Pender}; -/// An interrupt source that can be used to drive an [`InterruptExecutor`]. -// Name pending +/// Architecture-specific interface for an interrupt-mode executor. This trait describes what data +/// should be passed to the [`InterruptExecutor`]'s pender, and how to enable the interrupt that +/// triggers polling the executor. +// TODO: Name pending pub trait InterruptContext { - /// Creates an opaque identifier for this interrupt. + /// A pointer-sized piece of data that is passed to the pender function. + /// + /// Usually, the context contains the interrupt that should be used to wake the executor. fn context(&self) -> OpaqueInterruptContext; - /// Sets up the interrupt request. + /// Enabled the interrupt request. fn enable(&self); } @@ -36,8 +40,8 @@ pub trait InterruptContext { /// Some chips reserve some interrupts for this purpose, sometimes named "software interrupts" (SWI). /// If this is not the case, you may use an interrupt from any unused peripheral. /// -/// It is somewhat more complex to use, it's recommended to use the thread-mode -/// [`Executor`] instead, if it works for your use case. +/// It is somewhat more complex to use, it's recommended to use the +/// [`crate::thread::ThreadModeExecutor`] instead, if it works for your use case. pub struct InterruptModeExecutor { started: AtomicBool, executor: UnsafeCell>, diff --git a/embassy-executor/src/thread.rs b/embassy-executor/src/thread.rs index 2d2c6daa..f977d41e 100644 --- a/embassy-executor/src/thread.rs +++ b/embassy-executor/src/thread.rs @@ -5,13 +5,21 @@ use core::marker::PhantomData; use crate::raw::{OpaqueThreadContext, Pender}; use crate::{raw, Spawner}; -/// TODO -// Name pending +/// Architecture-specific interface for a thread-mode executor. This trait describes what the +/// executor should do when idle, and what data should be passed to its pender. +// TODO: Name pending pub trait ThreadContext: Sized { - /// TODO + /// A pointer-sized piece of data that is passed to the pender function. + /// + /// For example, on multi-core systems, this can be used to store the ID of the core that + /// should be woken up. + #[cfg(feature = "thread-context")] fn context(&self) -> OpaqueThreadContext; - /// TODO + /// Waits for the executor to be waken. + /// + /// While it is valid for this function can be empty, it is recommended to use a WFE instruction + /// or equivalent to let the CPU sleep. fn wait(&mut self); } @@ -40,11 +48,17 @@ impl ThreadModeExecutor { Self::with_context(C::default()) } - /// Create a new Executor. - pub fn with_context(context: C) -> Self { + /// Create a new Executor using the given thread context. + pub fn with_context(thread_context: C) -> Self { + #[cfg(not(feature = "thread-context"))] + let context = OpaqueThreadContext(()); + + #[cfg(feature = "thread-context")] + let context = thread_context.context(); + Self { - inner: raw::Executor::new(Pender::Thread(context.context())), - context, + inner: raw::Executor::new(Pender::Thread(context)), + context: thread_context, not_send: PhantomData, } }