diff --git a/Cargo.toml b/Cargo.toml index c262312..b0d8d84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thread-priority" -version = "0.4.1" +version = "0.5.0" authors = ["Victor Polevoy "] description = "Library for managing threads priority and schedule policies" repository = "https://github.com/vityafx/thread-priority" @@ -14,7 +14,7 @@ edition = "2018" [dependencies] log = "0.4" -[target.'cfg(unix)'.dependencies] +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] libc = "0.2" [target.'cfg(windows)'.dependencies] diff --git a/README.md b/README.md index db85a58..fd2964f 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,15 @@ A simple library to control thread schedule policies and thread priority. -This crate does not support all the plaforms yet but it is inteded to be developed so, -so feel free to contribute! +If your operating system isn't yet supported, please, create an issue. ## Supported platforms - Linux +- DragonFly +- FreeBSD +- OpenBSD +- NetBSD +- macOS - Windows ## Examples diff --git a/src/lib.rs b/src/lib.rs index 56d35b3..2f13b92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,9 +87,23 @@ #![warn(missing_docs)] #![deny(warnings)] -#[cfg(unix)] +#[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd" +))] pub mod unix; -#[cfg(unix)] +#[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd" +))] pub use unix::*; #[cfg(windows)] diff --git a/src/unix.rs b/src/unix.rs index cbbb878..9bc9661 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -7,11 +7,13 @@ use std::convert::TryFrom; use crate::{Error, ThreadPriority, ThreadPriorityValue}; +use std::mem::MaybeUninit; /// An alias type for a thread id. pub type ThreadId = libc::pthread_t; /// Proxy structure to maintain compatibility between glibc and musl +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct ScheduleParams { /// Copy of `sched_priority` from `libc::sched_param` pub sched_priority: libc::c_int, @@ -45,30 +47,10 @@ pub struct SchedAttr { } impl ScheduleParams { - #[cfg(not(target_env = "musl"))] fn into_posix(self) -> libc::sched_param { - libc::sched_param { - sched_priority: self.sched_priority, - } - } - - #[cfg(target_env = "musl")] - fn into_posix(self) -> libc::sched_param { - use libc::timespec as TimeSpec; - - libc::sched_param { - sched_priority: self.sched_priority, - sched_ss_low_priority: 0, - sched_ss_repl_period: TimeSpec { - tv_sec: 0, - tv_nsec: 0, - }, - sched_ss_init_budget: TimeSpec { - tv_sec: 0, - tv_nsec: 0, - }, - sched_ss_max_repl: 0, - } + let mut param = unsafe { MaybeUninit::::zeroed().assume_init() }; + param.sched_priority = self.sched_priority; + param } fn from_posix(sched_param: libc::sched_param) -> Self { @@ -95,7 +77,10 @@ pub enum RealtimeThreadSchedulePolicy { impl RealtimeThreadSchedulePolicy { fn to_posix(self) -> libc::c_int { match self { + #[cfg(not(target_os = "macos"))] RealtimeThreadSchedulePolicy::Fifo => 1, + #[cfg(target_os = "macos")] + RealtimeThreadSchedulePolicy::Fifo => 4, RealtimeThreadSchedulePolicy::RoundRobin => 2, #[cfg(target_os = "linux")] RealtimeThreadSchedulePolicy::Deadline => 6, @@ -116,6 +101,7 @@ pub enum NormalThreadSchedulePolicy { Normal, } impl NormalThreadSchedulePolicy { + #[cfg(not(target_os = "macos"))] fn to_posix(self) -> libc::c_int { match self { NormalThreadSchedulePolicy::Idle => 5, @@ -123,6 +109,14 @@ impl NormalThreadSchedulePolicy { NormalThreadSchedulePolicy::Other | NormalThreadSchedulePolicy::Normal => 0, } } + + #[cfg(target_os = "macos")] + fn to_posix(self) -> libc::c_int { + match self { + NormalThreadSchedulePolicy::Other => 1, + _ => panic!("Invalid value for berkley schedule policy."), + } + } } /// Thread schedule policy definition @@ -141,6 +135,7 @@ impl ThreadSchedulePolicy { } } + #[cfg(not(target_os = "macos"))] fn from_posix(policy: libc::c_int) -> Result { match policy { 0 => Ok(ThreadSchedulePolicy::Normal( @@ -165,6 +160,24 @@ impl ThreadSchedulePolicy { _ => Err(Error::Ffi("Can't parse schedule policy from posix")), } } + + #[cfg(target_os = "macos")] + fn from_posix(policy: libc::c_int) -> Result { + match policy { + 1 => Ok(ThreadSchedulePolicy::Normal( + NormalThreadSchedulePolicy::Other, + )), + 4 => Ok(ThreadSchedulePolicy::Realtime( + RealtimeThreadSchedulePolicy::Fifo, + )), + 2 => Ok(ThreadSchedulePolicy::Realtime( + RealtimeThreadSchedulePolicy::RoundRobin, + )), + _ => Err(Error::Ffi( + "Can't parse schedule policy from berkley values", + )), + } + } } impl ThreadPriority { @@ -243,14 +256,32 @@ impl ThreadPriority { /// /// Setting thread priority to minimum with normal schedule policy: /// -/// ```rust -/// use thread_priority::*; -/// -/// let thread_id = thread_native_id(); -/// assert!(set_thread_priority_and_policy(thread_id, -/// ThreadPriority::Min, -/// ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Normal)).is_ok()); -/// ``` +#[cfg_attr( + target_os = "macos", + doc = "\ +```rust +use thread_priority::*; + +let thread_id = thread_native_id(); +assert!(set_thread_priority_and_policy(thread_id, + ThreadPriority::Min, + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other)).is_ok()); +``` +" +)] +#[cfg_attr( + not(target_os = "macos"), + doc = "\ +```rust +use thread_priority::*; + +let thread_id = thread_native_id(); +assert!(set_thread_priority_and_policy(thread_id, + ThreadPriority::Min, + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Normal)).is_ok()); +``` +" +)] pub fn set_thread_priority_and_policy( native: ThreadId, priority: ThreadPriority, @@ -268,6 +299,9 @@ pub fn set_thread_priority_and_policy( /// Set current thread's priority. pub fn set_current_thread_priority(priority: ThreadPriority) -> Result<(), Error> { let thread_id = thread_native_id(); + #[cfg(target_os = "macos")] + let policy = ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other); + #[cfg(not(target_os = "macos"))] let policy = ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Normal); set_thread_priority_and_policy(thread_id, priority, policy) } @@ -281,6 +315,7 @@ pub fn set_current_thread_priority(priority: ThreadPriority) -> Result<(), Error /// /// assert!(thread_schedule_policy().is_ok()); /// ``` +#[cfg(not(target_os = "macos"))] pub fn thread_schedule_policy() -> Result { unsafe { ThreadSchedulePolicy::from_posix(libc::sched_getscheduler(libc::getpid())) } } @@ -511,6 +546,32 @@ mod tests { assert!(thread_schedule_policy_param(thread_id).is_ok()); } + #[cfg(target_os = "macos")] + #[test] + fn set_thread_priority_test() { + let thread_id = thread_native_id(); + + assert!(set_thread_priority_and_policy( + thread_id, + ThreadPriority::Min, + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other) + ) + .is_ok()); + assert!(set_thread_priority_and_policy( + thread_id, + ThreadPriority::Max, + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other) + ) + .is_ok()); + assert!(set_thread_priority_and_policy( + thread_id, + ThreadPriority::Specific(0), + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other) + ) + .is_ok()); + } + + #[cfg(not(target_os = "macos"))] #[test] fn set_thread_priority_test() { let thread_id = thread_native_id();