aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2023-08-14 08:57:14 +0200
committerDániel Buga <[email protected]>2023-08-14 09:00:08 +0200
commitf6007869bffd3ed4f48e74222dc40d11c7c87ec0 (patch)
treebd8e1afe8d0a959a52ddcb75bdc30988a7d1615e /embassy-executor
parent454a7cbf4c0eb3a4e651e7da5512ec49ff7d4050 (diff)
Remove the Pender enum
Diffstat (limited to 'embassy-executor')
-rw-r--r--embassy-executor/src/arch/cortex_m.rs103
-rw-r--r--embassy-executor/src/arch/riscv32.rs10
-rw-r--r--embassy-executor/src/arch/std.rs10
-rw-r--r--embassy-executor/src/arch/wasm.rs6
-rw-r--r--embassy-executor/src/arch/xtensa.rs8
-rw-r--r--embassy-executor/src/interrupt.rs6
-rw-r--r--embassy-executor/src/raw/mod.rs48
-rw-r--r--embassy-executor/src/thread.rs8
8 files changed, 98 insertions, 101 deletions
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
index a29e5b23e..7f8a97ef1 100644
--- a/embassy-executor/src/arch/cortex_m.rs
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -1,28 +1,84 @@
1#[cfg(feature = "executor-thread")] 1#[cfg(feature = "executor-thread")]
2pub use thread::*; 2pub use thread::*;
3 3
4use crate::raw::PenderContext;
5
6#[cfg(feature = "executor-interrupt")]
7
8/// # Safety
9///
10/// `irq` must be a valid interrupt request number
11unsafe fn nvic_pend(irq: u16) {
12 use cortex_m::interrupt::InterruptNumber;
13
14 #[derive(Clone, Copy)]
15 struct Irq(u16);
16 unsafe impl InterruptNumber for Irq {
17 fn number(self) -> u16 {
18 self.0
19 }
20 }
21
22 let irq = Irq(irq);
23
24 // STIR is faster, but is only available in v7 and higher.
25 #[cfg(not(armv6m))]
26 {
27 let mut nvic: cortex_m::peripheral::NVIC = unsafe { core::mem::transmute(()) };
28 nvic.request(irq);
29 }
30
31 #[cfg(armv6m)]
32 cortex_m::peripheral::NVIC::pend(irq);
33}
34
35#[cfg(all(feature = "executor-thread", feature = "executor-interrupt"))]
36#[export_name = "__pender"]
37fn __pender(context: PenderContext) {
38 unsafe {
39 // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
40 // request number given to `InterruptExecutor::start`.
41 if context as usize == usize::MAX {
42 core::arch::asm!("sev")
43 } else {
44 nvic_pend(context as u16)
45 }
46 }
47}
48
49#[cfg(all(feature = "executor-thread", not(feature = "executor-interrupt")))]
50#[export_name = "__pender"]
51fn __pender(_context: PenderContext) {
52 unsafe { core::arch::asm!("sev") }
53}
54
55#[cfg(all(not(feature = "executor-thread"), feature = "executor-interrupt"))]
56#[export_name = "__pender"]
57fn __pender(context: PenderContext) {
58 unsafe {
59 // Safety: `context` is the same value we passed to `InterruptExecutor::start`, which must
60 // be a valid interrupt request number.
61 nvic_pend(context as u16)
62 }
63}
64
4#[cfg(feature = "executor-thread")] 65#[cfg(feature = "executor-thread")]
5mod thread { 66mod thread {
6 67
7 #[cfg(feature = "nightly")] 68 #[cfg(feature = "nightly")]
8 pub use embassy_macros::main_cortex_m as main; 69 pub use embassy_macros::main_cortex_m as main;
9 70
10 use crate::raw::OpaqueThreadContext; 71 use crate::raw::PenderContext;
11 use crate::thread::ThreadContext; 72 use crate::thread::ThreadContext;
12 73
13 #[export_name = "__thread_mode_pender"]
14 fn __thread_mode_pender(_context: OpaqueThreadContext) {
15 unsafe { core::arch::asm!("sev") }
16 }
17
18 /// TODO 74 /// TODO
19 // Name pending 75 // Name pending
20 #[derive(Default)] // Default enables Executor::new 76 #[derive(Default)] // Default enables Executor::new
21 pub struct Context; 77 pub struct Context;
22 78
23 impl ThreadContext for Context { 79 impl ThreadContext for Context {
24 fn context(&self) -> OpaqueThreadContext { 80 fn context(&self) -> PenderContext {
25 OpaqueThreadContext(0) 81 usize::MAX
26 } 82 }
27 83
28 fn wait(&mut self) { 84 fn wait(&mut self) {
@@ -35,7 +91,6 @@ mod thread {
35 pub type Executor = crate::thread::ThreadModeExecutor<Context>; 91 pub type Executor = crate::thread::ThreadModeExecutor<Context>;
36} 92}
37 93
38// None of this has to be public, I guess?
39#[cfg(feature = "executor-interrupt")] 94#[cfg(feature = "executor-interrupt")]
40pub use interrupt::*; 95pub use interrupt::*;
41#[cfg(feature = "executor-interrupt")] 96#[cfg(feature = "executor-interrupt")]
@@ -44,23 +99,14 @@ mod interrupt {
44 use cortex_m::peripheral::NVIC; 99 use cortex_m::peripheral::NVIC;
45 100
46 use crate::interrupt::InterruptContext; 101 use crate::interrupt::InterruptContext;
47 use crate::raw::OpaqueInterruptContext; 102 use crate::raw::PenderContext;
48
49 #[derive(Clone, Copy)]
50 struct CortexMInterruptContext(u16);
51
52 unsafe impl cortex_m::interrupt::InterruptNumber for CortexMInterruptContext {
53 fn number(self) -> u16 {
54 self.0
55 }
56 }
57 103
58 impl<T> InterruptContext for T 104 impl<T> InterruptContext for T
59 where 105 where
60 T: InterruptNumber, 106 T: InterruptNumber,
61 { 107 {
62 fn context(&self) -> OpaqueInterruptContext { 108 fn context(&self) -> PenderContext {
63 OpaqueInterruptContext(self.number() as usize) 109 self.number() as usize
64 } 110 }
65 111
66 fn enable(&self) { 112 fn enable(&self) {
@@ -68,21 +114,6 @@ mod interrupt {
68 } 114 }
69 } 115 }
70 116
71 #[export_name = "__interrupt_mode_pender"]
72 fn __interrupt_mode_pender(interrupt: OpaqueInterruptContext) {
73 let interrupt = CortexMInterruptContext(unsafe { core::mem::transmute::<_, usize>(interrupt) as u16 });
74
75 // STIR is faster, but is only available in v7 and higher.
76 #[cfg(not(armv6m))]
77 {
78 let mut nvic: NVIC = unsafe { core::mem::transmute(()) };
79 nvic.request(interrupt);
80 }
81
82 #[cfg(armv6m)]
83 NVIC::pend(interrupt);
84 }
85
86 /// TODO 117 /// TODO
87 // Type alias for backwards compatibility 118 // Type alias for backwards compatibility
88 pub type InterruptExecutor = crate::interrupt::InterruptModeExecutor; 119 pub type InterruptExecutor = crate::interrupt::InterruptModeExecutor;
diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs
index 976e7bcb3..886056e84 100644
--- a/embassy-executor/src/arch/riscv32.rs
+++ b/embassy-executor/src/arch/riscv32.rs
@@ -10,14 +10,14 @@ mod thread {
10 #[cfg(feature = "nightly")] 10 #[cfg(feature = "nightly")]
11 pub use embassy_macros::main_riscv as main; 11 pub use embassy_macros::main_riscv as main;
12 12
13 use crate::raw::OpaqueThreadContext; 13 use crate::raw::PenderContext;
14 use crate::thread::ThreadContext; 14 use crate::thread::ThreadContext;
15 15
16 /// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV 16 /// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
17 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); 17 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
18 18
19 #[export_name = "__thread_mode_pender"] 19 #[export_name = "__pender"]
20 fn __thread_mode_pender(_context: OpaqueThreadContext) { 20 fn __thread_mode_pender(_context: PenderContext) {
21 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); 21 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
22 } 22 }
23 23
@@ -27,8 +27,8 @@ mod thread {
27 pub struct Context; 27 pub struct Context;
28 28
29 impl ThreadContext for Context { 29 impl ThreadContext for Context {
30 fn context(&self) -> OpaqueThreadContext { 30 fn context(&self) -> PenderContext {
31 OpaqueThreadContext(0) 31 0
32 } 32 }
33 33
34 fn wait(&mut self) { 34 fn wait(&mut self) {
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 {
10 #[cfg(feature = "nightly")] 10 #[cfg(feature = "nightly")]
11 pub use embassy_macros::main_std as main; 11 pub use embassy_macros::main_std as main;
12 12
13 use crate::raw::OpaqueThreadContext; 13 use crate::raw::PenderContext;
14 use crate::thread::ThreadContext; 14 use crate::thread::ThreadContext;
15 15
16 /// TODO 16 /// TODO
@@ -28,8 +28,8 @@ mod thread {
28 } 28 }
29 29
30 impl ThreadContext for Context { 30 impl ThreadContext for Context {
31 fn context(&self) -> OpaqueThreadContext { 31 fn context(&self) -> PenderContext {
32 OpaqueThreadContext(self.signaler as *const _ as usize) 32 self.signaler as *const _ as usize
33 } 33 }
34 34
35 fn wait(&mut self) { 35 fn wait(&mut self) {
@@ -37,8 +37,8 @@ mod thread {
37 } 37 }
38 } 38 }
39 39
40 #[export_name = "__thread_mode_pender"] 40 #[export_name = "__pender"]
41 fn __thread_mode_pender(context: OpaqueThreadContext) { 41 fn __pender(context: PenderContext) {
42 let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; 42 let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
43 signaler.signal() 43 signaler.signal()
44 } 44 }
diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs
index c393722b2..634f48d1a 100644
--- a/embassy-executor/src/arch/wasm.rs
+++ b/embassy-executor/src/arch/wasm.rs
@@ -14,11 +14,11 @@ mod thread {
14 use wasm_bindgen::prelude::*; 14 use wasm_bindgen::prelude::*;
15 15
16 use crate::raw::util::UninitCell; 16 use crate::raw::util::UninitCell;
17 use crate::raw::{OpaqueThreadContext, Pender}; 17 use crate::raw::PenderContext;
18 use crate::{raw, Spawner}; 18 use crate::{raw, Spawner};
19 19
20 #[export_name = "__thread_mode_pender"] 20 #[export_name = "__thread_mode_pender"]
21 fn __thread_mode_pender(context: OpaqueThreadContext) { 21 fn __thread_mode_pender(context: PenderContext) {
22 let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) }; 22 let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) };
23 let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() }); 23 let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() });
24 } 24 }
@@ -49,7 +49,7 @@ mod thread {
49 pub fn new() -> Self { 49 pub fn new() -> Self {
50 let ctx = &*Box::leak(Box::new(WasmContext::new())); 50 let ctx = &*Box::leak(Box::new(WasmContext::new()));
51 Self { 51 Self {
52 inner: raw::Executor::new(Pender::Thread(OpaqueThreadContext(ctx as *const _ as usize))), 52 inner: raw::Executor::new(ctx as *const _ as usize),
53 ctx, 53 ctx,
54 not_send: PhantomData, 54 not_send: PhantomData,
55 } 55 }
diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs
index 28abf352c..3986c6c19 100644
--- a/embassy-executor/src/arch/xtensa.rs
+++ b/embassy-executor/src/arch/xtensa.rs
@@ -8,14 +8,14 @@ mod thread {
8 use core::marker::PhantomData; 8 use core::marker::PhantomData;
9 use core::sync::atomic::{AtomicBool, Ordering}; 9 use core::sync::atomic::{AtomicBool, Ordering};
10 10
11 use crate::raw::OpaqueThreadContext; 11 use crate::raw::PenderContext;
12 use crate::thread::ThreadContext; 12 use crate::thread::ThreadContext;
13 13
14 /// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa 14 /// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
15 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); 15 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
16 16
17 #[export_name = "__thread_mode_pender"] 17 #[export_name = "__thread_mode_pender"]
18 fn __thread_mode_pender(_context: OpaqueThreadContext) { 18 fn __thread_mode_pender(_context: PenderContext) {
19 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); 19 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
20 } 20 }
21 21
@@ -25,8 +25,8 @@ mod thread {
25 pub struct Context; 25 pub struct Context;
26 26
27 impl ThreadContext for Context { 27 impl ThreadContext for Context {
28 fn context(&self) -> OpaqueThreadContext { 28 fn context(&self) -> PenderContext {
29 OpaqueThreadContext(0) 29 0
30 } 30 }
31 31
32 fn wait(&mut self) { 32 fn wait(&mut self) {
diff --git a/embassy-executor/src/interrupt.rs b/embassy-executor/src/interrupt.rs
index 6f310651b..28a1cd525 100644
--- a/embassy-executor/src/interrupt.rs
+++ b/embassy-executor/src/interrupt.rs
@@ -5,7 +5,7 @@ use core::mem::MaybeUninit;
5 5
6use atomic_polyfill::{AtomicBool, Ordering}; 6use atomic_polyfill::{AtomicBool, Ordering};
7 7
8use crate::raw::{self, OpaqueInterruptContext, Pender}; 8use crate::raw::{self, PenderContext};
9 9
10/// Architecture-specific interface for an interrupt-mode executor. This trait describes what data 10/// Architecture-specific interface for an interrupt-mode executor. This trait describes what data
11/// should be passed to the [`InterruptExecutor`]'s pender, and how to enable the interrupt that 11/// should be passed to the [`InterruptExecutor`]'s pender, and how to enable the interrupt that
@@ -15,7 +15,7 @@ pub trait InterruptContext {
15 /// A pointer-sized piece of data that is passed to the pender function. 15 /// A pointer-sized piece of data that is passed to the pender function.
16 /// 16 ///
17 /// Usually, the context contains the interrupt that should be used to wake the executor. 17 /// Usually, the context contains the interrupt that should be used to wake the executor.
18 fn context(&self) -> OpaqueInterruptContext; 18 fn context(&self) -> PenderContext;
19 19
20 /// Enabled the interrupt request. 20 /// Enabled the interrupt request.
21 fn enable(&self); 21 fn enable(&self);
@@ -104,7 +104,7 @@ impl InterruptModeExecutor {
104 unsafe { 104 unsafe {
105 (&mut *self.executor.get()) 105 (&mut *self.executor.get())
106 .as_mut_ptr() 106 .as_mut_ptr()
107 .write(raw::Executor::new(Pender::Interrupt(irq.context()))) 107 .write(raw::Executor::new(irq.context()))
108 } 108 }
109 109
110 let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; 110 let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 81ad1e53d..a0a940e25 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -292,54 +292,20 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
292} 292}
293 293
294/// Context given to the thread-mode executor's pender. 294/// Context given to the thread-mode executor's pender.
295#[repr(transparent)] 295pub type PenderContext = usize;
296#[derive(Clone, Copy)]
297pub struct OpaqueThreadContext(pub(crate) usize);
298
299/// Context given to the interrupt-mode executor's pender.
300#[derive(Clone, Copy)]
301#[repr(transparent)]
302pub struct OpaqueInterruptContext(pub(crate) usize);
303 296
304/// Platform/architecture-specific action executed when an executor has pending work.
305///
306/// When a task within an executor is woken, the `Pender` is called. This does a
307/// platform/architecture-specific action to signal there is pending work in the executor.
308/// When this happens, you must arrange for [`Executor::poll`] to be called.
309///
310/// You can think of it as a waker, but for the whole executor.
311#[derive(Clone, Copy)] 297#[derive(Clone, Copy)]
312pub enum Pender { 298pub(crate) struct Pender(PenderContext);
313 /// Pender for a thread-mode executor.
314 #[cfg(feature = "executor-thread")]
315 Thread(OpaqueThreadContext),
316
317 /// Pender for an interrupt-mode executor.
318 #[cfg(feature = "executor-interrupt")]
319 Interrupt(OpaqueInterruptContext),
320}
321 299
322unsafe impl Send for Pender {} 300unsafe impl Send for Pender {}
323unsafe impl Sync for Pender {} 301unsafe impl Sync for Pender {}
324 302
325impl Pender { 303impl Pender {
326 pub(crate) fn pend(self) { 304 pub(crate) fn pend(self) {
327 match self { 305 extern "Rust" {
328 #[cfg(feature = "executor-thread")] 306 fn __pender(context: PenderContext);
329 Pender::Thread(core_id) => {
330 extern "Rust" {
331 fn __thread_mode_pender(core_id: OpaqueThreadContext);
332 }
333 unsafe { __thread_mode_pender(core_id) };
334 }
335 #[cfg(feature = "executor-interrupt")]
336 Pender::Interrupt(interrupt) => {
337 extern "Rust" {
338 fn __interrupt_mode_pender(interrupt: OpaqueInterruptContext);
339 }
340 unsafe { __interrupt_mode_pender(interrupt) };
341 }
342 } 307 }
308 unsafe { __pender(self.0) };
343 } 309 }
344} 310}
345 311
@@ -499,9 +465,9 @@ impl Executor {
499 /// When the executor has work to do, it will call the [`Pender`]. 465 /// When the executor has work to do, it will call the [`Pender`].
500 /// 466 ///
501 /// See [`Executor`] docs for details on `Pender`. 467 /// See [`Executor`] docs for details on `Pender`.
502 pub fn new(pender: Pender) -> Self { 468 pub fn new(context: PenderContext) -> Self {
503 Self { 469 Self {
504 inner: SyncExecutor::new(pender), 470 inner: SyncExecutor::new(Pender(context)),
505 _not_sync: PhantomData, 471 _not_sync: PhantomData,
506 } 472 }
507 } 473 }
diff --git a/embassy-executor/src/thread.rs b/embassy-executor/src/thread.rs
index ef703003d..8ff4071da 100644
--- a/embassy-executor/src/thread.rs
+++ b/embassy-executor/src/thread.rs
@@ -2,8 +2,8 @@
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5use crate::raw::{OpaqueThreadContext, Pender}; 5use crate::raw::{self, PenderContext};
6use crate::{raw, Spawner}; 6use crate::Spawner;
7 7
8/// Architecture-specific interface for a thread-mode executor. This trait describes what the 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. 9/// executor should do when idle, and what data should be passed to its pender.
@@ -13,7 +13,7 @@ pub trait ThreadContext: Sized {
13 /// 13 ///
14 /// For example, on multi-core systems, this can be used to store the ID of the core that 14 /// For example, on multi-core systems, this can be used to store the ID of the core that
15 /// should be woken up. 15 /// should be woken up.
16 fn context(&self) -> OpaqueThreadContext; 16 fn context(&self) -> PenderContext;
17 17
18 /// Waits for the executor to be waken. 18 /// Waits for the executor to be waken.
19 /// 19 ///
@@ -50,7 +50,7 @@ impl<C: ThreadContext> ThreadModeExecutor<C> {
50 /// Create a new Executor using the given thread context. 50 /// Create a new Executor using the given thread context.
51 pub fn with_context(context: C) -> Self { 51 pub fn with_context(context: C) -> Self {
52 Self { 52 Self {
53 inner: raw::Executor::new(Pender::Thread(context.context())), 53 inner: raw::Executor::new(context.context()),
54 context, 54 context,
55 not_send: PhantomData, 55 not_send: PhantomData,
56 } 56 }