mirror of
https://github.com/RGBCube/superfreq
synced 2025-07-27 17:07:44 +00:00
cpu: add cpu info scanning
This commit is contained in:
parent
303a84479c
commit
ee7ea6b86d
2 changed files with 56 additions and 32 deletions
57
src/cpu.rs
57
src/cpu.rs
|
@ -1,13 +1,14 @@
|
||||||
use anyhow::{Context, bail};
|
use anyhow::{Context, bail};
|
||||||
use yansi::Paint as _;
|
use yansi::Paint as _;
|
||||||
|
|
||||||
use std::{cell::OnceCell, collections::HashMap, fmt, string::ToString};
|
use std::{cell::OnceCell, collections::HashMap, fmt, mem, rc::Rc, string::ToString};
|
||||||
|
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq)]
|
#[derive(Default, Debug, Clone, PartialEq)]
|
||||||
pub struct CpuRescanCache {
|
pub struct CpuRescanCache {
|
||||||
stat: OnceCell<HashMap<u32, CpuStat>>,
|
stat: OnceCell<HashMap<u32, CpuStat>>,
|
||||||
|
info: OnceCell<HashMap<u32, Rc<HashMap<String, String>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -63,6 +64,7 @@ pub struct Cpu {
|
||||||
pub epb: Option<String>,
|
pub epb: Option<String>,
|
||||||
|
|
||||||
pub stat: CpuStat,
|
pub stat: CpuStat,
|
||||||
|
pub info: Option<Rc<HashMap<String, String>>>,
|
||||||
|
|
||||||
pub temperature: Option<f64>,
|
pub temperature: Option<f64>,
|
||||||
}
|
}
|
||||||
|
@ -104,6 +106,7 @@ impl Cpu {
|
||||||
softirq: 0,
|
softirq: 0,
|
||||||
steal: 0,
|
steal: 0,
|
||||||
},
|
},
|
||||||
|
info: None,
|
||||||
|
|
||||||
temperature: None,
|
temperature: None,
|
||||||
};
|
};
|
||||||
|
@ -171,6 +174,7 @@ impl Cpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.rescan_stat(cache)?;
|
self.rescan_stat(cache)?;
|
||||||
|
self.rescan_info(cache)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -345,6 +349,57 @@ impl Cpu {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rescan_info(&mut self, cache: &CpuRescanCache) -> anyhow::Result<()> {
|
||||||
|
// OnceCell::get_or_try_init is unstable. Cope:
|
||||||
|
let info = match cache.info.get() {
|
||||||
|
Some(stat) => stat,
|
||||||
|
|
||||||
|
None => {
|
||||||
|
let content = fs::read("/proc/cpuinfo")
|
||||||
|
.context("failed to read CPU info")?
|
||||||
|
.context("/proc/cpuinfo does not exist")?;
|
||||||
|
|
||||||
|
let mut info = HashMap::new();
|
||||||
|
let mut current_number = None;
|
||||||
|
let mut current_data = HashMap::new();
|
||||||
|
|
||||||
|
macro_rules! try_save_data {
|
||||||
|
() => {
|
||||||
|
if let Some(number) = current_number.take() {
|
||||||
|
info.insert(number, Rc::new(mem::take(&mut current_data)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for line in content.lines() {
|
||||||
|
let parts = line.splitn(2, ':').collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if parts.len() == 2 {
|
||||||
|
let key = parts[0].trim();
|
||||||
|
let value = parts[1].trim();
|
||||||
|
|
||||||
|
if key == "processor" {
|
||||||
|
try_save_data!();
|
||||||
|
|
||||||
|
current_number = value.parse::<u32>().ok();
|
||||||
|
} else {
|
||||||
|
current_data.insert(key.to_owned(), value.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try_save_data!();
|
||||||
|
|
||||||
|
cache.info.set(info).unwrap();
|
||||||
|
cache.info.get().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.info = info.get(&self.number).cloned();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_governor(&mut self, governor: &str) -> anyhow::Result<()> {
|
pub fn set_governor(&mut self, governor: &str) -> anyhow::Result<()> {
|
||||||
let Self {
|
let Self {
|
||||||
number,
|
number,
|
||||||
|
|
|
@ -1,15 +1,3 @@
|
||||||
use crate::config::AppConfig;
|
|
||||||
use crate::core::{BatteryInfo, CpuCoreInfo, CpuGlobalInfo, SystemInfo, SystemLoad, SystemReport};
|
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
str::FromStr,
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
time::SystemTime,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try /sys/devices/platform paths for thermal zones as a last resort
|
// Try /sys/devices/platform paths for thermal zones as a last resort
|
||||||
// if temperature_celsius.is_none() {
|
// if temperature_celsius.is_none() {
|
||||||
// if let Ok(thermal_zones) = fs::read_dir("/sys/devices/virtual/thermal") {
|
// if let Ok(thermal_zones) = fs::read_dir("/sys/devices/virtual/thermal") {
|
||||||
|
@ -34,22 +22,3 @@ use std::{
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn get_cpu_model() -> anyhow::Result<String> {
|
|
||||||
let path = Path::new("/proc/cpuinfo");
|
|
||||||
let content = fs::read_to_string(path).map_err(|_| {
|
|
||||||
SysMonitorError::ReadError(format!("Cannot read contents of {}.", path.display()))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for line in content.lines() {
|
|
||||||
if line.starts_with("model name") {
|
|
||||||
if let Some(val) = line.split(':').nth(1) {
|
|
||||||
let cpu_model = val.trim().to_string();
|
|
||||||
return Ok(cpu_model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(SysMonitorError::ParseError(
|
|
||||||
"Could not find CPU model name in /proc/cpuinfo.".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue