From 74037f04933f4ec9a678e0b47fd6819e7c0489a9 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 4 Aug 2025 00:05:25 +0200 Subject: Make TimerQueueItem opaque --- embassy-executor-timer-queue/CHANGELOG.md | 10 ++++ embassy-executor-timer-queue/Cargo.toml | 35 +++++++++++ embassy-executor-timer-queue/README.md | 10 ++++ embassy-executor-timer-queue/src/lib.rs | 97 +++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 embassy-executor-timer-queue/CHANGELOG.md create mode 100644 embassy-executor-timer-queue/Cargo.toml create mode 100644 embassy-executor-timer-queue/README.md create mode 100644 embassy-executor-timer-queue/src/lib.rs (limited to 'embassy-executor-timer-queue') diff --git a/embassy-executor-timer-queue/CHANGELOG.md b/embassy-executor-timer-queue/CHANGELOG.md new file mode 100644 index 000000000..d43e0060d --- /dev/null +++ b/embassy-executor-timer-queue/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog for embassy-time-queue-utils + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreeased + +- Initial implementation diff --git a/embassy-executor-timer-queue/Cargo.toml b/embassy-executor-timer-queue/Cargo.toml new file mode 100644 index 000000000..0db327ba9 --- /dev/null +++ b/embassy-executor-timer-queue/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "embassy-executor-timer-queue" +version = "0.1.0" +edition = "2021" +description = "Timer queue item and interface between embassy-executor and timer queues" +repository = "https://github.com/embassy-rs/embassy" +documentation = "https://docs.embassy.dev/embassy-executor-timer-queue" +readme = "README.md" +license = "MIT OR Apache-2.0" +categories = [ + "embedded", + "no-std", + "concurrency", + "asynchronous", +] + +[dependencies] + +[features] +#! ### Timer Queue Item Size +#! Sets the size of the timer items. + +## 4 words +timer-item-size-4-words = [] + +## 6 words +timer-item-size-6-words = [] + +## 8 words +timer-item-size-8-words = [] + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-timer-queue-v$VERSION/embassy-executor-timer-queue/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor-timer-queue/src/" +target = "x86_64-unknown-linux-gnu" diff --git a/embassy-executor-timer-queue/README.md b/embassy-executor-timer-queue/README.md new file mode 100644 index 000000000..602aca7b1 --- /dev/null +++ b/embassy-executor-timer-queue/README.md @@ -0,0 +1,10 @@ +# embassy-executor-time-queue + +This crate defines the timer queue item that embassy-executor provides, and a way to access it, for +executor-integrated timer queues. The crate decouples the release cycle of embassy-executor from +that of the queue implementations'. + +As a HAL implementer, you only need to depend on this crate if you want to implement executor-integrated +timer queues yourself, without using [`embassy-time-queue-utils`](https://crates.io/crates/embassy-time-queue-utils). + +As a HAL user, you should not need to depend on this crate. diff --git a/embassy-executor-timer-queue/src/lib.rs b/embassy-executor-timer-queue/src/lib.rs new file mode 100644 index 000000000..456ccaec3 --- /dev/null +++ b/embassy-executor-timer-queue/src/lib.rs @@ -0,0 +1,97 @@ +//! Timer queue item for embassy-executor integrated timer queues +//! +//! `embassy-executor` provides the memory needed to implement integrated timer queues. This crate +//! exists to separate that memory from `embassy-executor` itself, to decouple the timer queue's +//! release cycle from `embassy-executor`. +//! +//! This crate contains two things: +//! - [`TimerQueueItem`]: The item type that can be requested from the executor. The size of this +//! type can be configured using the `timer-item-size-N-words` Cargo features. +//! - The expectation that `extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &mut TimerQueueItem` +//! is implemented (by `embassy-executor`, most likely). This function must return a mutable +//! reference to the `TimerQueueItem` associated with the given waker. +//! +//! As a queue implementor, you will need to choose one of the `timer-item-size-N-words` features to +//! select a queue item size. You can then define your own item type, which must be +//! `#[repr(align(8))]` (or less) and must fit into the size you selected. +//! +//! You can access the `TimerQueueItem` from a `Waker` using the [`from_embassy_waker`](TimerQueueItem::from_embassy_waker) +//! method. You can then use the [`as_ref`](TimerQueueItem::as_ref) and [`as_mut`](TimerQueueItem::as_mut) +//! methods to reinterpret the data stored in the item as your custom item type. +#![no_std] + +use core::task::Waker; + +const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { + 8 +} else if cfg!(feature = "timer-item-size-6-words") { + 6 +} else if cfg!(feature = "timer-item-size-4-words") { + 4 +} else { + 0 +}; + +/// The timer queue item provided by the executor. +/// +/// This type is opaque, it only provides the raw storage for a queue item. The queue implementation +/// is responsible for reinterpreting the contents of the item using [`TimerQueueItem::as_ref`] and +/// [`TimerQueueItem::as_mut`]. +#[repr(align(8))] +pub struct TimerQueueItem { + data: [usize; ITEM_SIZE], +} + +impl TimerQueueItem { + /// Creates a new, zero-initialized `TimerQueueItem`. + pub const fn new() -> Self { + Self { data: [0; ITEM_SIZE] } + } + + /// Retrieves the `TimerQueueItem` reference that belongs to the task of the waker. + /// + /// Panics if called with a non-embassy waker. + /// + /// # Safety + /// + /// The caller must ensure they are not violating Rust's aliasing rules - it is not allowed + /// to use this method to create multiple mutable references to the same `TimerQueueItem` at + /// the same time. + /// + /// This function must only be called in the context of a timer queue implementation. + pub unsafe fn from_embassy_waker(waker: &Waker) -> &'static mut Self { + unsafe extern "Rust" { + // Waker -> TimerQueueItem, validates that Waker is an embassy Waker. + fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem; + } + unsafe { __embassy_time_queue_item_from_waker(waker) } + } + + /// Access the data as a reference to a type `T`. + /// + /// Safety: + /// + /// - The type must be valid when zero-initialized. + /// - The timer queue should only be interpreted as a single type `T` during its lifetime. + pub unsafe fn as_ref(&self) -> &T { + const { + assert!(core::mem::size_of::() >= core::mem::size_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + } + unsafe { &*(self.data.as_ptr() as *const T) } + } + + /// Access the data as a reference to a type `T`. + /// + /// Safety: + /// + /// - The type must be valid when zero-initialized. + /// - The timer queue should only be interpreted as a single type `T` during its lifetime. + pub unsafe fn as_mut(&self) -> &mut T { + const { + assert!(core::mem::size_of::() >= core::mem::size_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + } + unsafe { &mut *(self.data.as_ptr() as *mut T) } + } +} -- cgit From 31967e1f901454014d0c452dd0328f98a80c8a9c Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 16 Aug 2025 11:50:14 +0200 Subject: Print more informative panic messages --- embassy-executor-timer-queue/src/lib.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'embassy-executor-timer-queue') diff --git a/embassy-executor-timer-queue/src/lib.rs b/embassy-executor-timer-queue/src/lib.rs index 456ccaec3..de94e3faf 100644 --- a/embassy-executor-timer-queue/src/lib.rs +++ b/embassy-executor-timer-queue/src/lib.rs @@ -22,7 +22,7 @@ use core::task::Waker; -const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { +const ITEM_WORDS: usize = if cfg!(feature = "timer-item-size-8-words") { 8 } else if cfg!(feature = "timer-item-size-6-words") { 6 @@ -39,13 +39,13 @@ const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { /// [`TimerQueueItem::as_mut`]. #[repr(align(8))] pub struct TimerQueueItem { - data: [usize; ITEM_SIZE], + data: [usize; ITEM_WORDS], } impl TimerQueueItem { /// Creates a new, zero-initialized `TimerQueueItem`. pub const fn new() -> Self { - Self { data: [0; ITEM_SIZE] } + Self { data: [0; ITEM_WORDS] } } /// Retrieves the `TimerQueueItem` reference that belongs to the task of the waker. @@ -74,10 +74,7 @@ impl TimerQueueItem { /// - The type must be valid when zero-initialized. /// - The timer queue should only be interpreted as a single type `T` during its lifetime. pub unsafe fn as_ref(&self) -> &T { - const { - assert!(core::mem::size_of::() >= core::mem::size_of::()); - assert!(core::mem::align_of::() >= core::mem::align_of::()); - } + const { validate::() } unsafe { &*(self.data.as_ptr() as *const T) } } @@ -88,10 +85,20 @@ impl TimerQueueItem { /// - The type must be valid when zero-initialized. /// - The timer queue should only be interpreted as a single type `T` during its lifetime. pub unsafe fn as_mut(&self) -> &mut T { - const { - assert!(core::mem::size_of::() >= core::mem::size_of::()); - assert!(core::mem::align_of::() >= core::mem::align_of::()); - } + const { validate::() } unsafe { &mut *(self.data.as_ptr() as *mut T) } } } + +const fn validate() { + const { + assert!( + core::mem::size_of::() >= core::mem::size_of::(), + "embassy-executor-timer-queue item size is smaller than the requested type. Select a larger timer-item-size-N-words feature." + ); + assert!( + core::mem::align_of::() >= core::mem::align_of::(), + "the alignment of the requested type is greater than 8" + ); + } +} -- cgit From ce4ffe52da4ec042c44f6073e036b363c9f89189 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 19:47:08 +0200 Subject: add metadata for embassy-executor-time-queue --- embassy-executor-timer-queue/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'embassy-executor-timer-queue') diff --git a/embassy-executor-timer-queue/Cargo.toml b/embassy-executor-timer-queue/Cargo.toml index 0db327ba9..a0ac44420 100644 --- a/embassy-executor-timer-queue/Cargo.toml +++ b/embassy-executor-timer-queue/Cargo.toml @@ -33,3 +33,9 @@ timer-item-size-8-words = [] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-timer-queue-v$VERSION/embassy-executor-timer-queue/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor-timer-queue/src/" target = "x86_64-unknown-linux-gnu" + +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = []}, + {target = "thumbv6m-none-eabi", features = []}, +] -- cgit From f77693092a59970ac3b3594c53e53099295cbbff Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Tue, 26 Aug 2025 16:26:41 +0200 Subject: Fix changelog --- embassy-executor-timer-queue/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-executor-timer-queue') diff --git a/embassy-executor-timer-queue/CHANGELOG.md b/embassy-executor-timer-queue/CHANGELOG.md index d43e0060d..b4a462b66 100644 --- a/embassy-executor-timer-queue/CHANGELOG.md +++ b/embassy-executor-timer-queue/CHANGELOG.md @@ -1,10 +1,10 @@ -# Changelog for embassy-time-queue-utils +# Changelog for embassy-executor-timer-queue All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreeased +## 0.1.0 - 2025-08-25 - Initial implementation -- cgit