aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src')
-rw-r--r--embassy-executor/src/raw/deadline.rs101
-rw-r--r--embassy-executor/src/raw/mod.rs4
-rw-r--r--embassy-executor/src/raw/run_queue.rs8
3 files changed, 55 insertions, 58 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}
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index cc43690cb..be2c5ee28 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -106,7 +106,7 @@ pub(crate) struct TaskHeader {
106 /// Earliest Deadline First scheduler Deadline. This field should not be accessed 106 /// Earliest Deadline First scheduler Deadline. This field should not be accessed
107 /// outside the context of the task itself as it being polled by the executor. 107 /// outside the context of the task itself as it being polled by the executor.
108 #[cfg(feature = "edf-scheduler")] 108 #[cfg(feature = "edf-scheduler")]
109 pub(crate) deadline: SyncUnsafeCell<u64>, 109 pub(crate) deadline: Deadline,
110 110
111 pub(crate) executor: AtomicPtr<SyncExecutor>, 111 pub(crate) executor: AtomicPtr<SyncExecutor>,
112 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, 112 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>,
@@ -215,7 +215,7 @@ impl<F: Future + 'static> TaskStorage<F> {
215 // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This 215 // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This
216 // will be lazily initalized in `initialize_impl` 216 // will be lazily initalized in `initialize_impl`
217 #[cfg(feature = "edf-scheduler")] 217 #[cfg(feature = "edf-scheduler")]
218 deadline: SyncUnsafeCell::new(0u64), 218 deadline: Deadline::new_unset(),
219 executor: AtomicPtr::new(core::ptr::null_mut()), 219 executor: AtomicPtr::new(core::ptr::null_mut()),
220 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` 220 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss`
221 poll_fn: SyncUnsafeCell::new(None), 221 poll_fn: SyncUnsafeCell::new(None),
diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs
index 97060f4b9..e8a046a48 100644
--- a/embassy-executor/src/raw/run_queue.rs
+++ b/embassy-executor/src/raw/run_queue.rs
@@ -108,11 +108,9 @@ impl RunQueue {
108 /// runqueue are both empty, at which point this function will return. 108 /// runqueue are both empty, at which point this function will return.
109 #[cfg(feature = "edf-scheduler")] 109 #[cfg(feature = "edf-scheduler")]
110 pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { 110 pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) {
111 // SAFETY: `deadline` can only be set through the `Deadline` interface, which 111 let mut sorted = SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| {
112 // only allows access to this value while the given task is being polled. 112 lhs.deadline.instant_ticks().cmp(&rhs.deadline.instant_ticks())
113 // This acts as mutual exclusion for access. 113 });
114 let mut sorted =
115 SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) });
116 114
117 loop { 115 loop {
118 // For each loop, grab any newly pended items 116 // For each loop, grab any newly pended items