From 7d66f1ca192bb5de83626cdb91f82c1caf265d73 Mon Sep 17 00:00:00 2001 From: lsartory Date: Sat, 1 Feb 2025 16:43:41 +0100 Subject: [PATCH] Fix issue #3828 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. --- embassy-sync/src/zerocopy_channel.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/embassy-sync/src/zerocopy_channel.rs b/embassy-sync/src/zerocopy_channel.rs index 15914578e..ad6fe74c5 100644 --- a/embassy-sync/src/zerocopy_channel.rs +++ b/embassy-sync/src/zerocopy_channel.rs @@ -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, phantom: PhantomData<&'a mut T>, state: Mutex>, } @@ -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(*mut T); + +impl BufferPtr { + unsafe fn add(&self, count: usize) -> *mut T { + self.0.add(count) + } +} + +unsafe impl Send for BufferPtr {} +unsafe impl Sync for BufferPtr {} + /// Send-only access to a [`Channel`]. pub struct Sender<'a, M: RawMutex, T> { channel: &'a Channel<'a, M, T>,