heim_cpu/sys/windows/
freq.rs1use 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}