diff options
| author | Emil Fresk <emil.fresk@gmail.com> | 2023-01-28 21:11:18 +0100 |
|---|---|---|
| committer | Henrik Tjäder <henrik@tjaders.com> | 2023-03-01 00:33:37 +0100 |
| commit | 2bd70baeb9362050196d431f2801551066e27e59 (patch) | |
| tree | d100c383fbc32fe1d5c008da120eb79bdae696e2 | |
| parent | bef6c359a0802cb93c7bf0963d0fca7db540f64b (diff) | |
rtic-time: Make Send happy
| -rw-r--r-- | rtic-channel/src/lib.rs | 2 | ||||
| -rw-r--r-- | rtic-channel/src/wait_queue.rs | 2 | ||||
| -rw-r--r-- | rtic-time/src/lib.rs | 28 |
3 files changed, 26 insertions, 6 deletions
diff --git a/rtic-channel/src/lib.rs b/rtic-channel/src/lib.rs index eafa25c..acfa801 100644 --- a/rtic-channel/src/lib.rs +++ b/rtic-channel/src/lib.rs @@ -532,7 +532,7 @@ mod tests { #[tokio::test] async fn stress_channel() { - const NUM_RUNS: usize = 1_000000; + const NUM_RUNS: usize = 1_000; const QUEUE_SIZE: usize = 10; let (s, mut r) = make_channel!(u32, QUEUE_SIZE); diff --git a/rtic-channel/src/wait_queue.rs b/rtic-channel/src/wait_queue.rs index e6d5a8b..2de6311 100644 --- a/rtic-channel/src/wait_queue.rs +++ b/rtic-channel/src/wait_queue.rs @@ -105,8 +105,6 @@ pub struct Link<T> { _up: PhantomPinned, } -unsafe impl<T> Send for Link<T> {} - impl<T: Clone> Link<T> { const R: Ordering = Ordering::Relaxed; diff --git a/rtic-time/src/lib.rs b/rtic-time/src/lib.rs index 6b23f76..44fdbce 100644 --- a/rtic-time/src/lib.rs +++ b/rtic-time/src/lib.rs @@ -73,6 +73,26 @@ pub struct TimerQueue<Mono: Monotonic> { /// This indicates that there was a timeout. pub struct TimeoutError; +/// This is needed to make the async closure in `delay_until` accept that we "share" +/// the link possible between threads. +struct LinkPtr<Mono: Monotonic>(*mut Option<linked_list::Link<WaitingWaker<Mono>>>); + +impl<Mono: Monotonic> Clone for LinkPtr<Mono> { + fn clone(&self) -> Self { + LinkPtr(self.0) + } +} + +impl<Mono: Monotonic> LinkPtr<Mono> { + /// This will dereference the pointer stored within and give out an `&mut`. + unsafe fn get(&mut self) -> &mut Option<linked_list::Link<WaitingWaker<Mono>>> { + &mut *self.0 + } +} + +unsafe impl<Mono: Monotonic> Send for LinkPtr<Mono> {} +unsafe impl<Mono: Monotonic> Sync for LinkPtr<Mono> {} + impl<Mono: Monotonic> TimerQueue<Mono> { /// Make a new queue. pub const fn new() -> Self { @@ -189,7 +209,9 @@ impl<Mono: Monotonic> TimerQueue<Mono> { 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 mut link_ptr = + LinkPtr(&mut link_ptr as *mut Option<linked_list::Link<WaitingWaker<Mono>>>); + let mut link_ptr2 = link_ptr.clone(); let queue = &self.queue; let marker = &AtomicUsize::new(0); @@ -205,7 +227,7 @@ impl<Mono: Monotonic> TimerQueue<Mono> { // 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 }; + let link = unsafe { link_ptr2.get() }; if link.is_none() { let mut link_ref = link.insert(Link::new(WaitingWaker { waker: cx.waker().clone(), @@ -231,7 +253,7 @@ impl<Mono: Monotonic> TimerQueue<Mono> { // 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 let Some(link) = unsafe { link_ptr.get() } { if link.val.was_poped.load(Ordering::Relaxed) { // If it was poped from the queue there is no need to run delete dropper.defuse(); |
