diff options
Diffstat (limited to 'embassy-executor/src')
| -rw-r--r-- | embassy-executor/src/metadata.rs | 26 | ||||
| -rw-r--r-- | embassy-executor/src/raw/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-executor/src/raw/run_queue.rs | 29 |
3 files changed, 50 insertions, 10 deletions
diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index 4220048a6..bc0df0f83 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #[cfg(feature = "metadata-name")] | 1 | #[cfg(feature = "metadata-name")] |
| 2 | use core::cell::Cell; | 2 | use core::cell::Cell; |
| 3 | use core::future::{poll_fn, Future}; | 3 | use core::future::{poll_fn, Future}; |
| 4 | #[cfg(feature = "scheduler-priority")] | ||
| 5 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 4 | use core::task::Poll; | 6 | use core::task::Poll; |
| 5 | 7 | ||
| 6 | #[cfg(feature = "metadata-name")] | 8 | #[cfg(feature = "metadata-name")] |
| @@ -14,6 +16,8 @@ use crate::raw::Deadline; | |||
| 14 | pub struct Metadata { | 16 | pub struct Metadata { |
| 15 | #[cfg(feature = "metadata-name")] | 17 | #[cfg(feature = "metadata-name")] |
| 16 | name: Mutex<Cell<Option<&'static str>>>, | 18 | name: Mutex<Cell<Option<&'static str>>>, |
| 19 | #[cfg(feature = "scheduler-priority")] | ||
| 20 | priority: AtomicU8, | ||
| 17 | #[cfg(feature = "scheduler-deadline")] | 21 | #[cfg(feature = "scheduler-deadline")] |
| 18 | deadline: raw::Deadline, | 22 | deadline: raw::Deadline, |
| 19 | } | 23 | } |
| @@ -23,6 +27,8 @@ impl Metadata { | |||
| 23 | Self { | 27 | Self { |
| 24 | #[cfg(feature = "metadata-name")] | 28 | #[cfg(feature = "metadata-name")] |
| 25 | name: Mutex::new(Cell::new(None)), | 29 | name: Mutex::new(Cell::new(None)), |
| 30 | #[cfg(feature = "scheduler-priority")] | ||
| 31 | priority: AtomicU8::new(0), | ||
| 26 | // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This | 32 | // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This |
| 27 | // will be lazily initalized in `initialize_impl` | 33 | // will be lazily initalized in `initialize_impl` |
| 28 | #[cfg(feature = "scheduler-deadline")] | 34 | #[cfg(feature = "scheduler-deadline")] |
| @@ -33,6 +39,14 @@ impl Metadata { | |||
| 33 | pub(crate) fn reset(&self) { | 39 | pub(crate) fn reset(&self) { |
| 34 | #[cfg(feature = "metadata-name")] | 40 | #[cfg(feature = "metadata-name")] |
| 35 | critical_section::with(|cs| self.name.borrow(cs).set(None)); | 41 | critical_section::with(|cs| self.name.borrow(cs).set(None)); |
| 42 | |||
| 43 | #[cfg(feature = "scheduler-priority")] | ||
| 44 | self.set_priority(0); | ||
| 45 | |||
| 46 | // By default, deadlines are set to the maximum value, so that any task WITH | ||
| 47 | // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline | ||
| 48 | #[cfg(feature = "scheduler-deadline")] | ||
| 49 | self.unset_deadline(); | ||
| 36 | } | 50 | } |
| 37 | 51 | ||
| 38 | /// Get the metadata for the current task. | 52 | /// Get the metadata for the current task. |
| @@ -61,6 +75,18 @@ impl Metadata { | |||
| 61 | critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) | 75 | critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) |
| 62 | } | 76 | } |
| 63 | 77 | ||
| 78 | /// Get this task's priority. | ||
| 79 | #[cfg(feature = "scheduler-priority")] | ||
| 80 | pub fn priority(&self) -> u8 { | ||
| 81 | self.priority.load(Ordering::Relaxed) | ||
| 82 | } | ||
| 83 | |||
| 84 | /// Set this task's priority. | ||
| 85 | #[cfg(feature = "scheduler-priority")] | ||
| 86 | pub fn set_priority(&self, priority: u8) { | ||
| 87 | self.priority.store(priority, Ordering::Relaxed) | ||
| 88 | } | ||
| 89 | |||
| 64 | /// Get this task's deadline. | 90 | /// Get this task's deadline. |
| 65 | #[cfg(feature = "scheduler-deadline")] | 91 | #[cfg(feature = "scheduler-deadline")] |
| 66 | pub fn deadline(&self) -> u64 { | 92 | pub fn deadline(&self) -> u64 { |
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 51a363385..9f36c60bc 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs | |||
| @@ -300,11 +300,6 @@ impl<F: Future + 'static> AvailableTask<F> { | |||
| 300 | self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll)); | 300 | self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll)); |
| 301 | self.task.future.write_in_place(future); | 301 | self.task.future.write_in_place(future); |
| 302 | 302 | ||
| 303 | // By default, deadlines are set to the maximum value, so that any task WITH | ||
| 304 | // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline | ||
| 305 | #[cfg(feature = "scheduler-deadline")] | ||
| 306 | self.task.raw.metadata.unset_deadline(); | ||
| 307 | |||
| 308 | let task = TaskRef::new(self.task); | 303 | let task = TaskRef::new(self.task); |
| 309 | 304 | ||
| 310 | SpawnToken::new(task) | 305 | SpawnToken::new(task) |
diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index d98c26f73..b8b052310 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs | |||
| @@ -2,7 +2,7 @@ use core::ptr::{addr_of_mut, NonNull}; | |||
| 2 | 2 | ||
| 3 | use cordyceps::sorted_list::Links; | 3 | use cordyceps::sorted_list::Links; |
| 4 | use cordyceps::Linked; | 4 | use cordyceps::Linked; |
| 5 | #[cfg(feature = "scheduler-deadline")] | 5 | #[cfg(any(feature = "scheduler-priority", feature = "scheduler-deadline"))] |
| 6 | use cordyceps::SortedList; | 6 | use cordyceps::SortedList; |
| 7 | 7 | ||
| 8 | #[cfg(target_has_atomic = "ptr")] | 8 | #[cfg(target_has_atomic = "ptr")] |
| @@ -83,7 +83,7 @@ impl RunQueue { | |||
| 83 | /// Empty the queue, then call `on_task` for each task that was in the queue. | 83 | /// Empty the queue, then call `on_task` for each task that was in the queue. |
| 84 | /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue | 84 | /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue |
| 85 | /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. | 85 | /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. |
| 86 | #[cfg(not(feature = "scheduler-deadline"))] | 86 | #[cfg(not(any(feature = "scheduler-priority", feature = "scheduler-deadline")))] |
| 87 | pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { | 87 | pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { |
| 88 | let taken = self.stack.take_all(); | 88 | let taken = self.stack.take_all(); |
| 89 | for taskref in taken { | 89 | for taskref in taken { |
| @@ -106,10 +106,29 @@ impl RunQueue { | |||
| 106 | /// | 106 | /// |
| 107 | /// This process will repeat until the local `sorted` queue AND the global | 107 | /// This process will repeat until the local `sorted` queue AND the global |
| 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 = "scheduler-deadline")] | 109 | #[cfg(any(feature = "scheduler-priority", feature = "scheduler-deadline"))] |
| 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 | let mut sorted = | 111 | let mut sorted = SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| { |
| 112 | SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| lhs.metadata.deadline().cmp(&rhs.metadata.deadline())); | 112 | // compare by priority first |
| 113 | #[cfg(feature = "scheduler-priority")] | ||
| 114 | { | ||
| 115 | let lp = lhs.metadata.priority(); | ||
| 116 | let rp = rhs.metadata.priority(); | ||
| 117 | if lp != rp { | ||
| 118 | return lp.cmp(&rp).reverse(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | // compare deadlines in case of tie. | ||
| 122 | #[cfg(feature = "scheduler-deadline")] | ||
| 123 | { | ||
| 124 | let ld = lhs.metadata.deadline(); | ||
| 125 | let rd = rhs.metadata.deadline(); | ||
| 126 | if ld != rd { | ||
| 127 | return ld.cmp(&rd); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | core::cmp::Ordering::Equal | ||
| 131 | }); | ||
| 113 | 132 | ||
| 114 | loop { | 133 | loop { |
| 115 | // For each loop, grab any newly pended items | 134 | // For each loop, grab any newly pended items |
