1
Fork 0
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:
RGBCube 2025-06-04 18:51:27 +03:00
parent 303a84479c
commit ee7ea6b86d
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
2 changed files with 56 additions and 32 deletions

View file

@ -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,

View file

@ -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(),
))
}