From e05f6da2692f2b61986ef2b77789e27d68e4e74a Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Fri, 22 Nov 2024 09:21:44 +0100 Subject: Generalize AtomicWaker --- embassy-sync/src/waitqueue/atomic_waker.rs | 42 +++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'embassy-sync/src/waitqueue') diff --git a/embassy-sync/src/waitqueue/atomic_waker.rs b/embassy-sync/src/waitqueue/atomic_waker.rs index 63fe04a6e..231902c5a 100644 --- a/embassy-sync/src/waitqueue/atomic_waker.rs +++ b/embassy-sync/src/waitqueue/atomic_waker.rs @@ -1,26 +1,25 @@ use core::cell::Cell; use core::task::Waker; -use crate::blocking_mutex::raw::CriticalSectionRawMutex; +use crate::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; use crate::blocking_mutex::Mutex; /// Utility struct to register and wake a waker. -pub struct AtomicWaker { - waker: Mutex>>, +pub struct GenericAtomicWaker { + waker: Mutex>>, } -impl AtomicWaker { +impl GenericAtomicWaker { /// Create a new `AtomicWaker`. - pub const fn new() -> Self { + pub const fn new(mutex: M) -> Self { Self { - waker: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), + waker: Mutex::const_new(mutex, Cell::new(None)), } } /// Register a waker. Overwrites the previous waker, if any. pub fn register(&self, w: &Waker) { - critical_section::with(|cs| { - let cell = self.waker.borrow(cs); + self.waker.lock(|cell| { cell.set(match cell.replace(None) { Some(w2) if (w2.will_wake(w)) => Some(w2), _ => Some(w.clone()), @@ -30,8 +29,7 @@ impl AtomicWaker { /// Wake the registered waker, if any. pub fn wake(&self) { - critical_section::with(|cs| { - let cell = self.waker.borrow(cs); + self.waker.lock(|cell| { if let Some(w) = cell.replace(None) { w.wake_by_ref(); cell.set(Some(w)); @@ -39,3 +37,27 @@ impl AtomicWaker { }) } } + +/// Utility struct to register and wake a waker. +pub struct AtomicWaker { + waker: GenericAtomicWaker, +} + +impl AtomicWaker { + /// Create a new `AtomicWaker`. + pub const fn new() -> Self { + Self { + waker: GenericAtomicWaker::new(CriticalSectionRawMutex::new()), + } + } + + /// Register a waker. Overwrites the previous waker, if any. + pub fn register(&self, w: &Waker) { + self.waker.register(w); + } + + /// Wake the registered waker, if any. + pub fn wake(&self) { + self.waker.wake(); + } +} -- cgit From c2173591aa77ab7aa0a1b3d921883667fb9881f4 Mon Sep 17 00:00:00 2001 From: ckrenslehner Date: Sat, 26 Apr 2025 20:07:30 +0200 Subject: docs: extend the waker documentation --- embassy-sync/src/waitqueue/atomic_waker.rs | 3 +++ embassy-sync/src/waitqueue/atomic_waker_turbo.rs | 3 +++ embassy-sync/src/waitqueue/multi_waker.rs | 2 ++ embassy-sync/src/waitqueue/waker_registration.rs | 4 ++++ 4 files changed, 12 insertions(+) (limited to 'embassy-sync/src/waitqueue') diff --git a/embassy-sync/src/waitqueue/atomic_waker.rs b/embassy-sync/src/waitqueue/atomic_waker.rs index 231902c5a..5a9910e7f 100644 --- a/embassy-sync/src/waitqueue/atomic_waker.rs +++ b/embassy-sync/src/waitqueue/atomic_waker.rs @@ -5,6 +5,9 @@ use crate::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; use crate::blocking_mutex::Mutex; /// Utility struct to register and wake a waker. +/// If a waker is registered, registering another waker will replace the previous one without waking it. +/// Intended to wake a task from an interrupt. Therefore, it is generally not expected, +/// that multiple tasks register try to register a waker simultaneously. pub struct GenericAtomicWaker { waker: Mutex>>, } diff --git a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs index 5c6a96ec8..c06b83056 100644 --- a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs +++ b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs @@ -4,6 +4,9 @@ use core::sync::atomic::{AtomicPtr, Ordering}; use core::task::Waker; /// Utility struct to register and wake a waker. +/// If a waker is registered, registering another waker will replace the previous one without waking it. +/// The intended use case is to wake tasks from interrupts. Therefore, it is generally not expected, +/// that multiple tasks register try to register a waker simultaneously. pub struct AtomicWaker { waker: AtomicPtr<()>, } diff --git a/embassy-sync/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs index 0e520bf40..0384d6bed 100644 --- a/embassy-sync/src/waitqueue/multi_waker.rs +++ b/embassy-sync/src/waitqueue/multi_waker.rs @@ -3,6 +3,8 @@ use core::task::Waker; use heapless::Vec; /// Utility struct to register and wake multiple wakers. +/// Queue of wakers with a maximum length of `N`. +/// Intended for waking multiple tasks. pub struct MultiWakerRegistration { wakers: Vec, } diff --git a/embassy-sync/src/waitqueue/waker_registration.rs b/embassy-sync/src/waitqueue/waker_registration.rs index 9b666e7c4..7f24f8fb6 100644 --- a/embassy-sync/src/waitqueue/waker_registration.rs +++ b/embassy-sync/src/waitqueue/waker_registration.rs @@ -2,6 +2,10 @@ use core::mem; use core::task::Waker; /// Utility struct to register and wake a waker. +/// If a waker is registered, registering another waker will replace the previous one. +/// The previous waker will be woken in this case, giving it a chance to reregister itself. +/// Although it is possible to wake multiple tasks this way, +/// this will cause them to wake each other in a loop registering themselves. #[derive(Debug, Default)] pub struct WakerRegistration { waker: Option, -- cgit From 89d52827564b7997f0900614c7b0eb67664c121a Mon Sep 17 00:00:00 2001 From: Brezak Date: Fri, 1 Aug 2025 18:42:25 +0200 Subject: embassy-sync: Update `MultiWakerRegistration::register` docs In 3081ecf301a54f8ed3d0f72350dd21f8ac9e1b18 `register` was changed to clear the buffer when it's full, but the docs weren't updated. --- embassy-sync/src/waitqueue/multi_waker.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'embassy-sync/src/waitqueue') diff --git a/embassy-sync/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs index 0384d6bed..1c05f8eaf 100644 --- a/embassy-sync/src/waitqueue/multi_waker.rs +++ b/embassy-sync/src/waitqueue/multi_waker.rs @@ -15,7 +15,9 @@ impl MultiWakerRegistration { Self { wakers: Vec::new() } } - /// Register a waker. If the buffer is full the function returns it in the error + /// Register a waker. + /// + /// If the buffer is full, [wakes all the wakers](Self::wake), clears its buffer and registers the waker. pub fn register(&mut self, w: &Waker) { // If we already have some waker that wakes the same task as `w`, do nothing. // This avoids cloning wakers, and avoids unnecessary mass-wakes. -- cgit From 368738bef44dbba1a178383d878a6d9423b1ccd9 Mon Sep 17 00:00:00 2001 From: Curly Date: Tue, 19 Aug 2025 22:30:53 -0700 Subject: chore: add more `Debug` impls to `embassy-sync`, particularly on `OnceLock` All tests green --- embassy-sync/src/waitqueue/atomic_waker_turbo.rs | 1 + embassy-sync/src/waitqueue/multi_waker.rs | 1 + 2 files changed, 2 insertions(+) (limited to 'embassy-sync/src/waitqueue') diff --git a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs index c06b83056..a45adeab8 100644 --- a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs +++ b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs @@ -7,6 +7,7 @@ use core::task::Waker; /// If a waker is registered, registering another waker will replace the previous one without waking it. /// The intended use case is to wake tasks from interrupts. Therefore, it is generally not expected, /// that multiple tasks register try to register a waker simultaneously. +#[derive(Debug)] pub struct AtomicWaker { waker: AtomicPtr<()>, } diff --git a/embassy-sync/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs index 1c05f8eaf..56c0cd1b2 100644 --- a/embassy-sync/src/waitqueue/multi_waker.rs +++ b/embassy-sync/src/waitqueue/multi_waker.rs @@ -5,6 +5,7 @@ use heapless::Vec; /// Utility struct to register and wake multiple wakers. /// Queue of wakers with a maximum length of `N`. /// Intended for waking multiple tasks. +#[derive(Debug)] pub struct MultiWakerRegistration { wakers: Vec, } -- cgit From 8730a013c395cf0bf4c2fa8eeb7f138288103039 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 6 Oct 2025 22:56:31 +0200 Subject: Rustfmt for edition 2024. --- embassy-sync/src/waitqueue/atomic_waker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'embassy-sync/src/waitqueue') diff --git a/embassy-sync/src/waitqueue/atomic_waker.rs b/embassy-sync/src/waitqueue/atomic_waker.rs index 5a9910e7f..d2bf890e5 100644 --- a/embassy-sync/src/waitqueue/atomic_waker.rs +++ b/embassy-sync/src/waitqueue/atomic_waker.rs @@ -1,8 +1,8 @@ use core::cell::Cell; use core::task::Waker; -use crate::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; use crate::blocking_mutex::Mutex; +use crate::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; /// Utility struct to register and wake a waker. /// If a waker is registered, registering another waker will replace the previous one without waking it. -- cgit