aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/arch/std.rs
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2023-08-12 16:00:18 +0200
committerDániel Buga <[email protected]>2023-08-12 18:29:56 +0200
commit675b7fb6056d8c3dfaca759b7cd373e2f4a0e111 (patch)
treeef4f786edd849f9ce82cffa3b1d58e939a4f53a7 /embassy-executor/src/arch/std.rs
parent0727f8690c4684d0622547edee2cf9dc22215a9b (diff)
POC: allow custom executors
Diffstat (limited to 'embassy-executor/src/arch/std.rs')
-rw-r--r--embassy-executor/src/arch/std.rs74
1 files changed, 29 insertions, 45 deletions
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 @@
1#[cfg(feature = "executor-interrupt")] 1#[cfg(feature = "executor-interrupt")]
2compile_error!("`executor-interrupt` is not supported with `arch-std`."); 2compile_error!("`executor-interrupt` is not supported with `arch-std`.");
3 3
4#[cfg(not(feature = "thread-context"))]
5compile_error!("`arch-std` requires `thread-context`.");
6
4#[cfg(feature = "executor-thread")] 7#[cfg(feature = "executor-thread")]
5pub use thread::*; 8pub use thread::*;
6#[cfg(feature = "executor-thread")] 9#[cfg(feature = "executor-thread")]
@@ -11,65 +14,42 @@ mod thread {
11 #[cfg(feature = "nightly")] 14 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_std as main; 15 pub use embassy_macros::main_std as main;
13 16
14 use crate::raw::{Pender, PenderInner}; 17 use crate::raw::OpaqueThreadContext;
15 use crate::{raw, Spawner}; 18 use crate::thread::ThreadContext;
16
17 #[derive(Copy, Clone)]
18 pub(crate) struct ThreadPender(&'static Signaler);
19
20 impl ThreadPender {
21 #[allow(unused)]
22 pub(crate) fn pend(self) {
23 self.0.signal()
24 }
25 }
26 19
27 /// Single-threaded std-based executor. 20 /// TODO
28 pub struct Executor { 21 // Name pending
29 inner: raw::Executor, 22 pub struct StdThreadCtx {
30 not_send: PhantomData<*mut ()>, 23 _not_send: PhantomData<*mut ()>,
31 signaler: &'static Signaler, 24 signaler: &'static Signaler,
32 } 25 }
33 26
34 impl Executor { 27 impl Default for StdThreadCtx {
35 /// Create a new Executor. 28 fn default() -> Self {
36 pub fn new() -> Self {
37 let signaler = &*Box::leak(Box::new(Signaler::new())); 29 let signaler = &*Box::leak(Box::new(Signaler::new()));
38 Self { 30 Self {
39 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(signaler)))), 31 _not_send: PhantomData,
40 not_send: PhantomData,
41 signaler, 32 signaler,
42 } 33 }
43 } 34 }
35 }
44 36
45 /// Run the executor. 37 impl ThreadContext for StdThreadCtx {
46 /// 38 fn context(&self) -> OpaqueThreadContext {
47 /// The `init` closure is called with a [`Spawner`] that spawns tasks on 39 OpaqueThreadContext(self.signaler as *const _ as usize)
48 /// this executor. Use it to spawn the initial task(s). After `init` returns, 40 }
49 /// the executor starts running the tasks.
50 ///
51 /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
52 /// for example by passing it as an argument to the initial tasks.
53 ///
54 /// This function requires `&'static mut self`. This means you have to store the
55 /// Executor instance in a place where it'll live forever and grants you mutable
56 /// access. There's a few ways to do this:
57 ///
58 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
59 /// - a `static mut` (unsafe)
60 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
61 ///
62 /// This function never returns.
63 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
64 init(self.inner.spawner());
65 41
66 loop { 42 fn wait(&mut self) {
67 unsafe { self.inner.poll() }; 43 self.signaler.wait()
68 self.signaler.wait()
69 }
70 } 44 }
71 } 45 }
72 46
47 #[export_name = "__thread_mode_pender"]
48 fn __thread_mode_pender(core_id: OpaqueThreadContext) {
49 let signaler: &'static Signaler = unsafe { std::mem::transmute(core_id) };
50 signaler.signal()
51 }
52
73 struct Signaler { 53 struct Signaler {
74 mutex: Mutex<bool>, 54 mutex: Mutex<bool>,
75 condvar: Condvar, 55 condvar: Condvar,
@@ -97,4 +77,8 @@ mod thread {
97 self.condvar.notify_one(); 77 self.condvar.notify_one();
98 } 78 }
99 } 79 }
80
81 /// TODO
82 // Type alias for backwards compatibility
83 pub type Executor = crate::thread::ThreadModeExecutor<StdThreadCtx>;
100} 84}