aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/thread.rs')
-rw-r--r--embassy-executor/src/thread.rs87
1 files changed, 0 insertions, 87 deletions
diff --git a/embassy-executor/src/thread.rs b/embassy-executor/src/thread.rs
deleted file mode 100644
index 8ff4071da..000000000
--- a/embassy-executor/src/thread.rs
+++ /dev/null
@@ -1,87 +0,0 @@
1//! Thread-mode executor.
2
3use core::marker::PhantomData;
4
5use crate::raw::{self, PenderContext};
6use crate::Spawner;
7
8/// Architecture-specific interface for a thread-mode executor. This trait describes what the
9/// executor should do when idle, and what data should be passed to its pender.
10// TODO: Name pending
11pub trait ThreadContext: Sized {
12 /// A pointer-sized piece of data that is passed to the pender function.
13 ///
14 /// For example, on multi-core systems, this can be used to store the ID of the core that
15 /// should be woken up.
16 fn context(&self) -> PenderContext;
17
18 /// Waits for the executor to be waken.
19 ///
20 /// While it is valid for this function can be empty, it is recommended to use a WFE instruction
21 /// or equivalent to let the CPU sleep.
22 fn wait(&mut self);
23}
24
25/// Thread mode executor, using WFE/SEV.
26///
27/// This is the simplest and most common kind of executor. It runs on
28/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction
29/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction
30/// is executed, to make the `WFE` exit from sleep and poll the task.
31///
32/// This executor allows for ultra low power consumption for chips where `WFE`
33/// triggers low-power sleep without extra steps. If your chip requires extra steps,
34/// you may use [`raw::Executor`] directly to program custom behavior.
35pub struct ThreadModeExecutor<C: ThreadContext> {
36 inner: raw::Executor,
37 context: C,
38 not_send: PhantomData<*mut ()>,
39}
40
41impl<C: ThreadContext> ThreadModeExecutor<C> {
42 /// Create a new Executor.
43 pub fn new() -> Self
44 where
45 C: Default,
46 {
47 Self::with_context(C::default())
48 }
49
50 /// Create a new Executor using the given thread context.
51 pub fn with_context(context: C) -> Self {
52 Self {
53 inner: raw::Executor::new(context.context()),
54 context,
55 not_send: PhantomData,
56 }
57 }
58
59 /// Run the executor.
60 ///
61 /// The `init` closure is called with a [`Spawner`] that spawns tasks on
62 /// this executor. Use it to spawn the initial task(s). After `init` returns,
63 /// the executor starts running the tasks.
64 ///
65 /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
66 /// for example by passing it as an argument to the initial tasks.
67 ///
68 /// This function requires `&'static mut self`. This means you have to store the
69 /// Executor instance in a place where it'll live forever and grants you mutable
70 /// access. There's a few ways to do this:
71 ///
72 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
73 /// - a `static mut` (unsafe)
74 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
75 ///
76 /// This function never returns.
77 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
78 init(self.inner.spawner());
79
80 loop {
81 unsafe {
82 self.inner.poll();
83 self.context.wait();
84 };
85 }
86 }
87}