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

cpu: store EPP and EPB

This commit is contained in:
RGBCube 2025-05-21 18:43:31 +03:00
parent 961d1dfcd7
commit 99feb831a8
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
2 changed files with 95 additions and 82 deletions

View file

@ -18,6 +18,12 @@ pub struct Cpu {
pub frequency_mhz_minimum: Option<u64>, pub frequency_mhz_minimum: Option<u64>,
pub frequency_mhz_maximum: Option<u64>, pub frequency_mhz_maximum: Option<u64>,
pub available_epps: Vec<String>,
pub epp: Option<String>,
pub available_epbs: Vec<String>,
pub epb: Option<String>,
pub time_user: u64, pub time_user: u64,
pub time_nice: u64, pub time_nice: u64,
pub time_system: u64, pub time_system: u64,
@ -66,6 +72,12 @@ impl Cpu {
frequency_mhz_minimum: None, frequency_mhz_minimum: None,
frequency_mhz_maximum: None, frequency_mhz_maximum: None,
available_epps: Vec::new(),
epp: None,
available_epbs: Vec::new(),
epb: None,
time_user: 0, time_user: 0,
time_nice: 0, time_nice: 0,
time_system: 0, time_system: 0,
@ -133,6 +145,8 @@ impl Cpu {
if self.has_cpufreq { if self.has_cpufreq {
self.rescan_governor()?; self.rescan_governor()?;
self.rescan_frequency()?; self.rescan_frequency()?;
self.rescan_epp()?;
self.rescan_epb()?;
} }
Ok(()) Ok(())
@ -252,6 +266,75 @@ impl Cpu {
Ok(()) Ok(())
} }
fn rescan_epp(&mut self) -> anyhow::Result<()> {
let Self { number, .. } = self;
self.available_epps = 'available_epps: {
let Some(Ok(content)) = fs::read(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/energy_performance_available_preferences"
)) else {
break 'available_epps Vec::new();
};
content
.split_whitespace()
.map(ToString::to_string)
.collect()
};
self.epp = Some(
fs::read(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/energy_performance_preference"
))
.with_context(|| format!("failed to find {self} EPP"))?
.with_context(|| format!("failed to read {self} EPP"))?,
);
Ok(())
}
fn rescan_epb(&mut self) -> anyhow::Result<()> {
let Self { number, .. } = self;
self.available_epbs = if self.has_cpufreq {
vec![
"1".to_owned(),
"2".to_owned(),
"3".to_owned(),
"4".to_owned(),
"5".to_owned(),
"6".to_owned(),
"7".to_owned(),
"8".to_owned(),
"9".to_owned(),
"10".to_owned(),
"11".to_owned(),
"12".to_owned(),
"13".to_owned(),
"14".to_owned(),
"15".to_owned(),
"performance".to_owned(),
"balance-performance".to_owned(),
"balance_performance".to_owned(), // Alternative form with underscore.
"balance-power".to_owned(),
"balance_power".to_owned(), // Alternative form with underscore.
"power".to_owned(),
]
} else {
Vec::new()
};
self.epb = Some(
fs::read(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/energy_performance_bias"
))
.with_context(|| format!("failed to find {self} EPB"))?
.with_context(|| format!("failed to read {self} EPB"))?,
);
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,
@ -284,25 +367,12 @@ impl Cpu {
Ok(()) Ok(())
} }
pub fn get_available_epps(&self) -> Vec<String> { pub fn set_epp(&mut self, epp: &str) -> anyhow::Result<()> {
let Self { number, .. } = self; let Self {
number,
let Some(Ok(content)) = fs::read(format!( available_epps: ref epps,
"/sys/devices/system/cpu/cpu{number}/cpufreq/energy_performance_available_preferences" ..
)) else { } = *self;
return Vec::new();
};
content
.split_whitespace()
.map(ToString::to_string)
.collect()
}
pub fn set_epp(&self, epp: &str) -> anyhow::Result<()> {
let Self { number, .. } = self;
let epps = self.get_available_epps();
if !epps.iter().any(|avail_epp| avail_epp == epp) { if !epps.iter().any(|avail_epp| avail_epp == epp) {
bail!( bail!(
@ -320,42 +390,14 @@ impl Cpu {
}) })
} }
pub fn get_available_epbs(&self) -> &'static [&'static str] {
if !self.has_cpufreq {
return &[];
}
&[
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"performance",
"balance-performance",
"balance_performance", // Alternative form with underscore.
"balance-power",
"balance_power", // Alternative form with underscore.
"power",
]
}
pub fn set_epb(&self, epb: &str) -> anyhow::Result<()> { pub fn set_epb(&self, epb: &str) -> anyhow::Result<()> {
let Self { number, .. } = self; let Self {
number,
available_epbs: ref epbs,
..
} = *self;
let epbs = self.get_available_epbs(); if !epbs.iter().any(|avail_epb| avail_epb == epb) {
if !epbs.contains(&epb) {
bail!( bail!(
"EPB value '{epb}' is not available for {self}. available EPB values: {valid}", "EPB value '{epb}' is not available for {self}. available EPB values: {valid}",
valid = epbs.join(", "), valid = epbs.join(", "),

View file

@ -238,25 +238,6 @@ pub fn get_all_cpu_core_info() -> anyhow::Result<Vec<CpuCoreInfo>> {
} }
pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo { pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo {
// Find a valid CPU to read global settings from
// Try cpu0 first, then fall back to any available CPU with cpufreq
let mut cpufreq_base_path_buf = PathBuf::from("/sys/devices/system/cpu/cpu0/cpufreq/");
if !cpufreq_base_path_buf.exists() {
let core_count = get_real_cpus().unwrap_or_else(|e| {
eprintln!("Warning: {e}");
0
});
for i in 0..core_count {
let test_path = PathBuf::from(format!("/sys/devices/system/cpu/cpu{i}/cpufreq/"));
if test_path.exists() {
cpufreq_base_path_buf = test_path;
break; // Exit the loop as soon as we find a valid path
}
}
}
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");
@ -272,14 +253,6 @@ pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo {
None None
}; };
// EPP (Energy Performance Preference)
let energy_perf_pref =
read_sysfs_file_trimmed(cpufreq_base_path_buf.join("energy_performance_preference")).ok();
// EPB (Energy Performance Bias)
let energy_perf_bias =
read_sysfs_file_trimmed(cpufreq_base_path_buf.join("energy_performance_bias")).ok();
let platform_profile = read_sysfs_file_trimmed("/sys/firmware/acpi/platform_profile").ok(); let platform_profile = read_sysfs_file_trimmed("/sys/firmware/acpi/platform_profile").ok();
// Calculate average CPU temperature from the core temperatures // Calculate average CPU temperature from the core temperatures
@ -307,8 +280,6 @@ pub fn get_cpu_global_info(cpu_cores: &[CpuCoreInfo]) -> CpuGlobalInfo {
// Return the constructed CpuGlobalInfo // Return the constructed CpuGlobalInfo
CpuGlobalInfo { CpuGlobalInfo {
turbo_status, turbo_status,
epp: energy_perf_pref,
epb: energy_perf_bias,
platform_profile, platform_profile,
average_temperature_celsius, average_temperature_celsius,
} }