зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1633266 - mach vendor rust r=kinetik
Depends on D72636 Differential Revision: https://phabricator.services.mozilla.com/D72637
This commit is contained in:
Родитель
58207a1a00
Коммит
f0c2c239ef
|
@ -110,9 +110,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "audio_thread_priority"
|
||||
version = "0.22.0"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "407b1b70ad4072a4ff430679b331450166b56631091d6ba46a885cf427392055"
|
||||
checksum = "f8fba1500e466a39dd3faa5aed20a50dfe0aa1b905264a453bbe9f49508994cc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dbus",
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"a052ce27f486df5cdd0cb1324e2f79546637d70dba561bf0bc882c0c7c81390b","Makefile":"0f9a771cfb30c7c4b9961d82fdca4e9e229a955bb2e636474a4101389e18e938","README.md":"bcfa4948edf52fdacd485200a0c1c886a92232cc1931eeb4e1044050f46ec253","atp_test.cpp":"8075a040941a65fb9e3f7cbf0535853ca6661c3ac442ec35569b42b24bbec797","audio_thread_priority.h":"f0ecaf1b674f794cde0dc834028e074d4e4675d22ae96acf08b2ae1dceb3474e","generate_osx_bindings.sh":"06e4e03450f788ced18d31fff5660919e6f6ec1119ddace363ffeb82f0518a71","src/lib.rs":"bf13cd15ac452f11ff367b86693b5cd6f57f8b9a8524e8ab0777af1c84905dc4","src/mach_sys.rs":"352560fcb9b41d877cff92e5b3b04d6dc68b1f30508ce4b9aed78940120a883e","src/rt_linux.rs":"87468ace38db310cb4ea9b87dd4be25b9f1d3cea08978bc9aba504f1fa3ba689","src/rt_mach.rs":"3f864805297b1172ed39b0ffe8888d21ec51cdc6183b31273f3f915473e31234","src/rt_win.rs":"3aabdcf6db810e23086c8710f55027f322e721b43a28dc7c544ca32a6d7964a5"},"package":"407b1b70ad4072a4ff430679b331450166b56631091d6ba46a885cf427392055"}
|
||||
{"files":{"Cargo.toml":"ae2be582a99b1543db352c63c02a739dceb0c99ec3f632284d01f8504645c1e8","Makefile":"0f9a771cfb30c7c4b9961d82fdca4e9e229a955bb2e636474a4101389e18e938","README.md":"bcfa4948edf52fdacd485200a0c1c886a92232cc1931eeb4e1044050f46ec253","atp_test.cpp":"8075a040941a65fb9e3f7cbf0535853ca6661c3ac442ec35569b42b24bbec797","audio_thread_priority.h":"f0ecaf1b674f794cde0dc834028e074d4e4675d22ae96acf08b2ae1dceb3474e","generate_osx_bindings.sh":"06e4e03450f788ced18d31fff5660919e6f6ec1119ddace363ffeb82f0518a71","src/lib.rs":"bf13cd15ac452f11ff367b86693b5cd6f57f8b9a8524e8ab0777af1c84905dc4","src/mach_sys.rs":"352560fcb9b41d877cff92e5b3b04d6dc68b1f30508ce4b9aed78940120a883e","src/rt_linux.rs":"33f982272dd53b5e60f93ca7803c7fe3d6e615edd122bcc60cb5482e34cf8a35","src/rt_mach.rs":"a7b4deef4bebcdaa6ca6156fe5de5456bc8a61143d6764d1e3f54e639c9653da","src/rt_win.rs":"347e3ae753cefa38cf913f55f84a63a36d97f6be5f6e3c41e9da0c3ffa71ac17"},"package":"f8fba1500e466a39dd3faa5aed20a50dfe0aa1b905264a453bbe9f49508994cc"}
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "audio_thread_priority"
|
||||
version = "0.22.0"
|
||||
version = "0.22.1"
|
||||
authors = ["Paul Adenot <paul@paul.cx>"]
|
||||
description = "Bump a thread to real-time priority, for audio work, on Linux, Windows and macOS"
|
||||
license = "MPL-2.0"
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::cmp;
|
|||
use std::error::Error;
|
||||
use std::io::Error as OSError;
|
||||
|
||||
use dbus::{Connection, BusType, Props, MessageItem, Message};
|
||||
use dbus::{BusType, Connection, Message, MessageItem, Props};
|
||||
|
||||
use crate::AudioThreadPriorityError;
|
||||
|
||||
|
@ -23,7 +23,11 @@ type kernel_pid_t = libc::c_long;
|
|||
|
||||
impl From<dbus::Error> for AudioThreadPriorityError {
|
||||
fn from(error: dbus::Error) -> Self {
|
||||
AudioThreadPriorityError::new(&format!("{}:{}", error.name().unwrap(), error.message().unwrap()))
|
||||
AudioThreadPriorityError::new(&format!(
|
||||
"{}:{}",
|
||||
error.name().unwrap_or("?"),
|
||||
error.message().unwrap_or("?")
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +49,7 @@ pub struct RtPriorityThreadInfoInternal {
|
|||
/// The PID of the process containing `thread_id` below.
|
||||
pid: libc::pid_t,
|
||||
/// ...
|
||||
policy: libc::c_int
|
||||
policy: libc::c_int,
|
||||
}
|
||||
|
||||
impl RtPriorityThreadInfoInternal {
|
||||
|
@ -61,8 +65,7 @@ impl RtPriorityThreadInfoInternal {
|
|||
|
||||
impl PartialEq for RtPriorityThreadInfoInternal {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.thread_id == other.thread_id &&
|
||||
self.pthread_id == other.pthread_id
|
||||
self.thread_id == other.thread_id && self.pthread_id == other.pthread_id
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,23 +78,30 @@ fn item_as_i64(i: MessageItem) -> Result<i64, AudioThreadPriorityError> {
|
|||
match i {
|
||||
MessageItem::Int32(i) => Ok(i as i64),
|
||||
MessageItem::Int64(i) => Ok(i),
|
||||
_ => Err(AudioThreadPriorityError::new(&format!("Property is not integer ({:?})", i)))
|
||||
_ => Err(AudioThreadPriorityError::new(&format!(
|
||||
"Property is not integer ({:?})",
|
||||
i
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn rtkit_set_realtime(thread: u64, pid: u64, prio: u32) -> Result<(), Box<dyn Error>> {
|
||||
let m = if unsafe { libc::getpid() as u64 } == pid {
|
||||
let mut m = Message::new_method_call("org.freedesktop.RealtimeKit1",
|
||||
"/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtime")?;
|
||||
let mut m = Message::new_method_call(
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtime",
|
||||
)?;
|
||||
m.append_items(&[thread.into(), prio.into()]);
|
||||
m
|
||||
} else {
|
||||
let mut m = Message::new_method_call("org.freedesktop.RealtimeKit1",
|
||||
"/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtimeWithPID")?;
|
||||
let mut m = Message::new_method_call(
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtimeWithPID",
|
||||
)?;
|
||||
m.append_items(&[pid.into(), thread.into(), prio.into()]);
|
||||
m
|
||||
};
|
||||
|
@ -105,25 +115,37 @@ fn rtkit_set_realtime(thread: u64, pid: u64, prio: u32) -> Result<(), Box<dyn Er
|
|||
fn get_limits() -> Result<(i64, u64, libc::rlimit64), AudioThreadPriorityError> {
|
||||
let c = Connection::get_private(BusType::System)?;
|
||||
|
||||
let p = Props::new(&c, "org.freedesktop.RealtimeKit1", "/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1", DBUS_SOCKET_TIMEOUT);
|
||||
let p = Props::new(
|
||||
&c,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"/org/freedesktop/RealtimeKit1",
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
DBUS_SOCKET_TIMEOUT,
|
||||
);
|
||||
let mut current_limit = libc::rlimit64 {
|
||||
rlim_cur: 0,
|
||||
rlim_max: 0
|
||||
rlim_max: 0,
|
||||
};
|
||||
|
||||
let max_prio = item_as_i64(p.get("MaxRealtimePriority")?)?;
|
||||
if max_prio < 0 {
|
||||
return Err(AudioThreadPriorityError::new("invalid negative MaxRealtimePriority"));
|
||||
return Err(AudioThreadPriorityError::new(
|
||||
"invalid negative MaxRealtimePriority",
|
||||
));
|
||||
}
|
||||
|
||||
let max_rttime = item_as_i64(p.get("RTTimeUSecMax")?)?;
|
||||
if max_rttime < 0 {
|
||||
return Err(AudioThreadPriorityError::new("invalid negative RTTimeUSecMax"));
|
||||
return Err(AudioThreadPriorityError::new(
|
||||
"invalid negative RTTimeUSecMax",
|
||||
));
|
||||
}
|
||||
|
||||
if unsafe { libc::getrlimit64(libc::RLIMIT_RTTIME, &mut current_limit) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"getrlimit64", Box::new(OSError::last_os_error())));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"getrlimit64",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok((max_prio, (max_rttime as u64), current_limit))
|
||||
|
@ -132,48 +154,72 @@ fn get_limits() -> Result<(i64, u64, libc::rlimit64), AudioThreadPriorityError>
|
|||
fn set_limits(request: u64, max: u64) -> Result<(), AudioThreadPriorityError> {
|
||||
// Set a soft limit to the limit requested, to be able to handle going over the limit using
|
||||
// SIGXCPU. Set the hard limit to the maxium slice to prevent getting SIGKILL.
|
||||
let new_limit = libc::rlimit64 { rlim_cur: request,
|
||||
rlim_max: max };
|
||||
let new_limit = libc::rlimit64 {
|
||||
rlim_cur: request,
|
||||
rlim_max: max,
|
||||
};
|
||||
if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &new_limit) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner("setrlimit64", Box::new(OSError::last_os_error())));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
"setrlimit64",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
pub fn promote_current_thread_to_real_time_internal(
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
let thread_info = get_current_thread_info_internal()?;
|
||||
promote_thread_to_real_time_internal(thread_info, audio_buffer_frames, audio_samplerate_hz)
|
||||
}
|
||||
|
||||
pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
pub fn demote_current_thread_from_real_time_internal(
|
||||
rt_priority_handle: RtPriorityHandleInternal,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
assert!(unsafe { libc::pthread_self() } == rt_priority_handle.thread_info.pthread_id);
|
||||
|
||||
let param = unsafe { std::mem::zeroed::<libc::sched_param>() };
|
||||
|
||||
if unsafe { libc::pthread_setschedparam(rt_priority_handle.thread_info.pthread_id,
|
||||
rt_priority_handle.thread_info.policy,
|
||||
¶m) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"could not demote thread", Box::new(OSError::last_os_error())));
|
||||
if unsafe {
|
||||
libc::pthread_setschedparam(
|
||||
rt_priority_handle.thread_info.pthread_id,
|
||||
rt_priority_handle.thread_info.policy,
|
||||
¶m,
|
||||
)
|
||||
} < 0
|
||||
{
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"could not demote thread",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// This can be called by sandboxed code, it only restores priority to what they were.
|
||||
pub fn demote_thread_from_real_time_internal(thread_info: RtPriorityThreadInfoInternal)
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
pub fn demote_thread_from_real_time_internal(
|
||||
thread_info: RtPriorityThreadInfoInternal,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
let param = unsafe { std::mem::zeroed::<libc::sched_param>() };
|
||||
|
||||
// https://github.com/rust-lang/libc/issues/1511
|
||||
const SCHED_RESET_ON_FORK: libc::c_int = 0x40000000;
|
||||
|
||||
if unsafe { libc::pthread_setschedparam(thread_info.pthread_id,
|
||||
libc::SCHED_OTHER|SCHED_RESET_ON_FORK,
|
||||
¶m) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"could not demote thread", Box::new(OSError::last_os_error())));
|
||||
if unsafe {
|
||||
libc::pthread_setschedparam(
|
||||
thread_info.pthread_id,
|
||||
libc::SCHED_OTHER | SCHED_RESET_ON_FORK,
|
||||
¶m,
|
||||
)
|
||||
} < 0
|
||||
{
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"could not demote thread",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -181,14 +227,18 @@ pub fn demote_thread_from_real_time_internal(thread_info: RtPriorityThreadInfoIn
|
|||
/// Get the current thread information, as an opaque struct, that can be serialized and sent
|
||||
/// accross processes. This is enough to capture the current state of the scheduling policy, and
|
||||
/// an identifier to have another thread promoted to real-time.
|
||||
pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal, AudioThreadPriorityError> {
|
||||
pub fn get_current_thread_info_internal(
|
||||
) -> Result<RtPriorityThreadInfoInternal, AudioThreadPriorityError> {
|
||||
let thread_id = unsafe { libc::syscall(libc::SYS_gettid) };
|
||||
let pthread_id = unsafe { libc::pthread_self() };
|
||||
let mut param = unsafe { std::mem::zeroed::<libc::sched_param>() };
|
||||
let mut policy = 0;
|
||||
|
||||
if unsafe { libc::pthread_getschedparam(pthread_id, &mut policy, &mut param) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"pthread_getschedparam", Box::new(OSError::last_os_error())));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"pthread_getschedparam",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
|
||||
let pid = unsafe { libc::getpid() };
|
||||
|
@ -197,7 +247,7 @@ pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal
|
|||
pid,
|
||||
thread_id,
|
||||
pthread_id,
|
||||
policy
|
||||
policy,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -205,8 +255,10 @@ pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal
|
|||
/// rtkit request to succeed, and needs to hapen in the child. We can't get the real limit here,
|
||||
/// because we don't have access to DBUS, so it is hardcoded to 200ms, which is the default in the
|
||||
/// rtkit package.
|
||||
pub fn set_real_time_hard_limit_internal(audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32) -> Result<(), AudioThreadPriorityError> {
|
||||
pub fn set_real_time_hard_limit_internal(
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
let buffer_frames = if audio_buffer_frames > 0 {
|
||||
audio_buffer_frames
|
||||
} else {
|
||||
|
@ -227,10 +279,11 @@ pub fn set_real_time_hard_limit_internal(audio_buffer_frames: u32,
|
|||
}
|
||||
|
||||
/// Promote a thread (possibly in another process) identified by its tid, to real-time.
|
||||
pub fn promote_thread_to_real_time_internal(thread_info: RtPriorityThreadInfoInternal,
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError>
|
||||
{
|
||||
pub fn promote_thread_to_real_time_internal(
|
||||
thread_info: RtPriorityThreadInfoInternal,
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
let RtPriorityThreadInfoInternal { pid, thread_id, .. } = thread_info;
|
||||
|
||||
let handle = RtPriorityHandleInternal { thread_info };
|
||||
|
@ -246,10 +299,15 @@ pub fn promote_thread_to_real_time_internal(thread_info: RtPriorityThreadInfoInt
|
|||
}
|
||||
Err(e) => {
|
||||
if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &limits) } < 0 {
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"setrlimit64", Box::new(OSError::last_os_error())));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"setrlimit64",
|
||||
Box::new(OSError::last_os_error()),
|
||||
));
|
||||
}
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"Thread promotion error", e));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(
|
||||
&"Thread promotion error",
|
||||
e,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,37 +2,39 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use mach::kern_return::{kern_return_t, KERN_SUCCESS};
|
||||
use mach::port::mach_port_t;
|
||||
use mach::message::mach_msg_type_number_t;
|
||||
use crate::mach_sys::*;
|
||||
use std::mem::size_of;
|
||||
use mach::mach_time::{mach_timebase_info_data_t, mach_timebase_info};
|
||||
use libc::{pthread_t, pthread_self};
|
||||
use crate::AudioThreadPriorityError;
|
||||
use libc::{pthread_self, pthread_t};
|
||||
use log::info;
|
||||
use mach::kern_return::{kern_return_t, KERN_SUCCESS};
|
||||
use mach::mach_time::{mach_timebase_info, mach_timebase_info_data_t};
|
||||
use mach::message::mach_msg_type_number_t;
|
||||
use mach::port::mach_port_t;
|
||||
use std::mem::size_of;
|
||||
|
||||
extern "C" {
|
||||
fn pthread_mach_thread_np(tid: pthread_t) -> mach_port_t;
|
||||
// Those functions are commented out in thread_policy.h but somehow it works just fine !?
|
||||
fn thread_policy_set(thread: thread_t,
|
||||
flavor: thread_policy_flavor_t,
|
||||
policy_info: thread_policy_t,
|
||||
count: mach_msg_type_number_t)
|
||||
-> kern_return_t;
|
||||
fn thread_policy_get(thread: thread_t,
|
||||
flavor: thread_policy_flavor_t,
|
||||
policy_info: thread_policy_t,
|
||||
count: &mut mach_msg_type_number_t,
|
||||
get_default: &mut boolean_t)
|
||||
-> kern_return_t;
|
||||
fn thread_policy_set(
|
||||
thread: thread_t,
|
||||
flavor: thread_policy_flavor_t,
|
||||
policy_info: thread_policy_t,
|
||||
count: mach_msg_type_number_t,
|
||||
) -> kern_return_t;
|
||||
fn thread_policy_get(
|
||||
thread: thread_t,
|
||||
flavor: thread_policy_flavor_t,
|
||||
policy_info: thread_policy_t,
|
||||
count: &mut mach_msg_type_number_t,
|
||||
get_default: &mut boolean_t,
|
||||
) -> kern_return_t;
|
||||
}
|
||||
|
||||
// can't use size_of in const fn just now in stable, use a macro for now.
|
||||
macro_rules! THREAD_TIME_CONSTRAINT_POLICY_COUNT {
|
||||
() => {
|
||||
(size_of::<thread_time_constraint_policy_data_t>() / size_of::<integer_t>()) as u32;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -49,24 +51,28 @@ impl RtPriorityHandleInternal {
|
|||
period: 0,
|
||||
computation: 0,
|
||||
constraint: 0,
|
||||
preemptible: 0
|
||||
}
|
||||
}
|
||||
preemptible: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
pub fn demote_current_thread_from_real_time_internal(
|
||||
rt_priority_handle: RtPriorityHandleInternal,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
unsafe {
|
||||
let rv: kern_return_t;
|
||||
let mut h = rt_priority_handle;
|
||||
rv = thread_policy_set(h.tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut h.previous_time_constraint_policy) as *mut _ as
|
||||
thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!());
|
||||
rv = thread_policy_set(
|
||||
h.tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut h.previous_time_constraint_policy) as *mut _ as thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!(),
|
||||
);
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
return Err(AudioThreadPriorityError::new("thread demotion error: thread_policy_get: RT"));
|
||||
return Err(AudioThreadPriorityError::new(
|
||||
"thread demotion error: thread_policy_get: RT",
|
||||
));
|
||||
}
|
||||
|
||||
info!("thread {} priority restored.", h.tid);
|
||||
|
@ -75,10 +81,10 @@ pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPrior
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
|
||||
pub fn promote_current_thread_to_real_time_internal(
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
let mut rt_priority_handle = RtPriorityHandleInternal::new();
|
||||
|
||||
let buffer_frames = if audio_buffer_frames > 0 {
|
||||
|
@ -98,7 +104,6 @@ pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
|||
};
|
||||
let mut count: mach_msg_type_number_t;
|
||||
|
||||
|
||||
// Get current thread attributes, to revert back to the correct setting later if needed.
|
||||
rt_priority_handle.tid = tid;
|
||||
|
||||
|
@ -107,14 +112,18 @@ pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
|||
// default was returned instead.
|
||||
let mut get_default: boolean_t = 0;
|
||||
count = THREAD_TIME_CONSTRAINT_POLICY_COUNT!();
|
||||
rv = thread_policy_get(tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut time_constraints) as *mut _ as thread_policy_t,
|
||||
&mut count,
|
||||
&mut get_default);
|
||||
rv = thread_policy_get(
|
||||
tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut time_constraints) as *mut _ as thread_policy_t,
|
||||
&mut count,
|
||||
&mut get_default,
|
||||
);
|
||||
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
return Err(AudioThreadPriorityError::new("thread promotion error: thread_policy_get: time_constraint"));
|
||||
return Err(AudioThreadPriorityError::new(
|
||||
"thread promotion error: thread_policy_get: time_constraint",
|
||||
));
|
||||
}
|
||||
|
||||
rt_priority_handle.previous_time_constraint_policy = time_constraints;
|
||||
|
@ -134,12 +143,16 @@ pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
|||
preemptible: 1, // true
|
||||
};
|
||||
|
||||
rv = thread_policy_set(tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut time_constraints) as *mut _ as thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!());
|
||||
rv = thread_policy_set(
|
||||
tid,
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(&mut time_constraints) as *mut _ as thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!(),
|
||||
);
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
return Err(AudioThreadPriorityError::new("thread promotion error: thread_policy_set: time_constraint"));
|
||||
return Err(AudioThreadPriorityError::new(
|
||||
"thread promotion error: thread_policy_set: time_constraint",
|
||||
));
|
||||
}
|
||||
|
||||
info!("thread {} bumped to real time priority.", tid);
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use winapi::um::avrt::*;
|
||||
use winapi::shared::ntdef::HANDLE;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::shared::ntdef::HANDLE;
|
||||
use winapi::um::avrt::*;
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
|
||||
use crate::AudioThreadPriorityError;
|
||||
|
@ -13,47 +13,62 @@ use log::info;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct RtPriorityHandleInternal {
|
||||
mmcss_task_index: DWORD,
|
||||
task_handle: HANDLE
|
||||
mmcss_task_index: DWORD,
|
||||
task_handle: HANDLE,
|
||||
}
|
||||
|
||||
impl RtPriorityHandleInternal {
|
||||
pub fn new() -> RtPriorityHandleInternal {
|
||||
return RtPriorityHandleInternal {
|
||||
mmcss_task_index: 0 as DWORD,
|
||||
task_handle: 0 as HANDLE
|
||||
}
|
||||
mmcss_task_index: 0 as DWORD,
|
||||
task_handle: 0 as HANDLE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
pub fn demote_current_thread_from_real_time_internal(
|
||||
rt_priority_handle: RtPriorityHandleInternal,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
unsafe {
|
||||
let rv = AvRevertMmThreadCharacteristics(rt_priority_handle.task_handle);
|
||||
if rv == 0 {
|
||||
return Err(AudioThreadPriorityError::new(&format!("Unable to restore the thread priority ({})", GetLastError())));
|
||||
return Err(AudioThreadPriorityError::new(&format!(
|
||||
"Unable to restore the thread priority ({})",
|
||||
GetLastError()
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
info!("task {} priority restored.", rt_priority_handle.mmcss_task_index);
|
||||
info!(
|
||||
"task {} priority restored.",
|
||||
rt_priority_handle.mmcss_task_index
|
||||
);
|
||||
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn promote_current_thread_to_real_time_internal(_audio_buffer_frames: u32,
|
||||
_audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
pub fn promote_current_thread_to_real_time_internal(
|
||||
_audio_buffer_frames: u32,
|
||||
_audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
let mut handle = RtPriorityHandleInternal::new();
|
||||
|
||||
unsafe {
|
||||
handle.task_handle = AvSetMmThreadCharacteristicsA("Audio\0".as_ptr() as _, &mut handle.mmcss_task_index);
|
||||
handle.task_handle =
|
||||
AvSetMmThreadCharacteristicsA("Audio\0".as_ptr() as _, &mut handle.mmcss_task_index);
|
||||
|
||||
if handle.task_handle.is_null() {
|
||||
return Err(AudioThreadPriorityError::new(&format!("Unable to restore the thread priority ({})", GetLastError())));
|
||||
return Err(AudioThreadPriorityError::new(&format!(
|
||||
"Unable to restore the thread priority ({})",
|
||||
GetLastError()
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
info!("task {} bumped to real time priority.", handle.mmcss_task_index);
|
||||
info!(
|
||||
"task {} bumped to real time priority.",
|
||||
handle.mmcss_task_index
|
||||
);
|
||||
|
||||
Ok(handle)
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче