summaryrefslogtreecommitdiff
path: root/src/energy/trackers/kernel.rs
blob: 8ce84692d2e2147bd7760757827bde74c3a77eb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use iocuddle::*;
use std::fs::File;
use std::path::Path;

use crate::energy::Estimator;

#[derive(Debug)]
pub struct KernelDriver {
    file: File,
}

impl Default for KernelDriver {
    fn default() -> Self {
        KernelDriver::new("/dev/rust-pow")
            .unwrap_or_else(|_| panic!("Failed to open kernel driver. Is the module loaded?"))
    }
}

impl KernelDriver {
    pub fn new(path: impl AsRef<Path>) -> Result<Self, std::io::Error> {
        let file = File::open(path)?;
        Ok(Self { file })
    }
}

const PERF_MON: Group = Group::new(b'|');
const START_TRACE: Ioctl<Write, &u64> = unsafe { PERF_MON.write(0x80) };
const STOP_TRACE: Ioctl<Write, &u64> = unsafe { PERF_MON.write(0x81) };
const READ_POWER: Ioctl<WriteRead, &u64> = unsafe { PERF_MON.write_read(0x82) };

impl Estimator for KernelDriver {
    fn start_trace(&mut self, pid: u64, _cpu: i32) -> Result<(), ()> {
        let _ = START_TRACE.ioctl(&mut self.file, &pid);
        Ok(())
    }

    fn stop_trace(&mut self, pid: u64) {
        let _ = STOP_TRACE.ioctl(&mut self.file, &pid);
    }

    fn update_information(&mut self, _pid: u64, _cpu: i32) {}

    fn read_consumption(&mut self, pid: u64) -> Option<f64> {
        let mut arg = pid;
        if READ_POWER.ioctl(&mut self.file, &mut arg).is_ok() {
            Some(arg as f64)
        } else {
            None
        }
    }
}