diff options
| author | Emil Fresk <emil.fresk@gmail.com> | 2023-01-28 13:21:44 +0100 |
|---|---|---|
| committer | Henrik Tjäder <henrik@tjaders.com> | 2023-03-01 00:33:36 +0100 |
| commit | 3050fc0591f087a4fbe08840c69633e89d3f58a7 (patch) | |
| tree | 63c26184993ce42c63102e174d781c5d52da6623 /rtic-time/src/lib.rs | |
| parent | 5908d5bdbc3a3daf741d58b925fa280a3a81bf6a (diff) | |
Use `Pin` in the linked lists
Diffstat (limited to 'rtic-time/src/lib.rs')
| -rw-r--r-- | rtic-time/src/lib.rs | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/rtic-time/src/lib.rs b/rtic-time/src/lib.rs index eeecd86..6b23f76 100644 --- a/rtic-time/src/lib.rs +++ b/rtic-time/src/lib.rs @@ -7,6 +7,7 @@ #![feature(async_fn_in_trait)] use core::future::{poll_fn, Future}; +use core::pin::Pin; use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use core::task::{Poll, Waker}; use futures_util::{ @@ -185,7 +186,10 @@ impl<Mono: Monotonic> TimerQueue<Mono> { ); } - let mut link = None; + let mut link_ptr: Option<linked_list::Link<WaitingWaker<Mono>>> = None; + + // Make this future `Drop`-safe, also shadow the original definition so we can't abuse it. + let link_ptr = &mut link_ptr as *mut Option<linked_list::Link<WaitingWaker<Mono>>>; let queue = &self.queue; let marker = &AtomicUsize::new(0); @@ -199,6 +203,9 @@ impl<Mono: Monotonic> TimerQueue<Mono> { return Poll::Ready(()); } + // SAFETY: This pointer is only dereferenced here and on drop of the future + // which happens outside this `poll_fn`'s stack frame. + let link = unsafe { &mut *link_ptr }; if link.is_none() { let mut link_ref = link.insert(Link::new(WaitingWaker { waker: cx.waker().clone(), @@ -206,7 +213,9 @@ impl<Mono: Monotonic> TimerQueue<Mono> { was_poped: AtomicBool::new(false), })); - let (was_empty, addr) = queue.insert(&mut link_ref); + // SAFETY: The address to the link is stable as it is defined outside this stack + // frame. + let (was_empty, addr) = queue.insert(unsafe { Pin::new_unchecked(&mut link_ref) }); marker.store(addr, Ordering::Relaxed); if was_empty { @@ -219,7 +228,10 @@ impl<Mono: Monotonic> TimerQueue<Mono> { }) .await; - if let Some(link) = link { + // SAFETY: We only run this and dereference the pointer if we have + // exited the `poll_fn` below in the `drop(dropper)` call. The other dereference + // of this pointer is in the `poll_fn`. + if let Some(link) = unsafe { &mut *link_ptr } { if link.val.was_poped.load(Ordering::Relaxed) { // If it was poped from the queue there is no need to run delete dropper.defuse(); |
