Fix: simpler scheduling

This commit is contained in:
2026-02-03 15:55:43 +01:00
parent 266a625cf3
commit 3284354f40
4 changed files with 125 additions and 103 deletions

View File

@@ -42,6 +42,54 @@ pub fn is_memory_locked() -> bool {
MLOCKALL_SUCCESS.load(Ordering::Relaxed)
}
/// Attempts to set realtime scheduling priority for the current thread.
/// Returns true if RT priority was successfully set, false otherwise.
#[cfg(target_os = "macos")]
pub fn set_realtime_priority() -> bool {
// macOS: use THREAD_TIME_CONSTRAINT_POLICY for true RT scheduling.
// This is the same mechanism CoreAudio uses for its audio threads.
// SCHED_FIFO/RR require root on macOS, but time constraint policy does not.
unsafe {
let thread = libc::pthread_self();
#[repr(C)]
struct ThreadTimeConstraintPolicy {
period: u32,
computation: u32,
constraint: u32,
preemptible: i32,
}
const THREAD_TIME_CONSTRAINT_POLICY_ID: u32 = 2;
const THREAD_TIME_CONSTRAINT_POLICY_COUNT: u32 = 4;
// ~1ms period at ~1GHz mach_absolute_time ticks (typical for audio)
let policy = ThreadTimeConstraintPolicy {
period: 1_000_000,
computation: 500_000,
constraint: 1_000_000,
preemptible: 1,
};
extern "C" {
fn thread_policy_set(
thread: libc::pthread_t,
flavor: u32,
policy_info: *const ThreadTimeConstraintPolicy,
count: u32,
) -> i32;
}
let result = thread_policy_set(
thread,
THREAD_TIME_CONSTRAINT_POLICY_ID,
&policy,
THREAD_TIME_CONSTRAINT_POLICY_COUNT,
);
result == 0
}
}
/// Attempts to set realtime scheduling priority for the current thread.
/// Returns true if RT priority was successfully set, false otherwise.
///
@@ -50,7 +98,7 @@ pub fn is_memory_locked() -> bool {
/// - Configured rtprio limits in /etc/security/limits.conf:
/// @audio - rtprio 95
/// @audio - memlock unlimited
#[cfg(unix)]
#[cfg(target_os = "linux")]
pub fn set_realtime_priority() -> bool {
use thread_priority::unix::{
set_thread_priority_and_policy, thread_native_id, NormalThreadSchedulePolicy,
@@ -60,27 +108,22 @@ pub fn set_realtime_priority() -> bool {
let tid = thread_native_id();
// Try SCHED_FIFO first (requires CAP_SYS_NICE on Linux)
let fifo = ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Fifo);
if set_thread_priority_and_policy(tid, ThreadPriority::Max, fifo).is_ok() {
return true;
}
// Try SCHED_RR (round-robin realtime, sometimes works without caps)
let rr = ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::RoundRobin);
if set_thread_priority_and_policy(tid, ThreadPriority::Max, rr).is_ok() {
return true;
}
// Fall back to highest normal priority (SCHED_OTHER)
let _ = set_thread_priority_and_policy(
tid,
ThreadPriority::Max,
ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Other),
);
// Also try nice -20 on Linux
#[cfg(target_os = "linux")]
unsafe {
libc::setpriority(libc::PRIO_PROCESS, 0, -20);
}
@@ -88,7 +131,12 @@ pub fn set_realtime_priority() -> bool {
false
}
#[cfg(not(unix))]
#[cfg(not(any(unix, target_os = "windows")))]
pub fn set_realtime_priority() -> bool {
false
}
#[cfg(target_os = "windows")]
pub fn set_realtime_priority() -> bool {
use thread_priority::{set_current_thread_priority, ThreadPriority};
set_current_thread_priority(ThreadPriority::Max).is_ok()