use super::{Params, Scheduling};
use crate::{Error, Result};
use std::process::Stdio;
struct ChrtSchedArgument(&'static str);
impl From<Scheduling> for ChrtSchedArgument {
fn from(value: Scheduling) -> Self {
match value {
Scheduling::RoundRobin => ChrtSchedArgument("--rr"),
Scheduling::FIFO => ChrtSchedArgument("--fifo"),
Scheduling::Idle => ChrtSchedArgument("--idle"),
Scheduling::Batch => ChrtSchedArgument("--batch"),
Scheduling::DeadLine => ChrtSchedArgument("--deadline"),
Scheduling::Other => ChrtSchedArgument("--other"),
}
}
}
pub fn apply_for_current(params: &Params) -> Result<()> {
let tid = unsafe { i32::try_from(libc::syscall(libc::SYS_gettid)) }
.map_err(|e| Error::Failed(e.to_string()))?;
apply(tid, params)
}
pub fn apply(tid: libc::c_int, params: &Params) -> Result<()> {
let user_id = unsafe { libc::getuid() };
if !params.cpu_ids.is_empty() {
if user_id != 0 {
return Err(Error::AccessDenied);
}
let result = std::process::Command::new("taskset")
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg("-cp")
.arg(
¶ms
.cpu_ids
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(","),
)
.arg(tid.to_string())
.status()
.map_err(|e| Error::RTSchedSetAffinity(e.to_string()))?;
if !result.success() {
return Err(Error::RTSchedSetAffinity(format!(
"taskset exit code {}",
result.code().unwrap_or(-1)
)));
}
}
if let Some(priority) = params.priority {
if user_id != 0 {
return Err(Error::AccessDenied);
}
let sched = if priority == 0 {
Scheduling::Other
} else {
params.scheduling
};
let result = std::process::Command::new("chrt")
.stdout(Stdio::null())
.stderr(Stdio::null())
.arg(ChrtSchedArgument::from(sched).0)
.arg("-p")
.arg(priority.to_string())
.arg(tid.to_string())
.status()
.map_err(|e| Error::RTSchedSetScheduler(e.to_string()))?;
if !result.success() {
return Err(Error::RTSchedSetScheduler(format!(
"chrt exit code {}",
result.code().unwrap_or(-1)
)));
}
}
Ok(())
}
pub fn prealloc_heap(size: usize) -> Result<()> {
if size == 0 {
return Ok(());
}
Err(Error::Unimplemented)
}