aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-08-14 20:43:51 +0000
committerGitHub <[email protected]>2023-08-14 20:43:51 +0000
commitbd58b5002aee8ad3b01081595817afb2a70f0cc6 (patch)
treead636106836487272e7f581d7e7318387a05c3bb
parent0727f8690c4684d0622547edee2cf9dc22215a9b (diff)
parent890f29ccfe129f3205cf835c7131862c579d9349 (diff)
Merge pull request #1774 from bugadani/executor
Allow custom executors without indirection
-rw-r--r--embassy-executor/CHANGELOG.md4
-rw-r--r--embassy-executor/Cargo.toml7
-rw-r--r--embassy-executor/src/arch/cortex_m.rs88
-rw-r--r--embassy-executor/src/arch/riscv32.rs18
-rw-r--r--embassy-executor/src/arch/std.rs17
-rw-r--r--embassy-executor/src/arch/wasm.rs33
-rw-r--r--embassy-executor/src/arch/xtensa.rs22
-rw-r--r--embassy-executor/src/raw/mod.rs88
8 files changed, 124 insertions, 153 deletions
diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md
index 86a477589..e2e7bce3a 100644
--- a/embassy-executor/CHANGELOG.md
+++ b/embassy-executor/CHANGELOG.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
8## Unreleased
9
10- Replaced Pender. Implementations now must define an extern function called `__pender`.
11
8## 0.2.1 - 2023-08-10 12## 0.2.1 - 2023-08-10
9 13
10- Avoid calling `pend()` when waking expired timers 14- Avoid calling `pend()` when waking expired timers
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index ce5e2741f..d190c95a3 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -14,7 +14,7 @@ categories = [
14[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" 16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
17features = ["nightly", "defmt", "pender-callback"] 17features = ["nightly", "defmt"]
18flavors = [ 18flavors = [
19 { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, 19 { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
20 { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, 20 { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
@@ -25,7 +25,7 @@ flavors = [
25[package.metadata.docs.rs] 25[package.metadata.docs.rs]
26default-target = "thumbv7em-none-eabi" 26default-target = "thumbv7em-none-eabi"
27targets = ["thumbv7em-none-eabi"] 27targets = ["thumbv7em-none-eabi"]
28features = ["nightly", "defmt", "pender-callback", "arch-cortex-m", "executor-thread", "executor-interrupt"] 28features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
29 29
30[features] 30[features]
31 31
@@ -37,9 +37,6 @@ arch-xtensa = ["_arch"]
37arch-riscv32 = ["_arch"] 37arch-riscv32 = ["_arch"]
38arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"] 38arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]
39 39
40# Enable creating a `Pender` from an arbitrary function pointer callback.
41pender-callback = []
42
43# Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs) 40# Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
44executor-thread = [] 41executor-thread = []
45# Enable the interrupt-mode executor (available in Cortex-M only) 42# Enable the interrupt-mode executor (available in Cortex-M only)
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
index 94c8134d6..0806a22ab 100644
--- a/embassy-executor/src/arch/cortex_m.rs
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -1,3 +1,49 @@
1const THREAD_PENDER: usize = usize::MAX;
2
3#[export_name = "__pender"]
4#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))]
5fn __pender(context: *mut ()) {
6 unsafe {
7 // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
8 // request number given to `InterruptExecutor::start`.
9
10 let context = context as usize;
11
12 #[cfg(feature = "executor-thread")]
13 // Try to make Rust optimize the branching away if we only use thread mode.
14 if !cfg!(feature = "executor-interrupt") || context == THREAD_PENDER {
15 core::arch::asm!("sev");
16 return;
17 }
18
19 #[cfg(feature = "executor-interrupt")]
20 {
21 use cortex_m::interrupt::InterruptNumber;
22 use cortex_m::peripheral::NVIC;
23
24 #[derive(Clone, Copy)]
25 struct Irq(u16);
26 unsafe impl InterruptNumber for Irq {
27 fn number(self) -> u16 {
28 self.0
29 }
30 }
31
32 let irq = Irq(context as u16);
33
34 // STIR is faster, but is only available in v7 and higher.
35 #[cfg(not(armv6m))]
36 {
37 let mut nvic: NVIC = core::mem::transmute(());
38 nvic.request(irq);
39 }
40
41 #[cfg(armv6m)]
42 NVIC::pend(irq);
43 }
44 }
45}
46
1#[cfg(feature = "executor-thread")] 47#[cfg(feature = "executor-thread")]
2pub use thread::*; 48pub use thread::*;
3#[cfg(feature = "executor-thread")] 49#[cfg(feature = "executor-thread")]
@@ -8,18 +54,9 @@ mod thread {
8 #[cfg(feature = "nightly")] 54 #[cfg(feature = "nightly")]
9 pub use embassy_macros::main_cortex_m as main; 55 pub use embassy_macros::main_cortex_m as main;
10 56
11 use crate::raw::{Pender, PenderInner}; 57 use crate::arch::THREAD_PENDER;
12 use crate::{raw, Spawner}; 58 use crate::{raw, Spawner};
13 59
14 #[derive(Copy, Clone)]
15 pub(crate) struct ThreadPender;
16
17 impl ThreadPender {
18 pub(crate) fn pend(self) {
19 unsafe { core::arch::asm!("sev") }
20 }
21 }
22
23 /// Thread mode executor, using WFE/SEV. 60 /// Thread mode executor, using WFE/SEV.
24 /// 61 ///
25 /// This is the simplest and most common kind of executor. It runs on 62 /// This is the simplest and most common kind of executor. It runs on
@@ -39,7 +76,7 @@ mod thread {
39 /// Create a new Executor. 76 /// Create a new Executor.
40 pub fn new() -> Self { 77 pub fn new() -> Self {
41 Self { 78 Self {
42 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))), 79 inner: raw::Executor::new(THREAD_PENDER as *mut ()),
43 not_send: PhantomData, 80 not_send: PhantomData,
44 } 81 }
45 } 82 }
@@ -86,30 +123,7 @@ mod interrupt {
86 use cortex_m::interrupt::InterruptNumber; 123 use cortex_m::interrupt::InterruptNumber;
87 use cortex_m::peripheral::NVIC; 124 use cortex_m::peripheral::NVIC;
88 125
89 use crate::raw::{self, Pender, PenderInner}; 126 use crate::raw;
90
91 #[derive(Clone, Copy)]
92 pub(crate) struct InterruptPender(u16);
93
94 impl InterruptPender {
95 pub(crate) fn pend(self) {
96 // STIR is faster, but is only available in v7 and higher.
97 #[cfg(not(armv6m))]
98 {
99 let mut nvic: cortex_m::peripheral::NVIC = unsafe { core::mem::transmute(()) };
100 nvic.request(self);
101 }
102
103 #[cfg(armv6m)]
104 cortex_m::peripheral::NVIC::pend(self);
105 }
106 }
107
108 unsafe impl cortex_m::interrupt::InterruptNumber for InterruptPender {
109 fn number(self) -> u16 {
110 self.0
111 }
112 }
113 127
114 /// Interrupt mode executor. 128 /// Interrupt mode executor.
115 /// 129 ///
@@ -194,9 +208,7 @@ mod interrupt {
194 unsafe { 208 unsafe {
195 (&mut *self.executor.get()) 209 (&mut *self.executor.get())
196 .as_mut_ptr() 210 .as_mut_ptr()
197 .write(raw::Executor::new(Pender(PenderInner::Interrupt(InterruptPender( 211 .write(raw::Executor::new(irq.number() as *mut ()))
198 irq.number(),
199 )))))
200 } 212 }
201 213
202 let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; 214 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 ff7ec1575..40c6877e2 100644
--- a/embassy-executor/src/arch/riscv32.rs
+++ b/embassy-executor/src/arch/riscv32.rs
@@ -11,22 +11,16 @@ mod thread {
11 #[cfg(feature = "nightly")] 11 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_riscv as main; 12 pub use embassy_macros::main_riscv as main;
13 13
14 use crate::raw::{Pender, PenderInner};
15 use crate::{raw, Spawner}; 14 use crate::{raw, Spawner};
16 15
17 #[derive(Copy, Clone)]
18 pub(crate) struct ThreadPender;
19
20 impl ThreadPender {
21 #[allow(unused)]
22 pub(crate) fn pend(self) {
23 SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
24 }
25 }
26
27 /// 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
28 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); 17 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
29 18
19 #[export_name = "__pender"]
20 fn __pender(_context: *mut ()) {
21 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
22 }
23
30 /// RISCV32 Executor 24 /// RISCV32 Executor
31 pub struct Executor { 25 pub struct Executor {
32 inner: raw::Executor, 26 inner: raw::Executor,
@@ -37,7 +31,7 @@ mod thread {
37 /// Create a new Executor. 31 /// Create a new Executor.
38 pub fn new() -> Self { 32 pub fn new() -> Self {
39 Self { 33 Self {
40 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))), 34 inner: raw::Executor::new(core::ptr::null_mut()),
41 not_send: PhantomData, 35 not_send: PhantomData,
42 } 36 }
43 } 37 }
diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs
index 4e4a178f0..5b2f7e2e4 100644
--- a/embassy-executor/src/arch/std.rs
+++ b/embassy-executor/src/arch/std.rs
@@ -11,17 +11,12 @@ mod thread {
11 #[cfg(feature = "nightly")] 11 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_std as main; 12 pub use embassy_macros::main_std as main;
13 13
14 use crate::raw::{Pender, PenderInner};
15 use crate::{raw, Spawner}; 14 use crate::{raw, Spawner};
16 15
17 #[derive(Copy, Clone)] 16 #[export_name = "__pender"]
18 pub(crate) struct ThreadPender(&'static Signaler); 17 fn __pender(context: *mut ()) {
19 18 let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
20 impl ThreadPender { 19 signaler.signal()
21 #[allow(unused)]
22 pub(crate) fn pend(self) {
23 self.0.signal()
24 }
25 } 20 }
26 21
27 /// Single-threaded std-based executor. 22 /// Single-threaded std-based executor.
@@ -34,9 +29,9 @@ mod thread {
34 impl Executor { 29 impl Executor {
35 /// Create a new Executor. 30 /// Create a new Executor.
36 pub fn new() -> Self { 31 pub fn new() -> Self {
37 let signaler = &*Box::leak(Box::new(Signaler::new())); 32 let signaler = Box::leak(Box::new(Signaler::new()));
38 Self { 33 Self {
39 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(signaler)))), 34 inner: raw::Executor::new(signaler as *mut Signaler as *mut ()),
40 not_send: PhantomData, 35 not_send: PhantomData,
41 signaler, 36 signaler,
42 } 37 }
diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs
index 08ab16b99..934fd69e5 100644
--- a/embassy-executor/src/arch/wasm.rs
+++ b/embassy-executor/src/arch/wasm.rs
@@ -14,14 +14,12 @@ 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::{Pender, PenderInner};
18 use crate::{raw, Spawner}; 17 use crate::{raw, Spawner};
19 18
20 /// WASM executor, wasm_bindgen to schedule tasks on the JS event loop. 19 #[export_name = "__pender"]
21 pub struct Executor { 20 fn __pender(context: *mut ()) {
22 inner: raw::Executor, 21 let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) };
23 ctx: &'static WasmContext, 22 let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() });
24 not_send: PhantomData<*mut ()>,
25 } 23 }
26 24
27 pub(crate) struct WasmContext { 25 pub(crate) struct WasmContext {
@@ -29,16 +27,6 @@ mod thread {
29 closure: UninitCell<Closure<dyn FnMut(JsValue)>>, 27 closure: UninitCell<Closure<dyn FnMut(JsValue)>>,
30 } 28 }
31 29
32 #[derive(Copy, Clone)]
33 pub(crate) struct ThreadPender(&'static WasmContext);
34
35 impl ThreadPender {
36 #[allow(unused)]
37 pub(crate) fn pend(self) {
38 let _ = self.0.promise.then(unsafe { self.0.closure.as_mut() });
39 }
40 }
41
42 impl WasmContext { 30 impl WasmContext {
43 pub fn new() -> Self { 31 pub fn new() -> Self {
44 Self { 32 Self {
@@ -48,14 +36,21 @@ mod thread {
48 } 36 }
49 } 37 }
50 38
39 /// WASM executor, wasm_bindgen to schedule tasks on the JS event loop.
40 pub struct Executor {
41 inner: raw::Executor,
42 ctx: &'static WasmContext,
43 not_send: PhantomData<*mut ()>,
44 }
45
51 impl Executor { 46 impl Executor {
52 /// Create a new Executor. 47 /// Create a new Executor.
53 pub fn new() -> Self { 48 pub fn new() -> Self {
54 let ctx = &*Box::leak(Box::new(WasmContext::new())); 49 let ctx = Box::leak(Box::new(WasmContext::new()));
55 Self { 50 Self {
56 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(ctx)))), 51 inner: raw::Executor::new(ctx as *mut WasmContext as *mut ()),
57 not_send: PhantomData,
58 ctx, 52 ctx,
53 not_send: PhantomData,
59 } 54 }
60 } 55 }
61 56
diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs
index 017b2c52b..601d85002 100644
--- a/embassy-executor/src/arch/xtensa.rs
+++ b/embassy-executor/src/arch/xtensa.rs
@@ -8,22 +8,16 @@ 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::{Pender, PenderInner};
12 use crate::{raw, Spawner}; 11 use crate::{raw, Spawner};
13 12
14 #[derive(Copy, Clone)]
15 pub(crate) struct ThreadPender;
16
17 impl ThreadPender {
18 #[allow(unused)]
19 pub(crate) fn pend(self) {
20 SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
21 }
22 }
23
24 /// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa 13 /// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
25 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); 14 static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
26 15
16 #[export_name = "__pender"]
17 fn __pender(_context: *mut ()) {
18 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
19 }
20
27 /// Xtensa Executor 21 /// Xtensa Executor
28 pub struct Executor { 22 pub struct Executor {
29 inner: raw::Executor, 23 inner: raw::Executor,
@@ -34,7 +28,7 @@ mod thread {
34 /// Create a new Executor. 28 /// Create a new Executor.
35 pub fn new() -> Self { 29 pub fn new() -> Self {
36 Self { 30 Self {
37 inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))), 31 inner: raw::Executor::new(core::ptr::null_mut()),
38 not_send: PhantomData, 32 not_send: PhantomData,
39 } 33 }
40 } 34 }
@@ -77,8 +71,8 @@ mod thread {
77 SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst); 71 SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
78 72
79 core::arch::asm!( 73 core::arch::asm!(
80 "wsr.ps {0}", 74 "wsr.ps {0}",
81 "rsync", in(reg) token) 75 "rsync", in(reg) token)
82 } else { 76 } else {
83 // waiti sets the PS.INTLEVEL when slipping into sleep 77 // waiti sets the PS.INTLEVEL when slipping into sleep
84 // because critical sections in Xtensa are implemented via increasing 78 // because critical sections in Xtensa are implemented via increasing
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 25c2ab0da..7caa3302f 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -292,53 +292,17 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
292} 292}
293 293
294#[derive(Clone, Copy)] 294#[derive(Clone, Copy)]
295pub(crate) enum PenderInner { 295pub(crate) struct Pender(*mut ());
296 #[cfg(feature = "executor-thread")]
297 Thread(crate::arch::ThreadPender),
298 #[cfg(feature = "executor-interrupt")]
299 Interrupt(crate::arch::InterruptPender),
300 #[cfg(feature = "pender-callback")]
301 Callback { func: fn(*mut ()), context: *mut () },
302}
303
304unsafe impl Send for PenderInner {}
305unsafe impl Sync for PenderInner {}
306 296
307/// Platform/architecture-specific action executed when an executor has pending work. 297unsafe impl Send for Pender {}
308/// 298unsafe impl Sync for Pender {}
309/// When a task within an executor is woken, the `Pender` is called. This does a
310/// platform/architecture-specific action to signal there is pending work in the executor.
311/// When this happens, you must arrange for [`Executor::poll`] to be called.
312///
313/// You can think of it as a waker, but for the whole executor.
314pub struct Pender(pub(crate) PenderInner);
315 299
316impl Pender { 300impl Pender {
317 /// Create a `Pender` that will call an arbitrary function pointer. 301 pub(crate) fn pend(self) {
318 /// 302 extern "Rust" {
319 /// # Arguments 303 fn __pender(context: *mut ());
320 ///
321 /// - `func`: The function pointer to call.
322 /// - `context`: Opaque context pointer, that will be passed to the function pointer.
323 #[cfg(feature = "pender-callback")]
324 pub fn new_from_callback(func: fn(*mut ()), context: *mut ()) -> Self {
325 Self(PenderInner::Callback {
326 func,
327 context: context.into(),
328 })
329 }
330}
331
332impl Pender {
333 pub(crate) fn pend(&self) {
334 match self.0 {
335 #[cfg(feature = "executor-thread")]
336 PenderInner::Thread(x) => x.pend(),
337 #[cfg(feature = "executor-interrupt")]
338 PenderInner::Interrupt(x) => x.pend(),
339 #[cfg(feature = "pender-callback")]
340 PenderInner::Callback { func, context } => func(context),
341 } 304 }
305 unsafe { __pender(self.0) };
342 } 306 }
343} 307}
344 308
@@ -472,15 +436,31 @@ impl SyncExecutor {
472/// 436///
473/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks 437/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks
474/// that "want to run"). 438/// that "want to run").
475/// - You must supply a [`Pender`]. The executor will call it to notify you it has work 439/// - You must supply a pender function, as shown below. The executor will call it to notify you
476/// to do. You must arrange for `poll()` to be called as soon as possible. 440/// it has work to do. You must arrange for `poll()` to be called as soon as possible.
441/// - Enabling `arch-xx` features will define a pender function for you. This means that you
442/// are limited to using the executors provided to you by the architecture/platform
443/// implementation. If you need a different executor, you must not enable `arch-xx` features.
477/// 444///
478/// The [`Pender`] can be called from *any* context: any thread, any interrupt priority 445/// The pender can be called from *any* context: any thread, any interrupt priority
479/// level, etc. It may be called synchronously from any `Executor` method call as well. 446/// level, etc. It may be called synchronously from any `Executor` method call as well.
480/// You must deal with this correctly. 447/// You must deal with this correctly.
481/// 448///
482/// In particular, you must NOT call `poll` directly from the pender callback, as this violates 449/// In particular, you must NOT call `poll` directly from the pender callback, as this violates
483/// the requirement for `poll` to not be called reentrantly. 450/// the requirement for `poll` to not be called reentrantly.
451///
452/// The pender function must be exported with the name `__pender` and have the following signature:
453///
454/// ```rust
455/// #[export_name = "__pender"]
456/// fn pender(context: *mut ()) {
457/// // schedule `poll()` to be called
458/// }
459/// ```
460///
461/// The `context` argument is a piece of arbitrary data the executor will pass to the pender.
462/// You can set the `context` when calling [`Executor::new()`]. You can use it to, for example,
463/// differentiate between executors, or to pass a pointer to a callback that should be called.
484#[repr(transparent)] 464#[repr(transparent)]
485pub struct Executor { 465pub struct Executor {
486 pub(crate) inner: SyncExecutor, 466 pub(crate) inner: SyncExecutor,
@@ -495,12 +475,12 @@ impl Executor {
495 475
496 /// Create a new executor. 476 /// Create a new executor.
497 /// 477 ///
498 /// When the executor has work to do, it will call the [`Pender`]. 478 /// When the executor has work to do, it will call the pender function and pass `context` to it.
499 /// 479 ///
500 /// See [`Executor`] docs for details on `Pender`. 480 /// See [`Executor`] docs for details on the pender.
501 pub fn new(pender: Pender) -> Self { 481 pub fn new(context: *mut ()) -> Self {
502 Self { 482 Self {
503 inner: SyncExecutor::new(pender), 483 inner: SyncExecutor::new(Pender(context)),
504 _not_sync: PhantomData, 484 _not_sync: PhantomData,
505 } 485 }
506 } 486 }
@@ -523,16 +503,16 @@ impl Executor {
523 /// This loops over all tasks that are queued to be polled (i.e. they're 503 /// This loops over all tasks that are queued to be polled (i.e. they're
524 /// freshly spawned or they've been woken). Other tasks are not polled. 504 /// freshly spawned or they've been woken). Other tasks are not polled.
525 /// 505 ///
526 /// You must call `poll` after receiving a call to the [`Pender`]. It is OK 506 /// You must call `poll` after receiving a call to the pender. It is OK
527 /// to call `poll` even when not requested by the `Pender`, but it wastes 507 /// to call `poll` even when not requested by the pender, but it wastes
528 /// energy. 508 /// energy.
529 /// 509 ///
530 /// # Safety 510 /// # Safety
531 /// 511 ///
532 /// You must NOT call `poll` reentrantly on the same executor. 512 /// You must NOT call `poll` reentrantly on the same executor.
533 /// 513 ///
534 /// In particular, note that `poll` may call the `Pender` synchronously. Therefore, you 514 /// In particular, note that `poll` may call the pender synchronously. Therefore, you
535 /// must NOT directly call `poll()` from the `Pender` callback. Instead, the callback has to 515 /// must NOT directly call `poll()` from the pender callback. Instead, the callback has to
536 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's 516 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's
537 /// no `poll()` already running. 517 /// no `poll()` already running.
538 pub unsafe fn poll(&'static self) { 518 pub unsafe fn poll(&'static self) {