aboutsummaryrefslogtreecommitdiff
path: root/embassy-time-queue-driver/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-time-queue-driver/src/lib.rs')
-rw-r--r--embassy-time-queue-driver/src/lib.rs75
1 files changed, 32 insertions, 43 deletions
diff --git a/embassy-time-queue-driver/src/lib.rs b/embassy-time-queue-driver/src/lib.rs
index 50736e8c7..97c81a124 100644
--- a/embassy-time-queue-driver/src/lib.rs
+++ b/embassy-time-queue-driver/src/lib.rs
@@ -2,38 +2,25 @@
2#![doc = include_str!("../README.md")] 2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4 4
5//! ## Implementing a timer queue 5//! This crate is an implementation detail of `embassy-time-driver`.
6//! 6//!
7//! - Define a struct `MyTimerQueue` 7//! As a HAL user, you should only depend on this crate if your application does not use
8//! - Implement [`TimerQueue`] for it 8//! `embassy-executor` and your HAL does not configure a generic queue by itself.
9//! - Register it as the global timer queue with [`timer_queue_impl`](crate::timer_queue_impl).
10//! 9//!
11//! ## Example 10//! As a HAL implementer, you need to depend on this crate if you want to implement a time driver,
12//! 11//! but how you should do so is documented in `embassy-time-driver`.
13//! ``` 12
14//! use core::task::Waker;
15//!
16//! use embassy_time::Instant;
17//! use embassy_time::queue::{TimerQueue};
18//!
19//! struct MyTimerQueue{}; // not public!
20//!
21//! impl TimerQueue for MyTimerQueue {
22//! fn schedule_wake(&'static self, at: u64, waker: &Waker) {
23//! todo!()
24//! }
25//! }
26//!
27//! embassy_time_queue_driver::timer_queue_impl!(static QUEUE: MyTimerQueue = MyTimerQueue{});
28//! ```
29use core::task::Waker; 13use core::task::Waker;
30 14
31/// Timer queue 15#[cfg(feature = "_generic-queue")]
32pub trait TimerQueue { 16pub mod queue_generic;
33 /// Schedules a waker in the queue to be awoken at moment `at`. 17#[cfg(not(feature = "_generic-queue"))]
34 /// If this moment is in the past, the waker might be awoken immediately. 18pub mod queue_integrated;
35 fn schedule_wake(&'static self, at: u64, waker: &Waker); 19
36} 20#[cfg(feature = "_generic-queue")]
21pub use queue_generic::Queue;
22#[cfg(not(feature = "_generic-queue"))]
23pub use queue_integrated::Queue;
37 24
38extern "Rust" { 25extern "Rust" {
39 fn _embassy_time_schedule_wake(at: u64, waker: &Waker); 26 fn _embassy_time_schedule_wake(at: u64, waker: &Waker);
@@ -41,20 +28,22 @@ extern "Rust" {
41 28
42/// Schedule the given waker to be woken at `at`. 29/// Schedule the given waker to be woken at `at`.
43pub fn schedule_wake(at: u64, waker: &Waker) { 30pub fn schedule_wake(at: u64, waker: &Waker) {
44 unsafe { _embassy_time_schedule_wake(at, waker) } 31 // This function is not implemented in embassy-time-driver because it needs access to executor
45} 32 // internals. The function updates task state, then delegates to the implementation provided
46 33 // by the time driver.
47/// Set the TimerQueue implementation. 34 #[cfg(not(feature = "_generic-queue"))]
48/// 35 {
49/// See the module documentation for an example. 36 use embassy_executor::raw::task_from_waker;
50#[macro_export] 37 use embassy_executor::raw::timer_queue::TimerEnqueueOperation;
51macro_rules! timer_queue_impl { 38 // The very first thing we must do, before we even access the timer queue, is to
52 (static $name:ident: $t: ty = $val:expr) => { 39 // mark the task a TIMER_QUEUED. This ensures that the task that is being scheduled
53 static $name: $t = $val; 40 // can not be respawn while we are accessing the timer queue.
54 41 let task = task_from_waker(waker);
55 #[no_mangle] 42 if unsafe { task.timer_enqueue() } == TimerEnqueueOperation::Ignore {
56 fn _embassy_time_schedule_wake(at: u64, waker: &core::task::Waker) { 43 // We are not allowed to enqueue the task in the timer queue. This is because the
57 <$t as $crate::TimerQueue>::schedule_wake(&$name, at, waker); 44 // task is not spawned, and so it makes no sense to schedule it.
45 return;
58 } 46 }
59 }; 47 }
48 unsafe { _embassy_time_schedule_wake(at, waker) }
60} 49}