aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/state_atomics_arm.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_atomics_arm.rs
parentd45ea43892198484b5f6dcea4c351dc11d226cc4 (diff)
Prevent task from respawning while in the timer queue
Diffstat (limited to 'embassy-executor/src/raw/state_atomics_arm.rs')
-rw-r--r--embassy-executor/src/raw/state_atomics_arm.rs40
1 files changed, 38 insertions, 2 deletions
diff --git a/embassy-executor/src/raw/state_atomics_arm.rs b/embassy-executor/src/raw/state_atomics_arm.rs
index b673c7359..f6f2e8f08 100644
--- a/embassy-executor/src/raw/state_atomics_arm.rs
+++ b/embassy-executor/src/raw/state_atomics_arm.rs
@@ -1,9 +1,14 @@
1use core::arch::asm; 1use core::arch::asm;
2use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; 2use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering};
3 3
4#[cfg(feature = "integrated-timers")]
5use super::timer_queue::TimerEnqueueOperation;
6
4// Must be kept in sync with the layout of `State`! 7// Must be kept in sync with the layout of `State`!
5pub(crate) const STATE_SPAWNED: u32 = 1 << 0; 8pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
6pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 8; 9pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 8;
10#[cfg(feature = "integrated-timers")]
11pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 16;
7 12
8#[repr(C, align(4))] 13#[repr(C, align(4))]
9pub(crate) struct State { 14pub(crate) struct State {
@@ -11,8 +16,9 @@ pub(crate) struct State {
11 spawned: AtomicBool, 16 spawned: AtomicBool,
12 /// Task is in the executor run queue 17 /// Task is in the executor run queue
13 run_queued: AtomicBool, 18 run_queued: AtomicBool,
19 /// Task is in the executor timer queue
20 timer_queued: AtomicBool,
14 pad: AtomicBool, 21 pad: AtomicBool,
15 pad2: AtomicBool,
16} 22}
17 23
18impl State { 24impl State {
@@ -20,8 +26,8 @@ impl State {
20 Self { 26 Self {
21 spawned: AtomicBool::new(false), 27 spawned: AtomicBool::new(false),
22 run_queued: AtomicBool::new(false), 28 run_queued: AtomicBool::new(false),
29 timer_queued: AtomicBool::new(false),
23 pad: AtomicBool::new(false), 30 pad: AtomicBool::new(false),
24 pad2: AtomicBool::new(false),
25 } 31 }
26 } 32 }
27 33
@@ -85,4 +91,34 @@ impl State {
85 self.run_queued.store(false, Ordering::Relaxed); 91 self.run_queued.store(false, Ordering::Relaxed);
86 r 92 r
87 } 93 }
94
95 /// Mark the task as timer-queued. Return whether it can be enqueued.
96 #[cfg(feature = "integrated-timers")]
97 #[inline(always)]
98 pub fn timer_enqueue(&self) -> TimerEnqueueOperation {
99 if self
100 .as_u32()
101 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| {
102 // If not started, ignore it
103 if state & STATE_SPAWNED == 0 {
104 None
105 } else {
106 // Mark it as enqueued
107 Some(state | STATE_TIMER_QUEUED)
108 }
109 })
110 .is_ok()
111 {
112 TimerEnqueueOperation::Enqueue
113 } else {
114 TimerEnqueueOperation::Ignore
115 }
116 }
117
118 /// Unmark the task as timer-queued.
119 #[cfg(feature = "integrated-timers")]
120 #[inline(always)]
121 pub fn timer_dequeue(&self) {
122 self.timer_queued.store(false, Ordering::Relaxed);
123 }
88} 124}