Fix: simpler scheduling
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user