aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/state_atomics_arm.rs
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-12-13 20:35:40 +0100
committerDániel Buga <[email protected]>2024-12-16 15:28:19 +0100
commitf389ba37219d842d7db0ab94cd421c69645a5757 (patch)
treebee175817d7dc3119c5533bd78069cd6ce0a7f44 /embassy-executor/src/raw/state_atomics_arm.rs
parent2c3bc75da6008afa7cacc1045954cef7e3d8740f (diff)
Only lock once to wake a task
Diffstat (limited to 'embassy-executor/src/raw/state_atomics_arm.rs')
-rw-r--r--embassy-executor/src/raw/state_atomics_arm.rs19
1 files changed, 15 insertions, 4 deletions
diff --git a/embassy-executor/src/raw/state_atomics_arm.rs b/embassy-executor/src/raw/state_atomics_arm.rs
index 7a152e8c0..f0f014652 100644
--- a/embassy-executor/src/raw/state_atomics_arm.rs
+++ b/embassy-executor/src/raw/state_atomics_arm.rs
@@ -3,6 +3,15 @@ use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering};
3 3
4use super::timer_queue::TimerEnqueueOperation; 4use super::timer_queue::TimerEnqueueOperation;
5 5
6pub(crate) struct Token(());
7
8/// Creates a token and passes it to the closure.
9///
10/// This is a no-op replacement for `CriticalSection::with` because we don't need any locking.
11pub(crate) fn locked(f: impl FnOnce(Token)) {
12 f(Token(()));
13}
14
6// Must be kept in sync with the layout of `State`! 15// Must be kept in sync with the layout of `State`!
7pub(crate) const STATE_SPAWNED: u32 = 1 << 0; 16pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
8pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 8; 17pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 8;
@@ -57,9 +66,10 @@ impl State {
57 self.spawned.store(false, Ordering::Relaxed); 66 self.spawned.store(false, Ordering::Relaxed);
58 } 67 }
59 68
60 /// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success. 69 /// Mark the task as run-queued if it's spawned and isn't already run-queued. Run the given
70 /// function if the task was successfully marked.
61 #[inline(always)] 71 #[inline(always)]
62 pub fn run_enqueue(&self) -> bool { 72 pub fn run_enqueue(&self, f: impl FnOnce(Token)) {
63 unsafe { 73 unsafe {
64 loop { 74 loop {
65 let state: u32; 75 let state: u32;
@@ -67,14 +77,15 @@ impl State {
67 77
68 if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) { 78 if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) {
69 asm!("clrex", options(nomem, nostack)); 79 asm!("clrex", options(nomem, nostack));
70 return false; 80 return;
71 } 81 }
72 82
73 let outcome: usize; 83 let outcome: usize;
74 let new_state = state | STATE_RUN_QUEUED; 84 let new_state = state | STATE_RUN_QUEUED;
75 asm!("strex {}, {}, [{}]", out(reg) outcome, in(reg) new_state, in(reg) self, options(nostack)); 85 asm!("strex {}, {}, [{}]", out(reg) outcome, in(reg) new_state, in(reg) self, options(nostack));
76 if outcome == 0 { 86 if outcome == 0 {
77 return true; 87 locked(f);
88 return;
78 } 89 }
79 } 90 }
80 } 91 }