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

cpu: cleanup

This commit is contained in:
Bloxx12 2025-05-13 19:27:24 +02:00
parent c8361f0e26
commit 887544d276
No known key found for this signature in database

View file

@ -1,11 +1,6 @@
use crate::core::TurboSetting; use crate::core::TurboSetting;
use crate::monitor::Result as MonitorResult;
use core::str; use core::str;
use std::{ use std::{fs, io, path::Path, string::ToString};
fs, io,
path::{Path, PathBuf},
string::ToString,
};
#[derive(Debug)] #[derive(Debug)]
pub enum ControlError { pub enum ControlError {
@ -18,10 +13,10 @@ pub enum ControlError {
} }
impl From<io::Error> for ControlError { impl From<io::Error> for ControlError {
fn from(err: io::Error) -> ControlError { fn from(err: io::Error) -> Self {
match err.kind() { match err.kind() {
io::ErrorKind::PermissionDenied => ControlError::PermissionDenied(err.to_string()), io::ErrorKind::PermissionDenied => Self::PermissionDenied(err.to_string()),
_ => ControlError::Io(err), _ => Self::Io(err),
} }
} }
} }
@ -29,18 +24,17 @@ impl From<io::Error> for ControlError {
impl std::fmt::Display for ControlError { impl std::fmt::Display for ControlError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
ControlError::Io(e) => write!(f, "I/O error: {}", e), Self::Io(e) => write!(f, "I/O error: {e}"),
ControlError::WriteError(s) => write!(f, "Failed to write to sysfs path: {}", s), Self::WriteError(s) => write!(f, "Failed to write to sysfs path: {s}"),
ControlError::InvalidValueError(s) => write!(f, "Invalid value for setting: {}", s), Self::InvalidValueError(s) => write!(f, "Invalid value for setting: {s}"),
ControlError::NotSupported(s) => write!(f, "Control action not supported: {}", s), Self::NotSupported(s) => write!(f, "Control action not supported: {s}"),
ControlError::PermissionDenied(s) => { Self::PermissionDenied(s) => {
write!(f, "Permission denied: {}. Try running with sudo.", s) write!(f, "Permission denied: {s}. Try running with sudo.")
} }
ControlError::InvalidProfile(s) => { Self::InvalidProfile(s) => {
write!( write!(
f, f,
"Invalid platform control profile {} supplied, please provide a valid one.", "Invalid platform control profile {s} supplied, please provide a valid one."
s
) )
} }
} }
@ -75,27 +69,41 @@ where
// Let's use a similar discovery to monitor's get_logical_core_count // Let's use a similar discovery to monitor's get_logical_core_count
let mut cores_to_act_on = Vec::new(); let mut cores_to_act_on = Vec::new();
let path = Path::new("/sys/devices/system/cpu"); let path = Path::new("/sys/devices/system/cpu");
if path.exists() { if !path.exists() {
if let Ok(entries) = fs::read_dir(path) { return Err(ControlError::NotSupported(format!(
for entry in entries.flatten() { "No logical cores found at {}.",
let name = entry.file_name(); path.display()
if let Some(name_str) = name.to_str() { )));
if name_str.starts_with("cpu") }
&& name_str.len() > 3
&& name_str[3..].chars().all(char::is_numeric) let entries = fs::read_dir(path)
{ .map_err(|_| {
if entry.path().join("cpufreq").exists() { ControlError::PermissionDenied(format!("Cannot read contents of {}.", path.display()))
if let Ok(core_id) = name_str[3..].parse::<u32>() { })?
cores_to_act_on.push(core_id); .flatten();
}
} for entry in entries {
} let entry_file_name = entry.file_name();
} let Some(name) = entry_file_name.to_str() else {
} continue;
};
// Skip non-CPU directories (e.g., cpuidle, cpufreq)
if !name.starts_with("cpu") || name.len() <= 3 || !name[3..].chars().all(char::is_numeric) {
continue;
}
if !entry.path().join("cpufreq").exists() {
continue;
}
if let Ok(core_id) = name[3..].parse::<u32>() {
cores_to_act_on.push(core_id);
} }
} }
if cores_to_act_on.is_empty() { if cores_to_act_on.is_empty() {
// Fallback if sysfs iteration above fails to find any cpufreq cores // Fallback if sysfs iteration above fails to find any cpufreq cores
#[allow(clippy::cast_possible_truncation)]
let num_cores = num_cpus::get() as u32; let num_cores = num_cpus::get() as u32;
for core_id in 0..num_cores { for core_id in 0..num_cores {
cores_to_act_on.push(core_id); cores_to_act_on.push(core_id);
@ -110,7 +118,7 @@ where
pub fn set_governor(governor: &str, core_id: Option<u32>) -> Result<()> { pub fn set_governor(governor: &str, core_id: Option<u32>) -> Result<()> {
let action = |id: u32| { let action = |id: u32| {
let path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_governor", id); let path = format!("/sys/devices/system/cpu/cpu{id}/cpufreq/scaling_governor");
if Path::new(&path).exists() { if Path::new(&path).exists() {
write_sysfs_value(&path, governor) write_sysfs_value(&path, governor)
} else { } else {
@ -120,11 +128,7 @@ pub fn set_governor(governor: &str, core_id: Option<u32>) -> Result<()> {
} }
}; };
if let Some(id) = core_id { core_id.map_or_else(|| for_each_cpu_core(action), action)
action(id)
} else {
for_each_cpu_core(action)
}
} }
pub fn set_turbo(setting: TurboSetting) -> Result<()> { pub fn set_turbo(setting: TurboSetting) -> Result<()> {
@ -155,76 +159,54 @@ pub fn set_turbo(setting: TurboSetting) -> Result<()> {
pub fn set_epp(epp: &str, core_id: Option<u32>) -> Result<()> { pub fn set_epp(epp: &str, core_id: Option<u32>) -> Result<()> {
let action = |id: u32| { let action = |id: u32| {
let path = format!( let path = format!("/sys/devices/system/cpu/cpu{id}/cpufreq/energy_performance_preference");
"/sys/devices/system/cpu/cpu{}/cpufreq/energy_performance_preference",
id
);
if Path::new(&path).exists() { if Path::new(&path).exists() {
write_sysfs_value(&path, epp) write_sysfs_value(&path, epp)
} else { } else {
Ok(()) Ok(())
} }
}; };
if let Some(id) = core_id { core_id.map_or_else(|| for_each_cpu_core(action), action)
action(id)
} else {
for_each_cpu_core(action)
}
} }
pub fn set_epb(epb: &str, core_id: Option<u32>) -> Result<()> { pub fn set_epb(epb: &str, core_id: Option<u32>) -> Result<()> {
// EPB is often an integer 0-15. Ensure `epb` string is valid if parsing. // EPB is often an integer 0-15. Ensure `epb` string is valid if parsing.
// For now, writing it directly as a string. // For now, writing it directly as a string.
let action = |id: u32| { let action = |id: u32| {
let path = format!( let path = format!("/sys/devices/system/cpu/cpu{id}/cpufreq/energy_performance_bias");
"/sys/devices/system/cpu/cpu{}/cpufreq/energy_performance_bias",
id
);
if Path::new(&path).exists() { if Path::new(&path).exists() {
write_sysfs_value(&path, epb) write_sysfs_value(&path, epb)
} else { } else {
Ok(()) Ok(())
} }
}; };
if let Some(id) = core_id { core_id.map_or_else(|| for_each_cpu_core(action), action)
action(id)
} else {
for_each_cpu_core(action)
}
} }
pub fn set_min_frequency(freq_mhz: u32, core_id: Option<u32>) -> Result<()> { pub fn set_min_frequency(freq_mhz: u32, core_id: Option<u32>) -> Result<()> {
let freq_khz_str = (freq_mhz * 1000).to_string(); let freq_khz_str = (freq_mhz * 1000).to_string();
let action = |id: u32| { let action = |id: u32| {
let path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_min_freq", id); let path = format!("/sys/devices/system/cpu/cpu{id}/cpufreq/scaling_min_freq");
if Path::new(&path).exists() { if Path::new(&path).exists() {
write_sysfs_value(&path, &freq_khz_str) write_sysfs_value(&path, &freq_khz_str)
} else { } else {
Ok(()) Ok(())
} }
}; };
if let Some(id) = core_id { core_id.map_or_else(|| for_each_cpu_core(action), action)
action(id)
} else {
for_each_cpu_core(action)
}
} }
pub fn set_max_frequency(freq_mhz: u32, core_id: Option<u32>) -> Result<()> { pub fn set_max_frequency(freq_mhz: u32, core_id: Option<u32>) -> Result<()> {
let freq_khz_str = (freq_mhz * 1000).to_string(); let freq_khz_str = (freq_mhz * 1000).to_string();
let action = |id: u32| { let action = |id: u32| {
let path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_max_freq", id); let path = format!("/sys/devices/system/cpu/cpu{id}/cpufreq/scaling_max_freq");
if Path::new(&path).exists() { if Path::new(&path).exists() {
write_sysfs_value(&path, &freq_khz_str) write_sysfs_value(&path, &freq_khz_str)
} else { } else {
Ok(()) Ok(())
} }
}; };
if let Some(id) = core_id { core_id.map_or_else(|| for_each_cpu_core(action), action)
action(id)
} else {
for_each_cpu_core(action)
}
} }
/// Sets the platform profile. /// Sets the platform profile.