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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#[derive(Clone, Debug)]
pub struct CpuFreqs {
pub min: Option<f32>,
pub max: Option<f32>,
pub cur: Option<f32>,
}
pub fn get() -> Vec<CpuFreqs> {
get_cpu_freqs()
}
#[cfg(target_os = "linux")]
fn get_cpu_freqs() -> Vec<CpuFreqs> {
use std::fs;
use std::path::Path;
fn get_path(num: usize) -> Option<String> {
let policy_path = format!("/sys/devices/system/cpu/cpufreq/policy{}", num);
let cpu_path = format!("/sys/devices/system/cpu/cpu{}/cpufreq", num);
let base_path = match (
Path::new(&policy_path).exists(),
Path::new(&cpu_path).exists(),
) {
(true, true) => Some(cpu_path),
(true, false) => Some(policy_path),
(false, true) => Some(cpu_path),
(false, false) => None,
};
base_path
}
fn get_measurement(cpu: usize, measurement_file: &str) -> Option<f32> {
let base_path = get_path(cpu);
match base_path {
Some(path) => {
let val_ = fs::read_to_string(Path::new(&path).join(measurement_file));
let val = match val_ {
Ok(val) => Some(val.trim().parse::<f32>().unwrap() / 1000.0),
Err(_) => None,
};
val
}
None => None,
}
}
let mut res: Vec<CpuFreqs> = vec![];
let num_cpus = num_cpus::get();
if Path::new("/sys/devices/system/cpu/cpufreq").exists()
|| Path::new("/sys/devices/system/cpu/cpu0/cpufreq").exists()
{
for cpu in 0..num_cpus {
let min = get_measurement(cpu, "scaling_min_freq");
let max = get_measurement(cpu, "scaling_max_freq");
let cur = get_measurement(cpu, "scaling_cur_freq");
let r = CpuFreqs {
min: min,
max: max,
cur: cur,
};
res.push(r);
}
} else {
let data = fs::read_to_string("/proc/cpuinfo");
match data {
Ok(data) => {
for line in data.lines() {
if line.to_lowercase().starts_with("cpu mhz") {
let fields: Vec<&str> = line.split_whitespace().collect();
let cur = Some(fields[3].parse::<f32>().unwrap());
res.push(CpuFreqs {
cur: cur,
min: None,
max: None,
})
}
}
}
Err(_) => (),
}
}
res
}
#[cfg(not(target_os = "linux"))]
fn get_cpu_freqs() -> Vec<CpuFreqs> {
unimplemented!("cpu-freq is not yet supported on this system")
}
#[cfg(test)]
mod tests {
use super::get;
#[test]
fn test_cpu_freq() {
get().iter().for_each(|x| assert!(x.cur > Some(0.0)));
}
}