diff options
| author | datdenkikniet <jcdra1@gmail.com> | 2025-03-13 21:39:41 +0100 |
|---|---|---|
| committer | Emil Fresk <emil.fresk@gmail.com> | 2025-03-16 11:19:22 +0000 |
| commit | 76631309efe237080fc48e5a29e4274230e0a11f (patch) | |
| tree | 82c2423d9c851dc705347c6fea7f6c4cb5b92683 /rtic-sync/src | |
| parent | 70f57c3160565dc3f2c0b060b1349eb2dd2a13b5 (diff) | |
rtic-sync: replacing SlotPtr is not actually safe
Diffstat (limited to 'rtic-sync/src')
| -rw-r--r-- | rtic-sync/src/channel.rs | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/rtic-sync/src/channel.rs b/rtic-sync/src/channel.rs index 5b83fce..a83cfb2 100644 --- a/rtic-sync/src/channel.rs +++ b/rtic-sync/src/channel.rs @@ -215,7 +215,9 @@ struct SlotPtr(*mut Option<u8>); impl SlotPtr { /// Replace the value of this slot with `new_value`, and return /// the old value. - fn replace( + /// + /// SAFETY: the pointer in this `SlotPtr` must still be valid. + unsafe fn replace( &mut self, new_value: Option<u8>, _cs: critical_section::CriticalSection, @@ -314,8 +316,10 @@ impl<T, const N: usize> Sender<'_, T, N> { // 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... + // + // SAFETY(replace): the data pointed to by `free_slot_ptr2` is still alive. critical_section::with(|cs| { - if let Some(freed_slot) = free_slot_ptr2.replace(None, cs) { + if let Some(freed_slot) = unsafe { free_slot_ptr2.replace(None, cs) } { debug_assert!(!self.0.access(cs).freeq.is_full()); // SAFETY: freeq is not full. unsafe { @@ -358,8 +362,8 @@ impl<T, const N: usize> Sender<'_, T, N> { } } - let slot = free_slot_ptr - .replace(None, cs) + // SAFETY: the value pointed to by `free_slot_ptr` is still alive. + let slot = unsafe { free_slot_ptr.replace(None, cs) } .or_else(|| self.0.access(cs).freeq.pop_back()); if let Some(slot) = slot { @@ -471,7 +475,9 @@ impl<T, const N: usize> Receiver<'_, T, N> { // If someone is waiting in the WaiterQueue, wake the first one up & hand it the free slot. if let Some((wait_head, mut freeq_slot)) = self.0.wait_queue.pop() { - freeq_slot.replace(Some(rs), cs); + // SAFETY: the value pointed to by `freeq_slot` is still alive: we are in a critical + // section & the `SlotPtr` lives for at least the duration of the wait queue link. + unsafe { freeq_slot.replace(Some(rs), cs) }; wait_head.wake(); } else { assert!(!self.0.access(cs).freeq.is_full()); |
