summaryrefslogtreecommitdiff
path: root/libs/ardour/session.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2020-04-27 04:10:18 +0200
committerRobin Gareus <robin@gareus.org>2020-04-27 04:10:18 +0200
commit1983f56592dfea5f74983c3b7207f8c6e0ab7836 (patch)
tree8ee845592acc40df932c30acaea1782b82a45e84 /libs/ardour/session.cc
parentb0daa85bfbaa4bdbdd25f47d4d642726c37a4d38 (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.cc49
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);
}
}