Zero-copy channels could not be used between interrupts and thread-mode
tasks because the internal buffer is stored as a raw pointer.
A wrapper struct implementing the Sync trait fixes this.
This commit is contained in:
lsartory 2025-02-01 16:43:41 +01:00
parent 1b44034208
commit 7d66f1ca19

View File

@ -35,7 +35,7 @@ use crate::waitqueue::WakerRegistration;
/// The channel requires a buffer of recyclable elements. Writing to the channel is done through
/// an `&mut T`.
pub struct Channel<'a, M: RawMutex, T> {
buf: *mut T,
buf: BufferPtr<T>,
phantom: PhantomData<&'a mut T>,
state: Mutex<M, RefCell<State>>,
}
@ -50,7 +50,7 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> {
assert!(len != 0);
Self {
buf: buf.as_mut_ptr(),
buf: BufferPtr(buf.as_mut_ptr()),
phantom: PhantomData,
state: Mutex::new(RefCell::new(State {
capacity: len,
@ -94,6 +94,18 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> {
}
}
#[repr(transparent)]
struct BufferPtr<T>(*mut T);
impl<T> BufferPtr<T> {
unsafe fn add(&self, count: usize) -> *mut T {
self.0.add(count)
}
}
unsafe impl<T> Send for BufferPtr<T> {}
unsafe impl<T> Sync for BufferPtr<T> {}
/// Send-only access to a [`Channel`].
pub struct Sender<'a, M: RawMutex, T> {
channel: &'a Channel<'a, M, T>,