diff options
| author | Dion Dokter <[email protected]> | 2025-07-15 13:40:30 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-09-11 14:45:06 +0200 |
| commit | 3f606b28f3b32e9e3b9a9f136eeef52828a78512 (patch) | |
| tree | 640fec12732e7104516c9edbd79261d214887f96 /embassy-executor/src/raw/deadline.rs | |
| parent | b5c9e721009fd4331cdc1ce58a07698eb54f2959 (diff) | |
Change deadline to use internal atomics
Diffstat (limited to 'embassy-executor/src/raw/deadline.rs')
| -rw-r--r-- | embassy-executor/src/raw/deadline.rs | 101 |
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 @@ | |||
| 1 | use core::future::{poll_fn, Future}; | 1 | use core::future::{poll_fn, Future}; |
| 2 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 2 | use core::task::Poll; | 3 | use 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 |
| 7 | pub struct Deadline { | 8 | pub 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 | ||
| 12 | impl Deadline { | 13 | impl 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 | } |
