rtic-sync: we have exclusive access to the free slot pointer when in drop

This commit is contained in:
datdenkikniet 2025-03-19 21:44:14 +01:00 committed by datdenkikniet
parent ea56cc0ce8
commit 1dd279e86e

View file

@ -246,7 +246,19 @@ impl SlotPtr {
new_value: Option<u8>, new_value: Option<u8>,
_cs: critical_section::CriticalSection, _cs: critical_section::CriticalSection,
) -> Option<u8> { ) -> 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) } 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. // Return our potentially-unused free slot.
// Potentially unnecessary c-s because our link was already popped, so there // Since we are certain that our link has been removed from the list (either
// is no way for anything else to access the free slot ptr. Gotta think // pop-ed or removed just above), we have exclusive access to the free slot pointer.
// about this a bit more... if let Some(freed_slot) = unsafe { free_slot_ptr2.replace_exclusive(None) } {
critical_section::with(|cs| { // SAFETY: freed slot is passed to us from `return_free_slot`, which either
if let Some(freed_slot) = unsafe { free_slot_ptr2.replace(None, cs) } { // directly (through `try_recv`), or indirectly (through another `return_free_slot`)
// SAFETY: freed slot is passed to us from `return_free_slot`, which either // comes from `readyq`.
// directly (through `try_recv`), or indirectly (through another `return_free_slot`) unsafe { self.0.return_free_slot(freed_slot) };
// comes from `readyq`. }
unsafe { self.0.return_free_slot(freed_slot) };
}
});
}); });
let idx = poll_fn(|cx| { let idx = poll_fn(|cx| {