1use core::fmt;
78use core::marker::PhantomData;
79use core::sync::atomic::{Ordering, fence};
80
81use bytemuck::Zeroable;
82use smallvec::SmallVec;
83use thiserror::Error;
84
85use super::desc::{DescFlags, DescTable, Descriptor};
86use super::event::{EventFlags, EventSuppression};
87use super::{Layout, MemOps};
88
89#[derive(Debug, Copy, Clone, Zeroable)]
95pub struct BufferElement {
96 pub addr: u64,
98 pub len: u32,
100 pub writable: bool,
102}
103
104#[derive(Debug, Copy, Clone)]
110pub struct UsedBuffer {
111 pub id: u16,
113 pub len: u32,
116}
117
118#[derive(Debug, Copy, Clone)]
123pub struct SubmitResult {
124 pub id: u16,
127 pub notify: bool,
130}
131
132#[derive(Debug, Copy, Clone, PartialEq, Eq)]
134pub enum MemOp {
135 ReadDesc,
137 WriteDesc,
139 ReadEvent,
141 WriteEvent,
143}
144
145impl fmt::Display for MemOp {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 match self {
148 Self::ReadDesc => f.write_str("reading descriptor"),
149 Self::WriteDesc => f.write_str("writing descriptor"),
150 Self::ReadEvent => f.write_str("reading event suppression"),
151 Self::WriteEvent => f.write_str("writing event suppression"),
152 }
153 }
154}
155
156#[derive(Error, Debug)]
157pub enum RingError {
158 #[error("Buffer chain is empty")]
159 EmptyChain,
160 #[error("Buffer chain is malformed")]
161 BadChain,
162 #[error("Operation would block")]
163 WouldBlock,
164 #[error("Out of memory")]
165 OutOfMemory,
166 #[error("Invalid state")]
167 InvalidState,
168 #[error("Invalid memory layout")]
169 InvalidLayout,
170 #[error("Backend memory error while {op} at address 0x{addr:x}, len {len}")]
171 MemError {
172 op: MemOp,
174 addr: u64,
176 len: usize,
178 },
179}
180
181impl RingError {
182 #[inline]
183 fn mem_err(op: MemOp, addr: u64) -> Self {
184 let len = match op {
185 MemOp::ReadDesc | MemOp::WriteDesc => Descriptor::SIZE,
186 MemOp::ReadEvent | MemOp::WriteEvent => EventSuppression::SIZE,
187 };
188
189 Self::MemError { op, addr, len }
190 }
191}
192
193pub struct Readable;
195
196pub struct Writable;
198
199#[derive(Debug, Default)]
207pub struct BufferChainBuilder<T> {
208 elems: SmallVec<[BufferElement; 16]>,
209 split: usize,
210 marker: PhantomData<T>,
211}
212
213impl BufferChainBuilder<Readable> {
214 pub fn new() -> Self {
216 Self {
217 elems: Default::default(),
218 split: 0,
219 marker: PhantomData,
220 }
221 }
222
223 pub fn readable(mut self, addr: u64, len: u32) -> Self {
225 self.elems.push(BufferElement {
226 addr,
227 len,
228 writable: false,
229 });
230 self.split += 1;
231 self
232 }
233
234 pub fn readables(
236 mut self,
237 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
238 ) -> Self {
239 for elem in elements {
240 let mut elem = elem.into();
241 elem.writable = false;
242 self.elems.push(elem);
243 self.split += 1;
244 }
245
246 self
247 }
248
249 pub fn writable(mut self, addr: u64, len: u32) -> BufferChainBuilder<Writable> {
253 self.elems.push(BufferElement {
254 addr,
255 len,
256 writable: true,
257 });
258
259 BufferChainBuilder {
260 elems: self.elems,
261 split: self.split,
262 marker: PhantomData,
263 }
264 }
265
266 pub fn writables(
270 mut self,
271 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
272 ) -> BufferChainBuilder<Writable> {
273 for elem in elements {
274 let mut elem = elem.into();
275 elem.writable = true;
276 self.elems.push(elem);
277 }
278
279 BufferChainBuilder {
280 elems: self.elems,
281 split: self.split,
282 marker: PhantomData,
283 }
284 }
285
286 pub fn build(self) -> Result<BufferChain, RingError> {
290 if self.elems.is_empty() {
291 return Err(RingError::EmptyChain);
292 }
293
294 Ok(BufferChain {
295 elems: self.elems,
296 split: self.split,
297 })
298 }
299}
300
301impl BufferChainBuilder<Writable> {
302 pub fn writable(mut self, addr: u64, len: u32) -> Self {
304 self.elems.push(BufferElement {
305 addr,
306 len,
307 writable: true,
308 });
309 self
310 }
311
312 pub fn writables(
314 mut self,
315 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
316 ) -> Self {
317 for elem in elements {
318 let mut elem = elem.into();
319 elem.writable = true;
320 self.elems.push(elem);
321 }
322 self
323 }
324
325 pub fn build(self) -> Result<BufferChain, RingError> {
329 if self.elems.is_empty() {
330 return Err(RingError::EmptyChain);
331 }
332
333 Ok(BufferChain {
334 elems: self.elems,
335 split: self.split,
336 })
337 }
338}
339
340#[derive(Debug, Clone)]
345pub struct BufferChain {
346 elems: SmallVec<[BufferElement; 16]>,
348 split: usize,
350}
351
352impl BufferChain {
353 pub fn elems(&self) -> &[BufferElement] {
355 self.elems.as_slice()
356 }
357
358 pub fn readables(&self) -> &[BufferElement] {
360 &self.elems[..self.split]
361 }
362
363 pub(crate) fn readables_mut(&mut self) -> &mut [BufferElement] {
365 &mut self.elems[..self.split]
366 }
367
368 pub fn writables(&self) -> &[BufferElement] {
370 &self.elems[self.split..]
371 }
372
373 #[allow(clippy::len_without_is_empty)]
376 pub fn len(&self) -> usize {
377 self.elems.len()
378 }
379}
380
381#[derive(Debug, Copy, Clone, PartialEq, Eq)]
386pub struct RingCursor {
387 head: u16,
388 size: u16,
389 wrap: bool,
390}
391
392impl RingCursor {
393 pub(crate) fn new(size: usize) -> Self {
394 Self {
395 head: 0,
396 size: size as u16,
397 wrap: true,
398 }
399 }
400
401 #[inline]
403 fn advance(&mut self) {
404 debug_assert!(self.head.checked_add(1).is_some());
405 self.head += 1;
406 if self.head >= self.size {
407 self.head = 0;
408 self.wrap = !self.wrap;
409 }
410 }
411
412 #[inline]
414 fn advance_by(&mut self, n: u16) {
415 debug_assert!(self.head.checked_add(n).is_some());
416 let new = self.head + n;
417 let wraps = new / self.size;
418 self.head = new % self.size;
419 if !wraps.is_multiple_of(2) {
420 self.wrap = !self.wrap;
421 }
422 }
423
424 #[inline]
426 pub fn head(&self) -> u16 {
427 self.head
428 }
429
430 #[inline]
432 pub fn wrap(&self) -> bool {
433 self.wrap
434 }
435
436 #[inline]
438 pub fn reset(&mut self) {
439 self.head = 0;
440 self.wrap = true;
441 }
442}
443
444#[derive(Debug)]
457pub struct RingProducer<M> {
458 mem: M,
460 avail_cursor: RingCursor,
462 used_cursor: RingCursor,
464 num_free: usize,
466 desc_table: DescTable,
468 event_flags_shadow: EventFlags,
470 drv_evt_addr: u64,
472 dev_evt_addr: u64,
474 id_free: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
476 id_num: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
478}
479
480impl<M: MemOps> RingProducer<M> {
481 pub fn new(layout: Layout, mem: M) -> Self {
483 let size = layout.desc_table_len() as usize;
484 let raw = layout.desc_table_addr();
485
486 let table = unsafe { DescTable::from_raw_parts(raw, size) };
488 let cursor = RingCursor::new(size);
489
490 const DEFAULT_LEN: usize = DescTable::default_len();
491 let id_free = (0..size as u16).collect::<SmallVec<[_; DEFAULT_LEN]>>();
492 let id_num = SmallVec::<[_; DEFAULT_LEN]>::from_elem(0, size);
493
494 let event_flags_shadow = EventFlags::ENABLE;
496
497 Self {
498 mem,
499 avail_cursor: cursor,
500 used_cursor: cursor,
501 num_free: size,
502 desc_table: table,
503 id_free,
504 id_num,
505 event_flags_shadow,
506 drv_evt_addr: layout.drv_evt_addr(),
507 dev_evt_addr: layout.dev_evt_addr(),
508 }
509 }
510
511 pub fn submit_one(&mut self, addr: u64, len: u32, writable: bool) -> Result<u16, RingError> {
533 if self.num_free < 1 {
534 return Err(RingError::WouldBlock);
535 }
536
537 let id = self.id_free.pop().ok_or(RingError::OutOfMemory)?;
539
540 if self.id_num[id as usize] != 0 {
542 return Err(RingError::InvalidState);
543 }
544
545 self.id_num[id as usize] = 1;
547
548 let head_idx = self.avail_cursor.head();
550 let head_wrap = self.avail_cursor.wrap();
551
552 let mut flags = DescFlags::empty();
553 flags.set(DescFlags::WRITE, writable);
554 let mut desc = Descriptor::new(addr, len, id, flags);
555 desc.mark_avail(head_wrap);
556
557 let addr = self
558 .desc_table
559 .desc_addr(head_idx)
560 .ok_or(RingError::InvalidState)?;
561
562 desc.write_release(&self.mem, addr)
564 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
565
566 self.avail_cursor.advance();
568 self.num_free -= 1;
569
570 Ok(id)
571 }
572
573 pub fn submit_available_with_notify(
575 &mut self,
576 chain: &BufferChain,
577 ) -> Result<SubmitResult, RingError> {
578 let old = self.avail_cursor;
579 let id = self.submit_available(chain)?;
580 let new = self.avail_cursor;
581 let notify = self.should_notify_device(old, new)?;
582
583 Ok(SubmitResult { id, notify })
584 }
585
586 pub fn submit_one_with_notify(
588 &mut self,
589 addr: u64,
590 len: u32,
591 writable: bool,
592 ) -> Result<SubmitResult, RingError> {
593 let old = self.avail_cursor;
594 let id = self.submit_one(addr, len, writable)?;
595 let new = self.avail_cursor;
596 let notify = self.should_notify_device(old, new)?;
597 Ok(SubmitResult { id, notify })
598 }
599
600 pub fn submit_available(&mut self, chain: &BufferChain) -> Result<u16, RingError> {
623 let total_descs = chain.len();
624 if total_descs == 0 {
625 return Err(RingError::EmptyChain);
626 }
627
628 if self.num_free < total_descs {
629 return Err(RingError::WouldBlock);
630 }
631
632 if total_descs == 1 {
633 let elem = chain.elems()[0];
634 return self.submit_one(elem.addr, elem.len, elem.writable);
635 }
636
637 let head_idx = self.avail_cursor.head();
638 let head_wrap = self.avail_cursor.wrap();
639
640 let id = self.id_free.pop().ok_or(RingError::OutOfMemory)?;
641
642 if self.id_num[id as usize] != 0 {
644 return Err(RingError::InvalidState);
645 }
646
647 self.id_num[id as usize] = total_descs as u16;
649
650 let mut pos = self.avail_cursor;
652 pos.advance();
653
654 for (i, elem) in chain.elems().iter().enumerate().skip(1) {
655 let is_next = i + 1 < total_descs;
656 let mut flags = DescFlags::empty();
657
658 flags.set(DescFlags::NEXT, is_next);
659 flags.set(DescFlags::WRITE, elem.writable);
660
661 let mut desc = Descriptor::new(elem.addr, elem.len, id, flags);
662 desc.mark_avail(pos.wrap());
663
664 let addr = self
665 .desc_table
666 .desc_addr(pos.head())
667 .ok_or(RingError::InvalidState)?;
668
669 self.mem
670 .write_val(addr, desc)
671 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
672 pos.advance();
673 }
674
675 let head_elem = chain.elems()[0];
677 let mut head_flags = DescFlags::empty();
679 head_flags.set(DescFlags::NEXT, total_descs > 1);
680 head_flags.set(DescFlags::WRITE, head_elem.writable);
681
682 let mut head_desc = Descriptor::new(head_elem.addr, head_elem.len, id, head_flags);
683 head_desc.mark_avail(head_wrap);
684
685 let head_addr = self
686 .desc_table
687 .desc_addr(head_idx)
688 .ok_or(RingError::InvalidState)?;
689
690 head_desc
692 .write_release(&self.mem, head_addr)
693 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, head_addr))?;
694
695 self.num_free -= total_descs;
696 self.avail_cursor = pos;
697
698 Ok(id)
699 }
700
701 pub fn poll_used(&mut self) -> Result<UsedBuffer, RingError> {
711 let idx = self.used_cursor.head();
712 let wrap = self.used_cursor.wrap();
713
714 let addr = self
716 .desc_table
717 .desc_addr(idx)
718 .ok_or(RingError::InvalidState)?;
719
720 let flags = Descriptor::read_flags_acquire(&self.mem, addr)
722 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
723
724 if !flags.is_used(wrap) {
725 return Err(RingError::WouldBlock);
726 }
727
728 let desc = Descriptor::read_body(&self.mem, addr, flags)
729 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
730
731 let id = desc.id;
732 let count = *self
733 .id_num
734 .get(id as usize)
735 .ok_or(RingError::InvalidState)?;
736
737 if count == 0 {
738 return Err(RingError::InvalidState);
739 }
740
741 self.used_cursor.advance_by(count);
743 self.num_free += count as usize;
745 self.id_num[id as usize] = 0;
747 self.id_free.push(id);
749
750 Ok(UsedBuffer { id, len: desc.len })
751 }
752
753 #[inline]
755 pub fn num_free(&self) -> usize {
756 self.num_free
757 }
758
759 #[inline]
761 pub fn num_inflight(&self) -> usize {
762 self.desc_table.len() - self.num_free
763 }
764
765 #[inline]
767 pub fn is_full(&self) -> bool {
768 self.num_free == 0
769 }
770
771 #[inline]
773 #[allow(clippy::len_without_is_empty)]
774 pub fn len(&self) -> usize {
775 self.desc_table.len()
776 }
777
778 #[inline]
780 pub fn mem(&self) -> &M {
781 &self.mem
782 }
783
784 #[inline]
786 pub fn desc_table(&self) -> &DescTable {
787 &self.desc_table
788 }
789
790 #[inline]
795 pub fn avail_cursor(&self) -> RingCursor {
796 self.avail_cursor
797 }
798
799 #[inline]
803 pub fn used_cursor(&self) -> RingCursor {
804 self.used_cursor
805 }
806
807 pub fn should_notify_since(&self, old: RingCursor) -> Result<bool, RingError> {
815 self.should_notify_device(old, self.avail_cursor)
816 }
817
818 pub fn disable_used_notifications(&mut self) -> Result<(), RingError> {
820 if self.event_flags_shadow == EventFlags::DISABLE {
822 return Ok(());
823 }
824
825 let mut evt = self
826 .mem
827 .read_val::<EventSuppression>(self.drv_evt_addr)
828 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
829
830 evt.set_flags(EventFlags::DISABLE);
831
832 evt.write_release(&self.mem, self.drv_evt_addr)
833 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
834 self.event_flags_shadow = EventFlags::DISABLE;
835 Ok(())
836 }
837
838 pub fn enable_used_notifications(&mut self) -> Result<(), RingError> {
840 if self.event_flags_shadow == EventFlags::ENABLE {
841 return Ok(());
842 }
843
844 let mut evt = self
845 .mem
846 .read_val::<EventSuppression>(self.drv_evt_addr)
847 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
848
849 evt.set_flags(EventFlags::ENABLE);
850 evt.write_release(&self.mem, self.drv_evt_addr)
851 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
852
853 self.event_flags_shadow = EventFlags::ENABLE;
854 Ok(())
855 }
856
857 pub fn enable_used_notifications_desc(
864 &mut self,
865 off: u16,
866 wrap: bool,
867 ) -> Result<(), RingError> {
868 let mut evt = self
869 .mem
870 .read_val::<EventSuppression>(self.drv_evt_addr)
871 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
872
873 evt.set_desc_event(off, wrap);
874 evt.set_flags(EventFlags::DESC);
875
876 evt.write_release(&self.mem, self.drv_evt_addr)
878 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
879 self.event_flags_shadow = EventFlags::DESC;
881 Ok(())
882 }
883
884 pub fn enable_used_notifications_for_next(&mut self) -> Result<(), RingError> {
886 let off = self.used_cursor.head();
887 let wrap = self.used_cursor.wrap();
888
889 self.enable_used_notifications_desc(off, wrap)
890 }
891
892 fn should_notify_device(&self, old: RingCursor, new: RingCursor) -> Result<bool, RingError> {
894 fence(Ordering::SeqCst);
904
905 should_notify_evt(&self.mem, self.dev_evt_addr, self.len() as u16, old, new)
906 }
907
908 pub fn reset(&mut self) {
910 let size = self.desc_table.len();
911 self.avail_cursor.reset();
912 self.used_cursor.reset();
913 self.num_free = size;
914 self.id_free.clear();
915 self.id_free.extend(0..size as u16);
916 self.id_num.iter_mut().for_each(|n| *n = 0);
917 self.event_flags_shadow = EventFlags::ENABLE;
918 }
919
920 pub fn reset_prefilled(&mut self, ids: &[u16]) {
925 let size = self.desc_table.len();
926 let count = ids.len();
927 assert!(count <= size);
928
929 let wrapped = count >= size;
930 self.avail_cursor.head = if wrapped { 0 } else { count as u16 };
931 self.avail_cursor.wrap = !wrapped;
932
933 self.used_cursor.head = 0;
934 self.used_cursor.wrap = true;
935
936 self.id_num.iter_mut().for_each(|n| *n = 0);
937 for &id in ids {
938 assert!((id as usize) < size);
939 assert_eq!(self.id_num[id as usize], 0);
940 self.id_num[id as usize] = 1;
941 }
942
943 self.num_free = size - count;
944 self.id_free.clear();
945 self.id_free
946 .extend((0..size as u16).filter(|id| self.id_num[*id as usize] == 0));
947 }
948}
949
950#[derive(Debug)]
963pub struct RingConsumer<M> {
964 mem: M,
966 avail_cursor: RingCursor,
968 used_cursor: RingCursor,
970 desc_table: DescTable,
972 id_num: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
974 num_inflight: usize,
976 event_flags_shadow: EventFlags,
978 drv_evt_addr: u64,
980 dev_evt_addr: u64,
982}
983
984impl<M: MemOps> RingConsumer<M> {
985 pub fn new(layout: Layout, mem: M) -> Self {
986 let size = layout.desc_table_len() as usize;
987 let raw = layout.desc_table_addr();
988
989 let table = unsafe { DescTable::from_raw_parts(raw, size) };
991 let cursor = RingCursor::new(size);
992 let id_chain_len = SmallVec::<[u16; DescTable::DEFAULT_LEN]>::from_elem(0, size);
993
994 let event_flags_shadow = EventFlags::ENABLE;
996
997 Self {
998 mem,
999 avail_cursor: cursor,
1000 used_cursor: cursor,
1001 desc_table: table,
1002 id_num: id_chain_len,
1003 num_inflight: 0,
1004 event_flags_shadow,
1005 drv_evt_addr: layout.drv_evt_addr(),
1006 dev_evt_addr: layout.dev_evt_addr(),
1007 }
1008 }
1009
1010 pub fn poll_available(&mut self) -> Result<(u16, BufferChain), RingError> {
1022 let idx = self.avail_cursor.head();
1023 let wrap = self.avail_cursor.wrap();
1024
1025 let head_addr = self
1026 .desc_table
1027 .desc_addr(idx)
1028 .ok_or(RingError::InvalidState)?;
1029
1030 let flags = Descriptor::read_flags_acquire(&self.mem, head_addr)
1032 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, head_addr))?;
1033
1034 if !flags.is_avail(wrap) {
1036 return Err(RingError::WouldBlock);
1037 }
1038
1039 let head_desc = Descriptor::read_body(&self.mem, head_addr, flags)
1040 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, head_addr))?;
1041
1042 let mut elements = SmallVec::<[BufferElement; 16]>::new();
1044 let mut pos = self.avail_cursor;
1045 let mut chain_len: u16 = 1;
1046
1047 let mut steps = 1;
1048 let mut has_next = head_desc.is_next();
1049
1050 let max_steps = self.desc_table.len();
1051
1052 let head_elem = BufferElement::from(&head_desc);
1053 let mut seen_writable = head_elem.writable;
1054 let mut writables: usize = if seen_writable { 1 } else { 0 };
1055 elements.push(head_elem);
1056 pos.advance();
1057
1058 while has_next && steps < max_steps {
1059 let addr = self
1060 .desc_table
1061 .desc_addr(pos.head())
1062 .ok_or(RingError::InvalidState)?;
1063
1064 let desc: Descriptor = self
1066 .mem
1067 .read_val(addr)
1068 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
1069 let elem = BufferElement::from(&desc);
1070
1071 if elem.writable {
1072 seen_writable = true;
1073 writables += 1;
1074 } else if seen_writable {
1075 return Err(RingError::BadChain);
1076 }
1077
1078 elements.push(elem);
1079
1080 chain_len += 1;
1081 steps += 1;
1082
1083 has_next = desc.is_next();
1084 pos.advance();
1085 }
1086
1087 if steps >= max_steps && has_next {
1089 return Err(RingError::BadChain);
1090 }
1091
1092 if self.num_inflight + chain_len as usize > self.desc_table.len() {
1095 return Err(RingError::InvalidState);
1096 }
1097
1098 let readables = elements.len() - writables;
1099
1100 let id = head_desc.id;
1102 let id_num = self
1103 .id_num
1104 .get_mut(id as usize)
1105 .ok_or(RingError::InvalidState)?;
1106 if *id_num != 0 {
1107 return Err(RingError::InvalidState);
1108 }
1109
1110 *id_num = chain_len;
1112 self.avail_cursor = pos;
1114 self.num_inflight += chain_len as usize;
1116
1117 Ok((
1118 id,
1119 BufferChain {
1120 elems: elements,
1121 split: readables,
1122 },
1123 ))
1124 }
1125
1126 pub fn submit_used(&mut self, id: u16, written_len: u32) -> Result<(), RingError> {
1138 let chain_len = *self
1140 .id_num
1141 .get(id as usize)
1142 .ok_or(RingError::InvalidState)?;
1143
1144 if chain_len == 0 || chain_len > self.desc_table.len() as u16 {
1145 return Err(RingError::InvalidState);
1146 }
1147
1148 let idx = self.used_cursor.head();
1149 let wrap = self.used_cursor.wrap();
1150
1151 let mut used_desc = Descriptor::new(0, written_len, id, DescFlags::empty());
1153 used_desc.mark_used(wrap);
1154
1155 let addr = self
1156 .desc_table
1157 .desc_addr(idx)
1158 .ok_or(RingError::InvalidState)?;
1159
1160 used_desc
1162 .write_release(&self.mem, addr)
1163 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
1164
1165 self.used_cursor.advance_by(chain_len);
1167 self.id_num[id as usize] = 0;
1168
1169 self.num_inflight -= chain_len as usize;
1170 Ok(())
1171 }
1172
1173 pub fn peek_available(&self) -> Result<bool, RingError> {
1175 let Some(addr) = self.desc_table.desc_addr(self.avail_cursor.head()) else {
1176 return Err(RingError::InvalidState);
1177 };
1178
1179 let flags = Descriptor::read_flags_acquire(&self.mem, addr)
1180 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
1181
1182 Ok(flags.is_avail(self.avail_cursor.wrap()))
1183 }
1184
1185 pub fn submit_used_with_notify(
1187 &mut self,
1188 id: u16,
1189 written_len: u32,
1190 ) -> Result<bool, RingError> {
1191 let old = self.used_cursor;
1192 self.submit_used(id, written_len)?;
1193 let new = self.used_cursor;
1194 self.should_notify_driver(old, new)
1195 }
1196
1197 pub fn num_free(&self) -> usize {
1199 self.desc_table.len() - self.num_inflight
1200 }
1201
1202 pub fn num_inflight(&self) -> usize {
1204 self.num_inflight
1205 }
1206
1207 pub fn is_full(&self) -> bool {
1209 self.num_inflight == self.desc_table.len()
1210 }
1211
1212 #[allow(clippy::len_without_is_empty)]
1214 pub fn len(&self) -> usize {
1215 self.desc_table.len()
1216 }
1217
1218 pub fn mem(&self) -> &M {
1220 &self.mem
1221 }
1222
1223 #[inline]
1225 pub fn avail_cursor(&self) -> RingCursor {
1226 self.avail_cursor
1227 }
1228
1229 #[inline]
1231 pub fn used_cursor(&self) -> RingCursor {
1232 self.used_cursor
1233 }
1234
1235 pub fn disable_avail_notifications(&mut self) -> Result<(), RingError> {
1239 if self.event_flags_shadow == EventFlags::DISABLE {
1240 return Ok(());
1241 }
1242
1243 let mut evt = self
1244 .mem
1245 .read_val::<EventSuppression>(self.dev_evt_addr)
1246 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1247
1248 evt.set_flags(EventFlags::DISABLE);
1249 evt.write_release(&self.mem, self.dev_evt_addr)
1250 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1251
1252 self.event_flags_shadow = EventFlags::DISABLE;
1253 Ok(())
1254 }
1255
1256 pub fn enable_avail_notifications(&mut self) -> Result<(), RingError> {
1258 if self.event_flags_shadow == EventFlags::ENABLE {
1259 return Ok(());
1260 }
1261
1262 let mut evt = self
1263 .mem
1264 .read_val::<EventSuppression>(self.dev_evt_addr)
1265 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1266
1267 evt.set_flags(EventFlags::ENABLE);
1268 evt.write_release(&self.mem, self.dev_evt_addr)
1269 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1270
1271 self.event_flags_shadow = EventFlags::ENABLE;
1272 Ok(())
1273 }
1274
1275 pub fn enable_avail_notifications_desc(
1279 &mut self,
1280 off: u16,
1281 wrap: bool,
1282 ) -> Result<(), RingError> {
1283 let mut evt = self
1285 .mem
1286 .read_val::<EventSuppression>(self.dev_evt_addr)
1287 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1288
1289 evt.set_desc_event(off, wrap);
1290 evt.set_flags(EventFlags::DESC);
1291
1292 evt.write_release(&self.mem, self.dev_evt_addr)
1294 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1295
1296 self.event_flags_shadow = EventFlags::DESC;
1297 Ok(())
1298 }
1299
1300 pub fn enable_avail_notifications_for_next(&mut self) -> Result<(), RingError> {
1303 let off = self.avail_cursor.head();
1304 let wrap = self.avail_cursor.wrap();
1305 self.enable_avail_notifications_desc(off, wrap)
1306 }
1307
1308 fn should_notify_driver(&self, old: RingCursor, new: RingCursor) -> Result<bool, RingError> {
1310 fence(Ordering::SeqCst);
1313
1314 should_notify_evt(&self.mem, self.drv_evt_addr, self.len() as u16, old, new)
1315 }
1316
1317 pub fn reset(&mut self) {
1320 self.avail_cursor.reset();
1321 self.used_cursor.reset();
1322 self.id_num.iter_mut().for_each(|n| *n = 0);
1323 self.num_inflight = 0;
1324 self.event_flags_shadow = EventFlags::ENABLE;
1325 }
1326}
1327
1328fn should_notify_evt<M: MemOps>(
1330 mem: &M,
1331 evt_addr: u64,
1332 ring_len: u16,
1333 old: RingCursor,
1334 new: RingCursor,
1335) -> Result<bool, RingError> {
1336 let flags = EventSuppression::read_flags_acquire(mem, evt_addr)
1337 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, evt_addr))?;
1338
1339 let evt = if flags == EventFlags::DESC {
1340 EventSuppression::read_body(mem, evt_addr, flags)
1341 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, evt_addr))?
1342 } else {
1343 EventSuppression::new(0, flags)
1344 };
1345
1346 Ok(should_notify(evt, ring_len, old, new))
1347}
1348
1349#[inline]
1356fn should_notify(evt: EventSuppression, ring_len: u16, old: RingCursor, new: RingCursor) -> bool {
1357 match evt.flags() {
1358 EventFlags::DISABLE => false,
1359 EventFlags::ENABLE => true,
1360 EventFlags::DESC => {
1361 let mut off = evt.desc_event_off();
1362 let wrap = evt.desc_event_wrap();
1363
1364 if wrap != new.wrap() {
1365 off = off.wrapping_sub(ring_len);
1366 }
1367
1368 ring_need_event(off, new.head(), old.head())
1369 }
1370 _ => false,
1372 }
1373}
1374
1375#[inline(always)]
1376fn ring_need_event(event_idx: u16, new: u16, old: u16) -> bool {
1377 new.wrapping_sub(event_idx).wrapping_sub(1) < new.wrapping_sub(old)
1378}
1379
1380impl From<&Descriptor> for BufferElement {
1381 fn from(desc: &Descriptor) -> Self {
1382 BufferElement {
1383 addr: desc.addr,
1384 len: desc.len,
1385 writable: desc.is_writable(),
1386 }
1387 }
1388}
1389
1390#[cfg(test)]
1391pub(crate) mod tests {
1392 use alloc::sync::Arc;
1393 use core::cell::UnsafeCell;
1394 use core::num::NonZeroU16;
1395 use core::ptr;
1396 use core::sync::atomic::{AtomicU16, Ordering};
1397
1398 use bytemuck::{Pod, Zeroable};
1399
1400 use super::super::align_up;
1401 use super::*;
1402 use crate::virtq::event::EventSuppression;
1403
1404 #[derive(Clone)]
1410 pub struct TestMem {
1411 inner: Arc<TestMemInner>,
1412 }
1413
1414 struct TestMemInner {
1415 storage: UnsafeCell<Vec<u8>>,
1417 base_addr: u64,
1419 }
1420
1421 unsafe impl Send for TestMemInner {}
1424 unsafe impl Sync for TestMemInner {}
1425
1426 impl TestMem {
1427 pub fn new(size: usize) -> Self {
1428 let storage = vec![0u8; size];
1429 let base_addr = storage.as_ptr() as u64;
1430 Self {
1431 inner: Arc::new(TestMemInner {
1432 storage: UnsafeCell::new(storage),
1433 base_addr,
1434 }),
1435 }
1436 }
1437
1438 fn ptr_for_addr(&self, addr: u64) -> *mut u8 {
1440 let storage = unsafe { &mut *self.inner.storage.get() };
1441 let base_ptr = storage.as_mut_ptr();
1442 let offset = (addr - self.inner.base_addr) as usize;
1443 base_ptr.wrapping_add(offset)
1445 }
1446
1447 pub fn base_addr(&self) -> u64 {
1448 self.inner.base_addr
1449 }
1450 }
1451
1452 unsafe impl MemOps for TestMem {
1455 type Error = core::convert::Infallible;
1456
1457 fn read(&self, addr: u64, dst: &mut [u8]) -> Result<(), Self::Error> {
1458 let src = self.ptr_for_addr(addr);
1459 unsafe {
1460 ptr::copy_nonoverlapping(src, dst.as_mut_ptr(), dst.len());
1461 }
1462 Ok(())
1463 }
1464
1465 fn write(&self, addr: u64, src: &[u8]) -> Result<(), Self::Error> {
1466 let dst = self.ptr_for_addr(addr);
1467 unsafe {
1468 ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
1469 }
1470 Ok(())
1471 }
1472
1473 fn read_val<T: Pod>(&self, addr: u64) -> Result<T, Self::Error> {
1474 let ptr = self.ptr_for_addr(addr).cast::<T>();
1475 Ok(unsafe { ptr::read_volatile(ptr) })
1476 }
1477
1478 fn write_val<T: Pod>(&self, addr: u64, val: T) -> Result<(), Self::Error> {
1479 let ptr = self.ptr_for_addr(addr).cast::<T>();
1480 unsafe { ptr::write_volatile(ptr, val) };
1481 Ok(())
1482 }
1483
1484 fn load_acquire(&self, addr: u64) -> Result<u16, Self::Error> {
1485 let ptr = self.ptr_for_addr(addr).cast::<AtomicU16>();
1486 Ok(unsafe { (*ptr).load(Ordering::Acquire) })
1487 }
1488
1489 fn store_release(&self, addr: u64, val: u16) -> Result<(), Self::Error> {
1490 let ptr = self.ptr_for_addr(addr).cast::<AtomicU16>();
1491 unsafe { (*ptr).store(val, Ordering::Release) };
1492 Ok(())
1493 }
1494
1495 unsafe fn as_slice(&self, addr: u64, len: usize) -> Result<&[u8], Self::Error> {
1496 let ptr = self.ptr_for_addr(addr);
1497 Ok(unsafe { core::slice::from_raw_parts(ptr, len) })
1498 }
1499
1500 unsafe fn as_mut_slice(&self, addr: u64, len: usize) -> Result<&mut [u8], Self::Error> {
1501 let ptr = self.ptr_for_addr(addr);
1502 Ok(unsafe { core::slice::from_raw_parts_mut(ptr, len) })
1503 }
1504 }
1505
1506 pub struct OwnedRing {
1508 mem: TestMem,
1509 layout: Layout,
1510 }
1511
1512 impl OwnedRing {
1513 pub fn new(size: usize) -> Self {
1514 let num_descs = NonZeroU16::new(size as u16).unwrap();
1515 let needed = Layout::query_size(size);
1516
1517 let padding = Descriptor::ALIGN;
1521 let pool_headroom = 0x100 + 0x8000;
1522 let mem = TestMem::new(needed + padding + pool_headroom);
1523
1524 let aligned_base = align_up(mem.base_addr() as usize, Descriptor::ALIGN) as u64;
1526 let layout = unsafe { Layout::from_base(aligned_base, num_descs).unwrap() };
1527
1528 Self { mem, layout }
1529 }
1530
1531 pub fn layout(&self) -> Layout {
1532 self.layout
1533 }
1534
1535 pub fn mem(&self) -> TestMem {
1536 self.mem.clone()
1537 }
1538
1539 pub fn desc_addr(&self, idx: u16) -> u64 {
1541 self.layout.desc_table_addr() + (idx as u64 * Descriptor::SIZE as u64)
1542 }
1543
1544 pub fn read_desc(&self, idx: u16) -> Descriptor {
1546 self.mem.read_val(self.desc_addr(idx)).unwrap()
1547 }
1548
1549 pub fn write_desc(&self, idx: u16, desc: Descriptor) {
1551 self.mem.write_val(self.desc_addr(idx), desc).unwrap()
1552 }
1553
1554 pub fn read_driver_event(&self) -> EventSuppression {
1556 self.mem.read_val(self.layout.drv_evt_addr()).unwrap()
1557 }
1558
1559 pub fn read_device_event(&self) -> EventSuppression {
1561 self.mem.read_val(self.layout.dev_evt_addr()).unwrap()
1562 }
1563
1564 pub fn len(&self) -> usize {
1565 self.layout.desc_table_len() as usize
1566 }
1567 }
1568
1569 pub(crate) fn make_ring(size: usize) -> OwnedRing {
1571 OwnedRing::new(size)
1572 }
1573
1574 pub(crate) fn make_producer(ring: &OwnedRing) -> RingProducer<TestMem> {
1575 RingProducer::new(ring.layout(), ring.mem())
1576 }
1577
1578 pub(crate) fn make_consumer(ring: &OwnedRing) -> RingConsumer<TestMem> {
1579 RingConsumer::new(ring.layout(), ring.mem())
1580 }
1581
1582 fn assert_invariants(ring: &OwnedRing, prod: &RingProducer<TestMem>) {
1583 let outstanding: u16 = prod.id_num.iter().copied().sum();
1584 assert_eq!(outstanding as usize + prod.num_free, ring.len());
1585
1586 for id in prod.id_free.iter() {
1587 assert_eq!(prod.id_num[*id as usize], 0);
1588 }
1589
1590 for (id, &n) in prod.id_num.iter().enumerate() {
1591 if n > 0 {
1592 assert!(!prod.id_free.contains(&(id as u16)));
1593 }
1594 }
1595 }
1596
1597 #[test]
1598 fn test_initialization() {
1599 let ring = make_ring(8);
1600 let producer = make_producer(&ring);
1601
1602 for i in 0..8u16 {
1604 let desc = ring.read_desc(i);
1605 assert_eq!(desc, Descriptor::zeroed());
1606 assert_eq!(desc.flags, 0);
1607 assert_eq!(desc.addr, 0);
1608 assert_eq!(desc.len, 0);
1609 assert_eq!(desc.id, 0);
1610 }
1611
1612 assert_eq!(producer.avail_cursor.head(), 0);
1614 assert!(producer.avail_cursor.wrap());
1615 assert_eq!(producer.used_cursor.head(), 0);
1616 assert!(producer.used_cursor.wrap());
1617
1618 assert_eq!(producer.id_free.len(), 8);
1620 assert_eq!(producer.num_free, 8);
1621 for i in 0..8 {
1622 assert_eq!(producer.id_num[i], 0);
1623 }
1624 }
1625
1626 #[test]
1627 fn test_buffer_chain_builder_normalizes_element_direction() {
1628 let readable_as_writable = BufferElement {
1629 addr: 0x1000,
1630 len: 16,
1631 writable: true,
1632 };
1633 let writable_as_readable = BufferElement {
1634 addr: 0x2000,
1635 len: 32,
1636 writable: false,
1637 };
1638 let second_writable_as_readable = BufferElement {
1639 addr: 0x3000,
1640 len: 64,
1641 writable: false,
1642 };
1643
1644 let chain = BufferChainBuilder::new()
1645 .readables([readable_as_writable])
1646 .writables([writable_as_readable])
1647 .writables([second_writable_as_readable])
1648 .build()
1649 .unwrap();
1650
1651 assert!(!chain.readables()[0].writable);
1652 assert!(chain.writables().iter().all(|elem| elem.writable));
1653 }
1654
1655 #[test]
1656 fn test_submit_one_descriptor() {
1657 let ring = make_ring(8);
1658 let mut producer = make_producer(&ring);
1659
1660 let addr = 0x1000;
1661 let len = 512;
1662 let writable = false;
1663
1664 let id = producer.submit_one(addr, len, writable).unwrap();
1665
1666 let desc = ring.read_desc(0);
1668
1669 assert_eq!(desc.addr, addr);
1670 assert_eq!(desc.len, len);
1671 assert_eq!(desc.id, id);
1672
1673 let flags = desc.flags();
1675 assert!(flags.contains(DescFlags::AVAIL));
1676 assert!(!flags.contains(DescFlags::USED));
1677 assert!(!flags.contains(DescFlags::WRITE));
1678 assert!(!flags.contains(DescFlags::NEXT));
1679
1680 assert_eq!(producer.num_free, 7);
1682
1683 assert_eq!(producer.avail_cursor.head(), 1);
1685 assert!(producer.avail_cursor.wrap());
1686
1687 assert_eq!(producer.id_num[id as usize], 1);
1689 assert_eq!(producer.id_free.len(), 7);
1690 }
1691
1692 #[test]
1693 fn test_single_descriptor_wrap_toggle() {
1694 let ring = make_ring(4);
1695 let mut producer = make_producer(&ring);
1696
1697 producer.avail_cursor.head = 3;
1699 producer.avail_cursor.wrap = true;
1700 producer.num_free = 1;
1701 producer.id_free.clear();
1702 producer.id_free.push(0);
1703
1704 let _id = producer.submit_one(0x1000, 512, false).unwrap();
1705
1706 assert_eq!(producer.avail_cursor.head(), 0);
1708 assert!(!producer.avail_cursor.wrap());
1709
1710 let desc = ring.read_desc(3);
1712 let flags = desc.flags();
1713 assert!(flags.contains(DescFlags::AVAIL));
1714 assert!(!flags.contains(DescFlags::USED));
1715 }
1716
1717 #[test]
1718 fn test_multi_descriptor_no_wrap() {
1719 let ring = make_ring(8);
1720 let mut producer = make_producer(&ring);
1721
1722 let chain = BufferChainBuilder::new()
1723 .readable(0x1000, 256)
1724 .readable(0x2000, 256)
1725 .writable(0x3000, 512)
1726 .build()
1727 .unwrap();
1728
1729 let id = producer.submit_available(&chain).unwrap();
1730
1731 let head_desc = ring.read_desc(0);
1733 assert_eq!(head_desc.addr, 0x1000);
1734 assert_eq!(head_desc.len, 256);
1735 assert_eq!(head_desc.id, id);
1736
1737 let head_flags = head_desc.flags();
1738 assert!(head_flags.contains(DescFlags::NEXT));
1739 assert!(!head_flags.contains(DescFlags::WRITE));
1740 assert!(head_flags.contains(DescFlags::AVAIL));
1741 assert!(!head_flags.contains(DescFlags::USED));
1742
1743 let mid_desc = ring.read_desc(1);
1745 assert_eq!(mid_desc.addr, 0x2000);
1746 assert_eq!(mid_desc.len, 256);
1747 assert_eq!(mid_desc.id, id);
1748
1749 let mid_flags = mid_desc.flags();
1750 assert!(mid_flags.contains(DescFlags::NEXT));
1751 assert!(!mid_flags.contains(DescFlags::WRITE));
1752
1753 let tail_desc = ring.read_desc(2);
1755 assert_eq!(tail_desc.addr, 0x3000);
1756 assert_eq!(tail_desc.len, 512);
1757 assert_eq!(tail_desc.id, id);
1758
1759 let tail_flags = tail_desc.flags();
1760 assert!(!tail_flags.contains(DescFlags::NEXT));
1761 assert!(tail_flags.contains(DescFlags::WRITE));
1762
1763 assert_eq!(head_desc.id, mid_desc.id);
1765 assert_eq!(mid_desc.id, tail_desc.id);
1766
1767 assert_eq!(producer.num_free, 5);
1769 assert_eq!(producer.avail_cursor.head(), 3);
1770 assert_eq!(producer.id_num[id as usize], 3);
1771 }
1772
1773 #[test]
1774 fn test_multi_descriptor_with_wrap() {
1775 let ring = make_ring(4);
1776 let mut producer = make_producer(&ring);
1777
1778 producer.avail_cursor.head = 2;
1780 producer.avail_cursor.wrap = true;
1781
1782 let chain = BufferChainBuilder::new()
1783 .readable(0x1000, 256)
1784 .readable(0x2000, 256)
1785 .readable(0x3000, 256)
1786 .build()
1787 .unwrap();
1788
1789 let _id = producer.submit_available(&chain).unwrap();
1790
1791 let head_desc = ring.read_desc(2);
1793 let head_flags = head_desc.flags();
1794 assert!(head_flags.contains(DescFlags::AVAIL));
1795 assert!(!head_flags.contains(DescFlags::USED));
1796
1797 let mid_desc = ring.read_desc(3);
1799 let mid_flags = mid_desc.flags();
1800 assert!(mid_flags.contains(DescFlags::AVAIL));
1801 assert!(!mid_flags.contains(DescFlags::USED));
1802
1803 let tail_desc = ring.read_desc(0);
1805 let tail_flags = tail_desc.flags();
1806 assert!(!tail_flags.contains(DescFlags::AVAIL));
1807 assert!(tail_flags.contains(DescFlags::USED));
1808
1809 assert_eq!(producer.avail_cursor.head(), 1);
1811 assert!(!producer.avail_cursor.wrap());
1812 }
1813
1814 #[test]
1815 fn test_ring_full() {
1816 let ring = make_ring(4);
1817 let mut producer = make_producer(&ring);
1818
1819 for _ in 0..4 {
1821 producer.submit_one(0x1000, 256, false).unwrap();
1822 }
1823
1824 assert_eq!(producer.num_free, 0);
1825
1826 let result = producer.submit_one(0x5000, 256, false);
1828 assert!(matches!(result, Err(RingError::WouldBlock)));
1829 }
1830
1831 #[test]
1832 fn test_poll_and_reclaim() {
1833 let ring = make_ring(8);
1834 let mut producer = make_producer(&ring);
1835
1836 let id = producer.submit_one(0x1000, 512, false).unwrap();
1837
1838 let mut desc = ring.read_desc(0);
1840 desc.mark_used(true);
1841 desc.len = 256;
1842 ring.write_desc(0, desc);
1843
1844 let used = producer.poll_used().unwrap();
1846 assert_eq!(used.id, id);
1847 assert_eq!(used.len, 256);
1848
1849 assert_eq!(producer.num_free, 8);
1851 assert_eq!(producer.used_cursor.head(), 1);
1852 assert_eq!(producer.id_num[id as usize], 0);
1853 assert!(producer.id_free.contains(&id));
1854 }
1855
1856 #[test]
1857 fn test_poll_multi_descriptor_chain() {
1858 let ring = make_ring(8);
1859 let mut producer = make_producer(&ring);
1860
1861 let chain = BufferChainBuilder::new()
1862 .readable(0x1000, 256)
1863 .readable(0x2000, 256)
1864 .writable(0x3000, 512)
1865 .build()
1866 .unwrap();
1867
1868 let id = producer.submit_available(&chain).unwrap();
1869
1870 let mut head_desc = ring.read_desc(0);
1872 head_desc.mark_used(true);
1873 head_desc.len = 512;
1874 ring.write_desc(0, head_desc);
1875
1876 let used = producer.poll_used().unwrap();
1878 assert_eq!(used.id, id);
1879 assert_eq!(used.len, 512);
1880
1881 assert_eq!(producer.used_cursor.head(), 3);
1883 assert_eq!(producer.num_free, 8);
1884 }
1885
1886 #[test]
1887 fn test_id_reuse() {
1888 let ring = make_ring(4);
1889 let mut producer = make_producer(&ring);
1890
1891 let id1 = producer.submit_one(0x1000, 256, false).unwrap();
1893
1894 let mut desc = ring.read_desc(0);
1895 desc.mark_used(true);
1896 ring.write_desc(0, desc);
1897
1898 producer.poll_used().unwrap();
1899
1900 let id2 = producer.submit_one(0x2000, 256, false).unwrap();
1902
1903 assert_eq!(id2, id1);
1905 assert_eq!(producer.id_num[id2 as usize], 1);
1906 }
1907
1908 #[test]
1909 fn test_available_descriptor_flags() {
1910 let ring = make_ring(4);
1911 let mut producer = make_producer(&ring);
1912
1913 producer.submit_one(0x1000, 256, false).unwrap();
1914
1915 let desc = ring.read_desc(0);
1916
1917 let flags = desc.flags();
1919 assert_ne!(
1920 flags.contains(DescFlags::AVAIL),
1921 flags.contains(DescFlags::USED)
1922 );
1923
1924 assert!(flags.contains(DescFlags::AVAIL));
1926 assert!(!flags.contains(DescFlags::USED));
1927 }
1928
1929 #[test]
1930 fn test_used_descriptor_flags() {
1931 let ring = make_ring(4);
1932 let mut producer = make_producer(&ring);
1933
1934 producer.submit_one(0x1000, 256, false).unwrap();
1935
1936 let mut desc = ring.read_desc(0);
1937 desc.mark_used(true);
1938 ring.write_desc(0, desc);
1939
1940 let desc = ring.read_desc(0);
1941 let flags = desc.flags();
1942
1943 assert_eq!(
1945 flags.contains(DescFlags::AVAIL),
1946 flags.contains(DescFlags::USED)
1947 );
1948 }
1949
1950 #[test]
1951 fn test_poll_empty_ring() {
1952 let ring = make_ring(4);
1953 let mut producer = make_producer(&ring);
1954
1955 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
1957 }
1958
1959 #[test]
1960 fn test_submit_when_full() {
1961 let ring = make_ring(2);
1962 let mut producer = make_producer(&ring);
1963
1964 producer.submit_one(0x1000, 256, false).unwrap();
1965 producer.submit_one(0x2000, 256, false).unwrap();
1966
1967 assert!(matches!(
1969 producer.submit_one(0x3000, 256, false),
1970 Err(RingError::WouldBlock)
1971 ));
1972 }
1973
1974 #[test]
1975 fn test_wrap_stress() {
1976 let ring = make_ring(4);
1977 let mut producer = make_producer(&ring);
1978 let mut consumer = make_consumer(&ring);
1979
1980 for lap in 0..3 {
1982 let expected_wrap = lap % 2 == 0;
1983
1984 for _ in 0..4 {
1985 let id = producer.submit_one(0x1000, 256, false).unwrap();
1986
1987 let (dev_id, _) = consumer.poll_available().unwrap();
1988 assert_eq!(dev_id, id);
1989
1990 consumer.submit_used(dev_id, 256).unwrap();
1991
1992 producer.poll_used().unwrap();
1993 }
1994
1995 assert_eq!(producer.avail_cursor.wrap(), !expected_wrap);
1997 }
1998 assert_invariants(&ring, &producer);
1999 }
2000
2001 #[test]
2002 fn test_next_flag_termination() {
2003 let ring = make_ring(8);
2004 let mut producer = make_producer(&ring);
2005
2006 let chain = BufferChainBuilder::new()
2007 .readable(0x1000, 256)
2008 .readable(0x2000, 256)
2009 .readable(0x3000, 256)
2010 .build()
2011 .unwrap();
2012
2013 producer.submit_available(&chain).unwrap();
2014
2015 for i in 0..2 {
2017 let desc = ring.read_desc(i);
2018 assert!(desc.flags().contains(DescFlags::NEXT));
2019 }
2020
2021 let tail_desc = ring.read_desc(2);
2023 assert!(!tail_desc.flags().contains(DescFlags::NEXT));
2024 }
2025
2026 #[test]
2027 fn test_consumer_initialization() {
2028 let ring = make_ring(8);
2029 let consumer = make_consumer(&ring);
2030
2031 assert_eq!(consumer.avail_cursor.head(), 0);
2032 assert!(consumer.avail_cursor.wrap());
2033 assert_eq!(consumer.used_cursor.head(), 0);
2034 assert!(consumer.used_cursor.wrap());
2035
2036 for i in 0..8 {
2037 assert_eq!(consumer.id_num[i], 0);
2038 }
2039 }
2040
2041 #[test]
2042 fn test_consumer_poll_available_single() {
2043 let ring = make_ring(8);
2044 let mut producer = make_producer(&ring);
2045 let mut consumer = make_consumer(&ring);
2046
2047 let id = producer.submit_one(0x1000, 512, false).unwrap();
2048
2049 let (polled_id, chain) = consumer.poll_available().unwrap();
2050
2051 assert_eq!(polled_id, id);
2052 assert_eq!(chain.len(), 1);
2053 assert_eq!(chain.elems()[0].addr, 0x1000);
2054 assert_eq!(chain.elems()[0].len, 512);
2055 assert!(!chain.elems()[0].writable);
2056
2057 assert_eq!(consumer.id_num[id as usize], 1);
2059 assert_eq!(consumer.avail_cursor.head(), 1);
2060 }
2061
2062 #[test]
2063 fn test_consumer_poll_available_chain() {
2064 let ring = make_ring(8);
2065 let mut producer = make_producer(&ring);
2066 let mut consumer = make_consumer(&ring);
2067
2068 let chain = BufferChainBuilder::new()
2069 .readable(0x1000, 256)
2070 .readable(0x2000, 256)
2071 .writable(0x3000, 512)
2072 .build()
2073 .unwrap();
2074
2075 let id = producer.submit_available(&chain).unwrap();
2076
2077 let (polled_id, polled_chain) = consumer.poll_available().unwrap();
2078
2079 assert_eq!(polled_id, id);
2080 assert_eq!(polled_chain.len(), 3);
2081
2082 assert_eq!(polled_chain.elems()[0].addr, 0x1000);
2083 assert!(!polled_chain.elems()[0].writable);
2084
2085 assert_eq!(polled_chain.elems()[1].addr, 0x2000);
2086 assert!(!polled_chain.elems()[1].writable);
2087
2088 assert_eq!(polled_chain.elems()[2].addr, 0x3000);
2089 assert!(polled_chain.elems()[2].writable);
2090
2091 assert_eq!(consumer.id_num[id as usize], 3);
2092 }
2093
2094 #[test]
2095 fn test_consumer_rejects_duplicate_inflight_id() {
2096 let ring = make_ring(8);
2097 let mut producer = make_producer(&ring);
2098 let mut consumer = make_consumer(&ring);
2099
2100 let id = producer.submit_one(0x1000, 512, false).unwrap();
2101 let (polled_id, _) = consumer.poll_available().unwrap();
2102 assert_eq!(polled_id, id);
2103
2104 let mut desc = Descriptor::new(0x2000, 256, id, DescFlags::empty());
2105 desc.mark_avail(consumer.avail_cursor.wrap());
2106 ring.write_desc(consumer.avail_cursor.head(), desc);
2107
2108 assert!(matches!(
2109 consumer.poll_available(),
2110 Err(RingError::InvalidState)
2111 ));
2112 }
2113
2114 #[test]
2115 fn test_consumer_submit_used() {
2116 let ring = make_ring(8);
2117 let mut producer = make_producer(&ring);
2118 let mut consumer = make_consumer(&ring);
2119
2120 let id = producer.submit_one(0x1000, 512, true).unwrap();
2121
2122 let (polled_id, _) = consumer.poll_available().unwrap();
2123
2124 consumer.submit_used(polled_id, 256).unwrap();
2126
2127 let desc = ring.read_desc(0);
2129
2130 assert_eq!(desc.id, id);
2131 assert_eq!(desc.len, 256);
2132 assert!(desc.is_used(true));
2133
2134 assert_eq!(consumer.used_cursor.head(), 1);
2136 assert_eq!(consumer.id_num[id as usize], 0);
2137 }
2138
2139 #[test]
2140 fn test_consumer_submit_used_multi_descriptor() {
2141 let ring = make_ring(8);
2142 let mut producer = make_producer(&ring);
2143 let mut consumer = make_consumer(&ring);
2144
2145 let chain = BufferChainBuilder::new()
2146 .readable(0x1000, 256)
2147 .writable(0x2000, 512)
2148 .writable(0x3000, 512)
2149 .build()
2150 .unwrap();
2151
2152 producer.submit_available(&chain).unwrap();
2153
2154 let (id, _) = consumer.poll_available().unwrap();
2155
2156 consumer.submit_used(id, 1024).unwrap();
2157
2158 let head_desc = ring.read_desc(0);
2160 assert!(head_desc.is_used(true));
2161 assert_eq!(head_desc.len, 1024);
2162
2163 assert_eq!(consumer.used_cursor.head(), 3);
2165 assert_eq!(consumer.id_num[id as usize], 0);
2166 }
2167
2168 #[test]
2169 fn test_consumer_poll_empty() {
2170 let ring = make_ring(4);
2171 let mut consumer = make_consumer(&ring);
2172
2173 assert!(matches!(
2174 consumer.poll_available(),
2175 Err(RingError::WouldBlock)
2176 ));
2177 }
2178
2179 #[test]
2180 fn test_consumer_peek() {
2181 let ring = make_ring(8);
2182 let mut producer = make_producer(&ring);
2183 let consumer = make_consumer(&ring);
2184
2185 producer.submit_one(0x1000, 512, false).unwrap();
2186 assert!(consumer.peek_available().unwrap());
2187
2188 let empty_ring = make_ring(4);
2189 let empty_consumer = make_consumer(&empty_ring);
2190 assert!(!empty_consumer.peek_available().unwrap());
2191 }
2192
2193 #[test]
2194 fn test_full_roundtrip() {
2195 let ring = make_ring(8);
2196 let mut producer = make_producer(&ring);
2197 let mut consumer = make_consumer(&ring);
2198
2199 let chain = BufferChainBuilder::new()
2200 .readable(0x1000, 256)
2201 .writable(0x2000, 512)
2202 .build()
2203 .unwrap();
2204
2205 let id = producer.submit_available(&chain).unwrap();
2206
2207 let (consumer_id, consumer_chain) = consumer.poll_available().unwrap();
2208
2209 assert_eq!(consumer_id, id);
2210 assert_eq!(consumer_chain.len(), 2);
2211
2212 consumer.submit_used(consumer_id, 512).unwrap();
2213
2214 let used = producer.poll_used().unwrap();
2215 assert_eq!(used.id, id);
2216 assert_eq!(used.len, 512);
2217 }
2218
2219 #[test]
2220 fn ring_initial_poll_used_blocks() {
2221 let ring = make_ring(8);
2222 let mut producer = make_producer(&ring);
2223 for _ in 0..8 {
2225 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2226 }
2227 assert_eq!(producer.num_free, ring.len());
2229 }
2230
2231 #[test]
2232 fn ring_consumer_blocks_until_submit() {
2233 let ring = make_ring(8);
2234 let mut producer = make_producer(&ring);
2235 let mut consumer = make_consumer(&ring);
2236
2237 assert!(matches!(
2238 consumer.poll_available(),
2239 Err(RingError::WouldBlock)
2240 ));
2241
2242 let chain = BufferChainBuilder::new()
2243 .readable(0x1000, 32)
2244 .readable(0x2000, 16)
2245 .build()
2246 .unwrap();
2247
2248 let id = producer.submit_available(&chain).unwrap();
2249
2250 let (cid, polled) = consumer.poll_available().unwrap();
2251 assert_eq!(cid, id);
2252 assert_eq!(polled.len(), chain.len());
2253 }
2254
2255 #[test]
2256 fn test_out_of_order_completion_stream() {
2257 let ring = make_ring(8);
2258 let mut producer = make_producer(&ring);
2259 let mut consumer = make_consumer(&ring);
2260
2261 let id_a = producer.submit_one(0x1000, 256, true).unwrap();
2263 let id_b = producer.submit_one(0x2000, 256, true).unwrap();
2264
2265 let (dev_id_a, chain_a) = consumer.poll_available().unwrap();
2267 assert_eq!(dev_id_a, id_a);
2268 assert_eq!(chain_a.len(), 1);
2269
2270 let (dev_id_b, chain_b) = consumer.poll_available().unwrap();
2271 assert_eq!(dev_id_b, id_b);
2272 assert_eq!(chain_b.len(), 1);
2273
2274 consumer.submit_used(dev_id_b, 128).unwrap();
2276 consumer.submit_used(dev_id_a, 256).unwrap();
2277
2278 let used_b = producer.poll_used().unwrap();
2280 assert_eq!(used_b.id, id_b);
2281 assert_eq!(used_b.len, 128);
2282
2283 let used_a = producer.poll_used().unwrap();
2285 assert_eq!(used_a.id, id_a);
2286 assert_eq!(used_a.len, 256);
2287
2288 assert!(producer.id_free.contains(&id_a));
2290 assert!(producer.id_free.contains(&id_b));
2291 }
2292
2293 #[test]
2294 fn test_mixed_chain_sizes_out_of_order_completion() {
2295 let ring = make_ring(16);
2296 let mut producer = make_producer(&ring);
2297 let mut consumer = make_consumer(&ring);
2298
2299 let chains = vec![
2300 BufferChainBuilder::new()
2301 .readable(0x1000, 10)
2302 .writable(0x2000, 5)
2303 .build()
2304 .unwrap(),
2305 BufferChainBuilder::new()
2306 .readable(0x3000, 8)
2307 .readable(0x3010, 8)
2308 .writable(0x3020, 16)
2309 .build()
2310 .unwrap(),
2311 BufferChainBuilder::new()
2312 .readable(0x4000, 4)
2313 .build()
2314 .unwrap(),
2315 BufferChainBuilder::new()
2316 .readable(0x5000, 4)
2317 .readable(0x5010, 4)
2318 .readable(0x5020, 4)
2319 .writable(0x5030, 4)
2320 .build()
2321 .unwrap(),
2322 ];
2323
2324 for c in &chains {
2325 producer.submit_available(c).unwrap();
2326 }
2327
2328 let mut dev_chain_lens = Vec::new();
2329 for _ in &chains {
2330 let (id, chain) = consumer.poll_available().unwrap();
2331 dev_chain_lens.push((id, chain.len() as u32));
2332 }
2333
2334 let order = [1, 3, 0, 2];
2335 let mut completion = Vec::new();
2336
2337 for &idx in &order {
2338 let (id, len) = dev_chain_lens[idx];
2339 consumer.submit_used(id, len).unwrap();
2340 completion.push((id, len));
2341 }
2342
2343 for (expected_id, expected_len) in &completion {
2344 let used = producer.poll_used().unwrap();
2345 assert_eq!(used.id, *expected_id);
2346 assert_eq!(used.len, *expected_len);
2347 assert_eq!(producer.id_num[*expected_id as usize], 0);
2348 assert!(producer.id_free.contains(expected_id));
2349 }
2350
2351 assert_invariants(&ring, &producer);
2352 }
2353
2354 #[test]
2356 fn test_used_stream_wrap_crossing() {
2357 let ring = make_ring(8);
2358 let mut producer = make_producer(&ring);
2359 let mut consumer = make_consumer(&ring);
2360
2361 let mut ids = Vec::new();
2363 for i in 0..8 {
2364 ids.push(producer.submit_one(0x1000 + i as u64, 1, false).unwrap());
2365 }
2366
2367 for _ in 0..8 {
2369 consumer.poll_available().unwrap();
2370 }
2371
2372 for &id in ids.iter().rev() {
2374 consumer.submit_used(id, 1).unwrap();
2375 }
2376
2377 for _ in 0..8 {
2379 producer.poll_used().unwrap();
2380 }
2381 assert_eq!(producer.used_cursor.head(), 0);
2382 assert!(!producer.used_cursor.wrap()); assert_invariants(&ring, &producer);
2384 }
2385
2386 #[test]
2388 fn test_interleaved_submit_completion() {
2389 let ring = make_ring(8);
2390 let mut producer = make_producer(&ring);
2391 let mut consumer = make_consumer(&ring);
2392
2393 let chain_a = BufferChainBuilder::new()
2395 .readable(0x1000, 8)
2396 .writable(0x2000, 8)
2397 .build()
2398 .unwrap();
2399 let id_a = producer.submit_available(&chain_a).unwrap();
2400
2401 let (dev_id_a, _) = consumer.poll_available().unwrap();
2403 assert_eq!(dev_id_a, id_a);
2404
2405 consumer.submit_used(dev_id_a, 8).unwrap();
2407
2408 let chain_b = BufferChainBuilder::new()
2410 .readable(0x3000, 4)
2411 .readable(0x3010, 4)
2412 .writable(0x3020, 4)
2413 .build()
2414 .unwrap();
2415 let id_b = producer.submit_available(&chain_b).unwrap();
2416
2417 let (dev_id_b, _) = consumer.poll_available().unwrap();
2419 assert_eq!(dev_id_b, id_b);
2420
2421 let used_a = producer.poll_used().unwrap();
2423 assert_eq!(used_a.id, id_a);
2424
2425 consumer.submit_used(dev_id_b, 12).unwrap();
2427
2428 let used_b = producer.poll_used().unwrap();
2430 assert_eq!(used_b.id, id_b);
2431
2432 assert_invariants(&ring, &producer);
2433 }
2434
2435 #[test]
2437 fn test_partial_publish_safety() {
2438 let ring = make_ring(8);
2439 let mut consumer = make_consumer(&ring);
2440 let mut producer = make_producer(&ring);
2441
2442 let chain = BufferChainBuilder::new()
2444 .readable(0x1000, 4)
2445 .readable(0x2000, 4)
2446 .writable(0x3000, 4)
2447 .build()
2448 .unwrap();
2449
2450 let id = producer.id_free.pop().unwrap();
2452 producer.id_num[id as usize] = chain.len() as u16;
2453
2454 let head_idx = producer.avail_cursor.head();
2456 let wrap_start = producer.avail_cursor.wrap();
2457 let mut pos = producer.avail_cursor;
2458 pos.advance();
2459
2460 for (i, elem) in chain.elems().iter().enumerate().skip(1) {
2461 let is_next = i + 1 < chain.len();
2462 let mut flags = DescFlags::empty();
2463 flags.set(DescFlags::NEXT, is_next);
2464 flags.set(DescFlags::WRITE, elem.writable);
2465 let mut d = Descriptor::new(elem.addr, elem.len, id, flags);
2466 d.mark_avail(pos.wrap());
2467 ring.write_desc(pos.head(), d);
2468 pos.advance();
2469 }
2470
2471 assert!(matches!(
2473 consumer.poll_available(),
2474 Err(RingError::WouldBlock)
2475 ));
2476
2477 let head_elem = chain.elems()[0];
2479 let mut head_flags = DescFlags::empty();
2480 head_flags.set(DescFlags::NEXT, true);
2481 head_flags.set(DescFlags::WRITE, head_elem.writable);
2482 let mut head_desc = Descriptor::new(head_elem.addr, head_elem.len, id, head_flags);
2483 head_desc.mark_avail(wrap_start);
2484 ring.write_desc(head_idx, head_desc);
2485 producer.avail_cursor = pos;
2486 producer.num_free -= chain.len();
2487
2488 let (dev_id, dev_chain) = consumer.poll_available().unwrap();
2490 assert_eq!(dev_id, id);
2491 assert_eq!(dev_chain.len(), chain.len());
2492 assert_invariants(&ring, &producer);
2493 }
2494
2495 #[test]
2497 fn test_tail_marked_used_ignored() {
2498 let ring = make_ring(8);
2499 let mut producer = make_producer(&ring);
2500
2501 let chain = BufferChainBuilder::new()
2502 .readable(0x1000, 4)
2503 .readable(0x2000, 4)
2504 .build()
2505 .unwrap();
2506 let id = producer.submit_available(&chain).unwrap();
2507
2508 let mut tail_desc = ring.read_desc(1);
2510 tail_desc.mark_used(producer.used_cursor.wrap());
2511 ring.write_desc(1, tail_desc);
2512
2513 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2515
2516 let mut head_desc = ring.read_desc(0);
2518 head_desc.mark_used(producer.used_cursor.wrap());
2519 ring.write_desc(0, head_desc);
2520
2521 let used = producer.poll_used().unwrap();
2523 assert_eq!(used.id, id);
2524 assert_invariants(&ring, &producer);
2525 }
2526
2527 #[test]
2529 fn test_max_chain_len_rejected() {
2530 let ring = make_ring(8);
2531 let mut producer = make_producer(&ring);
2532
2533 let elems = (0..9).map(|i| BufferElement {
2535 addr: 0x1000 + i as u64,
2536 len: 42,
2537 writable: false,
2538 });
2539
2540 let chain = BufferChainBuilder::new().readables(elems).build().unwrap();
2541
2542 assert!(matches!(
2544 producer.submit_available(&chain),
2545 Err(RingError::WouldBlock)
2546 ));
2547 }
2548
2549 #[test]
2551 fn test_descriptor_state_monotonicity() {
2552 let ring = make_ring(8);
2553 let mut producer = make_producer(&ring);
2554 let mut consumer = make_consumer(&ring);
2555
2556 let mut states = vec![0u8; 8];
2558
2559 for _ in 0..5 {
2560 for state in states.iter_mut() {
2561 let id = producer.submit_one(0x1000, 4, false).unwrap();
2562 *state = (*state).max(1);
2564
2565 let (dev_id, _) = consumer.poll_available().unwrap();
2567 consumer.submit_used(dev_id, 4).unwrap();
2568 *state = (*state).max(2);
2569
2570 let used = producer.poll_used().unwrap();
2571 assert_eq!(used.id, id);
2572 *state = (*state).max(3);
2573 }
2574
2575 assert_invariants(&ring, &producer);
2576 }
2577
2578 for s in states {
2580 assert!(s >= 3);
2581 }
2582 }
2583
2584 #[test]
2586 fn test_random_stress_small() {
2587 use rand::RngExt;
2588 use rand::seq::SliceRandom;
2589
2590 let ring = make_ring(16);
2591 let mut producer = make_producer(&ring);
2592 let mut consumer = make_consumer(&ring);
2593 let mut rng = rand::rng();
2594
2595 let mut active_ids = Vec::new();
2597 for _ in 0..8 {
2598 let len = rng.random_range(1..=4);
2599 let mut b = BufferChainBuilder::new().readable(0x1000, 4);
2600 for i in 1..len {
2601 b = b.readable(0x1000 + i as u64 * 0x10, 4);
2602 }
2603 let chain = b.build().unwrap();
2604 if let Ok(id) = producer.submit_available(&chain) {
2605 active_ids.push(id);
2606 }
2607 }
2608
2609 let mut dev_ids = Vec::new();
2610 while let Ok((id, _)) = consumer.poll_available() {
2611 dev_ids.push(id);
2612 }
2613
2614 dev_ids.shuffle(&mut rng);
2616 for id in &dev_ids {
2617 let chain_len = consumer.id_num[*id as usize];
2618 consumer.submit_used(*id, chain_len as u32 * 4).unwrap();
2619 }
2620 for _ in &dev_ids {
2622 if producer.poll_used().is_ok() {}
2623 }
2624
2625 assert_invariants(&ring, &producer);
2626 }
2627
2628 #[test]
2630 fn test_out_of_order_multi_length() {
2631 let ring = make_ring(16);
2632 let mut producer = make_producer(&ring);
2633 let mut consumer = make_consumer(&ring);
2634
2635 let chain_a = BufferChainBuilder::new()
2636 .readable(0x1000, 4)
2637 .writable(0x2000, 4)
2638 .build()
2639 .unwrap();
2640 let chain_b = BufferChainBuilder::new()
2641 .readable(0x3000, 4)
2642 .readable(0x3010, 4)
2643 .writable(0x3020, 4)
2644 .build()
2645 .unwrap();
2646 let chain_c = BufferChainBuilder::new()
2647 .readable(0x4000, 4)
2648 .build()
2649 .unwrap();
2650
2651 let id_a = producer.submit_available(&chain_a).unwrap();
2652 let id_b = producer.submit_available(&chain_b).unwrap();
2653 let id_c = producer.submit_available(&chain_c).unwrap();
2654
2655 let (d_a, _) = consumer.poll_available().unwrap();
2656 let (d_b, _) = consumer.poll_available().unwrap();
2657 let (d_c, _) = consumer.poll_available().unwrap();
2658 assert_eq!(d_a, id_a);
2659 assert_eq!(d_b, id_b);
2660 assert_eq!(d_c, id_c);
2661
2662 consumer.submit_used(d_b, 12).unwrap();
2664 consumer.submit_used(d_c, 4).unwrap();
2665 consumer.submit_used(d_a, 8).unwrap();
2666
2667 let u_b = producer.poll_used().unwrap();
2668 assert_eq!(u_b.id, id_b);
2669 let u_c = producer.poll_used().unwrap();
2670 assert_eq!(u_c.id, id_c);
2671 let u_a = producer.poll_used().unwrap();
2672 assert_eq!(u_a.id, id_a);
2673
2674 assert_invariants(&ring, &producer);
2675 }
2676
2677 #[test]
2678 fn interleave_submit_and_completion() {
2679 let ring = make_ring(16);
2680 let mut producer = make_producer(&ring);
2681 let mut consumer = make_consumer(&ring);
2682
2683 let chain_a = BufferChainBuilder::new()
2685 .readable(0x1000, 4)
2686 .writable(0x2000, 4)
2687 .build()
2688 .unwrap();
2689 let id_a = producer.submit_available(&chain_a).unwrap();
2690
2691 let (d_a, _) = consumer.poll_available().unwrap();
2693 assert_eq!(d_a, id_a);
2694
2695 consumer.submit_used(d_a, 8).unwrap();
2697
2698 let chain_b = BufferChainBuilder::new()
2700 .readable(0x3000, 4)
2701 .readable(0x3010, 4)
2702 .writable(0x3020, 4)
2703 .build()
2704 .unwrap();
2705 let id_b = producer.submit_available(&chain_b).unwrap();
2706
2707 let u_a = producer.poll_used().unwrap();
2709 assert_eq!(u_a.id, id_a);
2710 assert_eq!(u_a.len, 8);
2711
2712 let (d_b, _) = consumer.poll_available().unwrap();
2714 assert_eq!(d_b, id_b);
2715 consumer.submit_used(d_b, 12).unwrap();
2716
2717 let id_c = producer.submit_one(0x4000, 4, false).unwrap();
2719
2720 let (d_c, _) = consumer.poll_available().unwrap();
2722 assert_eq!(d_c, id_c);
2723 consumer.submit_used(d_c, 4).unwrap();
2724
2725 let u_b = producer.poll_used().unwrap();
2727 assert_eq!(u_b.id, id_b);
2728 assert_eq!(u_b.len, 12);
2729
2730 let u_c = producer.poll_used().unwrap();
2731 assert_eq!(u_c.id, id_c);
2732 assert_eq!(u_c.len, 4);
2733
2734 assert_invariants(&ring, &producer);
2735 }
2736
2737 #[test]
2739 fn producer_disable_used_notifications_writes_driver_disable() {
2740 let ring = make_ring(8);
2741 let mut producer = make_producer(&ring);
2742
2743 assert_eq!(ring.read_driver_event().flags(), EventFlags::ENABLE);
2744 producer.disable_used_notifications().unwrap();
2745 assert_eq!(ring.read_driver_event().flags(), EventFlags::DISABLE);
2746 }
2747
2748 #[test]
2749 fn producer_enable_used_notifications_writes_driver_enable() {
2750 let ring = make_ring(8);
2751 let mut producer = make_producer(&ring);
2752
2753 producer.disable_used_notifications().unwrap();
2754 assert_eq!(ring.read_driver_event().flags(), EventFlags::DISABLE);
2755
2756 producer.enable_used_notifications().unwrap();
2757 assert_eq!(ring.read_driver_event().flags(), EventFlags::ENABLE);
2758 }
2759
2760 #[test]
2761 fn producer_enable_used_notifications_desc_sets_off_wrap_and_flags() {
2762 let ring = make_ring(8);
2763 let mut producer = make_producer(&ring);
2764
2765 producer.enable_used_notifications_desc(5, true).unwrap();
2766
2767 let evt = ring.read_driver_event();
2768 assert_eq!(evt.flags(), EventFlags::DESC);
2769 assert_eq!(evt.desc_event_off(), 5);
2770 assert!(evt.desc_event_wrap());
2771 }
2772
2773 #[test]
2774 fn producer_enable_used_notifications_for_next_programs_used_cursor() {
2775 let ring = make_ring(8);
2776 let mut producer = make_producer(&ring);
2777
2778 producer.enable_used_notifications_for_next().unwrap();
2780
2781 let evt = ring.read_driver_event();
2782 assert_eq!(evt.flags(), EventFlags::DESC);
2783 assert_eq!(evt.desc_event_off(), 0);
2784 assert!(evt.desc_event_wrap());
2785 }
2786
2787 #[test]
2788 fn consumer_disable_avail_notifications_writes_device_disable() {
2789 let ring = make_ring(8);
2790 let mut consumer = make_consumer(&ring);
2791
2792 assert_eq!(ring.read_device_event().flags(), EventFlags::ENABLE);
2793 consumer.disable_avail_notifications().unwrap();
2794 assert_eq!(ring.read_device_event().flags(), EventFlags::DISABLE);
2795 }
2796
2797 #[test]
2798 fn consumer_enable_avail_notifications_writes_device_enable() {
2799 let ring = make_ring(8);
2800 let mut consumer = make_consumer(&ring);
2801
2802 consumer.disable_avail_notifications().unwrap();
2803 assert_eq!(ring.read_device_event().flags(), EventFlags::DISABLE);
2804
2805 consumer.enable_avail_notifications().unwrap();
2806 assert_eq!(ring.read_device_event().flags(), EventFlags::ENABLE);
2807 }
2808
2809 #[test]
2810 fn consumer_enable_avail_notifications_desc_sets_off_wrap_and_flags() {
2811 let ring = make_ring(8);
2812 let mut consumer = make_consumer(&ring);
2813
2814 consumer.enable_avail_notifications_desc(7, false).unwrap();
2815
2816 let evt = ring.read_device_event();
2817 assert_eq!(evt.flags(), EventFlags::DESC);
2818 assert_eq!(evt.desc_event_off(), 7);
2819 assert!(!evt.desc_event_wrap());
2820 }
2821
2822 #[test]
2823 fn consumer_enable_avail_notifications_for_next_programs_avail_cursor() {
2824 let ring = make_ring(8);
2825 let mut consumer = make_consumer(&ring);
2826
2827 consumer.enable_avail_notifications_for_next().unwrap();
2829
2830 let evt = ring.read_device_event();
2831 assert_eq!(evt.flags(), EventFlags::DESC);
2832 assert_eq!(evt.desc_event_off(), 0);
2833 assert!(evt.desc_event_wrap());
2834 }
2835
2836 #[test]
2837 fn producer_does_not_write_device_event_when_toggling_used_notifications() {
2838 let ring = make_ring(8);
2839 let mut producer = make_producer(&ring);
2840
2841 let dev_before = ring.read_device_event();
2842 producer.disable_used_notifications().unwrap();
2843 let dev_after = ring.read_device_event();
2844
2845 assert_eq!(dev_after, dev_before);
2846 }
2847
2848 #[test]
2849 fn consumer_does_not_write_driver_event_when_toggling_avail_notifications() {
2850 let ring = make_ring(8);
2851 let mut consumer = make_consumer(&ring);
2852
2853 let drv_before = ring.read_driver_event();
2854 consumer.disable_avail_notifications().unwrap();
2855 let drv_after = ring.read_driver_event();
2856
2857 assert_eq!(drv_after, drv_before);
2858 }
2859
2860 #[test]
2861 fn should_notify_flags_enable_disable() {
2862 let ring_len = 8;
2863
2864 let old = RingCursor {
2865 head: 0,
2866 size: ring_len,
2867 wrap: true,
2868 };
2869 let new = RingCursor {
2870 head: 1,
2871 size: ring_len,
2872 wrap: true,
2873 };
2874
2875 let evt = EventSuppression::new(0, EventFlags::DISABLE);
2877 assert!(!should_notify(evt, ring_len, old, new));
2878
2879 let evt = EventSuppression::new(0, EventFlags::ENABLE);
2881 assert!(should_notify(evt, ring_len, old, new));
2882 }
2883
2884 #[test]
2885 fn should_notify_desc_no_crossing() {
2886 let ring_len = 8;
2887
2888 let old = RingCursor {
2889 head: 2,
2890 size: ring_len,
2891 wrap: true,
2892 };
2893 let new = RingCursor {
2894 head: 3,
2895 size: ring_len,
2896 wrap: true,
2897 };
2898
2899 let mut evt = EventSuppression::zeroed();
2901 evt.set_desc_event(6, true);
2902 evt.set_flags(EventFlags::DESC);
2903
2904 assert!(!should_notify(evt, ring_len, old, new));
2905 }
2906
2907 #[test]
2908 fn should_notify_desc_wrap_mismatch_adjusts_event_idx() {
2909 let ring_len = 8;
2910
2911 let old = RingCursor {
2912 head: 7,
2913 size: ring_len,
2914 wrap: true,
2915 };
2916 let new = RingCursor {
2917 head: 1,
2918 size: ring_len,
2919 wrap: false,
2920 };
2921
2922 let mut evt = EventSuppression::zeroed();
2923 evt.set_desc_event(7, true);
2924 evt.set_flags(EventFlags::DESC);
2925
2926 assert!(should_notify(evt, ring_len, old, new));
2927 }
2928
2929 #[test]
2930 fn ring_need_event_basic_cases() {
2931 assert!(ring_need_event(4, 5, 2));
2933 assert!(!ring_need_event(4, 5, 5));
2935
2936 let old = 0xFFFE;
2938 let new = 1;
2939 assert!(ring_need_event(0xFFFF, new, old));
2941 }
2942
2943 #[test]
2945 fn bad_device_marks_tail_used() {
2946 let ring = make_ring(8);
2947 let mut producer = make_producer(&ring);
2948
2949 let chain = BufferChainBuilder::new()
2950 .readable(0x1000, 4)
2951 .readable(0x2000, 4)
2952 .build()
2953 .unwrap();
2954 let id = producer.submit_available(&chain).unwrap();
2955
2956 let mut tail = ring.read_desc(1);
2958 tail.mark_used(producer.used_cursor.wrap());
2959 ring.write_desc(1, tail);
2960
2961 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2963
2964 let mut head = ring.read_desc(0);
2966 head.mark_used(producer.used_cursor.wrap());
2967 ring.write_desc(0, head);
2968
2969 let used = producer.poll_used().unwrap();
2970 assert_eq!(used.id, id);
2971 }
2972
2973 #[test]
2974 fn bad_device_wrong_used_bits() {
2975 let ring = make_ring(4);
2976 let mut producer = make_producer(&ring);
2977
2978 let id = producer.submit_one(0x1000, 8, true).unwrap();
2979
2980 let mut d = ring.read_desc(0);
2982 d.mark_avail(producer.used_cursor.wrap());
2984 d.len = 8;
2985 ring.write_desc(0, d);
2986
2987 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2988
2989 let mut d2 = ring.read_desc(0);
2990 d2.mark_used(producer.used_cursor.wrap());
2991 ring.write_desc(0, d2);
2992
2993 let u = producer.poll_used().unwrap();
2994 assert_eq!(u.id, id);
2995 }
2996
2997 #[test]
2998 fn bad_driver_next_never_clears() {
2999 let ring = make_ring(8);
3000 let mut consumer = make_consumer(&ring);
3001 let mut producer = make_producer(&ring);
3002
3003 let id = producer.id_free.pop().unwrap();
3005 producer.id_num[id as usize] = 8;
3006
3007 let mut pos = producer.avail_cursor;
3008 let wrap_start = pos.wrap();
3009
3010 for _ in 0..8 {
3012 let idx = pos.head();
3013 let mut flags = DescFlags::empty();
3014 flags.set(DescFlags::NEXT, true); let mut desc = Descriptor::new(0x1000 + idx as u64 * 0x10, 4, id, flags);
3016 desc.mark_avail(pos.wrap());
3017 ring.write_desc(idx, desc);
3018 pos.advance();
3019 }
3020
3021 let head_idx = producer.avail_cursor.head();
3023 let mut head_flags = DescFlags::empty();
3024 head_flags.set(DescFlags::NEXT, true);
3025 let mut head_desc = Descriptor::new(0x42, 4, id, head_flags);
3026 head_desc.mark_avail(wrap_start);
3027 ring.write_desc(head_idx, head_desc);
3028
3029 assert!(matches!(
3031 consumer.poll_available(),
3032 Err(RingError::BadChain)
3033 ));
3034 }
3035
3036 #[test]
3037 fn bad_driver_interleaved_readables_and_writables() {
3038 let ring = make_ring(8);
3039 let mut consumer = make_consumer(&ring);
3040 let mut producer = make_producer(&ring);
3041
3042 let chain = BufferChainBuilder::new()
3043 .readable(0x1000, 4)
3044 .readable(0x2000, 4)
3045 .writable(0x2000, 4)
3046 .build()
3047 .unwrap();
3048
3049 let _id = producer.submit_available(&chain).unwrap();
3050
3051 let mut first = ring.read_desc(0);
3053 first.flags |= DescFlags::WRITE.bits();
3054 ring.write_desc(0, first);
3055
3056 assert!(matches!(
3057 consumer.poll_available(),
3058 Err(RingError::BadChain)
3059 ));
3060 }
3061
3062 #[test]
3063 fn bad_device_marks_multiple_used_in_chain() {
3064 let ring = make_ring(8);
3065 let mut producer = make_producer(&ring);
3066
3067 let chain = BufferChainBuilder::new()
3068 .readable(0x1000, 4)
3069 .readable(0x2000, 4)
3070 .build()
3071 .unwrap();
3072 let id = producer.submit_available(&chain).unwrap();
3073
3074 let mut head = ring.read_desc(0);
3076 head.mark_used(producer.used_cursor.wrap());
3077 ring.write_desc(0, head);
3078
3079 let mut tail = ring.read_desc(1);
3080 tail.mark_used(producer.used_cursor.wrap());
3081 ring.write_desc(1, tail);
3082
3083 let u = producer.poll_used().unwrap();
3085 assert_eq!(u.id, id);
3086
3087 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
3089 }
3090
3091 #[test]
3092 fn bad_device_writes_used_at_wrong_slot() {
3093 let ring = make_ring(8);
3094 let mut producer = make_producer(&ring);
3095
3096 let _id = producer.submit_one(0x1000, 4, true).unwrap();
3097
3098 let mut d = ring.read_desc(3);
3100 d.mark_used(producer.used_cursor.wrap());
3101 ring.write_desc(3, d);
3102
3103 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
3105
3106 let mut d0 = ring.read_desc(0);
3108 d0.mark_used(producer.used_cursor.wrap());
3109 ring.write_desc(0, d0);
3110 let _u = producer.poll_used().unwrap();
3111 }
3112
3113 #[test]
3114 fn bad_driver_reuses_id_while_outstanding() {
3115 let ring = make_ring(8);
3116 let mut producer = make_producer(&ring);
3117
3118 let id = producer.submit_one(0x1000, 4, false).unwrap();
3120 assert_eq!(producer.id_num[id as usize], 1);
3121
3122 producer.id_free.push(id);
3124
3125 let res = producer.submit_one(0x2000, 4, false);
3127 assert!(matches!(res, Err(RingError::InvalidState)));
3128 }
3129
3130 #[test]
3131 fn test_avail_cursor_accessor() {
3132 let ring = make_ring(8);
3133 let mut producer = make_producer(&ring);
3134
3135 let cursor = producer.avail_cursor();
3137 assert_eq!(cursor.head(), 0);
3138 assert!(cursor.wrap());
3139
3140 producer.submit_one(0x1000, 512, false).unwrap();
3142 let cursor = producer.avail_cursor();
3143 assert_eq!(cursor.head(), 1);
3144 assert!(cursor.wrap());
3145 }
3146
3147 #[test]
3148 fn test_should_notify_since() {
3149 let ring = make_ring(8);
3150 let mut producer = make_producer(&ring);
3151
3152 let before = producer.avail_cursor();
3153 producer.submit_one(0x1000, 512, false).unwrap();
3154
3155 let should_notify = producer.should_notify_since(before).unwrap();
3157 assert!(should_notify);
3158 }
3159
3160 #[test]
3161 fn test_batch_notification_single_check() {
3162 let ring = make_ring(8);
3163 let mut producer = make_producer(&ring);
3164 let mut consumer = make_consumer(&ring);
3165
3166 let before = producer.avail_cursor();
3167
3168 producer.submit_one(0x1000, 512, false).unwrap();
3170 producer.submit_one(0x2000, 512, false).unwrap();
3171 producer.submit_one(0x3000, 512, false).unwrap();
3172
3173 let should_notify = producer.should_notify_since(before).unwrap();
3175 assert!(should_notify);
3176
3177 for _ in 0..3 {
3179 let (_, _) = consumer.poll_available().unwrap();
3180 }
3181 }
3182
3183 #[test]
3184 fn test_ring_cursor_reset() {
3185 let mut cursor = RingCursor::new(16);
3186 cursor.advance_by(5);
3187 assert_eq!(cursor.head(), 5);
3188
3189 cursor.reset();
3190 assert_eq!(cursor, RingCursor::new(16));
3191 assert_eq!(cursor.head(), 0);
3192 assert!(cursor.wrap());
3193 }
3194
3195 #[test]
3196 fn test_ring_cursor_reset_after_wrap() {
3197 let mut cursor = RingCursor::new(4);
3198 cursor.advance_by(5);
3200 assert_eq!(cursor.head(), 1);
3201 assert!(!cursor.wrap());
3202
3203 cursor.reset();
3204 assert_eq!(cursor.head(), 0);
3205 assert!(cursor.wrap());
3206 }
3207
3208 #[test]
3209 fn test_ring_producer_reset_matches_new() {
3210 let ring = make_ring(8);
3211 let fresh = make_producer(&ring);
3212
3213 let mut used = make_producer(&ring);
3214 used.submit_one(0x1000, 64, false).unwrap();
3216 used.submit_one(0x2000, 128, true).unwrap();
3217
3218 used.reset();
3219
3220 assert_eq!(used.avail_cursor, fresh.avail_cursor);
3221 assert_eq!(used.used_cursor, fresh.used_cursor);
3222 assert_eq!(used.num_free, fresh.num_free);
3223 assert_eq!(used.id_free.len(), fresh.id_free.len());
3224 assert_eq!(used.id_num.as_slice(), fresh.id_num.as_slice());
3225 assert_eq!(used.event_flags_shadow, fresh.event_flags_shadow);
3226 }
3227
3228 #[test]
3229 fn test_ring_producer_reset_id_free_complete() {
3230 let ring = make_ring(8);
3231 let mut producer = make_producer(&ring);
3232
3233 for i in 0..4u64 {
3235 producer.submit_one(0x1000 + i * 0x100, 64, false).unwrap();
3236 }
3237 assert_eq!(producer.num_free, 4);
3238
3239 producer.reset();
3240
3241 assert_eq!(producer.num_free, 8);
3242 assert_eq!(producer.id_free.len(), 8);
3243 for id in 0..8u16 {
3245 assert!(producer.id_free.contains(&id));
3246 }
3247 }
3248
3249 #[test]
3250 fn test_ring_consumer_reset_matches_new() {
3251 let ring = make_ring(8);
3252 let fresh = make_consumer(&ring);
3253
3254 let mut used = make_consumer(&ring);
3255
3256 let mut producer = make_producer(&ring);
3258 producer.submit_one(0x1000, 64, false).unwrap();
3259
3260 let (id, _chain) = used.poll_available().unwrap();
3262 used.submit_used(id, 64).unwrap();
3263
3264 used.reset();
3265
3266 assert_eq!(used.avail_cursor, fresh.avail_cursor);
3267 assert_eq!(used.used_cursor, fresh.used_cursor);
3268 assert_eq!(used.id_num.as_slice(), fresh.id_num.as_slice());
3269 assert_eq!(used.num_inflight, fresh.num_inflight);
3270 assert_eq!(used.event_flags_shadow, fresh.event_flags_shadow);
3271 }
3272
3273 #[test]
3274 fn test_ring_consumer_reset_clears_inflight() {
3275 let ring = make_ring(8);
3276 let mut producer = make_producer(&ring);
3277 let mut consumer = make_consumer(&ring);
3278
3279 producer.submit_one(0x1000, 64, false).unwrap();
3281 producer.submit_one(0x2000, 64, false).unwrap();
3282 let _ = consumer.poll_available().unwrap();
3283 let _ = consumer.poll_available().unwrap();
3284 assert_eq!(consumer.num_inflight, 2);
3285
3286 consumer.reset();
3287 assert_eq!(consumer.num_inflight, 0);
3288 }
3289
3290 #[test]
3291 fn test_reset_prefilled_sets_cursors() {
3292 let ring = make_ring(8);
3293 let mut producer = make_producer(&ring);
3294 let ids: Vec<u16> = (0..8).collect();
3295 producer.reset_prefilled(&ids);
3296
3297 assert_eq!(producer.avail_cursor.head(), 0);
3299 assert!(!producer.avail_cursor.wrap());
3300 assert_eq!(producer.used_cursor.head(), 0);
3302 assert!(producer.used_cursor.wrap());
3303 }
3304
3305 #[test]
3306 fn test_reset_prefilled_all_ids_inflight() {
3307 let ring = make_ring(8);
3308 let mut producer = make_producer(&ring);
3309 let ids: Vec<u16> = (0..8).collect();
3310 producer.reset_prefilled(&ids);
3311
3312 assert_eq!(producer.num_free, 0);
3313 assert!(producer.id_free.is_empty());
3314 assert!(producer.id_num.iter().all(|&n| n == 1));
3315 }
3316
3317 #[test]
3318 fn test_reset_prefilled_partial() {
3319 let ring = make_ring(8);
3320 let mut producer = make_producer(&ring);
3321 producer.reset_prefilled(&[5, 6, 7, 3]);
3322
3323 assert_eq!(producer.avail_cursor.head(), 4);
3325 assert!(producer.avail_cursor.wrap());
3326 assert_eq!(producer.used_cursor.head(), 0);
3328 assert!(producer.used_cursor.wrap());
3329
3330 assert_eq!(producer.num_free, 4);
3331 assert_eq!(producer.id_free.len(), 4);
3332 for &id in &[0, 1, 2, 4] {
3333 assert!(producer.id_free.contains(&id));
3334 }
3335 for &id in &[5, 6, 7, 3] {
3337 assert_eq!(producer.id_num[id as usize], 1);
3338 }
3339 for &id in &[0, 1, 2, 4] {
3340 assert_eq!(producer.id_num[id as usize], 0);
3341 }
3342 }
3343
3344 #[test]
3345 fn test_reset_prefilled_partial_then_submit() {
3346 let ring = make_ring(8);
3347 let mut producer = make_producer(&ring);
3348 producer.reset_prefilled(&[4, 5, 6, 7]);
3349
3350 let id = producer.submit_one(0x8000, 128, false).unwrap();
3351
3352 assert!([0, 1, 2, 3].contains(&id));
3353 assert_eq!(producer.num_free, 3);
3354 assert_eq!(producer.id_num[id as usize], 1);
3355 }
3356
3357 #[test]
3358 fn test_reset_prefilled_then_poll_used() {
3359 let ring = make_ring(4);
3360 let mut producer = make_producer(&ring);
3361
3362 for i in 0..4u64 {
3364 producer.submit_one(0x1000 + i * 4096, 4096, true).unwrap();
3365 }
3366
3367 let mut consumer = make_consumer(&ring);
3369 let (id, _chain) = consumer.poll_available().unwrap();
3370 consumer.submit_used(id, 64).unwrap();
3371
3372 let mut restored = make_producer(&ring);
3374 restored.reset_prefilled(&[0, 1, 2, 3]);
3375
3376 let used = restored.poll_used().unwrap();
3378 assert_eq!(used.id, id);
3379 }
3380
3381 #[test]
3382 fn test_desc_table_read_after_submit() {
3383 let ring = make_ring(8);
3384 let mut writer = make_producer(&ring);
3385 writer.submit_one(0x1000, 4096, true).unwrap();
3386
3387 let reader = make_producer(&ring);
3388 let addr = reader.desc_table().desc_addr(0).unwrap();
3389 let flags = Descriptor::read_flags_acquire(reader.mem(), addr).unwrap();
3390 let desc = Descriptor::read_body(reader.mem(), addr, flags).unwrap();
3391 assert_eq!(desc.addr, 0x1000);
3392 assert_eq!(desc.len, 4096);
3393 assert!(desc.is_writable());
3394 assert!(desc.is_avail(true));
3395 assert!(!desc.is_used(true));
3396 }
3397
3398 #[test]
3399 fn test_desc_table_out_of_bounds() {
3400 let ring = make_ring(8);
3401 let reader = make_producer(&ring);
3402 assert!(reader.desc_table().desc_addr(8).is_none());
3403 }
3404
3405 #[test]
3406 fn test_desc_table_read_used_descriptor() {
3407 let ring = make_ring(8);
3408 let mut writer = make_producer(&ring);
3409 writer.submit_one(0x1000, 4096, true).unwrap();
3410
3411 let mut consumer = make_consumer(&ring);
3412 let (id, _chain) = consumer.poll_available().unwrap();
3413 consumer.submit_used(id, 128).unwrap();
3414
3415 let reader = make_producer(&ring);
3416 let addr = reader.desc_table().desc_addr(0).unwrap();
3417 let flags = Descriptor::read_flags_acquire(reader.mem(), addr).unwrap();
3418 let desc = Descriptor::read_body(reader.mem(), addr, flags).unwrap();
3419 assert!(desc.is_used(true));
3420 assert!(!desc.is_avail(true));
3421 }
3422}
3423
3424#[cfg(test)]
3425mod fuzz {
3426 use quickcheck::{Arbitrary, Gen, QuickCheck};
3427
3428 use super::tests::{OwnedRing, make_consumer, make_producer};
3429 use super::*;
3430
3431 const MAX_RING: usize = 64;
3432 const MAX_OPS: usize = 128;
3433 const MAX_CHAIN_LEN: usize = 8;
3434
3435 #[allow(clippy::large_enum_variant)]
3436 #[derive(Clone, Debug)]
3437 enum Op {
3438 Submit(BufferChain),
3440 PollAvail(u8),
3442 PollUsed(u8),
3444 CompleteOne,
3446 }
3447
3448 impl Arbitrary for Op {
3449 fn arbitrary(g: &mut Gen) -> Self {
3450 let choice = u8::arbitrary(g) % 4;
3451 match choice {
3452 0 => Op::Submit(BufferChain::arbitrary(g)),
3453 1 => Op::PollAvail(u8::arbitrary(g) % 8 + 1),
3454 2 => Op::PollUsed(u8::arbitrary(g) % 8 + 1),
3455 3 => Op::CompleteOne,
3456 _ => unreachable!(),
3457 }
3458 }
3459 }
3460
3461 #[derive(Clone, Debug)]
3462 struct Scenario {
3463 table_size: usize,
3464 ops: Vec<Op>,
3465 }
3466
3467 impl Arbitrary for Scenario {
3468 fn arbitrary(g: &mut Gen) -> Self {
3469 let table_size = (usize::arbitrary(g) % MAX_RING + 1).next_power_of_two();
3470 let num_ops = usize::arbitrary(g) % MAX_OPS + 1;
3471
3472 let ops = (0..num_ops).map(|_| Op::arbitrary(g)).collect();
3473 Scenario { table_size, ops }
3474 }
3475 }
3476
3477 impl Arbitrary for BufferElement {
3478 fn arbitrary(g: &mut Gen) -> Self {
3479 let addr = u64::arbitrary(g);
3480 let len = u32::arbitrary(g);
3481 let writable = bool::arbitrary(g);
3482
3483 BufferElement {
3484 addr,
3485 len,
3486 writable,
3487 }
3488 }
3489 }
3490
3491 impl Arbitrary for BufferChain {
3492 fn arbitrary(g: &mut Gen) -> Self {
3493 let chain_len = usize::arbitrary(g) % MAX_CHAIN_LEN + 1;
3494
3495 let mut elems = vec![BufferElement::zeroed(); chain_len];
3496 let mut readables = 0;
3497 let mut writables = 0;
3498
3499 for _ in 0..chain_len {
3500 let elem = BufferElement::arbitrary(g);
3501 if elem.writable {
3502 elems[chain_len - 1 - writables] = elem;
3503 writables += 1;
3504 } else {
3505 elems[readables] = elem;
3506 readables += 1;
3507 }
3508 }
3509
3510 BufferChain {
3511 elems: elems.into(),
3512 split: readables,
3513 }
3514 }
3515 }
3516
3517 fn run_scenario(s: Scenario) -> bool {
3518 let ring = OwnedRing::new(s.table_size);
3519 let mut producer = make_producer(&ring);
3520 let mut consumer = make_consumer(&ring);
3521
3522 let mut dev_order: Vec<u16> = Vec::new();
3524 let mut drv_order: Vec<u16> = Vec::new();
3525
3526 let mut dev_ready: Vec<(u16, u32)> = Vec::new();
3528
3529 for op in &s.ops {
3530 match op {
3531 Op::Submit(chain) => {
3532 let _ = producer.submit_available(chain);
3534 }
3535 Op::PollAvail(n) => {
3536 for _ in 0..*n {
3537 if let Ok((id, chain)) = consumer.poll_available() {
3538 dev_ready.push((id, chain.len() as u32));
3539 } else {
3540 break;
3541 }
3542 }
3543 }
3544 Op::PollUsed(n) => {
3545 for _ in 0..*n {
3546 match producer.poll_used() {
3547 Ok(u) => {
3548 drv_order.push(u.id);
3549 if producer.id_num[u.id as usize] != 0 {
3550 return false;
3551 }
3552 if !producer.id_free.contains(&u.id) {
3553 return false;
3554 }
3555 }
3556 Err(RingError::WouldBlock) => break,
3557 Err(_) => return false,
3558 }
3559 }
3560 }
3561 Op::CompleteOne => {
3562 if let Some((id, len)) = dev_ready.pop() {
3563 if consumer.submit_used(id, len).is_err() {
3564 return false;
3565 }
3566
3567 dev_order.push(id);
3568 }
3569 }
3570 }
3571
3572 let outstanding: u16 = producer.id_num.iter().copied().sum();
3574 if outstanding as usize + producer.num_free != ring.len() {
3575 return false;
3576 }
3577
3578 for id in producer.id_free.iter() {
3579 if producer.id_num[*id as usize] != 0 {
3580 return false;
3581 }
3582 }
3583 }
3584
3585 while let Some((id, len)) = dev_ready.pop() {
3587 if consumer.submit_used(id, len).is_err() {
3588 return false;
3589 }
3590 }
3591
3592 loop {
3593 match producer.poll_used() {
3594 Ok(u) => drv_order.push(u.id),
3595 Err(RingError::WouldBlock) => break,
3596 Err(_) => return false,
3597 }
3598 }
3599
3600 true
3601 }
3602
3603 #[test]
3604 fn prop_interleaved_with_order_verification() {
3605 #[cfg(miri)]
3606 let tests = 1;
3607 #[cfg(not(miri))]
3608 let tests = 100;
3609
3610 QuickCheck::new()
3611 .tests(tests)
3612 .quickcheck(run_scenario as fn(Scenario) -> bool);
3613 }
3614}