aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/state_critical_section.rs
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-12-09 08:43:57 +0100
committerDániel Buga <[email protected]>2024-12-13 21:20:57 +0100
commitec96395d084d5edc8be25ddaea8547e2ebd447a6 (patch)
treeb1edf825c8d67013df3cec1283376a7558951a3f /embassy-executor/src/raw/state_critical_section.rs
parentd45ea43892198484b5f6dcea4c351dc11d226cc4 (diff)
Prevent task from respawning while in the timer queue
Diffstat (limited to 'embassy-executor/src/raw/state_critical_section.rs')
-rw-r--r--embassy-executor/src/raw/state_critical_section.rs29
1 files changed, 29 insertions, 0 deletions
diff --git a/embassy-executor/src/raw/state_critical_section.rs b/embassy-executor/src/raw/state_critical_section.rs
index b92eed006..c0ec2f530 100644
--- a/embassy-executor/src/raw/state_critical_section.rs
+++ b/embassy-executor/src/raw/state_critical_section.rs
@@ -2,10 +2,16 @@ use core::cell::Cell;
2 2
3use critical_section::Mutex; 3use critical_section::Mutex;
4 4
5#[cfg(feature = "integrated-timers")]
6use super::timer_queue::TimerEnqueueOperation;
7
5/// Task is spawned (has a future) 8/// Task is spawned (has a future)
6pub(crate) const STATE_SPAWNED: u32 = 1 << 0; 9pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
7/// Task is in the executor run queue 10/// Task is in the executor run queue
8pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1; 11pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
12/// Task is in the executor timer queue
13#[cfg(feature = "integrated-timers")]
14pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
9 15
10pub(crate) struct State { 16pub(crate) struct State {
11 state: Mutex<Cell<u32>>, 17 state: Mutex<Cell<u32>>,
@@ -69,4 +75,27 @@ impl State {
69 ok 75 ok
70 }) 76 })
71 } 77 }
78
79 /// Mark the task as timer-queued. Return whether it can be enqueued.
80 #[cfg(feature = "integrated-timers")]
81 #[inline(always)]
82 pub fn timer_enqueue(&self) -> TimerEnqueueOperation {
83 self.update(|s| {
84 // FIXME: we need to split SPAWNED into two phases, to prevent enqueueing a task that is
85 // just being spawned, because its executor pointer may still be changing.
86 if *s & STATE_SPAWNED == STATE_SPAWNED {
87 *s |= STATE_TIMER_QUEUED;
88 TimerEnqueueOperation::Enqueue
89 } else {
90 TimerEnqueueOperation::Ignore
91 }
92 })
93 }
94
95 /// Unmark the task as timer-queued.
96 #[cfg(feature = "integrated-timers")]
97 #[inline(always)]
98 pub fn timer_dequeue(&self) {
99 self.update(|s| *s &= !STATE_TIMER_QUEUED);
100 }
72} 101}