From ee7ea6b86dd46a616f58aa2e5cfc926f7d7d872e Mon Sep 17 00:00:00 2001 From: RGBCube Date: Wed, 4 Jun 2025 18:51:27 +0300 Subject: [PATCH] cpu: add cpu info scanning --- src/cpu.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++- src/monitor.rs | 31 --------------------------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index 7a60ee3..70918be 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,13 +1,14 @@ use anyhow::{Context, bail}; 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; #[derive(Default, Debug, Clone, PartialEq)] pub struct CpuRescanCache { stat: OnceCell>, + info: OnceCell>>>, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -63,6 +64,7 @@ pub struct Cpu { pub epb: Option, pub stat: CpuStat, + pub info: Option>>, pub temperature: Option, } @@ -104,6 +106,7 @@ impl Cpu { softirq: 0, steal: 0, }, + info: None, temperature: None, }; @@ -171,6 +174,7 @@ impl Cpu { } self.rescan_stat(cache)?; + self.rescan_info(cache)?; Ok(()) } @@ -345,6 +349,57 @@ impl Cpu { 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::>(); + + if parts.len() == 2 { + let key = parts[0].trim(); + let value = parts[1].trim(); + + if key == "processor" { + try_save_data!(); + + current_number = value.parse::().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<()> { let Self { number, diff --git a/src/monitor.rs b/src/monitor.rs index 40b0242..e4ff659 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -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 // if temperature_celsius.is_none() { // 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 { - 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(), - )) -}