monoio/utils/
uring_detect.rs

1//! Detect if current platform support io_uring.
2
3#[cfg(all(target_os = "linux", feature = "iouring"))]
4macro_rules! err_to_false {
5    ($e: expr) => {
6        match $e {
7            Ok(x) => x,
8            Err(_) => {
9                return false;
10            }
11        }
12    };
13}
14#[cfg(all(target_os = "linux", feature = "iouring"))]
15fn detect_uring_inner() -> bool {
16    let val = std::env::var("MONOIO_FORCE_LEGACY_DRIVER");
17    match val {
18        Ok(v) if matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes") => {
19            return false;
20        }
21        _ => {}
22    }
23
24    use io_uring::opcode::*;
25    auto_const_array::auto_const_array! {
26        const USED_OP: [u8; _] = [
27            Accept::CODE,
28            AsyncCancel::CODE,
29            Close::CODE,
30            Connect::CODE,
31            Fsync::CODE,
32            #[cfg(feature = "mkdirat")]
33            MkDirAt::CODE,
34            OpenAt::CODE,
35            PollAdd::CODE,
36            ProvideBuffers::CODE,
37            Read::CODE,
38            Readv::CODE,
39            Recv::CODE,
40            #[cfg(feature = "renameat")]
41            RenameAt::CODE,
42            Send::CODE,
43            SendMsg::CODE,
44            RecvMsg::CODE,
45            #[cfg(feature = "splice")]
46            Splice::CODE,
47            Statx::CODE,
48            #[cfg(feature = "symlinkat")]
49            SymlinkAt::CODE,
50            Timeout::CODE,
51            #[cfg(feature = "unlinkat")]
52            UnlinkAt::CODE,
53            Write::CODE,
54            Writev::CODE,
55        ];
56    }
57
58    let uring = err_to_false!(io_uring::IoUring::new(2));
59    let mut probe = io_uring::Probe::new();
60    err_to_false!(uring.submitter().register_probe(&mut probe));
61    USED_OP.iter().all(|op| probe.is_supported(*op))
62}
63
64/// Detect if current platform supports our needed uring ops.
65#[cfg(all(target_os = "linux", feature = "iouring"))]
66pub fn detect_uring() -> bool {
67    static mut URING_SUPPORTED: bool = false;
68    static INIT: std::sync::Once = std::sync::Once::new();
69
70    unsafe {
71        INIT.call_once(|| {
72            URING_SUPPORTED = detect_uring_inner();
73        });
74        URING_SUPPORTED
75    }
76}
77
78/// Detect if current platform supports our needed uring ops.
79#[cfg(not(all(target_os = "linux", feature = "iouring")))]
80pub fn detect_uring() -> bool {
81    false
82}
83
84#[cfg(test)]
85mod tests {
86    #[cfg(all(target_os = "linux", feature = "iouring"))]
87    #[test]
88    fn test_detect() {
89        assert!(
90            super::detect_uring(),
91            "io_uring or ops not supported on current platform"
92        )
93    }
94}