diff options
author | Robin Gareus <robin@gareus.org> | 2020-04-27 04:10:18 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2020-04-27 04:10:18 +0200 |
commit | 1983f56592dfea5f74983c3b7207f8c6e0ab7836 (patch) | |
tree | 8ee845592acc40df932c30acaea1782b82a45e84 /libs/ardour/session.cc | |
parent | b0daa85bfbaa4bdbdd25f47d4d642726c37a4d38 (diff) |
Work around jack2's insane thread semantics
jack2 can process in parallel with calling a graph-order or
latency-callback, so Ardour takes a lock to update those in sync.
Yet jack2 can also block while port-registrations happen,
and concurrently emit latency-callback from another thread..
Diffstat (limited to 'libs/ardour/session.cc')
-rw-r--r-- | libs/ardour/session.cc | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 7f4740057d..4750f5f853 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -6539,16 +6539,6 @@ Session::update_latency (bool playback) return; } - /* Note; RouteList is sorted as process-graph */ - boost::shared_ptr<RouteList> r = routes.reader (); - - if (playback) { - /* reverse the list so that we work backwards from the last route to run to the first */ - RouteList* rl = routes.reader().get(); - r.reset (new RouteList (*rl)); - reverse (r->begin(), r->end()); - } - /* Session::new_midi_track -> Route::add_processors -> Delivery::configure_io * -> IO::ensure_ports -> PortManager::register_output_port * may run currently (adding many ports) while the backend @@ -6560,7 +6550,42 @@ Session::update_latency (bool playback) * IO::* uses BLOCK_PROCESS_CALLBACK to prevent concurrency, * so the same has to be done here to prevent a race. */ - Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); + Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::Threads::TRY_LOCK); + if (!lm.locked()) { + /* IO::ensure_ports() calls jack_port_register() while holding the process-lock, + * JACK2 may block and call JACKAudioBackend::_latency_callback() which + * ends up here. https://pastebin.com/mitGBwpq + * + * This is a stopgap to be able to use 6.0 with JACK2's insane threading. + * Yes JACK can also concurrently process (using the old graph) yet emit + * a latency-callback (for which we do need the lock). + * + * One alternative is to use _adding_routes_in_progress and + * call graph_reordered (false); however various entry-points + * to ensure_io don't originate from Session. + * + * Eventually Ardour will probably need to be changed to + * register ports lock-free, and mark those ports as "pending", + * and skip them during process and all other callbacks. + * + * Then clear the pending flags in the rt-process context after + * a port-registraion callback. + */ + cerr << "Session::update_latency called with process-lock held\n"; + DEBUG_TRACE (DEBUG::LatencyCompensation, "Engine latency callback: called with process-lock held. queue for later.\n"); + queue_latency_recompute (); + return; + } + + /* Note; RouteList is sorted as process-graph */ + boost::shared_ptr<RouteList> r = routes.reader (); + + if (playback) { + /* reverse the list so that we work backwards from the last route to run to the first */ + RouteList* rl = routes.reader().get(); + r.reset (new RouteList (*rl)); + reverse (r->begin(), r->end()); + } for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { samplecnt_t latency = (*i)->set_private_port_latencies (playback); (*i)->set_public_port_latencies (latency, playback); @@ -6993,7 +7018,7 @@ Session::auto_connect_thread_run () * modifies the capture-offset, which can be a problem. */ while (g_atomic_int_and (&_latency_recompute_pending, 0)) { - update_latency_compensation (false, false); + update_latency_compensation (true, false); } } |