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

cpu: store frequency

This commit is contained in:
RGBCube 2025-05-21 17:47:13 +03:00
parent 230967832b
commit d87237165b
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
4 changed files with 57 additions and 32 deletions

View file

@ -50,7 +50,7 @@ pub struct CpuDelta {
impl CpuDelta {
pub fn apply(&self) -> anyhow::Result<()> {
let cpus = match &self.for_ {
let mut cpus = match &self.for_ {
Some(numbers) => {
let mut cpus = Vec::with_capacity(numbers.len());
@ -63,7 +63,7 @@ impl CpuDelta {
None => cpu::Cpu::all().context("failed to get all CPUs and their information")?,
};
for cpu in cpus {
for cpu in &mut cpus {
if let Some(governor) = self.governor.as_ref() {
cpu.set_governor(governor)?;
}
@ -77,11 +77,11 @@ impl CpuDelta {
}
if let Some(mhz_minimum) = self.frequency_mhz_minimum {
cpu.set_frequency_minimum(mhz_minimum)?;
cpu.set_frequency_mhz_minimum(mhz_minimum)?;
}
if let Some(mhz_maximum) = self.frequency_mhz_maximum {
cpu.set_frequency_maximum(mhz_maximum)?;
cpu.set_frequency_mhz_maximum(mhz_maximum)?;
}
}

View file

@ -6,9 +6,6 @@ pub struct SystemInfo {
pub struct CpuCoreInfo {
// Per-core data
pub core_id: u32,
pub current_frequency_mhz: Option<u32>,
pub min_frequency_mhz: Option<u32>,
pub max_frequency_mhz: Option<u32>,
pub usage_percent: Option<f32>,
pub temperature_celsius: Option<f32>,
}

View file

@ -11,6 +11,10 @@ pub struct Cpu {
pub has_cpufreq: bool,
pub frequency_mhz: u64,
pub frequency_mhz_minimum: u64,
pub frequency_mhz_maximum: u64,
pub time_user: u64,
pub time_nice: u64,
pub time_system: u64,
@ -52,6 +56,10 @@ impl Cpu {
number,
has_cpufreq: false,
frequency_mhz: 0,
frequency_mhz_minimum: 0,
frequency_mhz_maximum: 0,
time_user: 0,
time_nice: 0,
time_system: 0,
@ -115,6 +123,7 @@ impl Cpu {
self.has_cpufreq = fs::exists(format!("/sys/devices/system/cpu/cpu{number}/cpufreq"));
self.rescan_times()?;
self.rescan_frequency()?;
Ok(())
}
@ -180,6 +189,32 @@ impl Cpu {
Ok(())
}
fn rescan_frequency(&mut self) -> anyhow::Result<()> {
let Self { number, .. } = *self;
let frequency_khz = fs::read_u64(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_cur_freq"
))
.with_context(|| format!("failed to find {self} frequency"))?
.with_context(|| format!("failed to parse {self} frequency"))?;
let frequency_khz_minimum = fs::read_u64(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_min_freq"
))
.with_context(|| format!("failed to find {self} frequency minimum"))?
.with_context(|| format!("failed to parse {self} frequency"))?;
let frequency_khz_maximum = fs::read_u64(format!(
"/sys/devices/system/cpu/cpu{number}/cpufreq/scaling_max_freq"
))
.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;
Ok(())
}
pub fn get_available_governors(&self) -> Vec<String> {
let Self { number, .. } = self;
@ -308,10 +343,10 @@ impl Cpu {
})
}
pub fn set_frequency_minimum(&self, frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = self;
pub fn set_frequency_mhz_minimum(&mut self, frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = *self;
self.validate_frequency_minimum(frequency_mhz)?;
self.validate_frequency_mhz_minimum(frequency_mhz)?;
// We use u64 for the intermediate calculation to prevent overflow
let frequency_khz = frequency_mhz * 1000;
@ -323,10 +358,14 @@ impl Cpu {
)
.with_context(|| {
format!("this probably means that {self} doesn't exist or doesn't support changing minimum frequency")
})
})?;
self.frequency_mhz_minimum = frequency_mhz;
Ok(())
}
fn validate_frequency_minimum(&self, new_frequency_mhz: u64) -> anyhow::Result<()> {
fn validate_frequency_mhz_minimum(&self, new_frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = self;
let Some(Ok(minimum_frequency_khz)) = fs::read_u64(format!(
@ -346,10 +385,10 @@ impl Cpu {
Ok(())
}
pub fn set_frequency_maximum(&self, frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = self;
pub fn set_frequency_mhz_maximum(&mut self, frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = *self;
self.validate_frequency_maximum(frequency_mhz)?;
self.validate_frequency_mhz_maximum(frequency_mhz)?;
// We use u64 for the intermediate calculation to prevent overflow
let frequency_khz = frequency_mhz * 1000;
@ -361,10 +400,14 @@ impl Cpu {
)
.with_context(|| {
format!("this probably means that {self} doesn't exist or doesn't support changing maximum frequency")
})
})?;
self.frequency_mhz_maximum = frequency_mhz;
Ok(())
}
fn validate_frequency_maximum(&self, new_frequency_mhz: u64) -> anyhow::Result<()> {
fn validate_frequency_mhz_maximum(&self, new_frequency_mhz: u64) -> anyhow::Result<()> {
let Self { number, .. } = self;
let Some(Ok(maximum_frequency_khz)) = fs::read_u64(format!(

View file

@ -21,18 +21,6 @@ pub fn get_cpu_core_info(
prev_times: &CpuTimes,
current_times: &CpuTimes,
) -> anyhow::Result<CpuCoreInfo> {
let cpufreq_path = PathBuf::from(format!("/sys/devices/system/cpu/cpu{core_id}/cpufreq/"));
let current_frequency_mhz = read_sysfs_value::<u32>(cpufreq_path.join("scaling_cur_freq"))
.map(|khz| khz / 1000)
.ok();
let min_frequency_mhz = read_sysfs_value::<u32>(cpufreq_path.join("scaling_min_freq"))
.map(|khz| khz / 1000)
.ok();
let max_frequency_mhz = read_sysfs_value::<u32>(cpufreq_path.join("scaling_max_freq"))
.map(|khz| khz / 1000)
.ok();
// Temperature detection.
// Should be generic enough to be able to support for multiple hardware sensors
// with the possibility of extending later down the road.
@ -144,9 +132,6 @@ pub fn get_cpu_core_info(
Ok(CpuCoreInfo {
core_id,
current_frequency_mhz,
min_frequency_mhz,
max_frequency_mhz,
usage_percent,
temperature_celsius,
})