aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src')
-rw-r--r--embassy-executor/src/metadata.rs26
-rw-r--r--embassy-executor/src/raw/mod.rs5
-rw-r--r--embassy-executor/src/raw/run_queue.rs29
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")]
2use core::cell::Cell; 2use core::cell::Cell;
3use core::future::{poll_fn, Future}; 3use core::future::{poll_fn, Future};
4#[cfg(feature = "scheduler-priority")]
5use core::sync::atomic::{AtomicU8, Ordering};
4use core::task::Poll; 6use core::task::Poll;
5 7
6#[cfg(feature = "metadata-name")] 8#[cfg(feature = "metadata-name")]
@@ -14,6 +16,8 @@ use crate::raw::Deadline;
14pub struct Metadata { 16pub 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
3use cordyceps::sorted_list::Links; 3use cordyceps::sorted_list::Links;
4use cordyceps::Linked; 4use cordyceps::Linked;
5#[cfg(feature = "scheduler-deadline")] 5#[cfg(any(feature = "scheduler-priority", feature = "scheduler-deadline"))]
6use cordyceps::SortedList; 6use 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