diff options
| -rw-r--r-- | embassy-executor/src/raw/mod.rs | 22 | ||||
| -rw-r--r-- | embassy-time-driver/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-time-queue-driver/src/lib.rs | 28 | ||||
| -rw-r--r-- | embassy-time/Cargo.toml | 8 | ||||
| -rw-r--r-- | embassy-time/src/timer.rs | 6 |
5 files changed, 13 insertions, 57 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 5a476213b..997db6756 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs | |||
| @@ -195,25 +195,7 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 195 | match future.poll(&mut cx) { | 195 | match future.poll(&mut cx) { |
| 196 | Poll::Ready(_) => { | 196 | Poll::Ready(_) => { |
| 197 | this.future.drop_in_place(); | 197 | this.future.drop_in_place(); |
| 198 | |||
| 199 | // Mark this task to be timer queued. | ||
| 200 | // We're splitting the enqueue in two parts, so that we can change task state | ||
| 201 | // to something that prevent re-queueing. | ||
| 202 | let op = this.raw.state.timer_enqueue(); | ||
| 203 | |||
| 204 | // Now mark the task as not spawned, so that | ||
| 205 | // - it can be spawned again once it has been removed from the timer queue | ||
| 206 | // - it can not be timer-queued again | ||
| 207 | // We must do this before scheduling the wake, to prevent the task from being | ||
| 208 | // dequeued by the time driver while it's still SPAWNED. | ||
| 209 | this.raw.state.despawn(); | 198 | this.raw.state.despawn(); |
| 210 | |||
| 211 | // Now let's finish enqueueing. While we shouldn't get an `Ignore` here, it's | ||
| 212 | // better to be safe. | ||
| 213 | if op == timer_queue::TimerEnqueueOperation::Enqueue { | ||
| 214 | // Schedule the task in the past, so it gets dequeued ASAP. | ||
| 215 | unsafe { _embassy_time_schedule_wake(0, &waker) } | ||
| 216 | } | ||
| 217 | } | 199 | } |
| 218 | Poll::Pending => {} | 200 | Poll::Pending => {} |
| 219 | } | 201 | } |
| @@ -232,10 +214,6 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 232 | } | 214 | } |
| 233 | } | 215 | } |
| 234 | 216 | ||
| 235 | extern "Rust" { | ||
| 236 | fn _embassy_time_schedule_wake(at: u64, waker: &core::task::Waker); | ||
| 237 | } | ||
| 238 | |||
| 239 | /// An uninitialized [`TaskStorage`]. | 217 | /// An uninitialized [`TaskStorage`]. |
| 240 | pub struct AvailableTask<F: Future + 'static> { | 218 | pub struct AvailableTask<F: Future + 'static> { |
| 241 | task: &'static TaskStorage<F>, | 219 | task: &'static TaskStorage<F>, |
diff --git a/embassy-time-driver/src/lib.rs b/embassy-time-driver/src/lib.rs index 57a9f7587..c776fbdf8 100644 --- a/embassy-time-driver/src/lib.rs +++ b/embassy-time-driver/src/lib.rs | |||
| @@ -131,6 +131,7 @@ pub trait Driver: Send + Sync + 'static { | |||
| 131 | 131 | ||
| 132 | extern "Rust" { | 132 | extern "Rust" { |
| 133 | fn _embassy_time_now() -> u64; | 133 | fn _embassy_time_now() -> u64; |
| 134 | fn _embassy_time_schedule_wake(at: u64, waker: &Waker); | ||
| 134 | } | 135 | } |
| 135 | 136 | ||
| 136 | /// See [`Driver::now`] | 137 | /// See [`Driver::now`] |
| @@ -138,6 +139,11 @@ pub fn now() -> u64 { | |||
| 138 | unsafe { _embassy_time_now() } | 139 | unsafe { _embassy_time_now() } |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 142 | /// Schedule the given waker to be woken at `at`. | ||
| 143 | pub fn schedule_wake(at: u64, waker: &Waker) { | ||
| 144 | unsafe { _embassy_time_schedule_wake(at, waker) } | ||
| 145 | } | ||
| 146 | |||
| 141 | /// Set the time Driver implementation. | 147 | /// Set the time Driver implementation. |
| 142 | /// | 148 | /// |
| 143 | /// See the module documentation for an example. | 149 | /// See the module documentation for an example. |
diff --git a/embassy-time-queue-driver/src/lib.rs b/embassy-time-queue-driver/src/lib.rs index 97c81a124..333b6124d 100644 --- a/embassy-time-queue-driver/src/lib.rs +++ b/embassy-time-queue-driver/src/lib.rs | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | //! As a HAL implementer, you need to depend on this crate if you want to implement a time driver, | 10 | //! As a HAL implementer, you need to depend on this crate if you want to implement a time driver, |
| 11 | //! but how you should do so is documented in `embassy-time-driver`. | 11 | //! but how you should do so is documented in `embassy-time-driver`. |
| 12 | 12 | ||
| 13 | use core::task::Waker; | ||
| 14 | |||
| 15 | #[cfg(feature = "_generic-queue")] | 13 | #[cfg(feature = "_generic-queue")] |
| 16 | pub mod queue_generic; | 14 | pub mod queue_generic; |
| 17 | #[cfg(not(feature = "_generic-queue"))] | 15 | #[cfg(not(feature = "_generic-queue"))] |
| @@ -21,29 +19,3 @@ pub mod queue_integrated; | |||
| 21 | pub use queue_generic::Queue; | 19 | pub use queue_generic::Queue; |
| 22 | #[cfg(not(feature = "_generic-queue"))] | 20 | #[cfg(not(feature = "_generic-queue"))] |
| 23 | pub use queue_integrated::Queue; | 21 | pub use queue_integrated::Queue; |
| 24 | |||
| 25 | extern "Rust" { | ||
| 26 | fn _embassy_time_schedule_wake(at: u64, waker: &Waker); | ||
| 27 | } | ||
| 28 | |||
| 29 | /// Schedule the given waker to be woken at `at`. | ||
| 30 | pub fn schedule_wake(at: u64, waker: &Waker) { | ||
| 31 | // This function is not implemented in embassy-time-driver because it needs access to executor | ||
| 32 | // internals. The function updates task state, then delegates to the implementation provided | ||
| 33 | // by the time driver. | ||
| 34 | #[cfg(not(feature = "_generic-queue"))] | ||
| 35 | { | ||
| 36 | use embassy_executor::raw::task_from_waker; | ||
| 37 | use embassy_executor::raw::timer_queue::TimerEnqueueOperation; | ||
| 38 | // The very first thing we must do, before we even access the timer queue, is to | ||
| 39 | // mark the task a TIMER_QUEUED. This ensures that the task that is being scheduled | ||
| 40 | // can not be respawn while we are accessing the timer queue. | ||
| 41 | let task = task_from_waker(waker); | ||
| 42 | if unsafe { task.timer_enqueue() } == TimerEnqueueOperation::Ignore { | ||
| 43 | // We are not allowed to enqueue the task in the timer queue. This is because the | ||
| 44 | // task is not spawned, and so it makes no sense to schedule it. | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | unsafe { _embassy_time_schedule_wake(at, waker) } | ||
| 49 | } | ||
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index e3074119f..4f4ea0b14 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml | |||
| @@ -24,8 +24,8 @@ target = "x86_64-unknown-linux-gnu" | |||
| 24 | features = ["defmt", "std"] | 24 | features = ["defmt", "std"] |
| 25 | 25 | ||
| 26 | [features] | 26 | [features] |
| 27 | std = ["tick-hz-1_000_000", "critical-section/std"] | 27 | std = ["tick-hz-1_000_000", "critical-section/std", "dep:embassy-time-queue-driver"] |
| 28 | wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"] | 28 | wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000", "dep:embassy-time-queue-driver"] |
| 29 | 29 | ||
| 30 | ## Display the time since startup next to defmt log messages. | 30 | ## Display the time since startup next to defmt log messages. |
| 31 | ## At most 1 `defmt-timestamp-uptime-*` feature can be used. | 31 | ## At most 1 `defmt-timestamp-uptime-*` feature can be used. |
| @@ -40,7 +40,7 @@ defmt-timestamp-uptime-tms = ["defmt"] | |||
| 40 | defmt-timestamp-uptime-tus = ["defmt"] | 40 | defmt-timestamp-uptime-tus = ["defmt"] |
| 41 | 41 | ||
| 42 | ## Create a `MockDriver` that can be manually advanced for testing purposes. | 42 | ## Create a `MockDriver` that can be manually advanced for testing purposes. |
| 43 | mock-driver = ["tick-hz-1_000_000"] | 43 | mock-driver = ["tick-hz-1_000_000", "dep:embassy-time-queue-driver"] |
| 44 | 44 | ||
| 45 | #! ### Tick Rate | 45 | #! ### Tick Rate |
| 46 | #! | 46 | #! |
| @@ -384,7 +384,7 @@ tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"] | |||
| 384 | 384 | ||
| 385 | [dependencies] | 385 | [dependencies] |
| 386 | embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver" } | 386 | embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver" } |
| 387 | embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver" } | 387 | embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver", optional = true} |
| 388 | 388 | ||
| 389 | defmt = { version = "0.3", optional = true } | 389 | defmt = { version = "0.3", optional = true } |
| 390 | log = { version = "0.4.14", optional = true } | 390 | log = { version = "0.4.14", optional = true } |
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index 4d7194b20..295ddbd9b 100644 --- a/embassy-time/src/timer.rs +++ b/embassy-time/src/timer.rs | |||
| @@ -157,7 +157,7 @@ impl Future for Timer { | |||
| 157 | if self.yielded_once && self.expires_at <= Instant::now() { | 157 | if self.yielded_once && self.expires_at <= Instant::now() { |
| 158 | Poll::Ready(()) | 158 | Poll::Ready(()) |
| 159 | } else { | 159 | } else { |
| 160 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); | 160 | embassy_time_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 161 | self.yielded_once = true; | 161 | self.yielded_once = true; |
| 162 | Poll::Pending | 162 | Poll::Pending |
| 163 | } | 163 | } |
| @@ -238,7 +238,7 @@ impl Ticker { | |||
| 238 | self.expires_at += dur; | 238 | self.expires_at += dur; |
| 239 | Poll::Ready(()) | 239 | Poll::Ready(()) |
| 240 | } else { | 240 | } else { |
| 241 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); | 241 | embassy_time_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 242 | Poll::Pending | 242 | Poll::Pending |
| 243 | } | 243 | } |
| 244 | }) | 244 | }) |
| @@ -255,7 +255,7 @@ impl Stream for Ticker { | |||
| 255 | self.expires_at += dur; | 255 | self.expires_at += dur; |
| 256 | Poll::Ready(Some(())) | 256 | Poll::Ready(Some(())) |
| 257 | } else { | 257 | } else { |
| 258 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); | 258 | embassy_time_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 259 | Poll::Pending | 259 | Poll::Pending |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
