mirror of
https://github.com/RGBCube/superfreq
synced 2025-07-27 17:07:44 +00:00
cpu: clean up dynamic CPU turbo management
This commit is contained in:
parent
6ef0a60002
commit
23c526a61e
3 changed files with 50 additions and 10 deletions
|
@ -124,6 +124,7 @@ pub struct ProfileConfigToml {
|
|||
pub min_freq_mhz: Option<u32>,
|
||||
pub max_freq_mhz: Option<u32>,
|
||||
pub platform_profile: Option<String>,
|
||||
pub turbo_auto_settings: Option<TurboAutoSettings>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub battery_charge_thresholds: Option<BatteryChargeThresholds>,
|
||||
}
|
||||
|
@ -151,6 +152,7 @@ impl Default for ProfileConfigToml {
|
|||
min_freq_mhz: None,
|
||||
max_freq_mhz: None,
|
||||
platform_profile: None,
|
||||
turbo_auto_settings: None,
|
||||
battery_charge_thresholds: None,
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +210,9 @@ impl From<ProfileConfigToml> for ProfileConfig {
|
|||
min_freq_mhz: toml_config.min_freq_mhz,
|
||||
max_freq_mhz: toml_config.max_freq_mhz,
|
||||
platform_profile: toml_config.platform_profile,
|
||||
turbo_auto_settings: Some(TurboAutoSettings::default()),
|
||||
turbo_auto_settings: toml_config
|
||||
.turbo_auto_settings
|
||||
.or_else(|| Some(TurboAutoSettings::default())),
|
||||
battery_charge_thresholds: toml_config.battery_charge_thresholds,
|
||||
}
|
||||
}
|
||||
|
|
12
src/cpu.rs
12
src/cpu.rs
|
@ -1,6 +1,7 @@
|
|||
use crate::core::{GovernorOverrideMode, TurboSetting};
|
||||
use crate::util::error::ControlError;
|
||||
use core::str;
|
||||
use log::debug;
|
||||
use std::{fs, io, path::Path, string::ToString};
|
||||
|
||||
pub type Result<T, E = ControlError> = std::result::Result<T, E>;
|
||||
|
@ -216,12 +217,19 @@ pub fn set_turbo(setting: TurboSetting) -> Result<()> {
|
|||
let value_pstate = match setting {
|
||||
TurboSetting::Always => "0", // no_turbo = 0 means turbo is enabled
|
||||
TurboSetting::Never => "1", // no_turbo = 1 means turbo is disabled
|
||||
TurboSetting::Auto => return Err(ControlError::InvalidValueError("Turbo Auto cannot be directly set via intel_pstate/no_turbo or cpufreq/boost. System default.".to_string())),
|
||||
// Auto mode is handled at the engine level, not directly at the sysfs level
|
||||
TurboSetting::Auto => {
|
||||
debug!("Turbo Auto mode is managed by engine logic based on system conditions");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let value_boost = match setting {
|
||||
TurboSetting::Always => "1", // boost = 1 means turbo is enabled
|
||||
TurboSetting::Never => "0", // boost = 0 means turbo is disabled
|
||||
TurboSetting::Auto => return Err(ControlError::InvalidValueError("Turbo Auto cannot be directly set via intel_pstate/no_turbo or cpufreq/boost. System default.".to_string())),
|
||||
TurboSetting::Auto => {
|
||||
debug!("Turbo Auto mode is managed by engine logic based on system conditions");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
// AMD specific paths
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::core::{OperationalMode, SystemReport, TurboSetting};
|
|||
use crate::cpu::{self};
|
||||
use crate::util::error::{ControlError, EngineError};
|
||||
use log::{debug, info, warn};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// Try applying a CPU feature and handle common error cases. Centralizes the where we
|
||||
/// previously did:
|
||||
|
@ -172,6 +173,10 @@ pub fn determine_and_apply_settings(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Keep track of current auto turbo state for hysteresis using thread-safe atomics
|
||||
static PREVIOUS_TURBO_STATE: AtomicBool = AtomicBool::new(false);
|
||||
static TURBO_STATE_INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<(), EngineError> {
|
||||
// Get the auto turbo settings from the config, or use defaults
|
||||
let turbo_settings = config.turbo_auto_settings.clone().unwrap_or_default();
|
||||
|
@ -204,10 +209,18 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
}
|
||||
};
|
||||
|
||||
// Decision logic for enabling/disabling turbo
|
||||
let enable_turbo = match (cpu_temp, avg_cpu_usage) {
|
||||
// Get previous state safely using atomic operations
|
||||
let has_previous_state = TURBO_STATE_INITIALIZED.load(Ordering::Relaxed);
|
||||
let previous_turbo_enabled = if has_previous_state {
|
||||
Some(PREVIOUS_TURBO_STATE.load(Ordering::Relaxed))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Decision logic for enabling/disabling turbo with hysteresis
|
||||
let enable_turbo = match (cpu_temp, avg_cpu_usage, previous_turbo_enabled) {
|
||||
// If temperature is too high, disable turbo regardless of load
|
||||
(Some(temp), _) if temp >= turbo_settings.temp_threshold_high => {
|
||||
(Some(temp), _, _) if temp >= turbo_settings.temp_threshold_high => {
|
||||
info!(
|
||||
"Auto Turbo: Disabled due to high temperature ({:.1}°C >= {:.1}°C)",
|
||||
temp, turbo_settings.temp_threshold_high
|
||||
|
@ -215,7 +228,7 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
false
|
||||
}
|
||||
// If load is high enough, enable turbo (unless temp already caused it to disable)
|
||||
(_, Some(usage)) if usage >= turbo_settings.load_threshold_high => {
|
||||
(_, Some(usage), _) if usage >= turbo_settings.load_threshold_high => {
|
||||
info!(
|
||||
"Auto Turbo: Enabled due to high CPU load ({:.1}% >= {:.1}%)",
|
||||
usage, turbo_settings.load_threshold_high
|
||||
|
@ -223,21 +236,36 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
true
|
||||
}
|
||||
// If load is low, disable turbo
|
||||
(_, Some(usage)) if usage <= turbo_settings.load_threshold_low => {
|
||||
(_, Some(usage), _) if usage <= turbo_settings.load_threshold_low => {
|
||||
info!(
|
||||
"Auto Turbo: Disabled due to low CPU load ({:.1}% <= {:.1}%)",
|
||||
usage, turbo_settings.load_threshold_low
|
||||
);
|
||||
false
|
||||
}
|
||||
// In intermediate load scenarios or if we can't determine, leave turbo in current state
|
||||
// For now, we'll disable it as a safe default
|
||||
// In intermediate load range, maintain previous state (hysteresis)
|
||||
(_, Some(usage), Some(prev_state))
|
||||
if usage > turbo_settings.load_threshold_low
|
||||
&& usage < turbo_settings.load_threshold_high =>
|
||||
{
|
||||
info!(
|
||||
"Auto Turbo: Maintaining previous state ({}) due to intermediate load ({:.1}%)",
|
||||
if prev_state { "enabled" } else { "disabled" },
|
||||
usage
|
||||
);
|
||||
prev_state
|
||||
}
|
||||
// In indeterminate states or unknown previous state, default to disabled
|
||||
_ => {
|
||||
info!("Auto Turbo: Disabled (default for indeterminate state)");
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Save the current state for next time using atomic operations
|
||||
PREVIOUS_TURBO_STATE.store(enable_turbo, Ordering::Relaxed);
|
||||
TURBO_STATE_INITIALIZED.store(true, Ordering::Relaxed);
|
||||
|
||||
// Apply the turbo setting
|
||||
let turbo_setting = if enable_turbo {
|
||||
TurboSetting::Always
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue