Initial commit

This commit is contained in:
2024-11-22 21:20:05 +01:00
commit 922e41fa10
10 changed files with 1173 additions and 0 deletions

87
src/lib.rs Normal file
View File

@@ -0,0 +1,87 @@
mod low_level_zbus_api;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Permission denied")]
PermissionDenied,
#[error(transparent)]
ZbusError(#[from] zbus::Error),
#[error(transparent)]
ZbusMethodError(#[from] zbus::fdo::Error),
}
/// Helper for [make_thread_realtime], uses the current thread's tid.
pub fn make_current_thread_realtime(priority: Option<u32>) -> Result<u32, Error> {
let thread_id = nix::unistd::gettid().as_raw().try_into().unwrap();
make_thread_realtime(thread_id, priority)
}
/// Elevates the realtime priority of a thread as close as possible to the requested priority.
///
/// If no priority is specified, the maximum priority allowed by the system will be used.
///
/// Returns the actual priority that was set.
pub fn make_thread_realtime(tid: u64, priority: Option<u32>) -> Result<u32, Error> {
debug_assert!(
priority.is_some_and(|p| p <= 99),
"priority must be between 0 and 99"
);
let connection = zbus::blocking::Connection::system()?;
let proxy = low_level_zbus_api::RTKitProxyBlocking::builder(&connection)
.cache_properties(zbus::proxy::CacheProperties::No)
.build()?;
let max_realtime_priority = proxy.max_realtime_priority()?;
debug_assert!(
(0..=99).contains(&max_realtime_priority),
"max_realtime_priority must be between 0 and 99"
);
let priority = priority.unwrap_or(max_realtime_priority as u32);
proxy
.make_thread_realtime(tid, priority)
.map(|_| priority)
.map_err(|e| match e {
zbus::fdo::Error::AccessDenied(_) => Error::PermissionDenied,
e => Error::ZbusMethodError(e),
})
}
/// Elevates the realtime priority of a specified processes thread as close as possible to the requested priority.
///
/// If no priority is specified, the maximum priority allowed by the system will be used.
///
/// Returns the actual priority that was set.
pub fn make_process_thread_realtime(
pid: u64,
tid: u64,
priority: Option<u32>,
) -> Result<u32, Error> {
debug_assert!(
priority.is_some_and(|p| p <= 99),
"priority must be between 0 and 99"
);
let connection = zbus::blocking::Connection::system()?;
let proxy = low_level_zbus_api::RTKitProxyBlocking::builder(&connection)
.cache_properties(zbus::proxy::CacheProperties::No)
.build()?;
let max_realtime_priority = proxy.max_realtime_priority()?;
debug_assert!(
(0..=99).contains(&max_realtime_priority),
"max_realtime_priority must be between 0 and 99"
);
let priority = priority.unwrap_or(max_realtime_priority as u32);
proxy
.make_thread_realtime_with_pid(pid, tid, priority)
.map(|_| priority)
.map_err(|e| match e {
zbus::fdo::Error::AccessDenied(_) => Error::PermissionDenied,
e => Error::ZbusMethodError(e),
})
}

36
src/low_level_zbus_api.rs Normal file
View File

@@ -0,0 +1,36 @@
use zbus::{fdo::Result, proxy};
/// Low level interface to the RealtimeKit1 D-Bus service.
///
/// Note: due to a missing implementation of GetAll in the canonical rtkit service,
/// you will need to disable the cache for properties in order not to trigger an UnknownMethod error.
#[proxy(
interface = "org.freedesktop.RealtimeKit1",
default_service = "org.freedesktop.RealtimeKit1",
default_path = "/org/freedesktop/RealtimeKit1"
)]
pub trait RTKit {
fn make_thread_realtime(&self, thread: u64, priority: u32) -> Result<()>;
fn make_thread_realtime_with_pid(&self, process: u64, thread: u64, priority: u32)
-> Result<()>;
fn make_thread_high_priority(&self, thread: u64, priority: i32) -> Result<()>;
fn make_thread_high_priority_with_pid(
&self,
process: u64,
thread: u64,
// lmao, why are these different?
priority: i32,
) -> Result<()>;
fn reset_known(&self) -> Result<()>;
fn reset_all(&self) -> Result<()>;
fn exit(&self) -> Result<()>;
#[zbus(property)]
fn rt_time_usec_max(&self) -> Result<i64>;
#[zbus(property)]
fn max_realtime_priority(&self) -> Result<i32>;
#[zbus(property)]
fn min_nice_level(&self) -> Result<i32>;
}