aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/deadline.rs
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2025-07-15 13:40:30 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-11 14:45:06 +0200
commit3f606b28f3b32e9e3b9a9f136eeef52828a78512 (patch)
tree640fec12732e7104516c9edbd79261d214887f96 /embassy-executor/src/raw/deadline.rs
parentb5c9e721009fd4331cdc1ce58a07698eb54f2959 (diff)
Change deadline to use internal atomics
Diffstat (limited to 'embassy-executor/src/raw/deadline.rs')
-rw-r--r--embassy-executor/src/raw/deadline.rs101
1 files changed, 50 insertions, 51 deletions
diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs
index 0fb22a7ce..a61852612 100644
--- a/embassy-executor/src/raw/deadline.rs
+++ b/embassy-executor/src/raw/deadline.rs
@@ -1,15 +1,41 @@
1use core::future::{poll_fn, Future}; 1use core::future::{poll_fn, Future};
2use core::sync::atomic::{AtomicU32, Ordering};
2use core::task::Poll; 3use core::task::Poll;
3 4
4/// A type for interacting with the deadline of the current task 5/// A type for interacting with the deadline of the current task
5/// 6///
6/// Requires the `edf-scheduler` feature 7/// Requires the `edf-scheduler` feature
7pub struct Deadline { 8pub struct Deadline {
8 /// Deadline value in ticks, same time base and ticks as `embassy-time` 9 instant_ticks_hi: AtomicU32,
9 pub instant_ticks: u64, 10 instant_ticks_lo: AtomicU32,
10} 11}
11 12
12impl Deadline { 13impl Deadline {
14 pub(crate) const fn new(instant_ticks: u64) -> Self {
15 Self {
16 instant_ticks_hi: AtomicU32::new((instant_ticks >> 32) as u32),
17 instant_ticks_lo: AtomicU32::new(instant_ticks as u32),
18 }
19 }
20
21 pub(crate) const fn new_unset() -> Self {
22 Self::new(Self::UNSET_DEADLINE_TICKS)
23 }
24
25 pub(crate) fn set(&self, instant_ticks: u64) {
26 self.instant_ticks_hi
27 .store((instant_ticks >> 32) as u32, Ordering::Relaxed);
28 self.instant_ticks_lo.store(instant_ticks as u32, Ordering::Relaxed);
29 }
30
31 /// Deadline value in ticks, same time base and ticks as `embassy-time`
32 pub fn instant_ticks(&self) -> u64 {
33 let hi = self.instant_ticks_hi.load(Ordering::Relaxed) as u64;
34 let lo = self.instant_ticks_lo.load(Ordering::Relaxed) as u64;
35
36 (hi << 32) | lo
37 }
38
13 /// Sentinel value representing an "unset" deadline, which has lower priority 39 /// Sentinel value representing an "unset" deadline, which has lower priority
14 /// than any other set deadline value 40 /// than any other set deadline value
15 pub const UNSET_DEADLINE_TICKS: u64 = u64::MAX; 41 pub const UNSET_DEADLINE_TICKS: u64 = u64::MAX;
@@ -17,7 +43,7 @@ impl Deadline {
17 /// Does the given Deadline represent an "unset" deadline? 43 /// Does the given Deadline represent an "unset" deadline?
18 #[inline] 44 #[inline]
19 pub fn is_unset(&self) -> bool { 45 pub fn is_unset(&self) -> bool {
20 self.instant_ticks == Self::UNSET_DEADLINE_TICKS 46 self.instant_ticks() == Self::UNSET_DEADLINE_TICKS
21 } 47 }
22 48
23 /// Set the current task's deadline at exactly `instant_ticks` 49 /// Set the current task's deadline at exactly `instant_ticks`
@@ -32,11 +58,7 @@ impl Deadline {
32 pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future<Output = ()> { 58 pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future<Output = ()> {
33 poll_fn(move |cx| { 59 poll_fn(move |cx| {
34 let task = super::task_from_waker(cx.waker()); 60 let task = super::task_from_waker(cx.waker());
35 // SAFETY: A task can only modify its own deadline, while the task is being 61 task.header().deadline.set(instant_ticks);
36 // polled, meaning that there cannot be concurrent access to the deadline.
37 unsafe {
38 task.header().deadline.set(instant_ticks);
39 }
40 Poll::Ready(()) 62 Poll::Ready(())
41 }) 63 })
42 } 64 }
@@ -61,14 +83,9 @@ impl Deadline {
61 // reasons later. 83 // reasons later.
62 let deadline = now.saturating_add(duration_ticks); 84 let deadline = now.saturating_add(duration_ticks);
63 85
64 // SAFETY: A task can only modify its own deadline, while the task is being 86 task.header().deadline.set(deadline);
65 // polled, meaning that there cannot be concurrent access to the deadline. 87
66 unsafe { 88 Poll::Ready(Deadline::new(deadline))
67 task.header().deadline.set(deadline);
68 }
69 Poll::Ready(Deadline {
70 instant_ticks: deadline,
71 })
72 }) 89 })
73 } 90 }
74 91
@@ -90,24 +107,18 @@ impl Deadline {
90 poll_fn(move |cx| { 107 poll_fn(move |cx| {
91 let task = super::task_from_waker(cx.waker()); 108 let task = super::task_from_waker(cx.waker());
92 109
93 // SAFETY: A task can only modify its own deadline, while the task is being 110 // Get the last value
94 // polled, meaning that there cannot be concurrent access to the deadline. 111 let last = task.header().deadline.instant_ticks();
95 unsafe {
96 // Get the last value
97 let last = task.header().deadline.get();
98 112
99 // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave 113 // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave
100 // it for now, we can probably make this wrapping_add for performance 114 // it for now, we can probably make this wrapping_add for performance
101 // reasons later. 115 // reasons later.
102 let deadline = last.saturating_add(increment_ticks); 116 let deadline = last.saturating_add(increment_ticks);
103 117
104 // Store the new value 118 // Store the new value
105 task.header().deadline.set(deadline); 119 task.header().deadline.set(deadline);
106 120
107 Poll::Ready(Deadline { 121 Poll::Ready(Deadline::new(deadline))
108 instant_ticks: deadline,
109 })
110 }
111 }) 122 })
112 } 123 }
113 124
@@ -119,12 +130,8 @@ impl Deadline {
119 poll_fn(move |cx| { 130 poll_fn(move |cx| {
120 let task = super::task_from_waker(cx.waker()); 131 let task = super::task_from_waker(cx.waker());
121 132
122 // SAFETY: A task can only modify its own deadline, while the task is being 133 let deadline = task.header().deadline.instant_ticks();
123 // polled, meaning that there cannot be concurrent access to the deadline. 134 Poll::Ready(Self::new(deadline))
124 let deadline = unsafe { task.header().deadline.get() };
125 Poll::Ready(Self {
126 instant_ticks: deadline,
127 })
128 }) 135 })
129 } 136 }
130 137
@@ -137,20 +144,12 @@ impl Deadline {
137 poll_fn(move |cx| { 144 poll_fn(move |cx| {
138 let task = super::task_from_waker(cx.waker()); 145 let task = super::task_from_waker(cx.waker());
139 146
140 // SAFETY: A task can only modify its own deadline, while the task is being 147 // get the old value
141 // polled, meaning that there cannot be concurrent access to the deadline. 148 let deadline = task.header().deadline.instant_ticks();
142 let deadline = unsafe { 149 // Store the default value
143 // get the old value 150 task.header().deadline.set(Self::UNSET_DEADLINE_TICKS);
144 let d = task.header().deadline.get(); 151
145 // Store the default value 152 Poll::Ready(Self::new(deadline))
146 task.header().deadline.set(Self::UNSET_DEADLINE_TICKS);
147 // return the old value
148 d
149 };
150
151 Poll::Ready(Self {
152 instant_ticks: deadline,
153 })
154 }) 153 })
155 } 154 }
156} 155}