Skip to main content

dope_core/driver/
ext.rs

1use std::io;
2
3use super::{Config, Driver};
4
5pub trait DriverExt: Sized {
6    fn new(cfg: Config) -> io::Result<Self>;
7    fn init_thread(cpu_id: u16) -> io::Result<()>;
8    fn allowed_cpus() -> io::Result<Vec<u16>>;
9}
10
11cfg_select! {
12    target_os = "linux" => {
13        use std::io::{Error, ErrorKind};
14        use std::mem;
15
16        use crate::backend::uring::driver::Uring;
17
18        impl DriverExt for Driver {
19            fn new(cfg: Config) -> io::Result<Self> {
20                cfg.validate()?;
21                let (state, slots) = Uring::new(&cfg)?;
22                Driver::from_state(
23                    state,
24                    slots,
25                    cfg.ready_slots,
26                    cfg.provided.entries as usize,
27                )
28            }
29
30            fn init_thread(cpu_id: u16) -> io::Result<()> {
31                if cpu_id >= libc::CPU_SETSIZE as u16 {
32                    return Err(Error::new(
33                        ErrorKind::InvalidInput,
34                        "dope: cpu index exceeds CPU_SETSIZE",
35                    ));
36                }
37                let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
38                unsafe {
39                    libc::CPU_ZERO(&mut set);
40                    libc::CPU_SET(cpu_id as usize, &mut set);
41                }
42                let rc = unsafe { libc::sched_setaffinity(0, size_of::<libc::cpu_set_t>(), &set) };
43                if rc != 0 {
44                    Err(Error::last_os_error())
45                } else {
46                    Ok(())
47                }
48            }
49
50            fn allowed_cpus() -> io::Result<Vec<u16>> {
51                let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
52                let rc = unsafe { libc::sched_getaffinity(0, size_of::<libc::cpu_set_t>(), &mut set) };
53                if rc != 0 {
54                    return Err(Error::last_os_error());
55                }
56                let mut cpus = Vec::new();
57                for cpu in 0..libc::CPU_SETSIZE as usize {
58                    if unsafe { libc::CPU_ISSET(cpu, &set) } {
59                        cpus.push(cpu as u16);
60                    }
61                }
62                Ok(cpus)
63            }
64        }
65    }
66    _ => {
67        use std::io::{Error, ErrorKind};
68
69        use crate::backend::kqueue::driver::Kqueue;
70
71        impl DriverExt for Driver {
72            fn new(cfg: Config) -> io::Result<Self> {
73                cfg.validate()?;
74                let (state, slots) = Kqueue::new(&cfg)?;
75                Driver::from_state(
76                    state,
77                    slots,
78                    cfg.ready_slots,
79                    cfg.provided.entries as usize,
80                )
81            }
82
83            fn init_thread(cpu_id: u16) -> io::Result<()> {
84                let _ = cpu_id;
85                Err(Error::new(
86                    ErrorKind::Unsupported,
87                    "dope: hard CPU affinity is unavailable on this target",
88                ))
89            }
90
91            fn allowed_cpus() -> io::Result<Vec<u16>> {
92                Err(Error::new(
93                    ErrorKind::Unsupported,
94                    "dope: CPU affinity discovery is unavailable on this target",
95                ))
96            }
97        }
98    }
99}