From 675b7fb6056d8c3dfaca759b7cd373e2f4a0e111 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 12 Aug 2023 16:00:18 +0200 Subject: POC: allow custom executors --- embassy-executor/src/arch/std.rs | 74 ++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 45 deletions(-) (limited to 'embassy-executor/src/arch/std.rs') diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs index 4e4a178f0..28e25fbd0 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -1,6 +1,9 @@ #[cfg(feature = "executor-interrupt")] compile_error!("`executor-interrupt` is not supported with `arch-std`."); +#[cfg(not(feature = "thread-context"))] +compile_error!("`arch-std` requires `thread-context`."); + #[cfg(feature = "executor-thread")] pub use thread::*; #[cfg(feature = "executor-thread")] @@ -11,65 +14,42 @@ mod thread { #[cfg(feature = "nightly")] pub use embassy_macros::main_std as main; - use crate::raw::{Pender, PenderInner}; - use crate::{raw, Spawner}; - - #[derive(Copy, Clone)] - pub(crate) struct ThreadPender(&'static Signaler); - - impl ThreadPender { - #[allow(unused)] - pub(crate) fn pend(self) { - self.0.signal() - } - } + use crate::raw::OpaqueThreadContext; + use crate::thread::ThreadContext; - /// Single-threaded std-based executor. - pub struct Executor { - inner: raw::Executor, - not_send: PhantomData<*mut ()>, + /// TODO + // Name pending + pub struct StdThreadCtx { + _not_send: PhantomData<*mut ()>, signaler: &'static Signaler, } - impl Executor { - /// Create a new Executor. - pub fn new() -> Self { + impl Default for StdThreadCtx { + fn default() -> Self { let signaler = &*Box::leak(Box::new(Signaler::new())); Self { - inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(signaler)))), - not_send: PhantomData, + _not_send: PhantomData, signaler, } } + } - /// Run the executor. - /// - /// The `init` closure is called with a [`Spawner`] that spawns tasks on - /// this executor. Use it to spawn the initial task(s). After `init` returns, - /// the executor starts running the tasks. - /// - /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), - /// for example by passing it as an argument to the initial tasks. - /// - /// This function requires `&'static mut self`. This means you have to store the - /// Executor instance in a place where it'll live forever and grants you mutable - /// access. There's a few ways to do this: - /// - /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) - /// - a `static mut` (unsafe) - /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) - /// - /// This function never returns. - pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { - init(self.inner.spawner()); + impl ThreadContext for StdThreadCtx { + fn context(&self) -> OpaqueThreadContext { + OpaqueThreadContext(self.signaler as *const _ as usize) + } - loop { - unsafe { self.inner.poll() }; - self.signaler.wait() - } + fn wait(&mut self) { + self.signaler.wait() } } + #[export_name = "__thread_mode_pender"] + fn __thread_mode_pender(core_id: OpaqueThreadContext) { + let signaler: &'static Signaler = unsafe { std::mem::transmute(core_id) }; + signaler.signal() + } + struct Signaler { mutex: Mutex, condvar: Condvar, @@ -97,4 +77,8 @@ mod thread { self.condvar.notify_one(); } } + + /// TODO + // Type alias for backwards compatibility + pub type Executor = crate::thread::ThreadModeExecutor; } -- cgit