Skip to content

Commit 3d7fa3d

Browse files
committed
rtic-sync: replacing SlotPtr is not actually safe
1 parent a2d8cfa commit 3d7fa3d

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

rtic-sync/src/channel.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ struct SlotPtr(*mut Option<u8>);
215215
impl SlotPtr {
216216
/// Replace the value of this slot with `new_value`, and return
217217
/// the old value.
218-
fn replace(
218+
///
219+
/// SAFETY: the pointer in this `SlotPtr` must still be valid.
220+
unsafe fn replace(
219221
&mut self,
220222
new_value: Option<u8>,
221223
_cs: critical_section::CriticalSection,
@@ -314,8 +316,10 @@ impl<T, const N: usize> Sender<'_, T, N> {
314316
// Potentially unnecessary c-s because our link was already popped, so there
315317
// is no way for anything else to access the free slot ptr. Gotta think
316318
// about this a bit more...
319+
//
320+
// SAFETY(replace): the data pointed to by `free_slot_ptr2` is still alive.
317321
critical_section::with(|cs| {
318-
if let Some(freed_slot) = free_slot_ptr2.replace(None, cs) {
322+
if let Some(freed_slot) = unsafe { free_slot_ptr2.replace(None, cs) } {
319323
debug_assert!(!self.0.access(cs).freeq.is_full());
320324
// SAFETY: freeq is not full.
321325
unsafe {
@@ -358,8 +362,8 @@ impl<T, const N: usize> Sender<'_, T, N> {
358362
}
359363
}
360364

361-
let slot = free_slot_ptr
362-
.replace(None, cs)
365+
// SAFETY: the value pointed to by `free_slot_ptr` is still alive.
366+
let slot = unsafe { free_slot_ptr.replace(None, cs) }
363367
.or_else(|| self.0.access(cs).freeq.pop_back());
364368

365369
if let Some(slot) = slot {
@@ -471,7 +475,9 @@ impl<T, const N: usize> Receiver<'_, T, N> {
471475

472476
// If someone is waiting in the WaiterQueue, wake the first one up & hand it the free slot.
473477
if let Some((wait_head, mut freeq_slot)) = self.0.wait_queue.pop() {
474-
freeq_slot.replace(Some(rs), cs);
478+
// SAFETY: the value pointed to by `freeq_slot` is still alive: we are in a critical
479+
// section & the `SlotPtr` lives for at least the duration of the wait queue link.
480+
unsafe { freeq_slot.replace(Some(rs), cs) };
475481
wait_head.wake();
476482
} else {
477483
assert!(!self.0.access(cs).freeq.is_full());

0 commit comments

Comments
 (0)