Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "thread-priority"
version = "0.4.1"
version = "0.5.0"
authors = ["Victor Polevoy <[email protected]>"]
description = "Library for managing threads priority and schedule policies"
repository = "https://github.com/vityafx/thread-priority"
Expand All @@ -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]
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 16 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
123 changes: 92 additions & 31 deletions src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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::<libc::sched_param>::zeroed().assume_init() };
param.sched_priority = self.sched_priority;
param
}

fn from_posix(sched_param: libc::sched_param) -> Self {
Expand All @@ -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,
Expand All @@ -116,13 +101,22 @@ pub enum NormalThreadSchedulePolicy {
Normal,
}
impl NormalThreadSchedulePolicy {
#[cfg(not(target_os = "macos"))]
fn to_posix(self) -> libc::c_int {
match self {
NormalThreadSchedulePolicy::Idle => 5,
NormalThreadSchedulePolicy::Batch => 3,
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
Expand All @@ -141,6 +135,7 @@ impl ThreadSchedulePolicy {
}
}

#[cfg(not(target_os = "macos"))]
fn from_posix(policy: libc::c_int) -> Result<ThreadSchedulePolicy, Error> {
match policy {
0 => Ok(ThreadSchedulePolicy::Normal(
Expand All @@ -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<ThreadSchedulePolicy, Error> {
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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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)
}
Expand All @@ -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<ThreadSchedulePolicy, Error> {
unsafe { ThreadSchedulePolicy::from_posix(libc::sched_getscheduler(libc::getpid())) }
}
Expand Down Expand Up @@ -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();
Expand Down
Loading