aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2023-08-14 15:59:47 +0200
committerDániel Buga <[email protected]>2023-08-14 16:04:11 +0200
commit995434614384bc5c218a16a026ce7c06737ca860 (patch)
tree961131c33677aad1ec1ff33daf69b716d104ef10
parent3a51e2d9cae6fad2fd903c07634b4a66de59b3bf (diff)
Remove interrupt executor, remove PenderContext
-rw-r--r--embassy-executor/src/arch/cortex_m.rs9
-rw-r--r--embassy-executor/src/arch/riscv32.rs4
-rw-r--r--embassy-executor/src/arch/std.rs6
-rw-r--r--embassy-executor/src/arch/wasm.rs7
-rw-r--r--embassy-executor/src/arch/xtensa.rs4
-rw-r--r--embassy-executor/src/interrupt.rs131
-rw-r--r--embassy-executor/src/lib.rs5
-rw-r--r--embassy-executor/src/raw/mod.rs17
8 files changed, 19 insertions, 164 deletions
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
index 2ed70dd1e..8fe5644d7 100644
--- a/embassy-executor/src/arch/cortex_m.rs
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -2,12 +2,12 @@ const THREAD_PENDER: usize = usize::MAX;
2 2
3#[export_name = "__pender"] 3#[export_name = "__pender"]
4#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))] 4#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))]
5fn __pender(context: crate::raw::PenderContext) { 5fn __pender(context: *mut ()) {
6 unsafe { 6 unsafe {
7 // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt 7 // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
8 // request number given to `InterruptExecutor::start`. 8 // request number given to `InterruptExecutor::start`.
9 9
10 let context: usize = core::mem::transmute(context); 10 let context = context as usize;
11 11
12 #[cfg(feature = "executor-thread")] 12 #[cfg(feature = "executor-thread")]
13 if context == THREAD_PENDER { 13 if context == THREAD_PENDER {
@@ -75,7 +75,7 @@ mod thread {
75 /// Create a new Executor. 75 /// Create a new Executor.
76 pub fn new() -> Self { 76 pub fn new() -> Self {
77 Self { 77 Self {
78 inner: raw::Executor::new(unsafe { core::mem::transmute(THREAD_PENDER) }), 78 inner: raw::Executor::new(THREAD_PENDER as *mut ()),
79 not_send: PhantomData, 79 not_send: PhantomData,
80 } 80 }
81 } 81 }
@@ -205,10 +205,9 @@ mod interrupt {
205 } 205 }
206 206
207 unsafe { 207 unsafe {
208 let context = core::mem::transmute(irq.number() as usize);
209 (&mut *self.executor.get()) 208 (&mut *self.executor.get())
210 .as_mut_ptr() 209 .as_mut_ptr()
211 .write(raw::Executor::new(context)) 210 .write(raw::Executor::new(irq.number() as *mut ()))
212 } 211 }
213 212
214 let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; 213 let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs
index 551d7527f..ce78bc258 100644
--- a/embassy-executor/src/arch/riscv32.rs
+++ b/embassy-executor/src/arch/riscv32.rs
@@ -17,7 +17,7 @@ mod thread {
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 = "__pender"] 19 #[export_name = "__pender"]
20 fn __thread_mode_pender(_context: crate::raw::PenderContext) { 20 fn __thread_mode_pender(_context: *mut ()) {
21 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); 21 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
22 } 22 }
23 23
@@ -31,7 +31,7 @@ mod thread {
31 /// Create a new Executor. 31 /// Create a new Executor.
32 pub fn new() -> Self { 32 pub fn new() -> Self {
33 Self { 33 Self {
34 inner: raw::Executor::new(unsafe { core::mem::transmute(0) }), 34 inner: raw::Executor::new(core::ptr::null_mut()),
35 not_send: PhantomData, 35 not_send: PhantomData,
36 } 36 }
37 } 37 }
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 {
14 use crate::{raw, Spawner}; 14 use crate::{raw, Spawner};
15 15
16 #[export_name = "__pender"] 16 #[export_name = "__pender"]
17 fn __pender(context: crate::raw::PenderContext) { 17 fn __pender(context: *mut ()) {
18 let signaler: &'static Signaler = unsafe { std::mem::transmute(context) }; 18 let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
19 signaler.signal() 19 signaler.signal()
20 } 20 }
@@ -29,9 +29,9 @@ mod thread {
29 impl Executor { 29 impl Executor {
30 /// Create a new Executor. 30 /// Create a new Executor.
31 pub fn new() -> Self { 31 pub fn new() -> Self {
32 let signaler = &*Box::leak(Box::new(Signaler::new())); 32 let signaler = Box::leak(Box::new(Signaler::new()));
33 Self { 33 Self {
34 inner: raw::Executor::new(unsafe { std::mem::transmute(signaler) }), 34 inner: raw::Executor::new(signaler as *mut Signaler as *mut ()),
35 not_send: PhantomData, 35 not_send: PhantomData,
36 signaler, 36 signaler,
37 } 37 }
diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs
index 452c3e394..5f9b2e705 100644
--- a/embassy-executor/src/arch/wasm.rs
+++ b/embassy-executor/src/arch/wasm.rs
@@ -14,11 +14,10 @@ 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::PenderContext;
18 use crate::{raw, Spawner}; 17 use crate::{raw, Spawner};
19 18
20 #[export_name = "__thread_mode_pender"] 19 #[export_name = "__thread_mode_pender"]
21 fn __thread_mode_pender(context: PenderContext) { 20 fn __thread_mode_pender(context: *mut ()) {
22 let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) }; 21 let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) };
23 let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() }); 22 let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() });
24 } 23 }
@@ -47,9 +46,9 @@ mod thread {
47 impl Executor { 46 impl Executor {
48 /// Create a new Executor. 47 /// Create a new Executor.
49 pub fn new() -> Self { 48 pub fn new() -> Self {
50 let ctx = &*Box::leak(Box::new(WasmContext::new())); 49 let ctx = Box::leak(Box::new(WasmContext::new()));
51 Self { 50 Self {
52 inner: raw::Executor::new(unsafe { core::mem::transmute(ctx) }), 51 inner: raw::Executor::new(ctx as *mut WasmContext as *mut ()),
53 ctx, 52 ctx,
54 not_send: PhantomData, 53 not_send: PhantomData,
55 } 54 }
diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs
index 8665a9cb6..66b3351c5 100644
--- a/embassy-executor/src/arch/xtensa.rs
+++ b/embassy-executor/src/arch/xtensa.rs
@@ -14,7 +14,7 @@ mod thread {
14 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); 14 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
15 15
16 #[export_name = "__thread_mode_pender"] 16 #[export_name = "__thread_mode_pender"]
17 fn __thread_mode_pender(_context: crate::raw::PenderContext) { 17 fn __thread_mode_pender(_context: *mut ()) {
18 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); 18 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
19 } 19 }
20 20
@@ -28,7 +28,7 @@ mod thread {
28 /// Create a new Executor. 28 /// Create a new Executor.
29 pub fn new() -> Self { 29 pub fn new() -> Self {
30 Self { 30 Self {
31 inner: raw::Executor::new(unsafe { core::mem::transmute(0) }), 31 inner: raw::Executor::new(core::ptr::null_mut()),
32 not_send: PhantomData, 32 not_send: PhantomData,
33 } 33 }
34 } 34 }
diff --git a/embassy-executor/src/interrupt.rs b/embassy-executor/src/interrupt.rs
deleted file mode 100644
index b68754ab2..000000000
--- a/embassy-executor/src/interrupt.rs
+++ /dev/null
@@ -1,131 +0,0 @@
1//! Interrupt-mode executor.
2
3use core::cell::UnsafeCell;
4use core::mem::MaybeUninit;
5
6use atomic_polyfill::{AtomicBool, Ordering};
7
8use crate::raw::{self, PenderContext};
9
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
12/// triggers polling the executor.
13// TODO: Name pending
14pub trait InterruptContext {
15 /// A pointer-sized piece of data that is passed to the pender function.
16 ///
17 /// Usually, the context contains the interrupt that should be used to wake the executor.
18 fn context(&self) -> PenderContext;
19
20 /// Enabled the interrupt request.
21 fn enable(&self);
22}
23
24/// Interrupt mode executor.
25///
26/// This executor runs tasks in interrupt mode. The interrupt handler is set up
27/// to poll tasks, and when a task is woken the interrupt is pended from software.
28///
29/// This allows running async tasks at a priority higher than thread mode. One
30/// use case is to leave thread mode free for non-async tasks. Another use case is
31/// to run multiple executors: one in thread mode for low priority tasks and another in
32/// interrupt mode for higher priority tasks. Higher priority tasks will preempt lower
33/// priority ones.
34///
35/// It is even possible to run multiple interrupt mode executors at different priorities,
36/// by assigning different priorities to the interrupts. For an example on how to do this,
37/// See the 'multiprio' example for 'embassy-nrf'.
38///
39/// To use it, you have to pick an interrupt that won't be used by the hardware.
40/// Some chips reserve some interrupts for this purpose, sometimes named "software interrupts" (SWI).
41/// If this is not the case, you may use an interrupt from any unused peripheral.
42///
43/// It is somewhat more complex to use, it's recommended to use the
44/// thread-mode executor instead, if it works for your use case.
45pub struct InterruptModeExecutor {
46 started: AtomicBool,
47 executor: UnsafeCell<MaybeUninit<raw::Executor>>,
48}
49
50unsafe impl Send for InterruptModeExecutor {}
51unsafe impl Sync for InterruptModeExecutor {}
52
53impl InterruptModeExecutor {
54 /// Create a new, not started `InterruptExecutor`.
55 #[inline]
56 pub const fn new() -> Self {
57 Self {
58 started: AtomicBool::new(false),
59 executor: UnsafeCell::new(MaybeUninit::uninit()),
60 }
61 }
62
63 /// Executor interrupt callback.
64 ///
65 /// # Safety
66 ///
67 /// You MUST call this from the interrupt handler, and from nowhere else.
68 pub unsafe fn on_interrupt(&'static self) {
69 let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
70 executor.poll();
71 }
72
73 /// Start the executor.
74 ///
75 /// This initializes the executor, enables the interrupt, and returns.
76 /// The executor keeps running in the background through the interrupt.
77 ///
78 /// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`]
79 /// is returned instead of a [`Spawner`](embassy_executor::Spawner) because the executor effectively runs in a
80 /// different "thread" (the interrupt), so spawning tasks on it is effectively
81 /// sending them.
82 ///
83 /// To obtain a [`Spawner`](embassy_executor::Spawner) for this executor, use [`Spawner::for_current_executor()`](embassy_executor::Spawner::for_current_executor()) from
84 /// a task running in it.
85 ///
86 /// # Interrupt requirements
87 ///
88 /// You must write the interrupt handler yourself, and make it call [`on_interrupt()`](Self::on_interrupt).
89 ///
90 /// This method already enables (unmasks) the interrupt, you must NOT do it yourself.
91 ///
92 /// You must set the interrupt priority before calling this method. You MUST NOT
93 /// do it after.
94 ///
95 pub fn start(&'static self, irq: impl InterruptContext) -> crate::SendSpawner {
96 if self
97 .started
98 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
99 .is_err()
100 {
101 panic!("InterruptExecutor::start() called multiple times on the same executor.");
102 }
103
104 unsafe {
105 (&mut *self.executor.get())
106 .as_mut_ptr()
107 .write(raw::Executor::new(irq.context()))
108 }
109
110 let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
111
112 irq.enable();
113
114 executor.spawner().make_send()
115 }
116
117 /// Get a SendSpawner for this executor
118 ///
119 /// This returns a [`SendSpawner`] you can use to spawn tasks on this
120 /// executor.
121 ///
122 /// This MUST only be called on an executor that has already been spawned.
123 /// The function will panic otherwise.
124 pub fn spawner(&'static self) -> crate::SendSpawner {
125 if !self.started.load(Ordering::Acquire) {
126 panic!("InterruptExecutor::spawner() called on uninitialized executor.");
127 }
128 let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
129 executor.spawner().make_send()
130 }
131}
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs
index 3be32d9c5..3ce687eb6 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -37,11 +37,6 @@ pub use arch::*;
37 37
38pub mod raw; 38pub mod raw;
39 39
40#[cfg(feature = "executor-interrupt")]
41pub mod interrupt;
42#[cfg(feature = "executor-interrupt")]
43pub use interrupt::*;
44
45mod spawner; 40mod spawner;
46pub use spawner::*; 41pub use spawner::*;
47 42
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 2bbbb132c..aa99b4cf3 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -291,11 +291,6 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
291 } 291 }
292} 292}
293 293
294/// Context given to the thread-mode executor's pender.
295#[repr(transparent)]
296#[derive(Clone, Copy)]
297pub struct PenderContext(*mut ());
298
299/// Platform/architecture-specific action executed when an executor has pending work. 294/// Platform/architecture-specific action executed when an executor has pending work.
300/// 295///
301/// When a task within an executor is woken, the `Pender` is called. This does a 296/// When a task within an executor is woken, the `Pender` is called. This does a
@@ -306,15 +301,13 @@ pub struct PenderContext(*mut ());
306/// 301///
307/// Platform/architecture implementations must provide a function that can be referred to as: 302/// Platform/architecture implementations must provide a function that can be referred to as:
308/// 303///
309/// ```rust 304/// ```rust///
310/// use embassy_executor::raw::PenderContext;
311///
312/// extern "Rust" { 305/// extern "Rust" {
313/// fn __pender(context: PenderContext); 306/// fn __pender(context: *mut ());
314/// } 307/// }
315/// ``` 308/// ```
316#[derive(Clone, Copy)] 309#[derive(Clone, Copy)]
317pub struct Pender(PenderContext); 310pub struct Pender(*mut ());
318 311
319unsafe impl Send for Pender {} 312unsafe impl Send for Pender {}
320unsafe impl Sync for Pender {} 313unsafe impl Sync for Pender {}
@@ -322,7 +315,7 @@ unsafe impl Sync for Pender {}
322impl Pender { 315impl Pender {
323 pub(crate) fn pend(self) { 316 pub(crate) fn pend(self) {
324 extern "Rust" { 317 extern "Rust" {
325 fn __pender(context: PenderContext); 318 fn __pender(context: *mut ());
326 } 319 }
327 unsafe { __pender(self.0) }; 320 unsafe { __pender(self.0) };
328 } 321 }
@@ -484,7 +477,7 @@ impl Executor {
484 /// When the executor has work to do, it will call the [`Pender`]. 477 /// When the executor has work to do, it will call the [`Pender`].
485 /// 478 ///
486 /// See [`Executor`] docs for details on `Pender`. 479 /// See [`Executor`] docs for details on `Pender`.
487 pub fn new(context: PenderContext) -> Self { 480 pub fn new(context: *mut ()) -> Self {
488 Self { 481 Self {
489 inner: SyncExecutor::new(Pender(context)), 482 inner: SyncExecutor::new(Pender(context)),
490 _not_sync: PhantomData, 483 _not_sync: PhantomData,