heim_cpu/sys/windows/
freq.rs

1use std::mem;
2use std::ptr;
3
4use winapi::shared::{minwindef, ntstatus};
5use winapi::um::{powerbase, winnt};
6
7use heim_common::prelude::*;
8use heim_common::units::{frequency, Frequency};
9
10use super::bindings::get_system_info;
11use super::bindings::power::PROCESSOR_POWER_INFORMATION;
12
13#[derive(Debug)]
14pub struct CpuFrequency(PROCESSOR_POWER_INFORMATION);
15
16impl CpuFrequency {
17    pub fn current(&self) -> Frequency {
18        Frequency::new::<frequency::megahertz>(self.0.CurrentMhz.into())
19    }
20
21    pub fn max(&self) -> Option<Frequency> {
22        Some(Frequency::new::<frequency::megahertz>(self.0.MaxMhz.into()))
23    }
24
25    pub fn min(&self) -> Option<Frequency> {
26        None
27    }
28}
29
30unsafe fn get_processors() -> Result<Vec<PROCESSOR_POWER_INFORMATION>> {
31    let info = get_system_info();
32    if info.dwNumberOfProcessors == 0 {
33        return Err(Error::incompatible("No processors was found"));
34    }
35
36    let proc_amount = info.dwNumberOfProcessors as usize;
37    let mut processors = Vec::<PROCESSOR_POWER_INFORMATION>::with_capacity(proc_amount);
38    let buffer_length = proc_amount * mem::size_of::<PROCESSOR_POWER_INFORMATION>();
39
40    let result = powerbase::CallNtPowerInformation(
41        winnt::ProcessorInformation,
42        ptr::null_mut(),
43        0,
44        processors.as_mut_ptr() as *mut _,
45        buffer_length as minwindef::ULONG,
46    );
47
48    if result == ntstatus::STATUS_SUCCESS {
49        processors.set_len(proc_amount);
50
51        Ok(processors)
52    } else {
53        Err(Error::last_os_error())
54    }
55}
56
57pub fn frequency() -> impl Future<Output = Result<CpuFrequency>> {
58    match unsafe { get_processors() } {
59        Ok(processors) => {
60            let freq = processors
61                .into_iter()
62                .next()
63                .map(CpuFrequency)
64                .ok_or_else(|| Error::incompatible("No processors was found"));
65
66            future::ready(freq)
67        }
68        Err(e) => future::err(e),
69    }
70}