mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 21:05:35 +01:00
Use Pin in the linked lists
This commit is contained in:
parent
5908d5bdbc
commit
3050fc0591
4 changed files with 42 additions and 15 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! ...
|
||||
|
||||
use core::marker::PhantomPinned;
|
||||
use core::pin::Pin;
|
||||
use core::sync::atomic::{AtomicPtr, Ordering};
|
||||
use critical_section as cs;
|
||||
|
||||
|
|
@ -92,8 +93,10 @@ impl<T: PartialOrd + Clone> LinkedList<T> {
|
|||
|
||||
/// Insert a new link into the linked list.
|
||||
/// The return is (was_empty, address), where the address of the link is for use with `delete`.
|
||||
pub fn insert(&self, val: &mut Link<T>) -> (bool, usize) {
|
||||
pub fn insert(&self, val: Pin<&mut Link<T>>) -> (bool, usize) {
|
||||
cs::with(|_| {
|
||||
// SAFETY: This datastructure does not move the underlying value.
|
||||
let val = unsafe { val.get_unchecked_mut() };
|
||||
let addr = val as *const _ as usize;
|
||||
|
||||
// Make sure all previous writes are visible
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue