CoreAudio: Set MachThread RT Priority
authorRobin Gareus <robin@gareus.org>
Fri, 4 Aug 2017 01:12:29 +0000 (03:12 +0200)
committerRobin Gareus <robin@gareus.org>
Fri, 4 Aug 2017 04:25:23 +0000 (06:25 +0200)
libs/backends/coreaudio/coreaudio_backend.cc
libs/backends/coreaudio/coreaudio_backend.h

index 7137b1d65a4927ae9a2fb5fc79fbbb7e37a2b204..b48809163244355f0b868ec008d3591a8f41efd4 100644 (file)
@@ -21,6 +21,9 @@
 #include <sys/mman.h>
 #include <sys/time.h>
 
+#include <mach/thread_policy.h>
+#include <mach/thread_act.h>
+
 #include <glibmm.h>
 
 #include "coreaudio_backend.h"
@@ -327,6 +330,12 @@ CoreAudioBackend::set_buffer_size (uint32_t bs)
        }
        _samples_per_period = bs;
        _pcmio->set_samples_per_period(bs);
+       if (_run) {
+               coreaudio_set_realtime_policy (_main_thread);
+       }
+       for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i) {
+               coreaudio_set_realtime_policy (*i);
+       }
        engine.buffer_size_change (bs);
        return 0;
 }
@@ -603,11 +612,6 @@ CoreAudioBackend::_start (bool for_latency_measurement)
                PBD::info << _("CoreAudioBackend: adjusted input channel count to match device.") << endmsg;
        }
 
-       if (_pcmio->samples_per_period() != _samples_per_period) {
-               _samples_per_period = _pcmio->samples_per_period();
-               PBD::warning << _("CoreAudioBackend: samples per period does not match.") << endmsg;
-       }
-
        if (_pcmio->sample_rate() != _samplerate) {
                _samplerate = _pcmio->sample_rate();
                engine.sample_rate_change (_samplerate);
@@ -816,6 +820,34 @@ CoreAudioBackend::coreaudio_process_thread (void *arg)
        return 0;
 }
 
+bool
+CoreAudioBackend::coreaudio_set_realtime_policy (pthread_t thread_id) const
+{
+       thread_time_constraint_policy_data_t policy;
+#ifndef NDEBUG
+       mach_msg_type_number_t msgt = 4;
+       boolean_t dflt = false;
+       kern_return_t rv = thread_policy_get (pthread_mach_thread_np (_main_thread),
+                       THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &policy,
+                       &msgt, &dflt);
+       printf ("Coreaudio Main Thread(%p) %d %d %d %d DFLT %d OK: %d\n", _main_thread, policy.period, policy.computation, policy.constraint, policy.preemptible, dflt, rv == KERN_SUCCESS);
+#endif
+
+       double period_ns = 1e9 * _samples_per_period / _samplerate;
+       policy.period = AudioConvertNanosToHostTime (period_ns);
+       policy.computation = AudioConvertNanosToHostTime (period_ns * .9);
+       policy.constraint = AudioConvertNanosToHostTime (period_ns * .95);
+       policy.preemptible = true;
+       kern_return_t res = thread_policy_set (pthread_mach_thread_np (thread_id),
+                       THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &policy,
+                       THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+
+#ifndef NDEBUG
+       printf ("Coreaudio Proc Thread(%p) %d %d %d %d OK: %d\n", thread_id, policy.period, policy.computation, policy.constraint, policy.preemptible, res == KERN_SUCCESS);
+#endif
+       return res != KERN_SUCCESS;
+}
+
 int
 CoreAudioBackend::create_process_thread (boost::function<void()> func)
 {
@@ -838,6 +870,10 @@ CoreAudioBackend::create_process_thread (boost::function<void()> func)
                pthread_attr_destroy (&attr);
        }
 
+       if (coreaudio_set_realtime_policy (thread_id)) {
+               PBD::warning << _("AudioEngine: process thread failed to set mach realtime policy.") << endmsg;
+       }
+
        _threads.push_back (thread_id);
        return 0;
 }
@@ -1673,6 +1709,7 @@ CoreAudioBackend::freewheel_thread ()
                        AudioEngine::thread_init_callback (this);
                        _midiio->set_enabled(false);
                        reset_midi_parsers ();
+                       coreaudio_set_realtime_policy (_main_thread);
                }
 
                // process port updates first in every cycle.
@@ -1738,6 +1775,7 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos
                _reinit_thread_callback = false;
                _main_thread = pthread_self();
                AudioEngine::thread_init_callback (this);
+               coreaudio_set_realtime_policy (_main_thread);
        }
 
        if (pthread_mutex_trylock (&_process_callback_mutex)) {
index 5211839a9ce7684c80ad957f19153f24f0f3e9dc..03edf4f6ed761e91dbe127882688022d8f618ebc 100644 (file)
@@ -447,6 +447,7 @@ class CoreAudioBackend : public AudioBackend {
 
        /* process threads */
        static void* coreaudio_process_thread (void *);
+       bool coreaudio_set_realtime_policy (pthread_t) const;
        std::vector<pthread_t> _threads;
 
        struct ThreadData {