Skip to main content

compio_driver/sys/driver/
mod.rs

1use std::sync::atomic::{AtomicU8, Ordering};
2
3cfg_select! {
4    windows => {
5        mod iocp;
6        pub use iocp::*;
7    }
8    fusion => {
9        mod fusion;
10        mod poll;
11        mod iour;
12        pub use fusion::*;
13    }
14    io_uring => {
15        mod iour;
16        pub use iour::*;
17    }
18    stub => {
19        mod stub;
20        pub use stub::*;
21    }
22    unix => {
23        mod poll;
24        pub use poll::*;
25    }
26    _ => {}
27}
28
29crate::assert_not_impl!(Driver, Send);
30crate::assert_not_impl!(Driver, Sync);
31
32/// An operation that can be optimized by making use of the "poll-first"
33/// feature.
34///
35/// By setting this, `io_uring` will assume the socket is currently empty and
36/// attempting to receive data will be unsuccessful. For this case, `io_uring`
37/// will arm internal poll and trigger a receive of the data when the socket has
38/// data to be read. This initial receive attempt can be wasteful for the case
39/// where the socket is expected to be empty, setting this flag will bypass the
40/// initial receive attempt and go straight to arming poll. If poll does
41/// indicate that data is ready to be received, the operation will proceed.
42pub trait PollFirst {
43    /// Poll first before syscall. This is only meaningful for io-uring. It sets
44    /// `IORING_RECVSEND_POLL_FIRST` flag in the `ioprio` of the SQE.
45    fn poll_first(&mut self);
46}
47
48const IDLE: u8 = 0b00;
49const NOTIFIED: u8 = 0b01;
50const AWAKE: u8 = 0b10;
51
52#[derive(Debug)]
53struct AwakeFlag(AtomicU8);
54
55impl AwakeFlag {
56    pub fn new() -> Self {
57        Self(AtomicU8::new(IDLE))
58    }
59
60    /// Mark the driver as awake by overwriting the flag byte with `AWAKE`.
61    /// This intentionally clears any previously set `NOTIFIED` flag.
62    pub fn set(&self) {
63        self.0.store(AWAKE, Ordering::Release);
64    }
65
66    /// Reset the flags. Returns true if it was notified.
67    pub fn reset(&self) -> bool {
68        (self.0.swap(IDLE, Ordering::AcqRel) & NOTIFIED) != 0
69    }
70
71    /// Set the notified flag. Returns true if the awake flag is set or the
72    /// notified flag is set. If the awake flag is not set, the driver needs
73    /// to be notified through a syscall.
74    pub fn wake(&self) -> bool {
75        self.0.fetch_or(NOTIFIED, Ordering::AcqRel) != 0
76    }
77}