aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/state_critical_section.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-12-16 14:46:08 +0000
committerGitHub <[email protected]>2024-12-16 14:46:08 +0000
commit47e96beff4fc4c8dff8bf6d6a67e1d2e81c40495 (patch)
treebee175817d7dc3119c5533bd78069cd6ce0a7f44 /embassy-executor/src/raw/state_critical_section.rs
parent2c3bc75da6008afa7cacc1045954cef7e3d8740f (diff)
parentf389ba37219d842d7db0ab94cd421c69645a5757 (diff)
Merge pull request #3644 from bugadani/lock_once
Only lock once to wake a task
Diffstat (limited to 'embassy-executor/src/raw/state_critical_section.rs')
-rw-r--r--embassy-executor/src/raw/state_critical_section.rs42
1 files changed, 25 insertions, 17 deletions
diff --git a/embassy-executor/src/raw/state_critical_section.rs b/embassy-executor/src/raw/state_critical_section.rs
index 367162ba2..8e570b33c 100644
--- a/embassy-executor/src/raw/state_critical_section.rs
+++ b/embassy-executor/src/raw/state_critical_section.rs
@@ -1,6 +1,7 @@
1use core::cell::Cell; 1use core::cell::Cell;
2 2
3use critical_section::Mutex; 3pub(crate) use critical_section::{with as locked, CriticalSection as Token};
4use critical_section::{CriticalSection, Mutex};
4 5
5use super::timer_queue::TimerEnqueueOperation; 6use super::timer_queue::TimerEnqueueOperation;
6 7
@@ -23,13 +24,15 @@ impl State {
23 } 24 }
24 25
25 fn update<R>(&self, f: impl FnOnce(&mut u32) -> R) -> R { 26 fn update<R>(&self, f: impl FnOnce(&mut u32) -> R) -> R {
26 critical_section::with(|cs| { 27 critical_section::with(|cs| self.update_with_cs(cs, f))
27 let s = self.state.borrow(cs); 28 }
28 let mut val = s.get(); 29
29 let r = f(&mut val); 30 fn update_with_cs<R>(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut u32) -> R) -> R {
30 s.set(val); 31 let s = self.state.borrow(cs);
31 r 32 let mut val = s.get();
32 }) 33 let r = f(&mut val);
34 s.set(val);
35 r
33 } 36 }
34 37
35 /// If task is idle, mark it as spawned + run_queued and return true. 38 /// If task is idle, mark it as spawned + run_queued and return true.
@@ -51,17 +54,22 @@ impl State {
51 self.update(|s| *s &= !STATE_SPAWNED); 54 self.update(|s| *s &= !STATE_SPAWNED);
52 } 55 }
53 56
54 /// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success. 57 /// Mark the task as run-queued if it's spawned and isn't already run-queued. Run the given
58 /// function if the task was successfully marked.
55 #[inline(always)] 59 #[inline(always)]
56 pub fn run_enqueue(&self) -> bool { 60 pub fn run_enqueue(&self, f: impl FnOnce(Token)) {
57 self.update(|s| { 61 critical_section::with(|cs| {
58 if (*s & STATE_RUN_QUEUED != 0) || (*s & STATE_SPAWNED == 0) { 62 if self.update_with_cs(cs, |s| {
59 false 63 if (*s & STATE_RUN_QUEUED != 0) || (*s & STATE_SPAWNED == 0) {
60 } else { 64 false
61 *s |= STATE_RUN_QUEUED; 65 } else {
62 true 66 *s |= STATE_RUN_QUEUED;
67 true
68 }
69 }) {
70 f(cs);
63 } 71 }
64 }) 72 });
65 } 73 }
66 74
67 /// Unmark the task as run-queued. Return whether the task is spawned. 75 /// Unmark the task as run-queued. Return whether the task is spawned.