diff --git a/src/utils/cpu.rs b/src/utils/cpu.rs index 1c0cd66..2dcc467 100644 --- a/src/utils/cpu.rs +++ b/src/utils/cpu.rs @@ -3,6 +3,7 @@ use glob::glob; use lazy_regex::{lazy_regex, Lazy, Regex}; use log::{debug, trace, warn}; use std::{ + collections::HashMap, path::{Path, PathBuf}, sync::LazyLock, }; @@ -28,54 +29,80 @@ static RE_LSCPU_VIRTUALIZATION: Lazy = lazy_regex!(r"Virtualization:\s*(. static RE_LSCPU_MAX_MHZ: Lazy = lazy_regex!(r"CPU max MHz:\s*(.*)"); static RE_PROC_STAT: Lazy = lazy_regex!( - r"cpu[0-9]+ *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*)" + r"cpu\d+ *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*) *(?P\d*)" ); static CPU_TEMPERATURE_PATH: LazyLock> = LazyLock::new(|| { - let cpu_temperature_path = - search_for_hwmons(KNOWN_HWMONS).or_else(|| search_for_thermal_zones(KNOWN_THERMAL_ZONES)); - - if let Some((sensor, path)) = &cpu_temperature_path { - debug!( - "CPU temperature sensor located at {} ({sensor})", - path.display() - ); - } else { - warn!("No sensor for CPU temperature found!"); - } - - cpu_temperature_path.map(|(_, path)| path) + search_for_hwmons(KNOWN_HWMONS) + .or_else(|| search_for_thermal_zones(KNOWN_THERMAL_ZONES)) + .or_else(|| { + warn!("No CPU temperature sensor found!"); + None + }) }); -/// Looks for hwmons with the given names. -/// This function is a bit inefficient since the `names` array is considered to be ordered by priority. -fn search_for_hwmons(names: &[&'static str]) -> Option<(&'static str, PathBuf)> { - for temp_name in names { - for path in (glob("/sys/class/hwmon/hwmon*").unwrap()).flatten() { - if let Ok(read_name) = std::fs::read_to_string(path.join("name")) { - if &read_name.trim_end() == temp_name { - return Some((temp_name, path.join("temp1_input"))); - } +fn search_for_first_temp>(base_path: S) -> Option { + glob(&format!("{}/temp*_input", base_path.as_ref())) + .unwrap() + .flatten() + .next() +} + +fn search_for_hwmons(names: &[&'static str]) -> Option { + let mut hwmon_map = HashMap::new(); + + trace!("Collecting hwmons for CPU temperature…"); + + for path in (glob("/sys/class/hwmon/hwmon*").unwrap()).flatten() { + trace!("Found hwmon {path:?}"); + if let Ok(read_name) = std::fs::read_to_string(path.join("name")) { + let read_name = read_name.trim_end().to_string(); + trace!("{path:?} is a hwmon for {read_name}"); + if let Some(first_temp) = search_for_first_temp(path.to_string_lossy()) { + hwmon_map.insert(read_name, first_temp); } } } + for name in names { + if let Some(hwmon) = hwmon_map.remove(*name) { + debug!( + "CPU temperature sensor located at {:?} ({name}, type: hwmon)", + hwmon + ); + return Some(hwmon); + } + } + + trace!("No hwmon CPU temperature sensor found"); None } -/// Looks for thermal zones with the given types. -/// This function is a bit inefficient since the `types` array is considered to be ordered by priority. -fn search_for_thermal_zones(types: &[&'static str]) -> Option<(&'static str, PathBuf)> { - for temp_type in types { - for path in (glob("/sys/class/thermal/thermal_zone*").unwrap()).flatten() { - if let Ok(read_type) = std::fs::read_to_string(path.join("type")) { - if &read_type.trim_end() == temp_type { - return Some((temp_type, path.join("temp"))); - } - } +fn search_for_thermal_zones(types: &[&'static str]) -> Option { + let mut thermal_zone_map = HashMap::new(); + + trace!("Collecting thermal zones for CPU temperature…"); + + for path in (glob("/sys/class/thermal/thermal_zone*").unwrap()).flatten() { + trace!("Found thermal zone {path:?}"); + if let Ok(read_type) = std::fs::read_to_string(path.join("type")) { + let read_type = read_type.trim_end().to_string(); + trace!("{path:?} is a thermal zone for {read_type}"); + thermal_zone_map.insert(read_type, path.join("temp")); + } + } + + for r#type in types { + if let Some(hwmon) = thermal_zone_map.remove(*r#type) { + debug!( + "CPU temperature sensor located at {:?} ({}, type: thermal zone)", + hwmon, r#type + ); + return Some(hwmon); } } + trace!("No thermal zone CPU temperature sensor found"); None } diff --git a/src/utils/gpu/mod.rs b/src/utils/gpu/mod.rs index 82af12b..d92045f 100644 --- a/src/utils/gpu/mod.rs +++ b/src/utils/gpu/mod.rs @@ -267,9 +267,7 @@ impl Gpu { let mut hwmon_vec: Vec = Vec::new(); for hwmon in glob(&format!( "{}/hwmon/hwmon?", - sysfs_device_path - .to_str() - .context("error transforming PathBuf to str")? + sysfs_device_path.to_string_lossy() ))? .flatten() {