зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1612512 - Update to audio_thread_priority 0.22. r=padenot
Differential Revision: https://phabricator.services.mozilla.com/D62664 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
33d729a0f1
Коммит
24e4bee487
|
@ -105,9 +105,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "audio_thread_priority"
|
||||
version = "0.20.2"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "197b2d259505d11c92d266e1784f01cc935eb764d2f54e16aedf4e5085197871"
|
||||
checksum = "407b1b70ad4072a4ff430679b331450166b56631091d6ba46a885cf427392055"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dbus",
|
||||
|
|
|
@ -19,7 +19,7 @@ serde = "1.*.*"
|
|||
serde_derive = "1.*.*"
|
||||
tokio = "0.1"
|
||||
tokio-io = "0.1"
|
||||
audio_thread_priority = "0.20.2"
|
||||
audio_thread_priority = "0.22"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
iovec = "0.1"
|
||||
|
|
|
@ -9,7 +9,7 @@ description = "Cubeb Backend for talking to remote cubeb server."
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
audio_thread_priority = "0.20.2"
|
||||
audio_thread_priority = "0.22"
|
||||
audioipc = { path="../audioipc" }
|
||||
cubeb-backend = "0.6.0"
|
||||
futures = { version="0.1.18", default-features=false, features=["use_std"] }
|
||||
|
|
|
@ -9,7 +9,7 @@ description = "Remote cubeb server"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
audio_thread_priority = "0.20.2"
|
||||
audio_thread_priority = "0.22"
|
||||
audioipc = { path = "../audioipc" }
|
||||
cubeb-core = "0.6.0"
|
||||
futures = "0.1.18"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"363ab43ea4980149350eb3a4da691a93f0b7c61a5d3b4ce8b59f73cde5866a92","Makefile":"0f9a771cfb30c7c4b9961d82fdca4e9e229a955bb2e636474a4101389e18e938","README.md":"bcfa4948edf52fdacd485200a0c1c886a92232cc1931eeb4e1044050f46ec253","atp_test.cpp":"8075a040941a65fb9e3f7cbf0535853ca6661c3ac442ec35569b42b24bbec797","audio_thread_priority.h":"f0ecaf1b674f794cde0dc834028e074d4e4675d22ae96acf08b2ae1dceb3474e","generate_osx_bindings.sh":"06e4e03450f788ced18d31fff5660919e6f6ec1119ddace363ffeb82f0518a71","src/lib.rs":"516388cf4ccf55f23a6ccb248f56ab525b759a24819e67605cd12f640517ddd3","src/mach_sys.rs":"352560fcb9b41d877cff92e5b3b04d6dc68b1f30508ce4b9aed78940120a883e","src/rt_linux.rs":"b4db36baa754ab166b40f3801acc4f2046d226a2645f0e136dbbfa1bc771344e","src/rt_mach.rs":"5fce324b9a64305ff221fdd185eaa4b1c7386b6e61edc32cf63e424f9f3d90ef","src/rt_win.rs":"f8f5b7af21cadd686cf7d8099d1972d3265c3889574020bd4ea088b832fbfa51"},"package":"197b2d259505d11c92d266e1784f01cc935eb764d2f54e16aedf4e5085197871"}
|
||||
{"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"}
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "audio_thread_priority"
|
||||
version = "0.20.2"
|
||||
version = "0.22.0"
|
||||
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"
|
||||
|
|
|
@ -3,14 +3,50 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[warn(missing_docs)]
|
||||
use cfg_if::cfg_if;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
#[cfg(feature = "terminal-logging")]
|
||||
extern crate simple_logger;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[derive(Debug)]
|
||||
pub struct AudioThreadPriorityError {
|
||||
message: String,
|
||||
inner: Option<Box<dyn Error + 'static>>,
|
||||
}
|
||||
|
||||
impl AudioThreadPriorityError {
|
||||
fn new_with_inner(message: &str, inner: Box<dyn Error>) -> AudioThreadPriorityError {
|
||||
AudioThreadPriorityError {
|
||||
message: message.into(),
|
||||
inner: Some(inner),
|
||||
}
|
||||
}
|
||||
fn new(message: &str) -> AudioThreadPriorityError {
|
||||
AudioThreadPriorityError {
|
||||
message: message.into(),
|
||||
inner: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AudioThreadPriorityError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut rv = write!(f, "AudioThreadPriorityError: {}", &self.message);
|
||||
if let Some(inner) = &self.inner {
|
||||
rv = write!(f, " ({})", inner);
|
||||
}
|
||||
rv
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for AudioThreadPriorityError {
|
||||
fn description(&self) -> &str {
|
||||
&self.message
|
||||
}
|
||||
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
self.inner.as_ref().map(|e| e.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
|
@ -46,14 +82,14 @@ cfg_if! {
|
|||
} else {
|
||||
// blanket implementations for Android and other systems.
|
||||
pub struct RtPriorityHandleInternal {}
|
||||
pub fn promote_current_thread_to_real_time_internal(_: u32, audio_samplerate_hz: u32) -> Result<RtPriorityHandle, ()> {
|
||||
pub fn promote_current_thread_to_real_time_internal(_: u32, audio_samplerate_hz: u32) -> Result<RtPriorityHandle, AudioThreadPriorityError> {
|
||||
if audio_samplerate_hz == 0 {
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError{message: "sample rate is zero".to_string(), inner: None});
|
||||
}
|
||||
// no-op
|
||||
Ok(RtPriorityHandle{})
|
||||
}
|
||||
pub fn demote_current_thread_from_real_time_internal(_: RtPriorityHandle) -> Result<(), ()> {
|
||||
pub fn demote_current_thread_from_real_time_internal(_: RtPriorityHandle) -> Result<(), AudioThreadPriorityError> {
|
||||
// no-op
|
||||
Ok(())
|
||||
}
|
||||
|
@ -84,7 +120,7 @@ pub type RtPriorityThreadInfo = RtPriorityThreadInfoInternal;
|
|||
///
|
||||
/// Ok in case of success, with an opaque structure containing relevant info for the platform, Err
|
||||
/// otherwise.
|
||||
pub fn get_current_thread_info() -> Result<RtPriorityThreadInfo, ()> {
|
||||
pub fn get_current_thread_info() -> Result<RtPriorityThreadInfo, AudioThreadPriorityError> {
|
||||
return get_current_thread_info_internal();
|
||||
}
|
||||
|
||||
|
@ -210,9 +246,9 @@ pub fn promote_thread_to_real_time(
|
|||
thread_info: RtPriorityThreadInfo,
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandle, ()> {
|
||||
) -> Result<RtPriorityHandle, AudioThreadPriorityError> {
|
||||
if audio_samplerate_hz == 0 {
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new("sample rate is zero"));
|
||||
}
|
||||
return promote_thread_to_real_time_internal(
|
||||
thread_info,
|
||||
|
@ -231,7 +267,7 @@ pub fn promote_thread_to_real_time(
|
|||
/// # Return value
|
||||
///
|
||||
/// `Ok` in case of success, `Err` otherwise.
|
||||
pub fn demote_thread_from_real_time(thread_info: RtPriorityThreadInfo) -> Result<(), ()> {
|
||||
pub fn demote_thread_from_real_time(thread_info: RtPriorityThreadInfo) -> Result<(), AudioThreadPriorityError> {
|
||||
return demote_thread_from_real_time_internal(thread_info);
|
||||
}
|
||||
|
||||
|
@ -329,9 +365,9 @@ pub extern "C" fn atp_set_real_time_limit(audio_buffer_frames: u32,
|
|||
pub fn promote_current_thread_to_real_time(
|
||||
audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32,
|
||||
) -> Result<RtPriorityHandle, ()> {
|
||||
) -> Result<RtPriorityHandle, AudioThreadPriorityError> {
|
||||
if audio_samplerate_hz == 0 {
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new("sample rate is zero"));
|
||||
}
|
||||
return promote_current_thread_to_real_time_internal(audio_buffer_frames, audio_samplerate_hz);
|
||||
}
|
||||
|
@ -346,7 +382,9 @@ pub fn promote_current_thread_to_real_time(
|
|||
/// # Return value
|
||||
///
|
||||
/// `Ok` in scase of success, `Err` otherwise.
|
||||
pub fn demote_current_thread_from_real_time(handle: RtPriorityHandle) -> Result<(), ()> {
|
||||
pub fn demote_current_thread_from_real_time(
|
||||
handle: RtPriorityHandle,
|
||||
) -> Result<(), AudioThreadPriorityError> {
|
||||
return demote_current_thread_from_real_time_internal(handle);
|
||||
}
|
||||
|
||||
|
@ -442,9 +480,11 @@ mod tests {
|
|||
match promote_current_thread_to_real_time(0, 44100) {
|
||||
Ok(rt_prio_handle) => {
|
||||
demote_current_thread_from_real_time(rt_prio_handle).unwrap();
|
||||
assert!(true);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(e);
|
||||
eprintln!("{}", e.description());
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,17 +492,22 @@ mod tests {
|
|||
match promote_current_thread_to_real_time(512, 44100) {
|
||||
Ok(rt_prio_handle) => {
|
||||
demote_current_thread_from_real_time(rt_prio_handle).unwrap();
|
||||
assert!(true);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(e);
|
||||
eprintln!("{}", e.description());
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
match promote_current_thread_to_real_time(512, 44100) {
|
||||
Ok(_) => {}
|
||||
Ok(_) => {
|
||||
assert!(true);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(e);
|
||||
eprintln!("{}", e.description());
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
// automatically deallocated, but not demoted until the thread exits.
|
||||
|
@ -479,9 +524,11 @@ mod tests {
|
|||
let info = get_current_thread_info().unwrap();
|
||||
match promote_thread_to_real_time(info, 512, 44100) {
|
||||
Ok(_) => {
|
||||
assert!(true);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(e);
|
||||
eprintln!("{}", e);
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -516,6 +563,7 @@ mod tests {
|
|||
}
|
||||
Err(_) => {
|
||||
eprintln!("promotion Err");
|
||||
kill(child, SIGKILL).expect("Could not kill the child?");
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
@ -537,7 +585,7 @@ mod tests {
|
|||
match write(wr, &bytes) {
|
||||
Ok(_) => {
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
eprintln!("child sleeping, waiting to be promoted...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,27 +13,39 @@ use std::io::Error as OSError;
|
|||
|
||||
use dbus::{Connection, BusType, Props, MessageItem, Message};
|
||||
|
||||
use crate::AudioThreadPriorityError;
|
||||
|
||||
const DBUS_SOCKET_TIMEOUT: i32 = 10_000;
|
||||
const RT_PRIO_DEFAULT: u32 = 10;
|
||||
// This is different from libc::pid_t, which is 32 bits, and is defined in sys/types.h.
|
||||
#[allow(non_camel_case_types)]
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<dyn Error>> for AudioThreadPriorityError {
|
||||
fn from(error: Box<dyn Error>) -> Self {
|
||||
AudioThreadPriorityError::new(&format!("{}", error.description()))
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RtPriorityThreadInfoInternal {
|
||||
/// The PID of the process containing `thread_id` below.
|
||||
pid: libc::pid_t,
|
||||
/// System-wise thread id, use to promote the thread via dbus.
|
||||
thread_id: kernel_pid_t,
|
||||
/// Process-local thread id, used to restore scheduler characteristics. This information is not
|
||||
/// useful in another process, but is useful tied to the `thread_id`, when back into the first
|
||||
/// process.
|
||||
pthread_id: libc::pthread_t,
|
||||
/// The PID of the process containing `thread_id` below.
|
||||
pid: libc::pid_t,
|
||||
/// ...
|
||||
policy: libc::c_int,
|
||||
/// ...
|
||||
param: libc::sched_param,
|
||||
policy: libc::c_int
|
||||
}
|
||||
|
||||
impl RtPriorityThreadInfoInternal {
|
||||
|
@ -59,11 +71,11 @@ pub struct RtPriorityHandleInternal {
|
|||
thread_info: RtPriorityThreadInfoInternal,
|
||||
}
|
||||
|
||||
fn item_as_i64(i: MessageItem) -> Result<i64, Box<dyn Error>> {
|
||||
fn item_as_i64(i: MessageItem) -> Result<i64, AudioThreadPriorityError> {
|
||||
match i {
|
||||
MessageItem::Int32(i) => Ok(i as i64),
|
||||
MessageItem::Int64(i) => Ok(i),
|
||||
_ => Err(Box::from(&*format!("Property is not integer ({:?})", i)))
|
||||
_ => Err(AudioThreadPriorityError::new(&format!("Property is not integer ({:?})", i)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +102,7 @@ fn rtkit_set_realtime(thread: u64, pid: u64, prio: u32) -> Result<(), Box<dyn Er
|
|||
|
||||
/// Returns the maximum priority, maximum real-time time slice, and the current real-time time
|
||||
/// slice for this process.
|
||||
fn get_limits() -> Result<(i64, u64, libc::rlimit64), Box<dyn Error>> {
|
||||
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",
|
||||
|
@ -102,29 +114,28 @@ fn get_limits() -> Result<(i64, u64, libc::rlimit64), Box<dyn Error>> {
|
|||
|
||||
let max_prio = item_as_i64(p.get("MaxRealtimePriority")?)?;
|
||||
if max_prio < 0 {
|
||||
return Err(Box::from("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(Box::from("invalid negative RTTimeUSecMax"));
|
||||
return Err(AudioThreadPriorityError::new("invalid negative RTTimeUSecMax"));
|
||||
}
|
||||
|
||||
if unsafe { libc::getrlimit64(libc::RLIMIT_RTTIME, &mut current_limit) } < 0 {
|
||||
error!("getrlimit64: {}", OSError::last_os_error().raw_os_error().unwrap());
|
||||
return Err(Box::from("getrlimit failed"));
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"getrlimit64", Box::new(OSError::last_os_error())));
|
||||
}
|
||||
|
||||
Ok((max_prio, (max_rttime as u64), current_limit))
|
||||
}
|
||||
|
||||
fn set_limits(request: u64, max: u64) -> Result<(), Box<dyn Error>> {
|
||||
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 };
|
||||
if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &new_limit) } < 0 {
|
||||
return Err(Box::from("setrlimit failed"));
|
||||
return Err(AudioThreadPriorityError::new_with_inner("setrlimit64", Box::new(OSError::last_os_error())));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -132,27 +143,28 @@ fn set_limits(request: u64, max: u64) -> Result<(), Box<dyn Error>> {
|
|||
|
||||
pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, ()> {
|
||||
-> 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<(), ()> {
|
||||
-> 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,
|
||||
&rt_priority_handle.thread_info.param) } < 0 {
|
||||
error!("could not demote thread {}", OSError::last_os_error().raw_os_error().unwrap());
|
||||
return Err(());
|
||||
¶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<(), ()> {
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
let param = unsafe { std::mem::zeroed::<libc::sched_param>() };
|
||||
|
||||
// https://github.com/rust-lang/libc/issues/1511
|
||||
|
@ -161,8 +173,7 @@ pub fn demote_thread_from_real_time_internal(thread_info: RtPriorityThreadInfoIn
|
|||
if unsafe { libc::pthread_setschedparam(thread_info.pthread_id,
|
||||
libc::SCHED_OTHER|SCHED_RESET_ON_FORK,
|
||||
¶m) } < 0 {
|
||||
error!("could not demote thread {}", OSError::last_os_error().raw_os_error().unwrap());
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"could not demote thread", Box::new(OSError::last_os_error())));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -170,15 +181,14 @@ 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, ()> {
|
||||
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 {
|
||||
error!("pthread_getschedparam error {}", OSError::last_os_error().raw_os_error().unwrap());
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new_with_inner(&"pthread_getschedparam", Box::new(OSError::last_os_error())));
|
||||
}
|
||||
|
||||
let pid = unsafe { libc::getpid() };
|
||||
|
@ -187,8 +197,7 @@ pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal
|
|||
pid,
|
||||
thread_id,
|
||||
pthread_id,
|
||||
policy,
|
||||
param
|
||||
policy
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -197,7 +206,7 @@ pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal
|
|||
/// 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<(), ()> {
|
||||
audio_samplerate_hz: u32) -> Result<(), AudioThreadPriorityError> {
|
||||
let buffer_frames = if audio_buffer_frames > 0 {
|
||||
audio_buffer_frames
|
||||
} else {
|
||||
|
@ -208,11 +217,11 @@ pub fn set_real_time_hard_limit_internal(audio_buffer_frames: u32,
|
|||
|
||||
// It's only necessary to set RLIMIT_RTTIME to something when in the child, skip it if it's a
|
||||
// remoting call.
|
||||
let (_, max_rttime, _) = get_limits().map_err(|_| {})?;
|
||||
let (_, max_rttime, _) = get_limits()?;
|
||||
|
||||
// Only take what we need, or cap at the system limit, no further.
|
||||
let rttime_request = cmp::min(budget_us, max_rttime as u64);
|
||||
set_limits(rttime_request, max_rttime).map_err(|_| {})?;
|
||||
set_limits(rttime_request, max_rttime)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -220,23 +229,27 @@ 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, ()>
|
||||
audio_samplerate_hz: u32) -> Result<RtPriorityHandleInternal, AudioThreadPriorityError>
|
||||
{
|
||||
let RtPriorityThreadInfoInternal { pid, thread_id, .. } = thread_info;
|
||||
|
||||
let handle = RtPriorityHandleInternal { thread_info };
|
||||
|
||||
let (_, _, limits) = get_limits().map_err(|_| {})?;
|
||||
let (_, _, limits) = get_limits()?;
|
||||
set_real_time_hard_limit_internal(audio_buffer_frames, audio_samplerate_hz)?;
|
||||
|
||||
let r = rtkit_set_realtime(thread_id as u64, pid as u64, RT_PRIO_DEFAULT);
|
||||
|
||||
if r.is_err() {
|
||||
if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &limits) } < 0 {
|
||||
error!("setrlimit64: {}", OSError::last_os_error().raw_os_error().unwrap());
|
||||
return Err(());
|
||||
match r {
|
||||
Ok(_) => {
|
||||
return Ok(handle);
|
||||
}
|
||||
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(&"Thread promotion error", e));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(handle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ 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 log::info;
|
||||
|
||||
extern "C" {
|
||||
fn pthread_mach_thread_np(tid: pthread_t) -> mach_port_t;
|
||||
|
@ -54,7 +56,7 @@ impl RtPriorityHandleInternal {
|
|||
}
|
||||
|
||||
pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
|
||||
-> Result<(), ()> {
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
unsafe {
|
||||
let rv: kern_return_t;
|
||||
let mut h = rt_priority_handle;
|
||||
|
@ -64,11 +66,10 @@ pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPrior
|
|||
thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!());
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
warn!("thread demotion error: thread_policy_set: RT");
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new("thread demotion error: thread_policy_get: RT"));
|
||||
}
|
||||
|
||||
warn!("thread {} priority restored.", h.tid);
|
||||
info!("thread {} priority restored.", h.tid);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
|
@ -76,7 +77,7 @@ pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPrior
|
|||
|
||||
pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
||||
audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, ()> {
|
||||
-> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
|
||||
let mut rt_priority_handle = RtPriorityHandleInternal::new();
|
||||
|
||||
|
@ -113,8 +114,7 @@ pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
|||
&mut get_default);
|
||||
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
error!("thread promotion error: thread_policy_get: time_constraint");
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new("thread promotion error: thread_policy_get: time_constraint"));
|
||||
}
|
||||
|
||||
rt_priority_handle.previous_time_constraint_policy = time_constraints;
|
||||
|
@ -139,8 +139,7 @@ pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
|
|||
(&mut time_constraints) as *mut _ as thread_policy_t,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT!());
|
||||
if rv != KERN_SUCCESS as i32 {
|
||||
warn!("thread promotion error: thread_policy_set: time_constraint");
|
||||
return Err(());
|
||||
return Err(AudioThreadPriorityError::new("thread promotion error: thread_policy_set: time_constraint"));
|
||||
}
|
||||
|
||||
info!("thread {} bumped to real time priority.", tid);
|
||||
|
|
|
@ -7,6 +7,10 @@ use winapi::shared::ntdef::HANDLE;
|
|||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
|
||||
use crate::AudioThreadPriorityError;
|
||||
|
||||
use log::info;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RtPriorityHandleInternal {
|
||||
mmcss_task_index: DWORD,
|
||||
|
@ -23,12 +27,11 @@ impl RtPriorityHandleInternal {
|
|||
}
|
||||
|
||||
pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
|
||||
-> Result<(), ()> {
|
||||
-> Result<(), AudioThreadPriorityError> {
|
||||
unsafe {
|
||||
let rv = AvRevertMmThreadCharacteristics(rt_priority_handle.task_handle);
|
||||
if rv == 0 {
|
||||
warn!("Unable to restore the thread priority ({})", GetLastError());
|
||||
return Err(())
|
||||
return Err(AudioThreadPriorityError::new(&format!("Unable to restore the thread priority ({})", GetLastError())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,15 +42,14 @@ pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPrior
|
|||
|
||||
pub fn promote_current_thread_to_real_time_internal(_audio_buffer_frames: u32,
|
||||
_audio_samplerate_hz: u32)
|
||||
-> Result<RtPriorityHandleInternal, ()> {
|
||||
-> Result<RtPriorityHandleInternal, AudioThreadPriorityError> {
|
||||
let mut handle = RtPriorityHandleInternal::new();
|
||||
|
||||
unsafe {
|
||||
handle.task_handle = AvSetMmThreadCharacteristicsA("Audio\0".as_ptr() as _, &mut handle.mmcss_task_index);
|
||||
|
||||
if handle.task_handle.is_null() {
|
||||
warn!("Unable to use mmcss to bump the thread priority ({})", GetLastError());
|
||||
return Err(())
|
||||
return Err(AudioThreadPriorityError::new(&format!("Unable to restore the thread priority ({})", GetLastError())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ storage = { path = "../../../../storage/rust" }
|
|||
bookmark_sync = { path = "../../../components/places/bookmark_sync", optional = true }
|
||||
shift_or_euc_c = "0.1.0"
|
||||
chardetng_c = "0.1.1"
|
||||
audio_thread_priority = "0.20.2"
|
||||
audio_thread_priority = "0.22"
|
||||
mdns_service = { path="../../../../media/mtransport/mdns_service", optional = true }
|
||||
neqo_glue = { path = "../../../../netwerk/socket/neqo_glue" }
|
||||
rlbox_lucet_sandbox = { version = "0.1.0", optional = true }
|
||||
|
|
Загрузка…
Ссылка в новой задаче