aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-executor/CHANGELOG.md4
-rw-r--r--embassy-executor/src/raw/mod.rs49
2 files changed, 29 insertions, 24 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/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 064831026..7caa3302f 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -291,21 +291,6 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
291 } 291 }
292} 292}
293 293
294/// Platform/architecture-specific action executed when an executor has pending work.
295///
296/// When a task within an executor is woken, the `Pender` is called. This does a
297/// platform/architecture-specific action to signal there is pending work in the executor.
298/// When this happens, you must arrange for [`Executor::poll`] to be called.
299///
300/// You can think of it as a waker, but for the whole executor.
301///
302/// Platform/architecture implementations must provide a function that can be referred to as:
303///
304/// ```rust
305/// extern "Rust" {
306/// fn __pender(context: *mut ());
307/// }
308/// ```
309#[derive(Clone, Copy)] 294#[derive(Clone, Copy)]
310pub(crate) struct Pender(*mut ()); 295pub(crate) struct Pender(*mut ());
311 296
@@ -451,15 +436,31 @@ impl SyncExecutor {
451/// 436///
452/// - 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
453/// that "want to run"). 438/// that "want to run").
454/// - 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
455/// 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.
456/// 444///
457/// 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
458/// 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.
459/// You must deal with this correctly. 447/// You must deal with this correctly.
460/// 448///
461/// 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
462/// 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.
463#[repr(transparent)] 464#[repr(transparent)]
464pub struct Executor { 465pub struct Executor {
465 pub(crate) inner: SyncExecutor, 466 pub(crate) inner: SyncExecutor,
@@ -474,9 +475,9 @@ impl Executor {
474 475
475 /// Create a new executor. 476 /// Create a new executor.
476 /// 477 ///
477 /// 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.
478 /// 479 ///
479 /// See [`Executor`] docs for details on `Pender`. 480 /// See [`Executor`] docs for details on the pender.
480 pub fn new(context: *mut ()) -> Self { 481 pub fn new(context: *mut ()) -> Self {
481 Self { 482 Self {
482 inner: SyncExecutor::new(Pender(context)), 483 inner: SyncExecutor::new(Pender(context)),
@@ -502,16 +503,16 @@ impl Executor {
502 /// 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
503 /// 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.
504 /// 505 ///
505 /// 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
506 /// 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
507 /// energy. 508 /// energy.
508 /// 509 ///
509 /// # Safety 510 /// # Safety
510 /// 511 ///
511 /// You must NOT call `poll` reentrantly on the same executor. 512 /// You must NOT call `poll` reentrantly on the same executor.
512 /// 513 ///
513 /// 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
514 /// 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
515 /// 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
516 /// no `poll()` already running. 517 /// no `poll()` already running.
517 pub unsafe fn poll(&'static self) { 518 pub unsafe fn poll(&'static self) {