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 From bce250bbdc18f025547f59c30a7bec24826b3aea Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 12 Aug 2023 22:08:46 +0200 Subject: Remove unnecessary !Send markers --- embassy-executor/src/arch/std.rs | 6 +----- 1 file changed, 1 insertion(+), 5 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 28e25fbd0..b08974a02 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -8,7 +8,6 @@ compile_error!("`arch-std` requires `thread-context`."); pub use thread::*; #[cfg(feature = "executor-thread")] mod thread { - use std::marker::PhantomData; use std::sync::{Condvar, Mutex}; #[cfg(feature = "nightly")] @@ -20,16 +19,13 @@ mod thread { /// TODO // Name pending pub struct StdThreadCtx { - _not_send: PhantomData<*mut ()>, signaler: &'static Signaler, } impl Default for StdThreadCtx { fn default() -> Self { - let signaler = &*Box::leak(Box::new(Signaler::new())); Self { - _not_send: PhantomData, - signaler, + signaler: &*Box::leak(Box::new(Signaler::new())), } } } -- cgit From 6ab0d71d9246cdc65f392212d03d639a51d21098 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 12 Aug 2023 22:42:50 +0200 Subject: Tweak identifiers and comments --- embassy-executor/src/arch/std.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 b08974a02..2731e275e 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; } -- cgit From ec6bd27df6101bc5f77fa4eace0e8963970231ad Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 14 Aug 2023 08:22:22 +0200 Subject: Remove thread-context feature --- embassy-executor/src/arch/std.rs | 3 --- 1 file changed, 3 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 2731e275e..ceaa5c7ab 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -1,9 +1,6 @@ #[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")] -- cgit From f6007869bffd3ed4f48e74222dc40d11c7c87ec0 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 14 Aug 2023 08:57:14 +0200 Subject: Remove the Pender enum --- embassy-executor/src/arch/std.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 ceaa5c7ab..d2a069d1c 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -10,7 +10,7 @@ mod thread { #[cfg(feature = "nightly")] pub use embassy_macros::main_std as main; - use crate::raw::OpaqueThreadContext; + use crate::raw::PenderContext; use crate::thread::ThreadContext; /// TODO @@ -28,8 +28,8 @@ mod thread { } impl ThreadContext for Context { - fn context(&self) -> OpaqueThreadContext { - OpaqueThreadContext(self.signaler as *const _ as usize) + fn context(&self) -> PenderContext { + self.signaler as *const _ as usize } fn wait(&mut self) { @@ -37,8 +37,8 @@ mod thread { } } - #[export_name = "__thread_mode_pender"] - fn __thread_mode_pender(context: OpaqueThreadContext) { + #[export_name = "__pender"] + fn __pender(context: PenderContext) { let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; signaler.signal() } -- cgit From 4c4b12c307bf77516299eb73f9da00ef777b9814 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 14 Aug 2023 15:16:40 +0200 Subject: Make PenderContext opaque --- embassy-executor/src/arch/std.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 d2a069d1c..d55de118d 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -29,7 +29,7 @@ mod thread { impl ThreadContext for Context { fn context(&self) -> PenderContext { - self.signaler as *const _ as usize + unsafe { core::mem::transmute(self.signaler) } } fn wait(&mut self) { -- cgit From 986a63ebb8611a4dc7c6b14e03146286942ec8e7 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 14 Aug 2023 15:35:22 +0200 Subject: Remove the non-specific thread-mode executor --- embassy-executor/src/arch/std.rs | 68 +++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 25 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 d55de118d..f490084d6 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -5,44 +5,66 @@ compile_error!("`executor-interrupt` is not supported with `arch-std`."); pub use thread::*; #[cfg(feature = "executor-thread")] mod thread { + use std::marker::PhantomData; use std::sync::{Condvar, Mutex}; #[cfg(feature = "nightly")] pub use embassy_macros::main_std as main; - use crate::raw::PenderContext; - use crate::thread::ThreadContext; + use crate::{raw, Spawner}; - /// TODO - // Name pending - pub struct Context { + #[export_name = "__pender"] + fn __pender(context: crate::raw::PenderContext) { + let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; + signaler.signal() + } + + /// Single-threaded std-based executor. + pub struct Executor { + inner: raw::Executor, + not_send: PhantomData<*mut ()>, signaler: &'static Signaler, } - impl Default for Context { - fn default() -> Self { + impl Executor { + /// Create a new Executor. + pub fn new() -> Self { + let signaler = &*Box::leak(Box::new(Signaler::new())); Self { - signaler: &*Box::leak(Box::new(Signaler::new())), + inner: raw::Executor::new(unsafe { std::mem::transmute(signaler) }), + not_send: PhantomData, + signaler, } } - } - impl ThreadContext for Context { - fn context(&self) -> PenderContext { - unsafe { core::mem::transmute(self.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()); - fn wait(&mut self) { - self.signaler.wait() + loop { + unsafe { self.inner.poll() }; + self.signaler.wait() + } } } - #[export_name = "__pender"] - fn __pender(context: PenderContext) { - let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; - signaler.signal() - } - struct Signaler { mutex: Mutex, condvar: Condvar, @@ -70,8 +92,4 @@ mod thread { self.condvar.notify_one(); } } - - /// TODO - // Type alias for backwards compatibility - pub type Executor = crate::thread::ThreadModeExecutor; } -- cgit From 995434614384bc5c218a16a026ce7c06737ca860 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 14 Aug 2023 15:59:47 +0200 Subject: Remove interrupt executor, remove PenderContext --- embassy-executor/src/arch/std.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 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 f490084d6..5b2f7e2e4 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -14,7 +14,7 @@ mod thread { use crate::{raw, Spawner}; #[export_name = "__pender"] - fn __pender(context: crate::raw::PenderContext) { + fn __pender(context: *mut ()) { let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; signaler.signal() } @@ -29,9 +29,9 @@ mod thread { impl Executor { /// Create a new Executor. pub fn new() -> Self { - let signaler = &*Box::leak(Box::new(Signaler::new())); + let signaler = Box::leak(Box::new(Signaler::new())); Self { - inner: raw::Executor::new(unsafe { std::mem::transmute(signaler) }), + inner: raw::Executor::new(signaler as *mut Signaler as *mut ()), not_send: PhantomData, signaler, } -- cgit