use iocuddle::*; use rand::Rng; pub mod perf; pub trait KernelModule { fn start_trace(&mut self, _pid: u64) {} fn stop_trace(&mut self, _pid: u64) {} fn read_consumption(&mut self, pid: u64) -> u64; } #[derive(Default)] pub struct MockModule; impl KernelModule for MockModule { fn start_trace(&mut self, pid: u64) { // println!("starting trace of {pid}"); } fn stop_trace(&mut self, pid: u64) { // println!("stopping trace of {pid}"); } fn read_consumption(&mut self, _pid: u64) -> u64 { // rand::rng().random() 14 } } #[derive(Debug)] pub struct KernelDriver { file: std::fs::File, } impl Default for KernelDriver { fn default() -> Self { KernelDriver::new("/dev/rust-pow").unwrap() } } impl KernelDriver { fn new(path: impl AsRef) -> Result { let file = std::fs::File::open(path)?; Ok(Self { file }) } } const PERF_MON: Group = Group::new(b'|'); const START_TRACE: Ioctl = unsafe { PERF_MON.write(0x80) }; const STOP_TRACE: Ioctl = unsafe { PERF_MON.write(0x81) }; const READ_POWER: Ioctl = unsafe { PERF_MON.write_read(0x82) }; impl KernelModule for KernelDriver { fn start_trace(&mut self, pid: u64) { START_TRACE.ioctl(&mut self.file, &pid).unwrap(); } fn stop_trace(&mut self, pid: u64) { STOP_TRACE.ioctl(&mut self.file, &pid).unwrap(); } fn read_consumption(&mut self, pid: u64) -> u64 { let mut arg = pid; READ_POWER.ioctl(&mut self.file, &mut arg).unwrap(); arg } }