@@ -246,7 +246,19 @@ impl SlotPtr {
246
246
new_value : Option < u8 > ,
247
247
_cs : critical_section:: CriticalSection ,
248
248
) -> 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.
250
262
unsafe { core:: ptr:: replace ( self . 0 , new_value) }
251
263
}
252
264
}
@@ -338,17 +350,14 @@ impl<T, const N: usize> Sender<'_, T, N> {
338
350
}
339
351
340
352
// 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
+ }
352
361
} ) ;
353
362
354
363
let idx = poll_fn ( |cx| {
0 commit comments