Skip to content

Commit 8623a8c

Browse files
committed
rtic-sync: we have exclusive access to the free slot pointer when in drop
1 parent 465a5e0 commit 8623a8c

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

rtic-sync/src/channel.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,19 @@ impl SlotPtr {
246246
new_value: Option<u8>,
247247
_cs: critical_section::CriticalSection,
248248
) -> Option<u8> {
249-
// SAFETY: we are in a critical section.
249+
// SAFETY: the critical section guarantees exclusive access, and the
250+
// caller guarantees that the pointer is valid.
251+
self.replace_exclusive(new_value)
252+
}
253+
254+
/// Replace the value of this slot with `new_value`, and return
255+
/// the old value.
256+
///
257+
/// SAFETY: the pointer in this `SlotPtr` must be valid for writes, and the caller must guarantee exclusive
258+
/// access to the underlying value..
259+
unsafe fn replace_exclusive(&mut self, new_value: Option<u8>) -> Option<u8> {
260+
// SAFETY: the caller has ensured that we have exclusive access & that
261+
// the pointer is valid.
250262
unsafe { core::ptr::replace(self.0, new_value) }
251263
}
252264
}
@@ -338,17 +350,14 @@ impl<T, const N: usize> Sender<'_, T, N> {
338350
}
339351

340352
// Return our potentially-unused free slot.
341-
// Potentially unnecessary c-s because our link was already popped, so there
342-
// is no way for anything else to access the free slot ptr. Gotta think
343-
// about this a bit more...
344-
critical_section::with(|cs| {
345-
if let Some(freed_slot) = unsafe { free_slot_ptr2.replace(None, cs) } {
346-
// SAFETY: freed slot is passed to us from `return_free_slot`, which either
347-
// directly (through `try_recv`), or indirectly (through another `return_free_slot`)
348-
// comes from `readyq`.
349-
unsafe { self.0.return_free_slot(freed_slot) };
350-
}
351-
});
353+
// Since we are certain that our link has been removed from the list (either
354+
// pop-ed or removed just above), we have exclusive access to the free slot pointer.
355+
if let Some(freed_slot) = unsafe { free_slot_ptr2.replace_exclusive(None) } {
356+
// SAFETY: freed slot is passed to us from `return_free_slot`, which either
357+
// directly (through `try_recv`), or indirectly (through another `return_free_slot`)
358+
// comes from `readyq`.
359+
unsafe { self.0.return_free_slot(freed_slot) };
360+
}
352361
});
353362

354363
let idx = poll_fn(|cx| {

0 commit comments

Comments
 (0)