1
Fork 0
mirror of https://github.com/RGBCube/superfreq synced 2025-07-27 17:07:44 +00:00

cpu: store governor and available governors

This commit is contained in:
RGBCube 2025-05-21 18:27:09 +03:00
parent d87237165b
commit 961d1dfcd7
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
4 changed files with 61 additions and 56 deletions

View file

@ -12,8 +12,6 @@ pub struct CpuCoreInfo {
pub struct CpuGlobalInfo { pub struct CpuGlobalInfo {
// System-wide CPU settings // System-wide CPU settings
pub current_governor: Option<String>,
pub available_governors: Vec<String>,
pub turbo_status: Option<bool>, // true for enabled, false for disabled pub turbo_status: Option<bool>, // true for enabled, false for disabled
pub epp: Option<String>, // Energy Performance Preference pub epp: Option<String>, // Energy Performance Preference
pub epb: Option<String>, // Energy Performance Bias pub epb: Option<String>, // Energy Performance Bias

View file

@ -11,9 +11,12 @@ pub struct Cpu {
pub has_cpufreq: bool, pub has_cpufreq: bool,
pub frequency_mhz: u64, pub available_governors: Vec<String>,
pub frequency_mhz_minimum: u64, pub governor: Option<String>,
pub frequency_mhz_maximum: u64,
pub frequency_mhz: Option<u64>,
pub frequency_mhz_minimum: Option<u64>,
pub frequency_mhz_maximum: Option<u64>,
pub time_user: u64, pub time_user: u64,
pub time_nice: u64, pub time_nice: u64,
@ -56,9 +59,12 @@ impl Cpu {
number, number,
has_cpufreq: false, has_cpufreq: false,
frequency_mhz: 0, available_governors: Vec::new(),
frequency_mhz_minimum: 0, governor: None,
frequency_mhz_maximum: 0,
frequency_mhz: None,
frequency_mhz_minimum: None,
frequency_mhz_maximum: None,
time_user: 0, time_user: 0,
time_nice: 0, time_nice: 0,
@ -123,7 +129,11 @@ impl Cpu {
self.has_cpufreq = fs::exists(format!("/sys/devices/system/cpu/cpu{number}/cpufreq")); self.has_cpufreq = fs::exists(format!("/sys/devices/system/cpu/cpu{number}/cpufreq"));
self.rescan_times()?; self.rescan_times()?;
if self.has_cpufreq {
self.rescan_governor()?;
self.rescan_frequency()?; self.rescan_frequency()?;
}
Ok(()) Ok(())
} }
@ -189,6 +199,33 @@ impl Cpu {
Ok(()) 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<()> { fn rescan_frequency(&mut self) -> anyhow::Result<()> {
let Self { number, .. } = *self; let Self { number, .. } = *self;
@ -208,32 +245,19 @@ impl Cpu {
.with_context(|| format!("failed to find {self} frequency maximum"))? .with_context(|| format!("failed to find {self} frequency maximum"))?
.with_context(|| format!("failed to parse {self} frequency"))?; .with_context(|| format!("failed to parse {self} frequency"))?;
self.frequency_mhz = frequency_khz / 1000; self.frequency_mhz = Some(frequency_khz / 1000);
self.frequency_mhz_minimum = frequency_khz_minimum / 1000; self.frequency_mhz_minimum = Some(frequency_khz_minimum / 1000);
self.frequency_mhz_maximum = frequency_khz_maximum / 1000; self.frequency_mhz_maximum = Some(frequency_khz_maximum / 1000);
Ok(()) Ok(())
} }
pub fn get_available_governors(&self) -> Vec<String> { pub fn set_governor(&mut self, governor: &str) -> anyhow::Result<()> {
let Self { number, .. } = self; let Self {
number,
let Some(Ok(content)) = fs::read(format!( available_governors: ref governors,
"/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_available_governors" ..
)) else { } = *self;
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();
if !governors if !governors
.iter() .iter()
@ -253,7 +277,11 @@ impl Cpu {
format!( format!(
"this probably means that {self} doesn't exist or doesn't support changing governors" "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<String> { pub fn get_available_epps(&self) -> Vec<String> {
@ -360,7 +388,7 @@ impl Cpu {
format!("this probably means that {self} doesn't exist or doesn't support changing minimum frequency") 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(()) Ok(())
} }
@ -402,7 +430,7 @@ impl Cpu {
format!("this probably means that {self} doesn't exist or doesn't support changing maximum frequency") 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(()) Ok(())
} }

View file

@ -19,7 +19,7 @@ pub fn read(path: impl AsRef<Path>) -> Option<anyhow::Result<String>> {
let path = path.as_ref(); let path = path.as_ref();
match fs::read_to_string(path) { 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, Err(error) if error.kind() == io::ErrorKind::NotFound => None,

View file

@ -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 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 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() { let turbo_status = if turbo_status_path.exists() {
// 0 means turbo enabled, 1 means disabled for intel_pstate // 0 means turbo enabled, 1 means disabled for intel_pstate
read_sysfs_value::<u8>(turbo_status_path) read_sysfs_value::<u8>(turbo_status_path)
@ -325,8 +306,6 @@ pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo {
// Return the constructed CpuGlobalInfo // Return the constructed CpuGlobalInfo
CpuGlobalInfo { CpuGlobalInfo {
current_governor,
available_governors,
turbo_status, turbo_status,
epp: energy_perf_pref, epp: energy_perf_pref,
epb: energy_perf_bias, epb: energy_perf_bias,