aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-04-01 19:32:12 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-11 14:45:06 +0200
commited2e51bfa4f92b422233343a0c5b1af98fb36537 (patch)
tree481133e93d5eb8f2017c9e308220e24007a58c04 /embassy-executor/src/raw
parentba0426f767bb602750bed4fae87a156b661c0e92 (diff)
Dependency enablement trickery
Diffstat (limited to 'embassy-executor/src/raw')
-rw-r--r--embassy-executor/src/raw/deadline.rs2
-rw-r--r--embassy-executor/src/raw/mod.rs11
-rw-r--r--embassy-executor/src/raw/run_queue_atomics.rs19
3 files changed, 25 insertions, 7 deletions
diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs
index 3f60936cc..c8cc94c52 100644
--- a/embassy-executor/src/raw/deadline.rs
+++ b/embassy-executor/src/raw/deadline.rs
@@ -2,6 +2,8 @@ use core::future::{poll_fn, Future};
2use core::task::Poll; 2use core::task::Poll;
3 3
4/// A type for interacting with the deadline of the current task 4/// A type for interacting with the deadline of the current task
5///
6/// Requires the `drs-scheduler` feature
5pub struct Deadline { 7pub struct Deadline {
6 /// Deadline value in ticks, same time base and ticks as `embassy-time` 8 /// Deadline value in ticks, same time base and ticks as `embassy-time`
7 pub instant_ticks: u64, 9 pub instant_ticks: u64,
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 0dd247d30..f4fbe1bfc 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -101,14 +101,14 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static
101/// - 5: Task is dequeued. The task's future is not polled, because exiting the task replaces its `poll_fn`. 101/// - 5: Task is dequeued. The task's future is not polled, because exiting the task replaces its `poll_fn`.
102/// - 6: A task is waken when it is not spawned - `wake_task -> State::run_enqueue` 102/// - 6: A task is waken when it is not spawned - `wake_task -> State::run_enqueue`
103pub(crate) struct TaskHeader { 103pub(crate) struct TaskHeader {
104 pub(crate) state: State,
104 pub(crate) run_queue_item: RunQueueItem, 105 pub(crate) run_queue_item: RunQueueItem,
105 106
106 #[cfg(feature = "drs-scheduler")]
107 /// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of 107 /// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of
108 /// the task itself as it being polled by the executor. 108 /// the task itself as it being polled by the executor.
109 #[cfg(feature = "drs-scheduler")]
109 pub(crate) deadline: SyncUnsafeCell<u64>, 110 pub(crate) deadline: SyncUnsafeCell<u64>,
110 111
111 pub(crate) state: State,
112 pub(crate) executor: AtomicPtr<SyncExecutor>, 112 pub(crate) executor: AtomicPtr<SyncExecutor>,
113 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, 113 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>,
114 114
@@ -211,10 +211,12 @@ impl<F: Future + 'static> TaskStorage<F> {
211 pub const fn new() -> Self { 211 pub const fn new() -> Self {
212 Self { 212 Self {
213 raw: TaskHeader { 213 raw: TaskHeader {
214 state: State::new(),
214 run_queue_item: RunQueueItem::new(), 215 run_queue_item: RunQueueItem::new(),
216 // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This
217 // will be lazily initalized in `initialize_impl`
215 #[cfg(feature = "drs-scheduler")] 218 #[cfg(feature = "drs-scheduler")]
216 deadline: SyncUnsafeCell::new(0u64), 219 deadline: SyncUnsafeCell::new(0u64),
217 state: State::new(),
218 executor: AtomicPtr::new(core::ptr::null_mut()), 220 executor: AtomicPtr::new(core::ptr::null_mut()),
219 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` 221 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss`
220 poll_fn: SyncUnsafeCell::new(None), 222 poll_fn: SyncUnsafeCell::new(None),
@@ -311,7 +313,8 @@ impl<F: Future + 'static> AvailableTask<F> {
311 self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll)); 313 self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll));
312 self.task.future.write_in_place(future); 314 self.task.future.write_in_place(future);
313 315
314 // TODO(AJM): Some other way of setting this? Just a placeholder 316 // By default, deadlines are set to the maximum value, so that any task WITH
317 // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline
315 #[cfg(feature = "drs-scheduler")] 318 #[cfg(feature = "drs-scheduler")]
316 self.task.raw.deadline.set(u64::MAX); 319 self.task.raw.deadline.set(u64::MAX);
317 320
diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs
index bc5d38250..3715fc658 100644
--- a/embassy-executor/src/raw/run_queue_atomics.rs
+++ b/embassy-executor/src/raw/run_queue_atomics.rs
@@ -66,6 +66,8 @@ impl RunQueue {
66 self.stack.push_was_empty(task) 66 self.stack.push_was_empty(task)
67 } 67 }
68 68
69 /// # Standard atomic runqueue
70 ///
69 /// Empty the queue, then call `on_task` for each task that was in the queue. 71 /// Empty the queue, then call `on_task` for each task that was in the queue.
70 /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue 72 /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue
71 /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. 73 /// and will be processed by the *next* call to `dequeue_all`, *not* the current one.
@@ -78,9 +80,20 @@ impl RunQueue {
78 } 80 }
79 } 81 }
80 82
81 /// Empty the queue, then call `on_task` for each task that was in the queue. 83 /// # Deadline Ranked Sorted Scheduler
82 /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue 84 ///
83 /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. 85 /// This algorithm will loop until all enqueued tasks are processed.
86 ///
87 /// Before polling a task, all currently enqueued tasks will be popped from the
88 /// runqueue, and will be added to the working `sorted` list, a linked-list that
89 /// sorts tasks by their deadline, with nearest deadline items in the front, and
90 /// furthest deadline items in the back.
91 ///
92 /// After popping and sorting all pending tasks, the SOONEST task will be popped
93 /// from the front of the queue, and polled by calling `on_task` on it.
94 ///
95 /// This process will repeat until the local `sorted` queue AND the global
96 /// runqueue are both empty, at which point this function will return.
84 #[cfg(feature = "drs-scheduler")] 97 #[cfg(feature = "drs-scheduler")]
85 pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { 98 pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) {
86 // SAFETY: `deadline` can only be set through the `Deadline` interface, which 99 // SAFETY: `deadline` can only be set through the `Deadline` interface, which