Init host_time_to_ns_ratio with context

The current HOST_TIME_TO_NS_RATIO implemented with lazy_static is
causing what appears to be false-positive TSAN errors. OnceLock and
LazyLock exhibit similar errors under TSAN.

It seemed easier to rewrite host_time_to_ns_ratio to be a init-once
context member, rather than making the unstable `no_sanitize` attribute
work. Being unstable it also needed to be included conditionally only
when compiled with the nightly compiler. And trying the rustversion
crate for this resulted in compilation failure due to TSAN reporting it
doesn't work...
This commit is contained in:
Andreas Pehrson 2024-06-25 21:37:42 +02:00 коммит произвёл Andreas Pehrson
Родитель 4a44ddc703
Коммит 8bce3b333a
3 изменённых файлов: 15 добавлений и 20 удалений

Просмотреть файл

@ -14,7 +14,6 @@ coreaudio-sys-utils = { path = "coreaudio-sys-utils" }
cubeb-backend = "0.13"
float-cmp = "0.6"
libc = "0.2"
lazy_static = "1.2"
mach = "0.3"
audio-mixer = "0.2"
ringbuf = "0.2.6"

Просмотреть файл

@ -4,7 +4,6 @@
// accompanying file LICENSE for details.
#![allow(unused_assignments)]
#![allow(unused_must_use)]
extern crate coreaudio_sys_utils;
extern crate libc;
extern crate ringbuf;
@ -106,16 +105,6 @@ bitflags! {
}
}
lazy_static! {
static ref HOST_TIME_TO_NS_RATIO: (u32, u32) = {
let mut timebase_info = mach_timebase_info { numer: 0, denom: 0 };
unsafe {
mach_timebase_info(&mut timebase_info);
}
(timebase_info.numer, timebase_info.denom)
};
}
#[cfg(feature = "audio-dump")]
fn dump_audio(stream: cubeb_audio_dump_stream_t, audio_samples: *mut c_void, count: u32) {
unsafe {
@ -682,10 +671,10 @@ extern "C" fn audiounit_input_callback(
}
}
fn host_time_to_ns(host_time: u64) -> u64 {
fn host_time_to_ns(ctx: &AudioUnitContext, host_time: u64) -> u64 {
let mut rv: f64 = host_time as f64;
rv *= HOST_TIME_TO_NS_RATIO.0 as f64;
rv /= HOST_TIME_TO_NS_RATIO.1 as f64;
rv *= ctx.host_time_to_ns_ratio.0 as f64;
rv /= ctx.host_time_to_ns_ratio.1 as f64;
rv as u64
}
@ -697,7 +686,7 @@ fn compute_output_latency(stm: &AudioUnitStream, audio_output_time: u64, now: u6
// The total output latency is the timestamp difference + the stream latency + the hardware
// latency.
let total_output_latency_ns =
fixed_latency_ns + host_time_to_ns(audio_output_time.saturating_sub(now));
fixed_latency_ns + host_time_to_ns(stm.context, audio_output_time.saturating_sub(now));
(total_output_latency_ns * output_hw_rate / NS2S) as u32
}
@ -710,7 +699,7 @@ fn compute_input_latency(stm: &AudioUnitStream, audio_input_time: u64, now: u64)
// The total input latency is the timestamp difference + the stream latency +
// the hardware latency.
let total_input_latency_ns =
host_time_to_ns(now.saturating_sub(audio_input_time)) + fixed_latency_ns;
host_time_to_ns(stm.context, now.saturating_sub(audio_input_time)) + fixed_latency_ns;
(total_input_latency_ns * input_hw_rate / NS2S) as u32
}
@ -2483,6 +2472,7 @@ pub struct AudioUnitContext {
serial_queue: Queue,
latency_controller: Mutex<LatencyController>,
devices: Mutex<SharedDevices>,
host_time_to_ns_ratio: (u32, u32),
// Storage for a context-global vpio unit. Duplex streams that need one will take this
// and return it when done.
shared_voice_processing_unit: SharedVoiceProcessingUnitManager,
@ -2497,11 +2487,19 @@ impl AudioUnitContext {
format!("{}.context.shared_vpio", DISPATCH_QUEUE_LABEL).as_str(),
&serial_queue,
);
let host_time_to_ns_ratio = {
let mut timebase_info = mach_timebase_info { numer: 0, denom: 0 };
unsafe {
mach_timebase_info(&mut timebase_info);
}
(timebase_info.numer, timebase_info.denom)
};
Self {
_ops: &OPS as *const _,
serial_queue,
latency_controller: Mutex::new(LatencyController::default()),
devices: Mutex::new(SharedDevices::default()),
host_time_to_ns_ratio,
shared_voice_processing_unit: SharedVoiceProcessingUnitManager::new(shared_vp_queue),
}
}
@ -4931,7 +4929,7 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
let now = unsafe { mach_absolute_time() };
let diff = now - timestamp;
let interpolated_frames = cmp::min(
host_time_to_ns(diff)
host_time_to_ns(self.context, diff)
* self.core_stream_data.output_stream_params.rate() as u64
/ NS2S,
buffer_size,

Просмотреть файл

@ -10,8 +10,6 @@ extern crate bitflags;
extern crate cubeb_backend;
#[macro_use]
extern crate float_cmp;
#[macro_use]
extern crate lazy_static;
extern crate mach;
mod backend;