1use std::fmt::{self, Debug};
4use std::mem;
5use std::mem::MaybeUninit;
6use std::sync::atomic;
7
8use crate::sys;
9use crate::util::{private, unsync_load, Mmap};
10
11pub(crate) struct Inner<E: EntryMarker> {
12 head: *const atomic::AtomicU32,
13 tail: *const atomic::AtomicU32,
14 ring_mask: u32,
15 ring_entries: u32,
16
17 overflow: *const atomic::AtomicU32,
18
19 cqes: *const E,
20
21 #[allow(dead_code)]
22 flags: *const atomic::AtomicU32,
23}
24
25pub struct CompletionQueue<'a, E: EntryMarker = Entry> {
27 head: u32,
28 tail: u32,
29 queue: &'a Inner<E>,
30}
31
32pub struct CompletionStatus {
50 head: *const atomic::AtomicU32,
51 tail: *const atomic::AtomicU32,
52}
53
54impl CompletionStatus {
55 #[inline]
60 pub fn is_empty(&self) -> bool {
61 unsafe { unsync_load(self.head) == (*self.tail).load(atomic::Ordering::Acquire) }
67 }
68}
69
70impl Debug for CompletionStatus {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 f.debug_struct("CompletionStatus")
73 .field("is_empty", &self.is_empty())
74 .finish()
75 }
76}
77
78pub trait EntryMarker: Clone + Debug + Into<Entry> + private::Sealed {
82 const BUILD_FLAGS: u32;
83
84 fn user_data(&self) -> u64;
86
87 fn set_user_data(&mut self, user_data: u64);
89}
90
91#[repr(C)]
93pub struct Entry(pub(crate) sys::io_uring_cqe);
94
95#[repr(C)]
97#[derive(Clone)]
98pub struct Entry32(pub(crate) Entry, pub(crate) [u64; 2]);
99
100#[test]
101fn test_entry_sizes() {
102 assert_eq!(mem::size_of::<Entry>(), 16);
103 assert_eq!(mem::size_of::<Entry32>(), 32);
104}
105
106#[test]
107fn test_user_data() {
108 fn cqe(user_data: u64) -> Entry {
109 Entry(sys::io_uring_cqe {
110 user_data,
111 res: 0,
112 flags: 0,
113 big_cqe: sys::__IncompleteArrayField::new(),
114 })
115 }
116
117 fn replace<E: EntryMarker>(entry: &mut E, user_data: u64) -> u64 {
118 let previous = entry.user_data();
119 entry.set_user_data(user_data);
120 previous
121 }
122
123 let mut entry = cqe(1);
124 assert_eq!(replace(&mut entry, 2), 1);
125 assert_eq!(entry.user_data(), 2);
126
127 let mut entry = Entry32(cqe(3), [0; 2]);
128 assert_eq!(replace(&mut entry, 4), 3);
129 assert_eq!(entry.user_data(), 4);
130}
131
132impl<E: EntryMarker> Inner<E> {
133 #[rustfmt::skip]
134 pub(crate) unsafe fn new(cq_mmap: &Mmap, p: &sys::io_uring_params) -> Self {
135 let head = cq_mmap.offset(p.cq_off.head ) as *const atomic::AtomicU32;
136 let tail = cq_mmap.offset(p.cq_off.tail ) as *const atomic::AtomicU32;
137 let ring_mask = cq_mmap.offset(p.cq_off.ring_mask ).cast::<u32>().read();
138 let ring_entries = cq_mmap.offset(p.cq_off.ring_entries ).cast::<u32>().read();
139 let overflow = cq_mmap.offset(p.cq_off.overflow ) as *const atomic::AtomicU32;
140 let cqes = cq_mmap.offset(p.cq_off.cqes ) as *const E;
141 let flags = cq_mmap.offset(p.cq_off.flags ) as *const atomic::AtomicU32;
142
143 Self {
144 head,
145 tail,
146 ring_mask,
147 ring_entries,
148 overflow,
149 cqes,
150 flags,
151 }
152 }
153
154 #[inline]
155 pub(crate) unsafe fn borrow_shared(&self) -> CompletionQueue<'_, E> {
156 CompletionQueue {
157 head: unsync_load(self.head),
158 tail: (*self.tail).load(atomic::Ordering::Acquire),
159 queue: self,
160 }
161 }
162
163 #[inline]
164 pub(crate) fn borrow(&mut self) -> CompletionQueue<'_, E> {
165 unsafe { self.borrow_shared() }
166 }
167}
168
169impl<E: EntryMarker> CompletionQueue<'_, E> {
170 #[inline]
178 pub unsafe fn status(&self) -> CompletionStatus {
179 CompletionStatus {
180 head: self.queue.head,
181 tail: self.queue.tail,
182 }
183 }
184
185 #[inline]
190 pub fn sync(&mut self) {
191 unsafe {
192 (*self.queue.head).store(self.head, atomic::Ordering::Release);
193 self.tail = (*self.queue.tail).load(atomic::Ordering::Acquire);
194 }
195 }
196
197 pub fn overflow(&self) -> u32 {
200 unsafe { (*self.queue.overflow).load(atomic::Ordering::Acquire) }
201 }
202
203 pub fn eventfd_disabled(&self) -> bool {
207 unsafe {
208 (*self.queue.flags).load(atomic::Ordering::Acquire) & sys::IORING_CQ_EVENTFD_DISABLED
209 != 0
210 }
211 }
212
213 #[inline]
215 pub fn capacity(&self) -> usize {
216 self.queue.ring_entries as usize
217 }
218
219 #[inline]
221 pub fn is_empty(&self) -> bool {
222 self.len() == 0
223 }
224
225 #[inline]
229 pub fn is_full(&self) -> bool {
230 self.len() == self.capacity()
231 }
232
233 #[inline]
234 pub fn fill<'a>(&mut self, entries: &'a mut [MaybeUninit<E>]) -> &'a mut [E] {
235 let len = std::cmp::min(self.len(), entries.len());
236
237 for entry in &mut entries[..len] {
238 entry.write(unsafe { self.pop() });
239 }
240
241 unsafe { std::slice::from_raw_parts_mut(entries as *mut _ as *mut E, len) }
242 }
243
244 #[inline]
245 unsafe fn pop(&mut self) -> E {
246 let entry = &*self
247 .queue
248 .cqes
249 .add((self.head & self.queue.ring_mask) as usize);
250 self.head = self.head.wrapping_add(1);
251 entry.clone()
252 }
253}
254
255impl<E: EntryMarker> Drop for CompletionQueue<'_, E> {
256 #[inline]
257 fn drop(&mut self) {
258 unsafe { &*self.queue.head }.store(self.head, atomic::Ordering::Release);
259 }
260}
261
262impl<E: EntryMarker> Iterator for CompletionQueue<'_, E> {
263 type Item = E;
264
265 #[inline]
266 fn next(&mut self) -> Option<Self::Item> {
267 if self.head != self.tail {
268 Some(unsafe { self.pop() })
269 } else {
270 None
271 }
272 }
273
274 #[inline]
275 fn size_hint(&self) -> (usize, Option<usize>) {
276 (self.len(), Some(self.len()))
277 }
278}
279
280impl<E: EntryMarker> ExactSizeIterator for CompletionQueue<'_, E> {
281 #[inline]
282 fn len(&self) -> usize {
283 self.tail.wrapping_sub(self.head) as usize
284 }
285}
286
287impl Entry {
288 #[inline]
291 pub fn result(&self) -> i32 {
292 self.0.res
293 }
294
295 #[inline]
298 pub fn user_data(&self) -> u64 {
299 self.0.user_data
300 }
301
302 #[inline]
304 pub fn set_user_data(&mut self, user_data: u64) {
305 self.0.user_data = user_data;
306 }
307
308 #[inline]
314 pub fn flags(&self) -> u32 {
315 self.0.flags
316 }
317}
318
319impl private::Sealed for Entry {}
320
321impl EntryMarker for Entry {
322 const BUILD_FLAGS: u32 = 0;
323
324 #[inline]
325 fn user_data(&self) -> u64 {
326 Entry::user_data(self)
327 }
328
329 #[inline]
330 fn set_user_data(&mut self, user_data: u64) {
331 Entry::set_user_data(self, user_data);
332 }
333}
334
335impl Clone for Entry {
336 fn clone(&self) -> Entry {
337 Entry(unsafe { mem::transmute_copy(&self.0) })
339 }
340}
341
342impl Debug for Entry {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 f.debug_struct("Entry")
345 .field("result", &self.result())
346 .field("user_data", &self.user_data())
347 .field("flags", &self.flags())
348 .finish()
349 }
350}
351
352impl Entry32 {
353 #[inline]
356 pub fn result(&self) -> i32 {
357 self.0 .0.res
358 }
359
360 #[inline]
363 pub fn user_data(&self) -> u64 {
364 self.0 .0.user_data
365 }
366
367 #[inline]
369 pub fn set_user_data(&mut self, user_data: u64) {
370 self.0 .0.user_data = user_data;
371 }
372
373 #[inline]
379 pub fn flags(&self) -> u32 {
380 self.0 .0.flags
381 }
382
383 #[inline]
385 pub fn big_cqe(&self) -> &[u64; 2] {
386 &self.1
387 }
388}
389
390impl private::Sealed for Entry32 {}
391
392impl EntryMarker for Entry32 {
393 const BUILD_FLAGS: u32 = sys::IORING_SETUP_CQE32;
394
395 #[inline]
396 fn user_data(&self) -> u64 {
397 Entry32::user_data(self)
398 }
399
400 #[inline]
401 fn set_user_data(&mut self, user_data: u64) {
402 Entry32::set_user_data(self, user_data);
403 }
404}
405
406impl From<Entry32> for Entry {
407 fn from(entry32: Entry32) -> Self {
408 entry32.0
409 }
410}
411
412impl Debug for Entry32 {
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 f.debug_struct("Entry32")
415 .field("result", &self.result())
416 .field("user_data", &self.user_data())
417 .field("flags", &self.flags())
418 .field("big_cqe", &self.big_cqe())
419 .finish()
420 }
421}
422
423pub fn buffer_more(flags: u32) -> bool {
430 flags & sys::IORING_CQE_F_BUF_MORE != 0
431}
432
433pub fn buffer_select(flags: u32) -> Option<u16> {
439 if flags & sys::IORING_CQE_F_BUFFER != 0 {
440 let id = flags >> sys::IORING_CQE_BUFFER_SHIFT;
441
442 Some(id as u16)
446 } else {
447 None
448 }
449}
450
451pub fn more(flags: u32) -> bool {
458 flags & sys::IORING_CQE_F_MORE != 0
459}
460
461pub fn sock_nonempty(flags: u32) -> bool {
469 flags & sys::IORING_CQE_F_SOCK_NONEMPTY != 0
470}
471
472pub fn notif(flags: u32) -> bool {
477 flags & sys::IORING_CQE_F_NOTIF != 0
478}