diff options
Diffstat (limited to 'embassy-executor')
| -rw-r--r-- | embassy-executor/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-executor/src/metadata.rs | 13 | ||||
| -rw-r--r-- | embassy-executor/src/raw/deadline.rs | 18 | ||||
| -rw-r--r-- | embassy-executor/src/raw/mod.rs | 19 | ||||
| -rw-r--r-- | embassy-executor/src/raw/run_queue.rs | 5 |
5 files changed, 36 insertions, 23 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 290e67bce..2de36d22d 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -118,6 +118,8 @@ arch-spin = ["_arch"] | |||
| 118 | 118 | ||
| 119 | ## Enable the `name` field in task metadata. | 119 | ## Enable the `name` field in task metadata. |
| 120 | metadata-name = ["embassy-executor-macros/metadata-name"] | 120 | metadata-name = ["embassy-executor-macros/metadata-name"] |
| 121 | ## Enable the `deadline` field in task metadata. | ||
| 122 | metadata-deadline = [] | ||
| 121 | 123 | ||
| 122 | #! ### Executor | 124 | #! ### Executor |
| 123 | 125 | ||
| @@ -133,4 +135,4 @@ _any_trace = [] | |||
| 133 | 135 | ||
| 134 | ## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize | 136 | ## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize |
| 135 | ## tasks based on the remaining time before their deadline. Adds some overhead. | 137 | ## tasks based on the remaining time before their deadline. Adds some overhead. |
| 136 | edf-scheduler = ["dep:embassy-time-driver"] | 138 | edf-scheduler = ["dep:embassy-time-driver", "metadata-deadline"] |
diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index f92c9b37c..fd8095629 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs | |||
| @@ -12,6 +12,8 @@ use crate::raw; | |||
| 12 | pub struct Metadata { | 12 | pub struct Metadata { |
| 13 | #[cfg(feature = "metadata-name")] | 13 | #[cfg(feature = "metadata-name")] |
| 14 | name: Mutex<Cell<Option<&'static str>>>, | 14 | name: Mutex<Cell<Option<&'static str>>>, |
| 15 | #[cfg(feature = "metadata-deadline")] | ||
| 16 | deadline: raw::Deadline, | ||
| 15 | } | 17 | } |
| 16 | 18 | ||
| 17 | impl Metadata { | 19 | impl Metadata { |
| @@ -19,6 +21,10 @@ impl Metadata { | |||
| 19 | Self { | 21 | Self { |
| 20 | #[cfg(feature = "metadata-name")] | 22 | #[cfg(feature = "metadata-name")] |
| 21 | name: Mutex::new(Cell::new(None)), | 23 | name: Mutex::new(Cell::new(None)), |
| 24 | // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This | ||
| 25 | // will be lazily initalized in `initialize_impl` | ||
| 26 | #[cfg(feature = "metadata-deadline")] | ||
| 27 | deadline: raw::Deadline::new_unset(), | ||
| 22 | } | 28 | } |
| 23 | } | 29 | } |
| 24 | 30 | ||
| @@ -52,4 +58,11 @@ impl Metadata { | |||
| 52 | pub fn set_name(&self, name: &'static str) { | 58 | pub fn set_name(&self, name: &'static str) { |
| 53 | critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) | 59 | critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) |
| 54 | } | 60 | } |
| 61 | |||
| 62 | /// Earliest Deadline First scheduler Deadline. This field should not be accessed | ||
| 63 | /// outside the context of the task itself as it being polled by the executor. | ||
| 64 | #[cfg(feature = "metadata-deadline")] | ||
| 65 | pub fn deadline(&self) -> &raw::Deadline { | ||
| 66 | &self.deadline | ||
| 67 | } | ||
| 55 | } | 68 | } |
diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index cbb379b82..5b585195d 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs | |||
| @@ -62,7 +62,7 @@ impl Deadline { | |||
| 62 | pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future<Output = ()> { | 62 | pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future<Output = ()> { |
| 63 | poll_fn(move |cx| { | 63 | poll_fn(move |cx| { |
| 64 | let task = super::task_from_waker(cx.waker()); | 64 | let task = super::task_from_waker(cx.waker()); |
| 65 | task.header().deadline.set(instant_ticks); | 65 | task.header().metadata.deadline().set(instant_ticks); |
| 66 | Poll::Ready(()) | 66 | Poll::Ready(()) |
| 67 | }) | 67 | }) |
| 68 | } | 68 | } |
| @@ -87,7 +87,7 @@ impl Deadline { | |||
| 87 | // reasons later. | 87 | // reasons later. |
| 88 | let deadline = now.saturating_add(duration_ticks); | 88 | let deadline = now.saturating_add(duration_ticks); |
| 89 | 89 | ||
| 90 | task.header().deadline.set(deadline); | 90 | task.header().metadata.deadline().set(deadline); |
| 91 | 91 | ||
| 92 | Poll::Ready(Deadline::new(deadline)) | 92 | Poll::Ready(Deadline::new(deadline)) |
| 93 | }) | 93 | }) |
| @@ -109,10 +109,10 @@ impl Deadline { | |||
| 109 | #[must_use = "Setting deadline must be polled to be effective"] | 109 | #[must_use = "Setting deadline must be polled to be effective"] |
| 110 | pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future<Output = Deadline> { | 110 | pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future<Output = Deadline> { |
| 111 | poll_fn(move |cx| { | 111 | poll_fn(move |cx| { |
| 112 | let task = super::task_from_waker(cx.waker()); | 112 | let task_header = super::task_from_waker(cx.waker()).header(); |
| 113 | 113 | ||
| 114 | // Get the last value | 114 | // Get the last value |
| 115 | let last = task.header().deadline.instant_ticks(); | 115 | let last = task_header.metadata.deadline().instant_ticks(); |
| 116 | 116 | ||
| 117 | // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave | 117 | // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave |
| 118 | // it for now, we can probably make this wrapping_add for performance | 118 | // it for now, we can probably make this wrapping_add for performance |
| @@ -120,7 +120,7 @@ impl Deadline { | |||
| 120 | let deadline = last.saturating_add(increment_ticks); | 120 | let deadline = last.saturating_add(increment_ticks); |
| 121 | 121 | ||
| 122 | // Store the new value | 122 | // Store the new value |
| 123 | task.header().deadline.set(deadline); | 123 | task_header.metadata.deadline().set(deadline); |
| 124 | 124 | ||
| 125 | Poll::Ready(Deadline::new(deadline)) | 125 | Poll::Ready(Deadline::new(deadline)) |
| 126 | }) | 126 | }) |
| @@ -134,7 +134,7 @@ impl Deadline { | |||
| 134 | poll_fn(move |cx| { | 134 | poll_fn(move |cx| { |
| 135 | let task = super::task_from_waker(cx.waker()); | 135 | let task = super::task_from_waker(cx.waker()); |
| 136 | 136 | ||
| 137 | let deadline = task.header().deadline.instant_ticks(); | 137 | let deadline = task.header().metadata.deadline().instant_ticks(); |
| 138 | Poll::Ready(Self::new(deadline)) | 138 | Poll::Ready(Self::new(deadline)) |
| 139 | }) | 139 | }) |
| 140 | } | 140 | } |
| @@ -146,12 +146,12 @@ impl Deadline { | |||
| 146 | #[must_use = "Clearing deadline must be polled to be effective"] | 146 | #[must_use = "Clearing deadline must be polled to be effective"] |
| 147 | pub fn clear_current_task_deadline() -> impl Future<Output = Self> { | 147 | pub fn clear_current_task_deadline() -> impl Future<Output = Self> { |
| 148 | poll_fn(move |cx| { | 148 | poll_fn(move |cx| { |
| 149 | let task = super::task_from_waker(cx.waker()); | 149 | let task_header = super::task_from_waker(cx.waker()).header(); |
| 150 | 150 | ||
| 151 | // get the old value | 151 | // get the old value |
| 152 | let deadline = task.header().deadline.instant_ticks(); | 152 | let deadline = task_header.metadata.deadline().instant_ticks(); |
| 153 | // Store the default value | 153 | // Store the default value |
| 154 | task.header().deadline.set(Self::UNSET_DEADLINE_TICKS); | 154 | task_header.metadata.deadline().set(Self::UNSET_DEADLINE_TICKS); |
| 155 | 155 | ||
| 156 | Poll::Ready(Self::new(deadline)) | 156 | Poll::Ready(Self::new(deadline)) |
| 157 | }) | 157 | }) |
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index be2c5ee28..f93bfdef9 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs | |||
| @@ -26,7 +26,7 @@ pub(crate) mod util; | |||
| 26 | #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] | 26 | #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] |
| 27 | mod waker; | 27 | mod waker; |
| 28 | 28 | ||
| 29 | #[cfg(feature = "edf-scheduler")] | 29 | #[cfg(feature = "metadata-deadline")] |
| 30 | mod deadline; | 30 | mod deadline; |
| 31 | 31 | ||
| 32 | use core::future::Future; | 32 | use core::future::Future; |
| @@ -43,7 +43,7 @@ use embassy_executor_timer_queue::TimerQueueItem; | |||
| 43 | #[cfg(feature = "arch-avr")] | 43 | #[cfg(feature = "arch-avr")] |
| 44 | use portable_atomic::AtomicPtr; | 44 | use portable_atomic::AtomicPtr; |
| 45 | 45 | ||
| 46 | #[cfg(feature = "edf-scheduler")] | 46 | #[cfg(feature = "metadata-deadline")] |
| 47 | pub use deadline::Deadline; | 47 | pub use deadline::Deadline; |
| 48 | #[cfg(feature = "arch-avr")] | 48 | #[cfg(feature = "arch-avr")] |
| 49 | use portable_atomic::AtomicPtr; | 49 | use portable_atomic::AtomicPtr; |
| @@ -103,11 +103,6 @@ pub(crate) struct TaskHeader { | |||
| 103 | pub(crate) state: State, | 103 | pub(crate) state: State, |
| 104 | pub(crate) run_queue_item: RunQueueItem, | 104 | pub(crate) run_queue_item: RunQueueItem, |
| 105 | 105 | ||
| 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. | ||
| 108 | #[cfg(feature = "edf-scheduler")] | ||
| 109 | pub(crate) deadline: Deadline, | ||
| 110 | |||
| 111 | pub(crate) executor: AtomicPtr<SyncExecutor>, | 106 | pub(crate) executor: AtomicPtr<SyncExecutor>, |
| 112 | poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, | 107 | poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, |
| 113 | 108 | ||
| @@ -212,10 +207,6 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 212 | raw: TaskHeader { | 207 | raw: TaskHeader { |
| 213 | state: State::new(), | 208 | state: State::new(), |
| 214 | run_queue_item: RunQueueItem::new(), | 209 | run_queue_item: RunQueueItem::new(), |
| 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` | ||
| 217 | #[cfg(feature = "edf-scheduler")] | ||
| 218 | deadline: Deadline::new_unset(), | ||
| 219 | executor: AtomicPtr::new(core::ptr::null_mut()), | 210 | executor: AtomicPtr::new(core::ptr::null_mut()), |
| 220 | // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` | 211 | // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` |
| 221 | poll_fn: SyncUnsafeCell::new(None), | 212 | poll_fn: SyncUnsafeCell::new(None), |
| @@ -315,7 +306,11 @@ impl<F: Future + 'static> AvailableTask<F> { | |||
| 315 | // By default, deadlines are set to the maximum value, so that any task WITH | 306 | // By default, deadlines are set to the maximum value, so that any task WITH |
| 316 | // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline | 307 | // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline |
| 317 | #[cfg(feature = "edf-scheduler")] | 308 | #[cfg(feature = "edf-scheduler")] |
| 318 | self.task.raw.deadline.set(deadline::Deadline::UNSET_DEADLINE_TICKS); | 309 | self.task |
| 310 | .raw | ||
| 311 | .metadata | ||
| 312 | .deadline() | ||
| 313 | .set(deadline::Deadline::UNSET_DEADLINE_TICKS); | ||
| 319 | 314 | ||
| 320 | let task = TaskRef::new(self.task); | 315 | let task = TaskRef::new(self.task); |
| 321 | 316 | ||
diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index e8a046a48..978ca082a 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs | |||
| @@ -109,7 +109,10 @@ impl RunQueue { | |||
| 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 | let mut sorted = SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| { | 111 | let mut sorted = SortedList::<TaskHeader>::new_with_cmp(|lhs, rhs| { |
| 112 | lhs.deadline.instant_ticks().cmp(&rhs.deadline.instant_ticks()) | 112 | lhs.metadata |
| 113 | .deadline() | ||
| 114 | .instant_ticks() | ||
| 115 | .cmp(&rhs.metadata.deadline().instant_ticks()) | ||
| 113 | }); | 116 | }); |
| 114 | 117 | ||
| 115 | loop { | 118 | loop { |
