diff options
| author | lsartory <[email protected]> | 2025-02-01 16:43:41 +0100 |
|---|---|---|
| committer | lsartory <[email protected]> | 2025-02-01 16:43:41 +0100 |
| commit | 7d66f1ca192bb5de83626cdb91f82c1caf265d73 (patch) | |
| tree | f6041d2e20664261eb0f8c4d07c11a6bb365b78f /embassy-sync | |
| parent | 1b440342085a0a4f752c795937cc038b41ca1e78 (diff) | |
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.
Diffstat (limited to 'embassy-sync')
| -rw-r--r-- | embassy-sync/src/zerocopy_channel.rs | 16 |
1 files 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; | |||
| 35 | /// The channel requires a buffer of recyclable elements. Writing to the channel is done through | 35 | /// The channel requires a buffer of recyclable elements. Writing to the channel is done through |
| 36 | /// an `&mut T`. | 36 | /// an `&mut T`. |
| 37 | pub struct Channel<'a, M: RawMutex, T> { | 37 | pub struct Channel<'a, M: RawMutex, T> { |
| 38 | buf: *mut T, | 38 | buf: BufferPtr<T>, |
| 39 | phantom: PhantomData<&'a mut T>, | 39 | phantom: PhantomData<&'a mut T>, |
| 40 | state: Mutex<M, RefCell<State>>, | 40 | state: Mutex<M, RefCell<State>>, |
| 41 | } | 41 | } |
| @@ -50,7 +50,7 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> { | |||
| 50 | assert!(len != 0); | 50 | assert!(len != 0); |
| 51 | 51 | ||
| 52 | Self { | 52 | Self { |
| 53 | buf: buf.as_mut_ptr(), | 53 | buf: BufferPtr(buf.as_mut_ptr()), |
| 54 | phantom: PhantomData, | 54 | phantom: PhantomData, |
| 55 | state: Mutex::new(RefCell::new(State { | 55 | state: Mutex::new(RefCell::new(State { |
| 56 | capacity: len, | 56 | capacity: len, |
| @@ -94,6 +94,18 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> { | |||
| 94 | } | 94 | } |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | #[repr(transparent)] | ||
| 98 | struct BufferPtr<T>(*mut T); | ||
| 99 | |||
| 100 | impl<T> BufferPtr<T> { | ||
| 101 | unsafe fn add(&self, count: usize) -> *mut T { | ||
| 102 | self.0.add(count) | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | unsafe impl<T> Send for BufferPtr<T> {} | ||
| 107 | unsafe impl<T> Sync for BufferPtr<T> {} | ||
| 108 | |||
| 97 | /// Send-only access to a [`Channel`]. | 109 | /// Send-only access to a [`Channel`]. |
| 98 | pub struct Sender<'a, M: RawMutex, T> { | 110 | pub struct Sender<'a, M: RawMutex, T> { |
| 99 | channel: &'a Channel<'a, M, T>, | 111 | channel: &'a Channel<'a, M, T>, |
