diff options
| author | datdenkikniet <jcdra1@gmail.com> | 2025-03-19 21:44:14 +0100 |
|---|---|---|
| committer | datdenkikniet <38322042+datdenkikniet@users.noreply.github.com> | 2025-03-23 10:47:25 +0000 |
| commit | 1dd279e86ed4ae509ffe6947ad967850131d6676 (patch) | |
| tree | 7f0a567996db86a1a8cea90b68f0d5cb306154f0 | |
| parent | ea56cc0ce8cfbe999872e371acfcc7fb86a0e839 (diff) | |
rtic-sync: we have exclusive access to the free slot pointer when in `drop`
| -rw-r--r-- | rtic-sync/src/channel.rs | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/rtic-sync/src/channel.rs b/rtic-sync/src/channel.rs index 0aeb4a4..0bd2cd2 100644 --- a/rtic-sync/src/channel.rs +++ b/rtic-sync/src/channel.rs @@ -246,7 +246,19 @@ impl SlotPtr { new_value: Option<u8>, _cs: critical_section::CriticalSection, ) -> Option<u8> { - // SAFETY: we are in a critical section. + // SAFETY: the critical section guarantees exclusive access, and the + // caller guarantees that the pointer is valid. + self.replace_exclusive(new_value) + } + + /// Replace the value of this slot with `new_value`, and return + /// the old value. + /// + /// SAFETY: the pointer in this `SlotPtr` must be valid for writes, and the caller must guarantee exclusive + /// access to the underlying value.. + unsafe fn replace_exclusive(&mut self, new_value: Option<u8>) -> Option<u8> { + // SAFETY: the caller has ensured that we have exclusive access & that + // the pointer is valid. unsafe { core::ptr::replace(self.0, new_value) } } } @@ -338,17 +350,14 @@ impl<T, const N: usize> Sender<'_, T, N> { } // Return our potentially-unused free slot. - // Potentially unnecessary c-s because our link was already popped, so there - // is no way for anything else to access the free slot ptr. Gotta think - // about this a bit more... - critical_section::with(|cs| { - if let Some(freed_slot) = unsafe { free_slot_ptr2.replace(None, cs) } { - // SAFETY: freed slot is passed to us from `return_free_slot`, which either - // directly (through `try_recv`), or indirectly (through another `return_free_slot`) - // comes from `readyq`. - unsafe { self.0.return_free_slot(freed_slot) }; - } - }); + // Since we are certain that our link has been removed from the list (either + // pop-ed or removed just above), we have exclusive access to the free slot pointer. + if let Some(freed_slot) = unsafe { free_slot_ptr2.replace_exclusive(None) } { + // SAFETY: freed slot is passed to us from `return_free_slot`, which either + // directly (through `try_recv`), or indirectly (through another `return_free_slot`) + // comes from `readyq`. + unsafe { self.0.return_free_slot(freed_slot) }; + } }); let idx = poll_fn(|cx| { |
