use crate::common::spsc::RtStatusFlags;
use std::sync::Arc;
use std::sync::atomic::Ordering;
const PR_THP_DISABLE_EXCEPT_ADVISED: libc::c_ulong = 2;
pub fn configure_process_wide() {
unsafe {
let ret = libc::prctl(
libc::PR_SET_THP_DISABLE,
1,
PR_THP_DISABLE_EXCEPT_ADVISED,
0,
0,
);
if ret == -1 && *libc::__errno_location() == libc::EINVAL {
let err = std::io::Error::last_os_error();
log::info!(
"Kernel does not support PR_THP_DISABLE_EXCEPT_ADVISED (errno={}: {}) — \
falling back to classic PR_SET_THP_DISABLE.",
err.raw_os_error().unwrap_or(-1),
err,
);
let classic_ret = libc::prctl(libc::PR_SET_THP_DISABLE, 1, 0, 0, 0);
if classic_ret == -1 {
let fallback_err = std::io::Error::last_os_error();
log::warn!(
"Classic PR_SET_THP_DISABLE also failed (errno={}: {}). \
THP may remain active — background compaction latencies possible.",
fallback_err.raw_os_error().unwrap_or(-1),
fallback_err,
);
} else {
log::info!(
"Transparent Huge Pages globally disabled (classic fallback). \
Only MADV_HUGEPAGE regions may use THP."
);
}
} else if ret == -1 {
let err = std::io::Error::last_os_error();
log::warn!(
"prctl(PR_SET_THP_DISABLE) failed with unexpected errno={}: {}. \
THP state unknown — background compaction latencies possible.",
err.raw_os_error().unwrap_or(-1),
err,
);
}
}
let ret_mlock = unsafe { libc::mlockall(libc::MCL_CURRENT | libc::MCL_FUTURE) };
if ret_mlock != 0 {
let err = std::io::Error::last_os_error();
log::warn!(
"mlockall() failed ({}). Audio may experience dropouts if the system swaps.\n Hint: Verify the 'memlock' limit in ulimits.",
err
);
} else {
log::info!("🔒 Memory Protection: Locked in physical RAM to prevent dropouts (mlockall).");
}
}
#[cold]
#[inline(never)]
pub fn configure_realtime_thread(target_cpu: usize, rt_status: Arc<RtStatusFlags>) {
let cpu_setsize = libc::CPU_SETSIZE as usize;
let cpu_in_bounds = target_cpu < cpu_setsize;
if !cpu_in_bounds {
rt_status.rt_affinity_err.store(-1, Ordering::Relaxed);
rt_status
.rt_target_cpu
.store(target_cpu as i32, Ordering::Relaxed);
}
unsafe {
crate::math::common::set_daz_ftz();
}
let thread_id = unsafe { libc::pthread_self() };
unsafe {
let name = b"nam_rs_dsp\0";
libc::pthread_setname_np(thread_id, name.as_ptr() as *const libc::c_char);
}
if cpu_in_bounds {
let mut cpuset = std::mem::MaybeUninit::<libc::cpu_set_t>::uninit();
unsafe {
libc::CPU_ZERO(cpuset.assume_init_mut());
libc::CPU_SET(target_cpu, cpuset.assume_init_mut());
}
let cpuset = unsafe { cpuset.assume_init() };
let ret_aff = unsafe {
libc::pthread_setaffinity_np(thread_id, std::mem::size_of::<libc::cpu_set_t>(), &cpuset)
};
if ret_aff != 0 {
rt_status.rt_affinity_err.store(ret_aff, Ordering::Relaxed);
rt_status
.rt_target_cpu
.store(target_cpu as i32, Ordering::Relaxed);
}
}
let mut actual_policy = 0i32;
let mut actual_param = libc::sched_param { sched_priority: 0 };
let ret_getsched =
unsafe { libc::pthread_getschedparam(thread_id, &mut actual_policy, &mut actual_param) };
let actual_cpu = unsafe { libc::sched_getcpu() };
rt_status.rt_cpu.store(actual_cpu, Ordering::Relaxed);
if ret_getsched == 0 {
let mut base_policy = actual_policy & !0x40000000i32;
if base_policy != libc::SCHED_FIFO {
let param = libc::sched_param { sched_priority: 90 };
let ret_sched =
unsafe { libc::pthread_setschedparam(thread_id, libc::SCHED_FIFO, ¶m) };
if ret_sched != 0 {
rt_status.rt_sched_err.store(ret_sched, Ordering::Relaxed);
} else {
base_policy = libc::SCHED_FIFO;
actual_param.sched_priority = 90;
}
}
let confirmed_fifo = base_policy == libc::SCHED_FIFO;
if confirmed_fifo {
rt_status.set_flag(crate::common::spsc::RT_STATUS_RT_IS_FIFO);
} else {
rt_status.clear_flag(crate::common::spsc::RT_STATUS_RT_IS_FIFO);
}
rt_status
.rt_priority
.store(actual_param.sched_priority, Ordering::Relaxed);
rt_status
.confirmed_priority
.store(actual_param.sched_priority, Ordering::Relaxed);
rt_status.rt_policy.store(base_policy, Ordering::Relaxed);
} else {
rt_status.clear_flag(crate::common::spsc::RT_STATUS_RT_IS_FIFO);
rt_status.rt_priority.store(0, Ordering::Relaxed);
rt_status.confirmed_priority.store(-1, Ordering::Relaxed);
rt_status.rt_policy.store(-1, Ordering::Relaxed);
rt_status
.rt_getsched_err
.store(ret_getsched, Ordering::Relaxed);
}
}