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}