From 4843992018a65704d136f2616a6e5ca95eb8f249 Mon Sep 17 00:00:00 2001 From: Victor Polevoy Date: Sat, 20 Aug 2022 15:53:35 +0200 Subject: [PATCH 1/4] Use thread niceness to control threads with non-relatime policies. If a thread has a non-realtime policy, its priority is controlled with niceness; otherwise via pthread's sched param. --- Cargo.toml | 4 +- src/lib.rs | 8 +- src/unix.rs | 259 +++++++++++++++++++++++++++++++++++--------------- tests/unix.rs | 33 ++++--- 4 files changed, 211 insertions(+), 93 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d2b4bb..f0340bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thread-priority" -version = "0.8.2" +version = "0.9.0" authors = ["Victor Polevoy "] description = "Library for managing threads priority and schedule policies" repository = "https://github.com/vityafx/thread-priority" @@ -12,7 +12,7 @@ categories = ["concurrency", "asynchronous", "os"] edition = "2018" [dev-dependencies] -rstest = "0.12" +rstest = "0.15" [dependencies] log = "0.4" diff --git a/src/lib.rs b/src/lib.rs index 3fadaff..d91c7eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,12 +165,18 @@ pub enum Error { /// ``` #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct ThreadPriorityValue(u8); +impl ThreadPriorityValue { + /// The maximum value for a thread priority. + pub const MAX: u8 = 100; + /// The minimum value for a thread priority. + pub const MIN: u8 = 0; +} impl std::convert::TryFrom for ThreadPriorityValue { type Error = &'static str; fn try_from(value: u8) -> Result { - if (0..=99).contains(&value) { + if (Self::MIN..Self::MAX).contains(&value) { Ok(Self(value)) } else { Err("The value is not in the range of [0;99]") diff --git a/src/unix.rs b/src/unix.rs index b3b1c1b..3758b90 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -24,6 +24,13 @@ use std::mem::MaybeUninit; /// An alias type for a thread id. pub type ThreadId = libc::pthread_t; +/// The maximum value possible for niceness. Threads with this value +/// of niceness have the highest priority possible +pub const NICENESS_MAX: i8 = -20; +/// The minimum value possible for niceness. Threads with this value +/// of niceness have the lowest priority possible. +pub const NICENESS_MIN: i8 = 19; + /// Proxy structure to maintain compatibility between glibc and musl #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct ScheduleParams { @@ -114,16 +121,46 @@ impl RealtimeThreadSchedulePolicy { } } -/// Normal (usual) schedule policies +/// Normal (non-realtime) schedule policies +/// For these schedule policies, [`niceness`](https://man7.org/linux/man-pages/man7/sched.7.html) +/// is used. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum NormalThreadSchedulePolicy { - /// For running very low priority background jobs + /// For running very low priority background jobs. + /// (Since Linux 2.6.23.) `SCHED_IDLE` can be used only at static priority 0; + /// the process nice value has no influence for this policy. + /// + /// This policy is intended for running jobs at extremely low priority (lower even + /// than a +19 nice value with the SCHED_OTHER or SCHED_BATCH policies). #[cfg(target_os = "linux")] Idle, - /// For "batch" style execution of processes + /// For "batch" style execution of processes. + /// (Since Linux 2.6.16.) `SCHED_BATCH` can be used only at static priority 0. + /// This policy is similar to SCHED_OTHER in that it schedules the thread + /// according to its dynamic priority (based on the nice value). The difference is + /// that this policy will cause the scheduler to always assume that the thread is + /// CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty + /// with respect to wakeup behavior, so that this thread is mildly disfavored in scheduling decisions. + /// + /// This policy is useful for workloads that are noninteractive, but do not want to lower their + /// nice value, and for workloads that want a deterministic scheduling policy without interactivity + /// causing extra preemptions (between the workload's tasks). #[cfg(target_os = "linux")] Batch, - /// The standard round-robin time-sharing policy + /// The standard round-robin time-sharing policy, also sometimes referred to as "Normal". + /// + /// `SCHED_OTHER` can be used at only static priority 0 (i.e., threads under real-time policies + /// always have priority over `SCHED_OTHER` processes). `SCHED_OTHER` is the standard Linux + /// time-sharing scheduler that is intended for all threads that do not require the special + /// real-time mechanisms. + /// + /// The thread to run is chosen from the static priority 0 list based on a dynamic priority that + /// is determined only inside this list. The dynamic priority is based on the nice value (see below) + /// and is increased for each time quantum the thread is ready to run, but denied to run by the scheduler. + /// + /// This ensures fair progress among all `SCHED_OTHER` threads. + /// + /// In the Linux kernel source code, the `SCHED_OTHER` policy is actually named `SCHED_NORMAL`. Other, } impl NormalThreadSchedulePolicy { @@ -138,12 +175,12 @@ impl NormalThreadSchedulePolicy { } } -/// Thread schedule policy definition +/// Thread schedule policy definition. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum ThreadSchedulePolicy { - /// Normal thread schedule policies + /// Normal thread schedule policies. Normal(NormalThreadSchedulePolicy), - /// Realtime thread schedule policies + /// Realtime thread schedule policies. Realtime(RealtimeThreadSchedulePolicy), } impl ThreadSchedulePolicy { @@ -186,22 +223,45 @@ impl ThreadPriority { /// Returns the maximum allowed value for using with the provided policy. /// The returned number is in the range of allowed values. pub fn max_value_for_policy(policy: ThreadSchedulePolicy) -> Result { - let max_priority = unsafe { libc::sched_get_priority_max(policy.to_posix()) }; - if max_priority < 0 { - Err(Error::OS(errno())) - } else { - Ok(max_priority) + match policy { + #[cfg(target_os = "linux")] + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) => { + // Only `0` can be returned for `Idle` threads. + Ok(0) + } + ThreadSchedulePolicy::Normal(_) => { + // Niceness can be used, from -20 to 19, where `-20` is the maximum. + Ok(NICENESS_MAX as libc::c_int) + } + _ => { + let max_priority = unsafe { libc::sched_get_priority_max(policy.to_posix()) }; + if max_priority < 0 { + Err(Error::OS(errno())) + } else { + Ok(max_priority) + } + } } } /// Returns the minimum allowed value for using with the provided policy. /// The returned number is in the range of allowed values. pub fn min_value_for_policy(policy: ThreadSchedulePolicy) -> Result { - let min_priority = unsafe { libc::sched_get_priority_min(policy.to_posix()) }; - if min_priority < 0 { - Err(Error::OS(errno())) - } else { - Ok(min_priority) + match policy { + #[cfg(target_os = "linux")] + ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) => Ok(0), + ThreadSchedulePolicy::Normal(_) => { + // Niceness can be used, from -20 to 19, where `-20` is the maximum. + Ok(NICENESS_MIN as libc::c_int) + } + _ => { + let min_priority = unsafe { libc::sched_get_priority_min(policy.to_posix()) }; + if min_priority < 0 { + Err(Error::OS(errno())) + } else { + Ok(min_priority) + } + } } } @@ -212,7 +272,11 @@ impl ThreadPriority { ) -> Result { let min_priority = Self::min_value_for_policy(policy)?; let max_priority = Self::max_value_for_policy(policy)?; - let allowed_range = min_priority..=max_priority; + let (min, max) = ( + std::cmp::min(min_priority, max_priority), + std::cmp::max(min_priority, max_priority), + ); + let allowed_range = min..=max; if allowed_range.contains(&priority) { Ok(priority) } else { @@ -223,6 +287,11 @@ impl ThreadPriority { /// Converts the priority stored to a posix number. /// POSIX value can not be known without knowing the scheduling policy /// + /// + /// For threads scheduled under one of the normal scheduling policies (SCHED_OTHER, SCHED_IDLE, SCHED_BATCH), sched_priority is not used in scheduling decisions (it must be specified as 0). + /// Source: + /// Due to this restriction of normal scheduling policies and the intention of the library, the niceness is used + /// instead for such processes. pub fn to_posix(self, policy: ThreadSchedulePolicy) -> Result { let ret = match self { ThreadPriority::Min => match policy { @@ -239,7 +308,16 @@ impl ThreadPriority { ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Deadline) => Err( Error::Priority("Deadline scheduling must use deadline priority."), ), - _ => Self::to_allowed_value_for_policy(p as i32, policy).map(|v| v as u32), + ThreadSchedulePolicy::Realtime(_) => { + Self::to_allowed_value_for_policy(p as i32, policy).map(|v| v as u32) + } + ThreadSchedulePolicy::Normal(_) => { + let niceness_values = NICENESS_MAX.abs() + NICENESS_MIN.abs(); + let ratio = p as f32 / ThreadPriorityValue::MAX as f32; + let niceness = ((niceness_values as f32 * ratio) as i8 + NICENESS_MAX) as i32; + dbg!(niceness_values, ratio, niceness); + Self::to_allowed_value_for_policy(niceness, policy).map(|v| v as u32) + } }, // TODO avoid code duplication. ThreadPriority::Os(crate::ThreadPriorityOsValue(p)) => match policy { @@ -278,6 +356,60 @@ impl ThreadPriority { } } +fn set_thread_priority_and_policy_deadline( + native: ThreadId, + priority: ThreadPriority, +) -> Result<(), Error> { + use std::convert::TryInto as _; + + let (runtime, deadline, period) = match priority { + ThreadPriority::Deadline { + runtime, + deadline, + period, + } => (|| { + Ok(( + runtime.as_nanos().try_into()?, + deadline.as_nanos().try_into()?, + period.as_nanos().try_into()?, + )) + })() + .map_err(|_: std::num::TryFromIntError| { + Error::Priority("Deadline policy durations don't fit into a `u64`.") + })?, + _ => { + return Err(Error::Priority( + "Deadline policy given without deadline priority.", + )) + } + }; + let tid = native as libc::pid_t; + let sched_attr = SchedAttr { + size: std::mem::size_of::() as u32, + sched_policy: RealtimeThreadSchedulePolicy::Deadline.to_posix() as u32, + + sched_runtime: runtime, + sched_deadline: deadline, + sched_period: period, + + ..Default::default() + }; + let ret = unsafe { + libc::syscall( + libc::SYS_sched_setattr, + tid, + &sched_attr as *const _, + // we are not setting SCHED_FLAG_RECLAIM nor SCHED_FLAG_DL_OVERRUN + 0, + ) as i32 + }; + + match ret { + 0 => Ok(()), + e => Err(Error::OS(e)), + } +} + /// Sets thread's priority and schedule policy /// /// * May require privileges @@ -305,71 +437,46 @@ pub fn set_thread_priority_and_policy( priority: ThreadPriority, policy: ThreadSchedulePolicy, ) -> Result<(), Error> { - let ret = match policy { + match policy { // SCHED_DEADLINE policy requires its own syscall #[cfg(target_os = "linux")] ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Deadline) => { - use std::convert::TryInto as _; - let (runtime, deadline, period) = match priority { - ThreadPriority::Deadline { - runtime, - deadline, - period, - } => (|| { - Ok(( - runtime.as_nanos().try_into()?, - deadline.as_nanos().try_into()?, - period.as_nanos().try_into()?, - )) - })() - .map_err(|_: std::num::TryFromIntError| { - Error::Priority("Deadline policy durations don't fit into a `u64`.") - })?, - _ => { - return Err(Error::Priority( - "Deadline policy given without deadline priority.", - )) - } - }; - let tid = native as libc::pid_t; - let sched_attr = SchedAttr { - size: std::mem::size_of::() as u32, - sched_policy: policy.to_posix() as u32, - - sched_runtime: runtime, - sched_deadline: deadline, - sched_period: period, - - ..Default::default() - }; - unsafe { - libc::syscall( - libc::SYS_sched_setattr, - tid, - &sched_attr as *const _, - // we are not setting SCHED_FLAG_RECLAIM nor SCHED_FLAG_DL_OVERRUN - 0, - ) as i32 - } + set_thread_priority_and_policy_deadline(native, priority) } _ => { let fixed_priority = priority.to_posix(policy)?; - let params = ScheduleParams { - sched_priority: fixed_priority, - } - .into_posix(); - unsafe { - libc::pthread_setschedparam( - native, - policy.to_posix(), - ¶ms as *const libc::sched_param, - ) + dbg!(policy, priority, fixed_priority); + if let ThreadSchedulePolicy::Realtime(_) = policy { + // If the policy is a realtime one, the priority is set via + // pthread_setschedparam. + let params = ScheduleParams { + sched_priority: fixed_priority, + } + .into_posix(); + + let ret = unsafe { + libc::pthread_setschedparam( + native, + policy.to_posix(), + ¶ms as *const libc::sched_param, + ) + }; + + match ret { + 0 => Ok(()), + e => Err(Error::OS(e)), + } + } else { + // If this is a normal-scheduled thread, the priority is + // set via niceness. + let ret = unsafe { libc::nice(fixed_priority) }; + + match ret { + -1 => Err(Error::OS(errno())), + _ => Ok(()), + } } } - }; - match ret { - 0 => Ok(()), - e => Err(Error::OS(e)), } } diff --git a/tests/unix.rs b/tests/unix.rs index cd7d294..6a4badb 100644 --- a/tests/unix.rs +++ b/tests/unix.rs @@ -13,16 +13,16 @@ fn get_and_set_priority_with_normal_policies( ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Batch) )] policy: ThreadSchedulePolicy, - #[values(ThreadPriority::Min, ThreadPriority::Max)] correct_priority: ThreadPriority, - #[values(ThreadPriority::Crossplatform(23u8.try_into().unwrap()))] - incorrect_priority: ThreadPriority, + #[values(ThreadPriority::Min, ThreadPriority::Max, ThreadPriority::Crossplatform(23u8.try_into().unwrap()))] + priority: ThreadPriority, ) { - // In Linux it is only allowed to specify zero as a priority for normal scheduling policies. - assert!( - set_thread_priority_and_policy(thread_native_id(), incorrect_priority, policy,).is_err() - ); - // For the case Min or Max is used, it is implicitly set to `0` so that there is no actual error. - assert!(set_thread_priority_and_policy(thread_native_id(), correct_priority, policy,).is_ok()); + let ret = set_thread_priority_and_policy(thread_native_id(), priority, policy); + if policy == ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) + && priority == ThreadPriority::Crossplatform(23u8.try_into().unwrap()) { + assert_eq!(ret, Err(Error::PriorityNotInRange(0..=0))); + } else { + assert!(ret.is_ok()); + } } #[cfg(any( @@ -46,8 +46,8 @@ fn get_and_set_priority_with_normal_policies( #[cfg(target_os = "linux")] #[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle), 0..=0)] #[cfg(target_os = "linux")] -#[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Batch), 0..=0)] -#[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other), 0..=0)] +#[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Batch), -20..=19)] +#[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other), -20..=19)] #[case(ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Fifo), 0..=99)] #[case(ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::RoundRobin), 0..=99)] fn check_min_and_max_priority_values( @@ -68,6 +68,13 @@ fn check_min_and_max_priority_values( #[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other))] fn set_priority_with_normal_policy_but_with_invalid_value(#[case] policy: ThreadSchedulePolicy) { let thread_id = thread_native_id(); + let expected = if policy == ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) { + // In Linux we should get an error whenever a non-zero value is passed as priority and a normal + // scheduling policy is used. + Err(Error::PriorityNotInRange(0..=0)) + } else { + Ok(()) + }; assert_eq!( set_thread_priority_and_policy( @@ -75,9 +82,7 @@ fn set_priority_with_normal_policy_but_with_invalid_value(#[case] policy: Thread ThreadPriority::Crossplatform(23u8.try_into().unwrap()), policy, ), - // In Linux we should get an error whenever a non-zero value is passed as priority and a normal - // scheduling policy is used. - Err(Error::PriorityNotInRange(0..=0)) + expected ); } From 449b614f25cbc0e7db5ff8f4c4ba1664d9e569b2 Mon Sep 17 00:00:00 2001 From: Victor Polevoy Date: Sat, 20 Aug 2022 15:55:35 +0200 Subject: [PATCH 2/4] Address clippy lints. --- tests/unix.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unix.rs b/tests/unix.rs index 6a4badb..ac1a9b5 100644 --- a/tests/unix.rs +++ b/tests/unix.rs @@ -18,7 +18,8 @@ fn get_and_set_priority_with_normal_policies( ) { let ret = set_thread_priority_and_policy(thread_native_id(), priority, policy); if policy == ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) - && priority == ThreadPriority::Crossplatform(23u8.try_into().unwrap()) { + && priority == ThreadPriority::Crossplatform(23u8.try_into().unwrap()) + { assert_eq!(ret, Err(Error::PriorityNotInRange(0..=0))); } else { assert!(ret.is_ok()); From abf7da7a74bd8b5bd5bcd34cba83c26ec4101bdd Mon Sep 17 00:00:00 2001 From: Victor Polevoy Date: Sat, 20 Aug 2022 16:02:17 +0200 Subject: [PATCH 3/4] Fix macOS and BSD tests. --- src/unix.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix.rs b/src/unix.rs index 3758b90..1914342 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -356,6 +356,7 @@ impl ThreadPriority { } } +#[cfg(target_os = "linux")] fn set_thread_priority_and_policy_deadline( native: ThreadId, priority: ThreadPriority, From 8a9e02cd7e137f09c9fab310216507af463baadd Mon Sep 17 00:00:00 2001 From: Victor Polevoy Date: Sat, 20 Aug 2022 16:27:09 +0200 Subject: [PATCH 4/4] Test that for BSD's normal threads niceness is used. Also attempts to solve the CI issue with the registry. --- .github/workflows/ci.yml | 14 +++++++++++--- Cargo.toml | 2 +- src/unix.rs | 28 ++++++++++++++++++++++------ tests/unix.rs | 19 +++++-------------- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35f95f4..9cc5c64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,9 +56,17 @@ jobs: if: matrix.features == '' run: cargo build --all-features - - name: Test all features (other) - if: matrix.features == '' && runner.os != 'Linux' - run: cargo test --all-features -- --skip set_deadline_policy + - name: Test all features (macos) + if: matrix.features == '' && runner.os == 'macOS' + run: sudo -E /Users/runner/.cargo/bin/cargo test --all-features + + - name: Test all features (Windows) + if: matrix.features == '' && runner.os == 'Windows' + run: cargo test --all-features + + - name: Test all features (non-linux and non-macOS) + if: matrix.features == '' && runner.os != 'Linux' && runner.os != 'macOS' && runner.os != 'Windows' + run: sudo -E /home/runner/.cargo/bin/cargo test --all-features -- --skip set_deadline_policy - name: Test all features (Linux) if: matrix.features == '' && runner.os == 'Linux' diff --git a/Cargo.toml b/Cargo.toml index f0340bd..161f6f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["concurrency", "asynchronous", "os"] edition = "2018" [dev-dependencies] -rstest = "0.15" +rstest = "0.13" [dependencies] log = "0.4" diff --git a/src/unix.rs b/src/unix.rs index 1914342..b0209f3 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -54,6 +54,22 @@ fn errno() -> libc::c_int { } } +fn set_errno(number: libc::c_int) { + unsafe { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] { + *libc::__errno() = number; + } else if #[cfg(target_os = "linux")] { + *libc::__errno_location() = number; + } else if #[cfg(any(target_os = "macos", target_os = "freebsd"))] { + *libc::__error() = number; + } else { + compile_error!("Your OS is probably not supported.") + } + } + } +} + /// Copy of the Linux kernel's sched_attr type #[repr(C)] #[derive(Debug, Default)] @@ -315,7 +331,6 @@ impl ThreadPriority { let niceness_values = NICENESS_MAX.abs() + NICENESS_MIN.abs(); let ratio = p as f32 / ThreadPriorityValue::MAX as f32; let niceness = ((niceness_values as f32 * ratio) as i8 + NICENESS_MAX) as i32; - dbg!(niceness_values, ratio, niceness); Self::to_allowed_value_for_policy(niceness, policy).map(|v| v as u32) } }, @@ -446,7 +461,6 @@ pub fn set_thread_priority_and_policy( } _ => { let fixed_priority = priority.to_posix(policy)?; - dbg!(policy, priority, fixed_priority); if let ThreadSchedulePolicy::Realtime(_) = policy { // If the policy is a realtime one, the priority is set via // pthread_setschedparam. @@ -470,11 +484,13 @@ pub fn set_thread_priority_and_policy( } else { // If this is a normal-scheduled thread, the priority is // set via niceness. - let ret = unsafe { libc::nice(fixed_priority) }; + set_errno(0); - match ret { - -1 => Err(Error::OS(errno())), - _ => Ok(()), + unsafe { libc::nice(fixed_priority) }; + + match errno() { + 0 => Ok(()), + e => Err(Error::OS(e)), } } } diff --git a/tests/unix.rs b/tests/unix.rs index ac1a9b5..4dc1569 100644 --- a/tests/unix.rs +++ b/tests/unix.rs @@ -26,6 +26,7 @@ fn get_and_set_priority_with_normal_policies( } } +// In macOS it is allowed to specify number as a SCHED_OTHER policy priority. #[cfg(any( target_os = "macos", target_os = "openbsd", @@ -39,8 +40,7 @@ fn get_and_set_priority_with_normal_policies( #[values(ThreadPriority::Min, ThreadPriority::Max, ThreadPriority::Crossplatform(23u8.try_into().unwrap()))] priority: ThreadPriority, ) { - // In macOS it is allowed to specify number as a SCHED_OTHER policy priority. - assert!(set_thread_priority_and_policy(thread_native_id(), priority, policy,).is_ok()); + assert!(set_thread_priority_and_policy(thread_native_id(), priority, policy).is_ok()); } #[rstest] @@ -69,6 +69,7 @@ fn check_min_and_max_priority_values( #[case(ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other))] fn set_priority_with_normal_policy_but_with_invalid_value(#[case] policy: ThreadSchedulePolicy) { let thread_id = thread_native_id(); + #[cfg(target_os = "linux")] let expected = if policy == ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Idle) { // In Linux we should get an error whenever a non-zero value is passed as priority and a normal // scheduling policy is used. @@ -94,7 +95,8 @@ fn set_priority_with_normal_policy_but_with_invalid_value(#[case] policy: Thread target_os = "netbsd" ))] #[test] -// In macOS the SCHED_OTHER policy allows having a non-zero priority value. +// In macOS the SCHED_OTHER policy allows having a non-zero priority value, +// but the crate doesn't use this opportunity for normal threads and uses niceness instead. fn get_and_set_priority_with_normal_policy() { let thread_id = thread_native_id(); let normal_policy = ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other); @@ -108,17 +110,6 @@ fn get_and_set_priority_with_normal_policy() { Ok(()) ); assert_eq!(thread_schedule_policy(), Ok(normal_policy)); - assert_eq!( - thread_schedule_policy_param(thread_native_id()), - Ok((normal_policy, ScheduleParams { sched_priority: 23 })) - ); - assert_eq!( - Thread::current(), - Ok(Thread { - priority: ThreadPriority::Crossplatform(23u8.try_into().unwrap()), - id: thread_native_id() - }) - ); } #[rstest]