uclamp: Add support for sched utilization clamping

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2023-12-04 18:40:15 +09:00
parent 60752494cd
commit c3307388aa
13 changed files with 81 additions and 0 deletions

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 4 channels = 4
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 2 channels = 2
period = 4096 period = 4096
link_gains = False link_gains = False
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 8 channels = 8
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 4 channels = 4
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 12 channels = 12
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 12 channels = 12
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 8 channels = 8
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 12 channels = 12
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
vsense = VSENSE Switch vsense = VSENSE Switch

View file

@ -6,6 +6,7 @@ t_window = 20.0
channels = 8 channels = 8
period = 4096 period = 4096
link_gains = True link_gains = True
uclamp_max = 64
[Controls] [Controls]
# vsense = # vsense =

View file

@ -58,6 +58,16 @@ where
.expect("{}/{}: Out of bounds") .expect("{}/{}: Out of bounds")
} }
pub fn parse_opt_int<T: TryFrom<i64>>(config: &Ini, section: &str, key: &str) -> Option<T>
where
<T as TryFrom<i64>>::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() Wrapper around configparser::ini::Ini.getfloat()
to safely unwrap the Result<Option<f64>, E> returned by to safely unwrap the Result<Option<f64>, E> returned by

View file

@ -26,6 +26,7 @@ use simple_logger::SimpleLogger;
mod blackbox; mod blackbox;
mod helpers; mod helpers;
mod types; mod types;
mod uclamp;
const DEFAULT_CONFIG_PATH: &str = "share/speakersafetyd"; const DEFAULT_CONFIG_PATH: &str = "share/speakersafetyd";
@ -143,6 +144,13 @@ fn main() {
let globals = types::Globals::parse(&cfg); 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| { let mut blackbox = args.blackbox_path.map(|p| {
info!("Enabling blackbox, path: {:?}", p); info!("Enabling blackbox, path: {:?}", p);
blackbox::Blackbox::new(&machine, &p, &globals) blackbox::Blackbox::new(&machine, &p, &globals)

View file

@ -192,6 +192,8 @@ pub struct Globals {
pub ctl_isense: String, pub ctl_isense: String,
pub ctl_amp_gain: String, pub ctl_amp_gain: String,
pub ctl_volume: String, pub ctl_volume: String,
pub uclamp_min: Option<usize>,
pub uclamp_max: Option<usize>,
} }
impl Globals { impl Globals {
@ -207,6 +209,8 @@ impl Globals {
ctl_isense: helpers::parse_string(config, "Controls", "isense"), ctl_isense: helpers::parse_string(config, "Controls", "isense"),
ctl_amp_gain: helpers::parse_string(config, "Controls", "amp_gain"), ctl_amp_gain: helpers::parse_string(config, "Controls", "amp_gain"),
ctl_volume: helpers::parse_string(config, "Controls", "volume"), 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"),
} }
} }
} }

50
src/uclamp.rs Normal file
View file

@ -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::<SchedAttr>(),
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);
}