mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-23 05:34:57 +02:00
add a _very_ basic runtime_status check for now
This commit is contained in:
parent
87ca73a2fd
commit
d7c614b75b
@ -3,36 +3,16 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::OnceLock,
|
|
||||||
time::Instant,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use humantime::Duration;
|
|
||||||
|
|
||||||
use super::{is_temp_filtered, TempHarvest, TemperatureReading, TemperatureType};
|
use super::{is_temp_filtered, TempHarvest, TemperatureReading, TemperatureType};
|
||||||
use crate::{app::filter::Filter, utils::error::BottomError};
|
use crate::{app::filter::Filter, utils::error::BottomError};
|
||||||
|
|
||||||
const EMPTY_NAME: &str = "Unknown";
|
const EMPTY_NAME: &str = "Unknown";
|
||||||
|
|
||||||
/// Holds some data about the power states of certain devices.
|
|
||||||
struct PowerStateInfo {
|
|
||||||
autosuspend: Option<Duration>,
|
|
||||||
last_read: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PowerStateInfo {
|
|
||||||
fn new(autosuspend: Option<Duration>) -> Self {
|
|
||||||
Self {
|
|
||||||
autosuspend,
|
|
||||||
last_read: Instant::now(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static POWER_STATE_MAP: OnceLock<HashMap<String, PowerStateInfo>> = OnceLock::new();
|
|
||||||
|
|
||||||
/// Returned results from grabbing hwmon/coretemp temperature sensor values/names.
|
/// Returned results from grabbing hwmon/coretemp temperature sensor values/names.
|
||||||
struct HwmonResults {
|
struct HwmonResults {
|
||||||
temperatures: Vec<TempHarvest>,
|
temperatures: Vec<TempHarvest>,
|
||||||
@ -57,7 +37,8 @@ fn get_hwmon_candidates() -> (HashSet<PathBuf>, usize) {
|
|||||||
let mut path = entry.path();
|
let mut path = entry.path();
|
||||||
|
|
||||||
// hwmon includes many sensors, we only want ones with at least one temperature sensor
|
// hwmon includes many sensors, we only want ones with at least one temperature sensor
|
||||||
// Reading this file will wake the device, but we're only checking existence, so it should be fine.
|
// _Reading_ this file will wake the device, but we're only checking _existence_, so
|
||||||
|
// this shouldn't wake up the device.
|
||||||
if !path.join("temp1_input").exists() {
|
if !path.join("temp1_input").exists() {
|
||||||
// Note we also check for a `device` subdirectory (e.g. `/sys/class/hwmon/hwmon*/device/`).
|
// Note we also check for a `device` subdirectory (e.g. `/sys/class/hwmon/hwmon*/device/`).
|
||||||
// This is needed for CentOS, which adds this extra `/device` directory. See:
|
// This is needed for CentOS, which adds this extra `/device` directory. See:
|
||||||
@ -194,18 +175,37 @@ fn finalize_name(
|
|||||||
counted_name(seen_names, candidate_name)
|
counted_name(seen_names, candidate_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the temperature should *actually* be read during enumeration.
|
/// Whether the temperature should *actually* be read during enumeration. Uses a combination of
|
||||||
/// Will return false if the state is not D0/unknown, or if it does not support `device/power_state`.
|
/// `power/runtime_status` if it is supported, and `device/power_state` as a fallback.
|
||||||
|
///
|
||||||
|
/// If `runtime_status` is supported, then it will return true only if it is in the "active" state.
|
||||||
|
/// If it is not supported, and we fall back to `device/power_state`, then it will return true
|
||||||
|
/// only if in D0 or unknown states.
|
||||||
|
/// If neither are found, it will always return true and be treated as "awake".
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_device_awake(path: &Path) -> bool {
|
fn is_device_awake(path: &Path) -> bool {
|
||||||
// Whether the temperature should *actually* be read during enumeration.
|
// Try checking `power/runtime_status` if it exists! For more information, see
|
||||||
// Set to false if the device is in ACPI D3cold.
|
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power
|
||||||
|
let runtime_status_path = path.join("power/runtime_status");
|
||||||
|
if runtime_status_path.exists() {
|
||||||
|
if let Ok(status) = fs::read_to_string(runtime_status_path) {
|
||||||
|
match status.as_str() {
|
||||||
|
"suspended" | "suspending" | "resuming" => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
"active" => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, check if the device is in ACPI D3Cold.
|
||||||
// Documented at https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power_state
|
// Documented at https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power_state
|
||||||
let device = path.join("device");
|
let power_state = path.join("device/power_state");
|
||||||
let power_state = device.join("power_state");
|
|
||||||
if power_state.exists() {
|
if power_state.exists() {
|
||||||
if let Ok(state) = fs::read_to_string(power_state) {
|
if let Ok(state) = fs::read_to_string(power_state) {
|
||||||
let state = state.trim();
|
|
||||||
// The zenpower3 kernel module (incorrectly?) reports "unknown", causing this check
|
// The zenpower3 kernel module (incorrectly?) reports "unknown", causing this check
|
||||||
// to fail and temperatures to appear as zero instead of having the file not exist.
|
// to fail and temperatures to appear as zero instead of having the file not exist.
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user