aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/state_critical_section.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-11-14 22:32:48 +0100
committerDario Nieuwenhuis <[email protected]>2023-11-15 18:43:27 +0100
commitbef9b7a8539c3dddb1cf6ab46db161f1ca56b1a1 (patch)
tree6d15736eec0029c13093bee120bd2189aa9537ac /embassy-executor/src/raw/state_critical_section.rs
parent50a983fd9b8f10fa5153757593e9f8cfccc902ac (diff)
executor: remove atomic-polyfill.
Diffstat (limited to 'embassy-executor/src/raw/state_critical_section.rs')
-rw-r--r--embassy-executor/src/raw/state_critical_section.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/embassy-executor/src/raw/state_critical_section.rs b/embassy-executor/src/raw/state_critical_section.rs
new file mode 100644
index 000000000..c3cc1b0b7
--- /dev/null
+++ b/embassy-executor/src/raw/state_critical_section.rs
@@ -0,0 +1,93 @@
1use core::cell::Cell;
2
3use critical_section::Mutex;
4
5/// Task is spawned (has a future)
6pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
7/// Task is in the executor run queue
8pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
9/// Task is in the executor timer queue
10#[cfg(feature = "integrated-timers")]
11pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
12
13pub(crate) struct State {
14 state: Mutex<Cell<u32>>,
15}
16
17impl State {
18 pub const fn new() -> State {
19 Self {
20 state: Mutex::new(Cell::new(0)),
21 }
22 }
23
24 fn update<R>(&self, f: impl FnOnce(&mut u32) -> R) -> R {
25 critical_section::with(|cs| {
26 let s = self.state.borrow(cs);
27 let mut val = s.get();
28 let r = f(&mut val);
29 s.set(val);
30 r
31 })
32 }
33
34 /// If task is idle, mark it as spawned + run_queued and return true.
35 #[inline(always)]
36 pub fn spawn(&self) -> bool {
37 self.update(|s| {
38 if *s == 0 {
39 *s = STATE_SPAWNED | STATE_RUN_QUEUED;
40 true
41 } else {
42 false
43 }
44 })
45 }
46
47 /// Unmark the task as spawned.
48 #[inline(always)]
49 pub fn despawn(&self) {
50 self.update(|s| *s &= !STATE_SPAWNED);
51 }
52
53 /// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success.
54 #[inline(always)]
55 pub fn run_enqueue(&self) -> bool {
56 self.update(|s| {
57 if (*s & STATE_RUN_QUEUED != 0) || (*s & STATE_SPAWNED == 0) {
58 false
59 } else {
60 *s |= STATE_RUN_QUEUED;
61 true
62 }
63 })
64 }
65
66 /// Unmark the task as run-queued. Return whether the task is spawned.
67 #[inline(always)]
68 pub fn run_dequeue(&self) -> bool {
69 self.update(|s| {
70 let ok = *s & STATE_SPAWNED != 0;
71 *s &= !STATE_RUN_QUEUED;
72 ok
73 })
74 }
75
76 /// Mark the task as timer-queued. Return whether it was newly queued (i.e. not queued before)
77 #[cfg(feature = "integrated-timers")]
78 #[inline(always)]
79 pub fn timer_enqueue(&self) -> bool {
80 self.update(|s| {
81 let ok = *s & STATE_TIMER_QUEUED == 0;
82 *s |= STATE_TIMER_QUEUED;
83 ok
84 })
85 }
86
87 /// Unmark the task as timer-queued.
88 #[cfg(feature = "integrated-timers")]
89 #[inline(always)]
90 pub fn timer_dequeue(&self) {
91 self.update(|s| *s &= !STATE_TIMER_QUEUED);
92 }
93}