Skip to main content

dope_uring/driver/
ring.rs

1use std::{io, time::Duration};
2
3use io_uring::{CompletionQueue, IoUring, Submitter, opcode, types};
4
5use crate::driver::wire;
6
7pub struct Ring {
8    inner: IoUring,
9}
10
11impl Ring {
12    pub(crate) fn new(uring: IoUring) -> Self {
13        Self { inner: uring }
14    }
15
16    pub(crate) fn submitter<'a>(&'a self) -> Submitter<'a> {
17        self.inner.submitter()
18    }
19
20    pub(crate) fn completion<'a>(&'a mut self) -> CompletionQueue<'a> {
21        self.inner.completion()
22    }
23
24    pub(in crate::driver) fn submission_len(&mut self) -> usize {
25        self.inner.submission().len()
26    }
27
28    pub(in crate::driver) fn is_full(&mut self) -> bool {
29        self.inner.submission().is_full()
30    }
31
32    pub(in crate::driver) fn has_submission(&mut self) -> bool {
33        !self.inner.submission().is_empty()
34    }
35
36    pub(in crate::driver) fn has_completion(&mut self) -> bool {
37        !self.inner.completion().is_empty()
38    }
39
40    pub(in crate::driver) fn submit_and_wait(&mut self, min_complete: u32) -> io::Result<()> {
41        self.inner.submit_and_wait(min_complete as usize)?;
42        Ok(())
43    }
44
45    pub(in crate::driver) fn submit(&mut self) -> io::Result<usize> {
46        let before = self.submission_len();
47        self.inner
48            .submit()
49            .map(|_| before.saturating_sub(self.submission_len()))
50    }
51
52    pub(in crate::driver) fn submit_with_timeout(
53        &mut self,
54        min_complete: u32,
55        duration: Duration,
56    ) -> io::Result<()> {
57        let ts = types::Timespec::from(duration);
58        let args = types::SubmitArgs::new().timespec(&ts);
59        let want = min_complete as usize;
60        match self.inner.submitter().submit_with_args(want, &args) {
61            Ok(_) => Ok(()),
62            Err(e) if e.raw_os_error() == Some(libc::ETIME) => Ok(()),
63            Err(e) => Err(e),
64        }
65    }
66
67    pub(in crate::driver) fn try_push_arm(&mut self, sqe: io_uring::squeue::Entry) -> bool {
68        unsafe {
69            let mut sq = self.inner.submission();
70            sq.push(&sqe).is_ok()
71        }
72    }
73
74    pub(in crate::driver) fn push(&mut self, sqe: &io_uring::squeue::Entry) -> bool {
75        unsafe {
76            let mut sq = self.inner.submission();
77            sq.push(sqe).is_ok()
78        }
79    }
80
81    pub(in crate::driver) fn submit_cancel(&mut self, target_user_data: u64) {
82        let sqe = opcode::AsyncCancel::new(target_user_data)
83            .build()
84            .user_data(wire::ignore());
85
86        unsafe {
87            let mut sq = self.inner.submission();
88            if sq.push(&sqe).is_ok() {
89                return;
90            }
91        }
92        if let Err(e) = self.submit() {
93            panic!("dope invariant violated: cancel submit failed: {e}");
94        }
95        unsafe {
96            let mut sq = self.inner.submission();
97            if sq.push(&sqe).is_err() {
98                panic!("dope invariant violated: cancel SQE enqueue failed after submit");
99            }
100        }
101    }
102}