|
| 1 | +use std::cell::{Cell, UnsafeCell}; |
1 | 2 | use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd}; |
2 | | -use std::{ |
3 | | - cell::Cell, cell::RefCell, cmp, collections::VecDeque, fmt, io, mem, net, rc::Rc, |
4 | | - sync::Arc, |
5 | | -}; |
| 3 | +use std::{cmp, collections::VecDeque, fmt, io, mem, net, ptr, rc::Rc, sync::Arc}; |
6 | 4 |
|
7 | 5 | #[cfg(unix)] |
8 | 6 | use std::os::unix::net::UnixStream as OsUnixStream; |
@@ -49,14 +47,15 @@ impl DriverApi { |
49 | 47 | where |
50 | 48 | F: FnOnce(&mut SEntry), |
51 | 49 | { |
52 | | - let mut changes = self.inner.changes.borrow_mut(); |
53 | | - let sq = self.inner.ring.submission(); |
54 | | - if !changes.is_empty() || sq.is_full() { |
55 | | - let mut entry = Default::default(); |
56 | | - f(&mut entry); |
57 | | - changes.push_back(entry); |
58 | | - } else { |
59 | | - unsafe { |
| 50 | + unsafe { |
| 51 | + let changes = &mut *self.inner.changes.get(); |
| 52 | + let sq = self.inner.ring.submission(); |
| 53 | + if !changes.is_empty() || sq.is_full() { |
| 54 | + changes.push_back(mem::MaybeUninit::uninit()); |
| 55 | + let entry = changes.back_mut().unwrap(); |
| 56 | + ptr::write_bytes(entry.as_mut_ptr(), 0, 1); |
| 57 | + f(entry.assume_init_mut()); |
| 58 | + } else { |
60 | 59 | sq.push_inline(f).expect("Queue size is checked"); |
61 | 60 | } |
62 | 61 | } |
@@ -135,7 +134,7 @@ struct DriverInner { |
135 | 134 | probe: Probe, |
136 | 135 | flags: Cell<Flags>, |
137 | 136 | ring: IoUring<SEntry, CEntry>, |
138 | | - changes: RefCell<VecDeque<SEntry>>, |
| 137 | + changes: UnsafeCell<VecDeque<mem::MaybeUninit<SEntry>>>, |
139 | 138 | } |
140 | 139 |
|
141 | 140 | impl Driver { |
@@ -189,7 +188,7 @@ impl Driver { |
189 | 188 | ring, |
190 | 189 | probe, |
191 | 190 | flags: Cell::new(if new { Flags::NEW } else { Flags::empty() }), |
192 | | - changes: RefCell::new(VecDeque::with_capacity(32)), |
| 191 | + changes: UnsafeCell::new(VecDeque::with_capacity(32)), |
193 | 192 | }); |
194 | 193 |
|
195 | 194 | Ok(Self { |
@@ -225,24 +224,35 @@ impl Driver { |
225 | 224 | } |
226 | 225 |
|
227 | 226 | fn apply_changes(&self, sq: SubmissionQueue<'_, SEntry>) -> bool { |
228 | | - let mut changes = self.inner.changes.borrow_mut(); |
229 | | - if changes.is_empty() { |
230 | | - false |
231 | | - } else { |
232 | | - let num = cmp::min(changes.len(), sq.capacity() - sq.len()); |
233 | | - let (s1, s2) = changes.as_slices(); |
234 | | - let s1_num = cmp::min(s1.len(), num); |
235 | | - if s1_num > 0 { |
236 | | - unsafe { sq.push_multiple(&s1[0..s1_num]) }.unwrap(); |
237 | | - } else if !s2.is_empty() { |
238 | | - let s2_num = cmp::min(s2.len(), num - s1_num); |
239 | | - if s2_num > 0 { |
240 | | - unsafe { sq.push_multiple(&s2[0..s2_num]) }.unwrap(); |
| 227 | + unsafe { |
| 228 | + let changes = &mut *self.inner.changes.get(); |
| 229 | + if changes.is_empty() { |
| 230 | + false |
| 231 | + } else { |
| 232 | + let num = cmp::min(changes.len(), sq.capacity() - sq.len()); |
| 233 | + let (s1, s2) = changes.as_slices(); |
| 234 | + let s1_num = cmp::min(s1.len(), num); |
| 235 | + if s1_num > 0 { |
| 236 | + // safety: "changes" contains only initialized entries |
| 237 | + sq.push_multiple(mem::transmute::< |
| 238 | + &[mem::MaybeUninit<SEntry>], |
| 239 | + &[SEntry], |
| 240 | + >(&s1[0..s1_num])) |
| 241 | + .unwrap(); |
| 242 | + } else if !s2.is_empty() { |
| 243 | + let s2_num = cmp::min(s2.len(), num - s1_num); |
| 244 | + if s2_num > 0 { |
| 245 | + sq.push_multiple(mem::transmute::< |
| 246 | + &[mem::MaybeUninit<SEntry>], |
| 247 | + &[SEntry], |
| 248 | + >(&s2[0..s2_num])) |
| 249 | + .unwrap(); |
| 250 | + } |
241 | 251 | } |
242 | | - } |
243 | | - changes.drain(0..num); |
| 252 | + changes.drain(0..num); |
244 | 253 |
|
245 | | - !changes.is_empty() |
| 254 | + !changes.is_empty() |
| 255 | + } |
246 | 256 | } |
247 | 257 | } |
248 | 258 |
|
|
0 commit comments