pub struct Raised(sys::Previous);
impl Drop for Raised {
fn drop(&mut self) {
sys::restore(self.0);
}
}
pub fn raise_to_realtime() -> Option<Raised> {
sys::raise().map(Raised)
}
#[cfg(unix)]
mod sys {
use core::ffi::c_int;
pub type Previous = c_int;
const PRIO_PROCESS: c_int = 0;
unsafe extern "C" {
fn getpriority(which: c_int, who: u32) -> c_int;
fn setpriority(which: c_int, who: u32, prio: c_int) -> c_int;
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "emscripten"))]
fn __errno_location() -> *mut c_int;
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos",
target_os = "freebsd",
target_os = "dragonfly"
))]
fn __error() -> *mut c_int;
#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
fn __errno() -> *mut c_int;
}
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "emscripten"))]
fn errno() -> Option<*mut c_int> {
Some(unsafe { __errno_location() })
}
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos",
target_os = "freebsd",
target_os = "dragonfly"
))]
fn errno() -> Option<*mut c_int> {
Some(unsafe { __error() })
}
#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
fn errno() -> Option<*mut c_int> {
Some(unsafe { __errno() })
}
#[cfg(not(any(
target_os = "linux",
target_os = "fuchsia",
target_os = "emscripten",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "android",
target_os = "netbsd",
target_os = "openbsd"
)))]
fn errno() -> Option<*mut c_int> {
None
}
pub fn current() -> Option<Previous> {
let errno = errno()?;
unsafe {
*errno = 0;
let nice = getpriority(PRIO_PROCESS, 0);
(nice != -1 || *errno == 0).then_some(nice)
}
}
pub fn raise() -> Option<Previous> {
let previous = current()?;
(unsafe { setpriority(PRIO_PROCESS, 0, -20) } == 0).then_some(previous)
}
pub fn restore(previous: Previous) {
unsafe {
setpriority(PRIO_PROCESS, 0, previous);
}
}
}
#[cfg(windows)]
mod sys {
use core::ffi::c_void;
pub type Previous = u32;
const REALTIME_PRIORITY_CLASS: u32 = 0x0000_0100;
#[link(name = "kernel32")]
unsafe extern "system" {
fn GetCurrentProcess() -> *mut c_void;
fn GetPriorityClass(process: *mut c_void) -> u32;
fn SetPriorityClass(process: *mut c_void, class: u32) -> i32;
}
pub fn current() -> Option<Previous> {
let class = unsafe { GetPriorityClass(GetCurrentProcess()) };
(class != 0).then_some(class)
}
pub fn raise() -> Option<Previous> {
let previous = current()?;
(unsafe { SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) } != 0)
.then_some(previous)
}
pub fn restore(previous: Previous) {
unsafe {
SetPriorityClass(GetCurrentProcess(), previous);
}
}
}
#[cfg(not(any(unix, windows)))]
mod sys {
pub type Previous = ();
pub fn current() -> Option<Previous> {
None
}
pub fn raise() -> Option<Previous> {
None
}
pub fn restore(_previous: Previous) {}
}
#[cfg(test)]
mod tests;