From 961d1dfcd76c4db534aae65e6bd5338543e1865b Mon Sep 17 00:00:00 2001 From: RGBCube Date: Wed, 21 May 2025 18:27:09 +0300 Subject: [PATCH] cpu: store governor and available governors --- src/core.rs | 2 -- src/cpu.rs | 92 ++++++++++++++++++++++++++++++++------------------ src/fs.rs | 2 +- src/monitor.rs | 21 ------------ 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/core.rs b/src/core.rs index 84f1886..38c3d0c 100644 --- a/src/core.rs +++ b/src/core.rs @@ -12,8 +12,6 @@ pub struct CpuCoreInfo { pub struct CpuGlobalInfo { // System-wide CPU settings - pub current_governor: Option, - pub available_governors: Vec, pub turbo_status: Option, // true for enabled, false for disabled pub epp: Option, // Energy Performance Preference pub epb: Option, // Energy Performance Bias diff --git a/src/cpu.rs b/src/cpu.rs index 9941020..7365940 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -11,9 +11,12 @@ pub struct Cpu { pub has_cpufreq: bool, - pub frequency_mhz: u64, - pub frequency_mhz_minimum: u64, - pub frequency_mhz_maximum: u64, + pub available_governors: Vec, + pub governor: Option, + + pub frequency_mhz: Option, + pub frequency_mhz_minimum: Option, + pub frequency_mhz_maximum: Option, pub time_user: u64, pub time_nice: u64, @@ -56,9 +59,12 @@ impl Cpu { number, has_cpufreq: false, - frequency_mhz: 0, - frequency_mhz_minimum: 0, - frequency_mhz_maximum: 0, + available_governors: Vec::new(), + governor: None, + + frequency_mhz: None, + frequency_mhz_minimum: None, + frequency_mhz_maximum: None, time_user: 0, time_nice: 0, @@ -123,7 +129,11 @@ impl Cpu { self.has_cpufreq = fs::exists(format!("/sys/devices/system/cpu/cpu{number}/cpufreq")); self.rescan_times()?; - self.rescan_frequency()?; + + if self.has_cpufreq { + self.rescan_governor()?; + self.rescan_frequency()?; + } Ok(()) } @@ -189,6 +199,33 @@ impl Cpu { Ok(()) } + fn rescan_governor(&mut self) -> anyhow::Result<()> { + let Self { number, .. } = *self; + + self.available_governors = 'available_governors: { + let Some(Ok(content)) = fs::read(format!( + "/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_available_governors" + )) else { + break 'available_governors Vec::new(); + }; + + content + .split_whitespace() + .map(ToString::to_string) + .collect() + }; + + self.governor = Some( + fs::read(format!( + "/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_governor" + )) + .with_context(|| format!("failed to find {self} scaling governor"))? + .with_context(|| format!("failed to read {self} scaling governor"))?, + ); + + Ok(()) + } + fn rescan_frequency(&mut self) -> anyhow::Result<()> { let Self { number, .. } = *self; @@ -208,32 +245,19 @@ impl Cpu { .with_context(|| format!("failed to find {self} frequency maximum"))? .with_context(|| format!("failed to parse {self} frequency"))?; - self.frequency_mhz = frequency_khz / 1000; - self.frequency_mhz_minimum = frequency_khz_minimum / 1000; - self.frequency_mhz_maximum = frequency_khz_maximum / 1000; + self.frequency_mhz = Some(frequency_khz / 1000); + self.frequency_mhz_minimum = Some(frequency_khz_minimum / 1000); + self.frequency_mhz_maximum = Some(frequency_khz_maximum / 1000); Ok(()) } - pub fn get_available_governors(&self) -> Vec { - let Self { number, .. } = self; - - let Some(Ok(content)) = fs::read(format!( - "/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_available_governors" - )) else { - return Vec::new(); - }; - - content - .split_whitespace() - .map(ToString::to_string) - .collect() - } - - pub fn set_governor(&self, governor: &str) -> anyhow::Result<()> { - let Self { number, .. } = self; - - let governors = self.get_available_governors(); + pub fn set_governor(&mut self, governor: &str) -> anyhow::Result<()> { + let Self { + number, + available_governors: ref governors, + .. + } = *self; if !governors .iter() @@ -253,7 +277,11 @@ impl Cpu { format!( "this probably means that {self} doesn't exist or doesn't support changing governors" ) - }) + })?; + + self.governor = Some(governor.to_owned()); + + Ok(()) } pub fn get_available_epps(&self) -> Vec { @@ -360,7 +388,7 @@ impl Cpu { format!("this probably means that {self} doesn't exist or doesn't support changing minimum frequency") })?; - self.frequency_mhz_minimum = frequency_mhz; + self.frequency_mhz_minimum = Some(frequency_mhz); Ok(()) } @@ -402,7 +430,7 @@ impl Cpu { format!("this probably means that {self} doesn't exist or doesn't support changing maximum frequency") })?; - self.frequency_mhz_maximum = frequency_mhz; + self.frequency_mhz_maximum = Some(frequency_mhz); Ok(()) } diff --git a/src/fs.rs b/src/fs.rs index 9b150b3..4c11178 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -19,7 +19,7 @@ pub fn read(path: impl AsRef) -> Option> { let path = path.as_ref(); match fs::read_to_string(path) { - Ok(string) => Some(Ok(string)), + Ok(string) => Some(Ok(string.trim().to_owned())), Err(error) if error.kind() == io::ErrorKind::NotFound => None, diff --git a/src/monitor.rs b/src/monitor.rs index 9f0c972..44a7146 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -260,25 +260,6 @@ pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo { let turbo_status_path = Path::new("/sys/devices/system/cpu/intel_pstate/no_turbo"); let boost_path = Path::new("/sys/devices/system/cpu/cpufreq/boost"); - let current_governor = if cpufreq_base_path_buf.join("scaling_governor").exists() { - read_sysfs_file_trimmed(cpufreq_base_path_buf.join("scaling_governor")).ok() - } else { - None - }; - - let available_governors = if cpufreq_base_path_buf - .join("scaling_available_governors") - .exists() - { - read_sysfs_file_trimmed(cpufreq_base_path_buf.join("scaling_available_governors")) - .map_or_else( - |_| vec![], - |s| s.split_whitespace().map(String::from).collect(), - ) - } else { - vec![] - }; - let turbo_status = if turbo_status_path.exists() { // 0 means turbo enabled, 1 means disabled for intel_pstate read_sysfs_value::(turbo_status_path) @@ -325,8 +306,6 @@ pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo { // Return the constructed CpuGlobalInfo CpuGlobalInfo { - current_governor, - available_governors, turbo_status, epp: energy_perf_pref, epb: energy_perf_bias,