From c3307388aa72e43af3bf6d6b2498f02a8016e2b1 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Mon, 4 Dec 2023 18:40:15 +0900 Subject: [PATCH] uclamp: Add support for sched utilization clamping Signed-off-by: Hector Martin --- conf/apple/j180.conf | 1 + conf/apple/j274.conf | 1 + conf/apple/j293.conf | 1 + conf/apple/j313.conf | 1 + conf/apple/j314.conf | 1 + conf/apple/j316.conf | 1 + conf/apple/j413.conf | 1 + conf/apple/j415.conf | 1 + conf/apple/j456.conf | 1 + src/helpers.rs | 10 +++++++++ src/main.rs | 8 +++++++ src/types.rs | 4 ++++ src/uclamp.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 81 insertions(+) create mode 100644 src/uclamp.rs diff --git a/conf/apple/j180.conf b/conf/apple/j180.conf index ee73cf2..a7745c7 100644 --- a/conf/apple/j180.conf +++ b/conf/apple/j180.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 4 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j274.conf b/conf/apple/j274.conf index 2bb2364..d23fcb3 100644 --- a/conf/apple/j274.conf +++ b/conf/apple/j274.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 2 period = 4096 link_gains = False +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j293.conf b/conf/apple/j293.conf index 28a6bbe..605b432 100644 --- a/conf/apple/j293.conf +++ b/conf/apple/j293.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 8 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j313.conf b/conf/apple/j313.conf index cda4ae9..bc9d565 100644 --- a/conf/apple/j313.conf +++ b/conf/apple/j313.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 4 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j314.conf b/conf/apple/j314.conf index 52821af..f6cb196 100644 --- a/conf/apple/j314.conf +++ b/conf/apple/j314.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 12 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j316.conf b/conf/apple/j316.conf index deba31f..7dd605c 100644 --- a/conf/apple/j316.conf +++ b/conf/apple/j316.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 12 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j413.conf b/conf/apple/j413.conf index effa817..a230eae 100644 --- a/conf/apple/j413.conf +++ b/conf/apple/j413.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 8 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j415.conf b/conf/apple/j415.conf index c97a332..5bf3afd 100644 --- a/conf/apple/j415.conf +++ b/conf/apple/j415.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 12 period = 4096 link_gains = True +uclamp_max = 64 [Controls] vsense = VSENSE Switch diff --git a/conf/apple/j456.conf b/conf/apple/j456.conf index 3ccba9d..f8535a1 100644 --- a/conf/apple/j456.conf +++ b/conf/apple/j456.conf @@ -6,6 +6,7 @@ t_window = 20.0 channels = 8 period = 4096 link_gains = True +uclamp_max = 64 [Controls] # vsense = diff --git a/src/helpers.rs b/src/helpers.rs index 8ce9a0d..7bfbd96 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -58,6 +58,16 @@ where .expect("{}/{}: Out of bounds") } +pub fn parse_opt_int>(config: &Ini, section: &str, key: &str) -> Option +where + >::Error: std::fmt::Debug, +{ + config + .getint(section, key) + .expect(&format!("{}/{}: Invalid value", section, key)) + .map(|a| a.try_into().expect("{}/{}: Out of bounds")) +} + /** Wrapper around configparser::ini::Ini.getfloat() to safely unwrap the Result, E> returned by diff --git a/src/main.rs b/src/main.rs index d5845b3..32c7c77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ use simple_logger::SimpleLogger; mod blackbox; mod helpers; mod types; +mod uclamp; const DEFAULT_CONFIG_PATH: &str = "share/speakersafetyd"; @@ -143,6 +144,13 @@ fn main() { let globals = types::Globals::parse(&cfg); + if globals.uclamp_min.is_some() || globals.uclamp_max.is_some() { + uclamp::set_uclamp( + globals.uclamp_min.unwrap_or(0).try_into().unwrap(), + globals.uclamp_max.unwrap_or(1024).try_into().unwrap(), + ); + } + let mut blackbox = args.blackbox_path.map(|p| { info!("Enabling blackbox, path: {:?}", p); blackbox::Blackbox::new(&machine, &p, &globals) diff --git a/src/types.rs b/src/types.rs index ef6255f..ac32cfc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -192,6 +192,8 @@ pub struct Globals { pub ctl_isense: String, pub ctl_amp_gain: String, pub ctl_volume: String, + pub uclamp_min: Option, + pub uclamp_max: Option, } impl Globals { @@ -207,6 +209,8 @@ impl Globals { ctl_isense: helpers::parse_string(config, "Controls", "isense"), ctl_amp_gain: helpers::parse_string(config, "Controls", "amp_gain"), ctl_volume: helpers::parse_string(config, "Controls", "volume"), + uclamp_min: helpers::parse_opt_int(config, "Globals", "uclamp_min"), + uclamp_max: helpers::parse_opt_int(config, "Globals", "uclamp_max"), } } } diff --git a/src/uclamp.rs b/src/uclamp.rs new file mode 100644 index 0000000..e0e8d0b --- /dev/null +++ b/src/uclamp.rs @@ -0,0 +1,50 @@ +use log::{info, warn}; + +#[derive(Default)] +#[repr(C)] +struct SchedAttr { + size: u32, + sched_policy: u32, + sched_flags: u64, + sched_nice: i32, + sched_priority: u32, + sched_runtime: u64, + sched_deadline: u64, + sched_period: u64, + sched_util_min: u32, + sched_util_max: u32, +} + +pub fn set_uclamp(uclamp_min: u32, uclamp_max: u32) { + let mut attr: SchedAttr = Default::default(); + let pid = unsafe { libc::getpid() }; + + if unsafe { + libc::syscall( + libc::SYS_sched_getattr, + pid, + &mut attr, + core::mem::size_of::(), + 0, + ) + } != 0 + { + warn!("Failed to set uclamp"); + return; + } + + /* SCHED_FLAG_KEEP_POLICY | + * SCHED_FLAG_KEEP_PARAMS | + * SCHED_FLAG_UTIL_CLAMP_MIN | + * SCHED_FLAG_UTIL_CLAMP_MAX */ + attr.sched_flags = 0x8 | 0x10 | 0x20 | 0x40; + attr.sched_util_min = uclamp_min; + attr.sched_util_max = uclamp_max; + + if unsafe { libc::syscall(libc::SYS_sched_setattr, pid, &mut attr, 0) } != 0 { + warn!("Failed to set uclamp"); + return; + } + + info!("Set task uclamp to {}:{}", uclamp_min, uclamp_max); +}