Skip to main content

compio_driver/sys/driver/iour/
op.rs

1use std::io;
2
3pub use OpCode as IourOpCode;
4use compio_buf::BufResult;
5
6use crate::control::Carrier;
7
8/// The created entry of [`OpCode`].
9pub enum OpEntry {
10    /// This operation creates an io-uring submission entry.
11    Submission(io_uring::squeue::Entry),
12    #[cfg(feature = "io-uring-sqe128")]
13    /// This operation creates an 128-bit io-uring submission entry.
14    Submission128(io_uring::squeue::Entry128),
15    /// This operation is a blocking one.
16    Blocking,
17}
18
19/// Abstraction of io-uring operations.
20///
21/// # Safety
22///
23/// The returned Entry from `create_entry` must be valid until the operation
24/// is completed.
25pub unsafe trait OpCode {
26    /// Type that contains self-references and other needed info during the
27    /// operation
28    type Control: Default;
29
30    /// Initialize the control
31    ///
32    /// # Safety
33    ///
34    /// Caller must guarantee that during the lifetime of `ctrl`, `Self` is
35    /// unmoved and valid.
36    unsafe fn init(&mut self, _: &mut Self::Control) {}
37
38    /// Create submission entry.
39    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry;
40
41    /// Create submission entry for fallback. This method will only be
42    /// called if `create_entry` returns an entry with unsupported
43    /// opcode.
44    fn create_entry_fallback(&mut self, _: &mut Self::Control) -> OpEntry {
45        OpEntry::Blocking
46    }
47
48    /// Call the operation in a blocking way. This method will be called if
49    /// * [`create_entry`] returns [`OpEntry::Blocking`].
50    /// * [`create_entry`] returns an entry with unsupported opcode, and
51    ///   [`create_entry_fallback`] returns [`OpEntry::Blocking`].
52    /// * [`create_entry`] and [`create_entry_fallback`] both return an entry
53    ///   with unsupported opcode.
54    ///
55    /// [`create_entry`]: OpCode::create_entry
56    /// [`create_entry_fallback`]: OpCode::create_entry_fallback
57    fn call_blocking(&mut self, _: &mut Self::Control) -> io::Result<usize> {
58        unreachable!("this operation is asynchronous")
59    }
60
61    /// Set the result when it completes.
62    /// The operation stores the result and is responsible to release it if
63    /// the operation is cancelled.
64    ///
65    /// # Safety
66    ///
67    /// The params must be the result coming from this operation.
68    unsafe fn set_result(
69        &mut self,
70        _: &mut Self::Control,
71        _: &io::Result<usize>,
72        _: &crate::Extra,
73    ) {
74    }
75
76    /// Push a multishot result to the inner queue.
77    ///
78    /// # Safety
79    ///
80    /// The params must be the result coming from this operation.
81    unsafe fn push_multishot(
82        &mut self,
83        _: &mut Self::Control,
84        _: io::Result<usize>,
85        _: crate::Extra,
86    ) {
87        unreachable!("this operation is not multishot")
88    }
89
90    /// Pop a multishot result from the inner queue.
91    fn pop_multishot(
92        &mut self,
93        _: &mut Self::Control,
94    ) -> Option<BufResult<usize, crate::sys::Extra>> {
95        unreachable!("this operation is not multishot")
96    }
97}
98
99impl OpEntry {
100    pub(crate) fn with_extra(self, extra: &crate::Extra) -> Self {
101        let Some(extra) = extra.try_as_iour() else {
102            return self;
103        };
104        match self {
105            Self::Submission(mut entry) => Self::Submission({
106                if let Some(personality) = extra.get_personality() {
107                    entry = entry.personality(personality);
108                }
109                // Set the union of two flags - it will not remove previous flags set by the Op
110                entry.flags(extra.get_sqe_flags())
111            }),
112            #[cfg(feature = "io-uring-sqe128")]
113            Self::Submission128(mut entry) => Self::Submission128({
114                if let Some(personality) = extra.get_personality() {
115                    entry = entry.personality(personality);
116                }
117                entry.flags(extra.get_sqe_flags())
118            }),
119            Self::Blocking => Self::Blocking,
120        }
121    }
122}
123
124pub(crate) trait Carry {
125    /// See [`OpCode::create_entry`].
126    fn create_entry(&mut self) -> OpEntry;
127
128    /// See [`OpCode::create_entry_fallback`].
129    fn create_entry_fallback(&mut self) -> OpEntry;
130
131    /// See [`OpCode::call_blocking`].
132    fn call_blocking(&mut self) -> io::Result<usize>;
133
134    /// See [`OpCode::set_result`].
135    unsafe fn set_result(&mut self, _: &io::Result<usize>, _: &crate::Extra);
136
137    /// See [`OpCode::push_multishot`].
138    unsafe fn push_multishot(&mut self, _: io::Result<usize>, _: crate::Extra);
139
140    /// See [`OpCode::pop_multishot`].
141    fn pop_multishot(&mut self) -> Option<BufResult<usize, crate::sys::Extra>>;
142}
143
144impl<T: crate::OpCode> Carry for Carrier<T> {
145    fn create_entry(&mut self) -> OpEntry {
146        let (op, control) = self.as_iour();
147        op.create_entry(control)
148    }
149
150    fn create_entry_fallback(&mut self) -> OpEntry {
151        let (op, control) = self.as_iour();
152        op.create_entry_fallback(control)
153    }
154
155    fn call_blocking(&mut self) -> io::Result<usize> {
156        let (op, control) = self.as_iour();
157        op.call_blocking(control)
158    }
159
160    unsafe fn set_result(&mut self, result: &io::Result<usize>, extra: &crate::Extra) {
161        let (op, control) = self.as_iour();
162        unsafe { OpCode::set_result(op, control, result, extra) }
163    }
164
165    unsafe fn push_multishot(&mut self, result: io::Result<usize>, extra: crate::Extra) {
166        let (op, control) = self.as_iour();
167        unsafe { op.push_multishot(control, result, extra) }
168    }
169
170    fn pop_multishot(&mut self) -> Option<BufResult<usize, crate::sys::Extra>> {
171        let (op, control) = self.as_iour();
172        op.pop_multishot(control)
173    }
174}
175
176impl From<io_uring::squeue::Entry> for OpEntry {
177    fn from(value: io_uring::squeue::Entry) -> Self {
178        Self::Submission(value)
179    }
180}
181
182#[cfg(feature = "io-uring-sqe128")]
183impl From<io_uring::squeue::Entry128> for OpEntry {
184    fn from(value: io_uring::squeue::Entry128) -> Self {
185        Self::Submission128(value)
186    }
187}