From 66faba2df76bf76bcfcca30d159c5a39b64819e8 Mon Sep 17 00:00:00 2001 From: loris <76793979+lorislibralato@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:04:51 +0200 Subject: [PATCH] add wake_task_no_pend for expired timer enqueue inside run_queue --- embassy-executor/src/raw/mod.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index f3760f58..25c2ab0d 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -409,7 +409,7 @@ impl SyncExecutor { #[allow(clippy::never_loop)] loop { #[cfg(feature = "integrated-timers")] - self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task)); + self.timer_queue.dequeue_expired(Instant::now(), wake_task_no_pend); self.run_queue.dequeue_all(|p| { let task = p.header(); @@ -573,6 +573,31 @@ pub fn wake_task(task: TaskRef) { } } +/// Wake a task by `TaskRef` without calling pend. +/// +/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`]. +pub fn wake_task_no_pend(task: TaskRef) { + let header = task.header(); + + let res = header.state.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| { + // If already scheduled, or if not started, + if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) { + None + } else { + // Mark it as scheduled + Some(state | STATE_RUN_QUEUED) + } + }); + + if res.is_ok() { + // We have just marked the task as scheduled, so enqueue it. + unsafe { + let executor = header.executor.get().unwrap_unchecked(); + executor.run_queue.enqueue(task); + } + } +} + #[cfg(feature = "integrated-timers")] struct TimerQueue;