Add opt-in realtime-like thread priority for the pacer and audio threads#10
Merged
Conversation
b98d521 to
194c2f3
Compare
Introduce a best-effort, off-by-default scheduling-priority feature for Copperline's two latency-critical host threads: the wall-clock pacer (the main thread) and the cpal audio callback. On a busy host the scheduler can preempt either at the wrong moment, showing up as frame stutter or audio underruns; raising their priority reduces both. It never changes emulated behaviour -- like all pacing, it only schedules host work. "Real-time priority" is portable in neither API nor semantics, so the new src/priority.rs handles each platform on its own terms: - macOS: the pacer thread joins the USER_INTERACTIVE QoS class via pthread_set_qos_class_self_np (the idiomatic unprivileged low-latency request). The audio callback is left alone -- Core Audio already runs it on a real-time thread, and pinning a QoS class onto it would only demote it. Uses the libc QoS API already in the tree, so no macOS build deps. - Windows: both threads are raised to THREAD_PRIORITY_HIGHEST via the thread-priority crate; no privilege required. - Linux/other Unix: raising priority needs privilege (rtprio rlimit, CAP_SYS_NICE, or root); without it the request is logged and declined. thread-priority is scoped to cfg(not(target_os = "macos")) so it never enters the macOS build. audio_thread_priority was deliberately avoided: it pulls libdbus into Linux builds for RtKit, which would need packaging/CI changes. The feature is gated by [emulation] realtime_priority (default false), overridable for one run by COPPERLINE_REALTIME_PRIORITY. The pacer is elevated only when actually pacing (skipped for unthrottled headless captures); the audio thread promotes itself once on its first callback. Documented in the configuration guide, the example config, and the timing and architecture internals. Covered by unit tests that exercise the real macOS QoS syscall and assert the wrappers are panic-free on every platform.
194c2f3 to
c1a2db8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a best-effort, off-by-default scheduling-priority feature for Copperline's two latency-critical host threads — the wall-clock pacer (the main thread) and the cpal audio callback. On a busy host the scheduler can preempt either at the wrong moment, showing up as frame stutter or audio underruns; raising their priority reduces both. It never changes emulated behaviour — like all pacing, it only schedules host work.
Per-platform handling
"Real-time priority" is portable in neither API nor semantics, so the new
src/priority.rshandles each platform on its own terms:USER_INTERACTIVEQoS class (pthread_set_qos_class_self_np), the idiomatic unprivileged low-latency request. The audio callback is left alone: Core Audio already runs it on a real-time thread, and pinning a QoS class onto it would only demote it. Uses thelibcQoS API already in the tree, so no new macOS build deps.THREAD_PRIORITY_HIGHESTvia thethread-prioritycrate; no privilege required.rtpriorlimit,CAP_SYS_NICE, or root); without it the request is logged and declined, and the thread keeps normal scheduling.Dependency notes
thread-priorityis scoped tocfg(not(target_os = "macos")), so it (and thewindows-sysit pulls in) never enters the macOS build.audio_thread_prioritywas deliberately avoided — it dragslibdbusinto Linux builds for RtKit, which would require packaging/CI changes.Configuration
Gated by
[emulation] realtime_priority(defaultfalse), overridable for one run by theCOPPERLINE_REALTIME_PRIORITYenv var (0/false/offforces off; anything else forces on). The pacer is elevated only when actually pacing (skipped for unthrottled headless captures); the audio thread promotes itself once on its first callback (latched, so steady-state audio does no extra work).Docs
docs/guide/configuration.md— the[emulation]reference.docs/internals/timing.md— a new Thread scheduling priority subsection under Real-time pacing.docs/internals/architecture.md— the threading model and thepriority.rssource-layout entry.copperline.example.toml— the commented key.Test plan
cargo fmt --check,cargo clippy --all-targets --all-features --locked -- -D warnings,cargo build --locked— all clean (the exact CI commands).priority.rsthat exercise the real macOS QoS syscall and assert the wrappers are panic-free on every platform).audio thread left as-is (Core Audio runs it real-time)and makes the correct call.main(), and uses the same syscall the unit test exercises directly.