1pub mod poll;
2
3use std::mem;
4
5use dope_sys::{
6 io::reactor::{Full, complete},
7 kernel, probe,
8 ring::{layout, prepare::Feature},
9};
10use o3::{alloc, buffer::pool, depot::arena::slab::Vacancy};
11
12use crate::{
13 Engine,
14 driver::{
15 receive,
16 result::poll::fault,
17 route::{indices, table::bounds},
18 settings::errors,
19 storage,
20 },
21 io::{socket, transfer},
22};
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub enum IoOperation {
26 Entropy,
27 ReactorCreate,
28 MapRing,
29 RegisterReactor,
30 CancelRegistrations,
31 RegisterOpcodes,
32 RegisterFileTable,
33 RegisterFileRange,
34 MapBuffers,
35 UnmapRing,
36 UnmapBuffers,
37 PopulateBuffers,
38 RegisterProvidedBuffers,
39 RegisterCanaryBuffers,
40 UnregisterCanaryBuffers,
41 InstallReceiveFile,
42 RemoveReceiveFile,
43 InstallReceiveMessageFile,
44 RemoveReceiveMessageFile,
45 Probe(Probe),
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub enum Cloexec {
50 Get(crate::Errno),
51 Set(crate::Errno),
52}
53
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub enum Capability {
56 Feature(Feature),
57 Opcode(Opcode),
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq)]
61#[repr(transparent)]
62pub struct Opcode(<crate::Backend as kernel::Source>::Code);
63
64impl<C> Opcode
65where
66 crate::Backend: kernel::Source<Code = C>,
67{
68 pub(crate) fn native<T: Into<C>>(code: T) -> Self {
69 Self(code.into())
70 }
71}
72
73#[derive(Clone, Copy, Debug, PartialEq, Eq)]
74#[repr(u8)]
75pub enum Probe {
76 Ring = 0,
77 DirectSocket = 1,
78 SocketOption = 2,
79 CloseDirectSocket = 3,
80 Receive = 4,
81 ReceiveMessage = 5,
82 DirectAccept = 6,
83 CloseDirectAccept = 7,
84 DirectAcceptMultishot = 8,
85 CloseDirectAcceptMultishot = 9,
86 RegisterAcceptListener = 10,
87 ReleaseAcceptListener = 11,
88}
89
90impl From<Probe> for u64 {
91 fn from(probe: Probe) -> Self {
92 probe as Self
93 }
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Eq)]
97pub struct ProbeError {
98 probe: Probe,
99 violation: Violation,
100}
101
102#[derive(Clone, Copy, Debug, PartialEq, Eq)]
103pub enum Violation {
104 MissingCompletion,
105 UnexpectedCompletion {
106 expected: Probe,
107 observed: fault::Observation,
108 },
109 Rejected(fault::Observation),
110 UnexpectedResult(fault::Observation),
111 Send(fault::Send),
112 InvalidFlags(fault::Observation),
113 MissingBuffer,
114 InvalidBuffer(receive::Selection),
115 BufferLength {
116 actual: transfer::Len,
117 capacity: transfer::NonZero,
118 },
119 EarlyTermination,
120 CorruptPayload,
121 FrameOverflow {
122 name: receive::Capacity,
123 control: receive::Capacity,
124 },
125 FrameShort {
126 actual: receive::Length,
127 required: receive::Length,
128 },
129 MissingFrameTruncation {
130 region: FrameRegion,
131 reported: receive::Length,
132 available: receive::Length,
133 },
134 TruncatedFrame,
135 InvalidAddress(socket::Error),
136 NonterminalCancellation(fault::Observation),
137 EscapedSlot(bounds::Slot),
138 ResidualWork {
139 submissions: fault::Pending,
140 completions: fault::Available,
141 },
142}
143
144#[derive(Clone, Copy, PartialEq, Eq, Debug)]
145pub enum FrameRegion {
146 Control,
147 Payload,
148}
149
150impl ProbeError {
151 pub(crate) fn decode(
152 failure: probe::Failure<Probe, <Engine as complete::Observe>::Observation>,
153 ) -> Self {
154 use dope_sys::probe::Check;
155 let (probe, check) = failure.into_parts();
156 let fault = match check {
157 Check::InvalidFlags(observed) => {
158 Violation::InvalidFlags(fault::Observation::new(observed))
159 }
160 Check::Rejected(observed) => Violation::Rejected(fault::Observation::new(observed)),
161 Check::Unexpected(observed) => {
162 Violation::UnexpectedResult(fault::Observation::new(observed))
163 }
164 Check::Nonterminal(observed) => {
165 Violation::NonterminalCancellation(fault::Observation::new(observed))
166 }
167 };
168 Self::new(probe, fault)
169 }
170
171 pub(crate) const fn new(probe: Probe, fault: Violation) -> Self {
172 Self {
173 probe,
174 violation: fault,
175 }
176 }
177
178 pub const fn into_parts(self) -> (Probe, Violation) {
179 (self.probe, self.violation)
180 }
181}
182
183#[derive(Clone, Copy, Debug, Eq, PartialEq)]
184#[repr(transparent)]
185pub struct SubmitError(SubmitCause);
186
187#[derive(Clone, Copy, Debug, Eq, PartialEq)]
188pub enum SubmitCause {
189 Full,
191 IdentityExhausted,
193}
194
195impl SubmitError {
196 pub(crate) const fn queue(full: Full) -> Self {
197 let Full = full;
198 Self(SubmitCause::Full)
199 }
200
201 pub fn cause(self) -> SubmitCause {
202 self.0
203 }
204}
205
206impl From<Vacancy> for SubmitError {
207 fn from(error: Vacancy) -> Self {
208 Self(match error {
209 Vacancy::Full => SubmitCause::Full,
210 Vacancy::IdentityExhausted => SubmitCause::IdentityExhausted,
211 })
212 }
213}
214
215#[derive(Clone, Copy, Debug, PartialEq, Eq)]
216#[repr(transparent)]
217pub struct Kernel(KernelCause);
218
219impl Kernel {
220 pub fn cause(self) -> KernelCause {
222 self.0
223 }
224
225 pub(crate) fn native<T: Into<KernelCause>>(cause: T) -> Self {
226 Self(cause.into())
227 }
228}
229
230const _: () = {
231 assert!(
232 mem::size_of::<Kernel>()
233 == mem::size_of::<<crate::Backend as kernel::Source>::Failure<indices::SlotIndex>>()
234 );
235 assert!(
236 mem::align_of::<Kernel>()
237 == mem::align_of::<<crate::Backend as kernel::Source>::Failure<indices::SlotIndex>>()
238 );
239};
240
241pub enum CreateError {
242 Plan(errors::Config),
243 Allocation(alloc::Error),
244 Queue(alloc::Error),
245 Buffer(pool::CreateError),
246 RingLayout(layout::Layout),
247 ReactorCloexec(Cloexec),
248 Kernel {
249 operation: IoOperation,
250 cause: Kernel,
251 },
252 Mapping(storage::Mapping),
253 Cleanup(storage::Cleanup),
254 Removal(storage::Removal),
255 Release(storage::Release),
256 Capability(Capability),
257 Probe(ProbeError),
258}
259
260#[derive(Debug)]
262pub enum CreateKind<'a> {
263 Plan(&'a errors::Config),
264 Allocation(&'a alloc::Error),
265 Queue(&'a alloc::Error),
266 Buffer(&'a pool::CreateError),
267 RingLayout(&'a layout::Layout),
268 ReactorCloexec(&'a Cloexec),
269 Kernel {
270 operation: &'a IoOperation,
271 cause: &'a Kernel,
272 },
273 Mapping(&'a storage::Mapping),
274 Cleanup {
275 primary: storage::Failure,
276 cleanup: Option<storage::Failure>,
277 },
278 Removal(&'a storage::Removal),
279 Release {
280 primary: storage::Removal,
281 cleanup: Option<storage::Mapping>,
282 },
283 Capability(&'a Capability),
284 Probe(&'a ProbeError),
285}
286
287impl CreateError {
288 pub fn kind(&self) -> CreateKind<'_> {
289 match self {
290 Self::Plan(error) => CreateKind::Plan(error),
291 Self::Allocation(error) => CreateKind::Allocation(error),
292 Self::Queue(error) => CreateKind::Queue(error),
293 Self::Buffer(error) => CreateKind::Buffer(error),
294 Self::RingLayout(error) => CreateKind::RingLayout(error),
295 Self::ReactorCloexec(error) => CreateKind::ReactorCloexec(error),
296 Self::Kernel {
297 operation: op,
298 cause,
299 } => CreateKind::Kernel {
300 operation: op,
301 cause,
302 },
303 Self::Mapping(error) => CreateKind::Mapping(error),
304 Self::Cleanup(state) => CreateKind::Cleanup {
305 primary: state.primary(),
306 cleanup: state.cleanup(),
307 },
308 Self::Removal(error) => CreateKind::Removal(error),
309 Self::Release(state) => CreateKind::Release {
310 primary: state.primary(),
311 cleanup: state.cleanup(),
312 },
313 Self::Capability(error) => CreateKind::Capability(error),
314 Self::Probe(error) => CreateKind::Probe(error),
315 }
316 }
317
318 pub(crate) const fn kernel(op: IoOperation, cause: Kernel) -> Self {
319 Self::Kernel {
320 operation: op,
321 cause,
322 }
323 }
324}
325
326impl From<alloc::Error> for CreateError {
327 fn from(cause: alloc::Error) -> Self {
328 Self::Allocation(cause)
329 }
330}
331
332impl From<alloc::Overflow> for CreateError {
333 fn from(cause: alloc::Overflow) -> Self {
334 Self::Allocation(cause.into())
335 }
336}
337
338impl From<alloc::Exhausted> for CreateError {
339 fn from(cause: alloc::Exhausted) -> Self {
340 Self::Allocation(cause.into())
341 }
342}
343
344impl From<storage::Failure> for CreateError {
345 fn from(error: storage::Failure) -> Self {
346 match error {
347 storage::Failure::Kernel {
348 operation: op,
349 cause,
350 } => Self::Kernel {
351 operation: op,
352 cause,
353 },
354 storage::Failure::Mapping(error) => Self::Mapping(error),
355 storage::Failure::RingLayout(error) => Self::RingLayout(error),
356 storage::Failure::Capability(error) => Self::Capability(error),
357 storage::Failure::Probe(error) => Self::Probe(error),
358 }
359 }
360}
361
362pub type KernelCause = kernel::Diagnostic<indices::SlotIndex>;