"Deadline Rank Sorted Scheduler" -> "Earliest Deadline First Scheduler"

This commit is contained in:
James Munns 2025-04-16 15:59:28 +02:00 committed by Dario Nieuwenhuis
parent 3929142f4c
commit 0e28ba1091
4 changed files with 17 additions and 16 deletions

View File

@ -46,7 +46,7 @@ flavors = [
[package.metadata.docs.rs]
default-target = "thumbv7em-none-eabi"
targets = ["thumbv7em-none-eabi"]
features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "drs-scheduler"]
features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "edf-scheduler"]
[dependencies]
defmt = { version = "1.0.1", optional = true }
@ -91,6 +91,7 @@ embassy-sync = { path = "../embassy-sync" }
rustversion = "1.0.21"
[features]
## Enable nightly-only features
nightly = ["embassy-executor-macros/nightly"]
@ -133,7 +134,7 @@ trace = ["_any_trace"]
rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"]
_any_trace = []
## Enable "Deadline Rank Sorted" Scheduler, using soft-realtime "deadlines" to prioritize
## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize
## tasks based on the remaining time before their deadline. Adds some overhead. Requires
## hardware atomic support
drs-scheduler = ["dep:embassy-time-driver"]
edf-scheduler = ["dep:embassy-time-driver"]

View File

@ -2,11 +2,11 @@ use core::future::{poll_fn, Future};
use core::task::Poll;
#[cfg(not(target_has_atomic = "ptr"))]
compile_error!("The `drs-scheduler` feature is currently only supported on targets with atomics.");
compile_error!("The `edf-scheduler` feature is currently only supported on targets with atomics.");
/// A type for interacting with the deadline of the current task
///
/// Requires the `drs-scheduler` feature
/// Requires the `edf-scheduler` feature
pub struct Deadline {
/// Deadline value in ticks, same time base and ticks as `embassy-time`
pub instant_ticks: u64,

View File

@ -28,7 +28,7 @@ pub(crate) mod util;
#[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")]
mod waker;
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
mod deadline;
use core::future::Future;
@ -45,7 +45,7 @@ use embassy_executor_timer_queue::TimerQueueItem;
#[cfg(feature = "arch-avr")]
use portable_atomic::AtomicPtr;
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
pub use deadline::Deadline;
#[cfg(feature = "arch-avr")]
use portable_atomic::AtomicPtr;
@ -105,9 +105,9 @@ pub(crate) struct TaskHeader {
pub(crate) state: State,
pub(crate) run_queue_item: RunQueueItem,
/// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of
/// the task itself as it being polled by the executor.
#[cfg(feature = "drs-scheduler")]
/// Earliest Deadline First scheduler Deadline. This field should not be accessed
/// outside the context of the task itself as it being polled by the executor.
#[cfg(feature = "edf-scheduler")]
pub(crate) deadline: SyncUnsafeCell<u64>,
pub(crate) executor: AtomicPtr<SyncExecutor>,
@ -216,7 +216,7 @@ impl<F: Future + 'static> TaskStorage<F> {
run_queue_item: RunQueueItem::new(),
// NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This
// will be lazily initalized in `initialize_impl`
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
deadline: SyncUnsafeCell::new(0u64),
executor: AtomicPtr::new(core::ptr::null_mut()),
// Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss`
@ -316,7 +316,7 @@ impl<F: Future + 'static> AvailableTask<F> {
// By default, deadlines are set to the maximum value, so that any task WITH
// a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
self.task.raw.deadline.set(deadline::Deadline::UNSET_DEADLINE_TICKS);
let task = TaskRef::new(self.task);

View File

@ -1,7 +1,7 @@
use core::ptr::{addr_of_mut, NonNull};
use cordyceps::sorted_list::Links;
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
use cordyceps::SortedList;
use cordyceps::{Linked, TransferStack};
@ -73,7 +73,7 @@ impl RunQueue {
/// Empty the queue, then call `on_task` for each task that was in the queue.
/// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue
/// and will be processed by the *next* call to `dequeue_all`, *not* the current one.
#[cfg(not(feature = "drs-scheduler"))]
#[cfg(not(feature = "edf-scheduler"))]
pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) {
let taken = self.stack.take_all();
for taskref in taken {
@ -82,7 +82,7 @@ impl RunQueue {
}
}
/// # Deadline Ranked Sorted Scheduler
/// # Earliest Deadline First Scheduler
///
/// This algorithm will loop until all enqueued tasks are processed.
///
@ -96,7 +96,7 @@ impl RunQueue {
///
/// This process will repeat until the local `sorted` queue AND the global
/// runqueue are both empty, at which point this function will return.
#[cfg(feature = "drs-scheduler")]
#[cfg(feature = "edf-scheduler")]
pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) {
// SAFETY: `deadline` can only be set through the `Deadline` interface, which
// only allows access to this value while the given task is being polled.