2 Copyright (C) 2010 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "pbd/compose.h"
24 #include "pbd/debug_rt_alloc.h"
26 #include "ardour/debug.h"
27 #include "ardour/graph.h"
28 #include "ardour/types.h"
29 #include "ardour/session.h"
30 #include "ardour/route.h"
31 #include "ardour/process_thread.h"
32 #include "ardour/audioengine.h"
34 #include <jack/thread.h>
38 using namespace ARDOUR
;
43 static Graph
* graph
= 0;
49 return !graph
->in_process_thread ();
55 Graph::Graph (Session
& session
)
56 : SessionHandleRef (session
)
57 , _quit_threads (false)
58 , _execution_sem ("graph_execution", 0)
59 , _callback_start_sem ("graph_start", 0)
60 , _callback_done_sem ("graph_done", 0)
61 , _cleanup_sem ("graph_cleanup", 0)
63 pthread_mutex_init( &_trigger_mutex
, NULL
);
65 /* XXX: rather hacky `fix' to stop _trigger_queue.push_back() allocating
66 memory in the RT thread.
68 _trigger_queue
.reserve (8192);
70 _execution_tokens
= 0;
75 _quit_threads
= false;
80 Config
->ParameterChanged
.connect_same_thread (processor_usage_connection
, boost::bind (&Graph::parameter_changed
, this, _1
));
84 pbd_alloc_allowed
= &::alloc_allowed
;
89 Graph::parameter_changed (std::string param
)
91 if (param
== X_("processor-usage")) {
97 Graph::reset_thread_list ()
99 uint32_t num_threads
= how_many_dsp_threads ();
101 /* don't bother doing anything here if we already have the right
105 if (_thread_list
.size() == num_threads
) {
109 Glib::Mutex::Lock
lm (_session
.engine().process_lock());
112 if (!_thread_list
.empty()) {
117 /* XXX this only makes sense when we can use just the AudioEngine thread
118 and still keep the graph current with the route list
120 if (num_threads
<= 1) {
121 /* no point creating 1 thread - the AudioEngine already gives us one
126 if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread
, this), &a_thread
, 100000) == 0) {
127 _thread_list
.push_back (a_thread
);
130 for (uint32_t i
= 1; i
< num_threads
; ++i
) {
131 if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread
, this), &a_thread
, 100000) == 0) {
132 _thread_list
.push_back (a_thread
);
138 Graph::session_going_away()
142 // now drop all references on the nodes.
143 _nodes_rt
[0].clear();
144 _nodes_rt
[1].clear();
145 _init_trigger_list
[0].clear();
146 _init_trigger_list
[1].clear();
147 _trigger_queue
.clear();
151 Graph::drop_threads ()
153 _quit_threads
= true;
155 for (unsigned int i
=0; i
< _thread_list
.size(); i
++) {
156 _execution_sem
.signal ();
159 _callback_start_sem
.signal ();
161 for (list
<pthread_t
>::iterator i
= _thread_list
.begin(); i
!= _thread_list
.end(); ++i
) {
163 pthread_join (*i
, &status
);
166 _thread_list
.clear ();
168 _execution_tokens
= 0;
170 _quit_threads
= false;
174 Graph::clear_other_chain ()
176 Glib::Mutex::Lock
ls (_swap_mutex
);
179 if (_setup_chain
!= _pending_chain
) {
181 for (node_list_t::iterator ni
=_nodes_rt
[_setup_chain
].begin(); ni
!=_nodes_rt
[_setup_chain
].end(); ni
++) {
182 (*ni
)->_activation_set
[_setup_chain
].clear();
185 _nodes_rt
[_setup_chain
].clear ();
186 _init_trigger_list
[_setup_chain
].clear ();
189 /* setup chain == pending chain - we have
190 to wait till this is no longer true.
192 _cleanup_cond
.wait (_swap_mutex
);
199 node_list_t::iterator i
;
202 if (_swap_mutex
.trylock()) {
203 // we got the swap mutex.
204 if (_current_chain
!= _pending_chain
)
206 // printf ("chain swap ! %d -> %d\n", _current_chain, _pending_chain);
207 _setup_chain
= _current_chain
;
208 _current_chain
= _pending_chain
;
209 _cleanup_cond
.signal ();
211 _swap_mutex
.unlock ();
214 chain
= _current_chain
;
217 for (i
=_nodes_rt
[chain
].begin(); i
!=_nodes_rt
[chain
].end(); i
++) {
219 _graph_empty
= false;
221 _finished_refcount
= _init_finished_refcount
[chain
];
223 for (i
=_init_trigger_list
[chain
].begin(); i
!=_init_trigger_list
[chain
].end(); i
++) {
224 this->trigger( i
->get() );
229 Graph::trigger (GraphNode
* n
)
231 pthread_mutex_lock (&_trigger_mutex
);
232 _trigger_queue
.push_back (n
);
233 pthread_mutex_unlock (&_trigger_mutex
);
239 if (g_atomic_int_dec_and_test (&_finished_refcount
)) {
241 // ok... this cycle is finished now.
242 // we are the only thread alive.
244 this->restart_cycle();
249 Graph::restart_cycle()
251 // we are through. wakeup our caller.
254 _callback_done_sem
.signal ();
256 // block until we are triggered.
257 _callback_start_sem
.wait();
269 // returning will restart the cycle.
270 // starting with waking up the others.
274 is_feedback (boost::shared_ptr
<RouteList
> routelist
, Route
* from
, boost::shared_ptr
<Route
> to
)
276 for (RouteList::iterator ri
=routelist
->begin(); ri
!=routelist
->end(); ri
++) {
277 if ((*ri
).get() == from
)
287 is_feedback (boost::shared_ptr
<RouteList
> routelist
, boost::shared_ptr
<Route
> from
, Route
* to
)
289 for (RouteList::iterator ri
=routelist
->begin(); ri
!=routelist
->end(); ri
++) {
290 if ((*ri
).get() == to
)
300 Graph::rechain (boost::shared_ptr
<RouteList
> routelist
)
302 node_list_t::iterator ni
;
303 Glib::Mutex::Lock
ls (_swap_mutex
);
305 int chain
= _setup_chain
;
306 DEBUG_TRACE (DEBUG::Graph
, string_compose ("============== setup %1\n", chain
));
307 // set all refcounts to 0;
309 _init_finished_refcount
[chain
] = 0;
310 _init_trigger_list
[chain
].clear();
312 _nodes_rt
[chain
].clear();
314 for (RouteList::iterator ri
=routelist
->begin(); ri
!=routelist
->end(); ri
++) {
315 node_ptr_t n
= boost::dynamic_pointer_cast
<GraphNode
> (*ri
);
317 n
->_init_refcount
[chain
] = 0;
318 n
->_activation_set
[chain
].clear();
319 _nodes_rt
[chain
].push_back(n
);
322 // now add refs for the connections.
324 for (ni
=_nodes_rt
[chain
].begin(); ni
!=_nodes_rt
[chain
].end(); ni
++) {
325 bool has_input
= false;
326 bool has_output
= false;
328 boost::shared_ptr
<Route
> rp
= boost::dynamic_pointer_cast
<Route
>( *ni
);
330 for (RouteList::iterator ri
=routelist
->begin(); ri
!=routelist
->end(); ri
++) {
331 if (rp
->direct_feeds (*ri
)) {
332 if (is_feedback (routelist
, rp
.get(), *ri
)) {
337 (*ni
)->_activation_set
[chain
].insert (boost::dynamic_pointer_cast
<GraphNode
> (*ri
) );
341 for (Route::FedBy::iterator fi
=rp
->fed_by().begin(); fi
!=rp
->fed_by().end(); fi
++) {
342 if (boost::shared_ptr
<Route
> r
= fi
->r
.lock()) {
343 if (!is_feedback (routelist
, r
, rp
.get())) {
349 for (node_set_t::iterator ai
=(*ni
)->_activation_set
[chain
].begin(); ai
!=(*ni
)->_activation_set
[chain
].end(); ai
++) {
350 (*ai
)->_init_refcount
[chain
] += 1;
354 _init_trigger_list
[chain
].push_back (*ni
);
357 _init_finished_refcount
[chain
] += 1;
360 _pending_chain
= chain
;
369 pthread_mutex_lock (&_trigger_mutex
);
370 if (_trigger_queue
.size()) {
371 to_run
= _trigger_queue
.back();
372 _trigger_queue
.pop_back();
377 int et
= _execution_tokens
;
378 int ts
= _trigger_queue
.size();
380 int wakeup
= min (et
, ts
);
381 _execution_tokens
-= wakeup
;
383 DEBUG_TRACE(DEBUG::ProcessThreads
, string_compose ("%1 signals %2\n", pthread_self(), wakeup
));
385 for (int i
= 0; i
< wakeup
; i
++) {
386 _execution_sem
.signal ();
389 while (to_run
== 0) {
390 _execution_tokens
+= 1;
391 pthread_mutex_unlock (&_trigger_mutex
);
392 DEBUG_TRACE (DEBUG::ProcessThreads
, string_compose ("%1 goes to sleep\n", pthread_self()));
393 _execution_sem
.wait ();
397 DEBUG_TRACE (DEBUG::ProcessThreads
, string_compose ("%1 is awake\n", pthread_self()));
398 pthread_mutex_lock (&_trigger_mutex
);
399 if (_trigger_queue
.size()) {
400 to_run
= _trigger_queue
.back();
401 _trigger_queue
.pop_back();
404 pthread_mutex_unlock (&_trigger_mutex
);
407 to_run
->finish (_current_chain
);
409 DEBUG_TRACE(DEBUG::ProcessThreads
, string_compose ("%1 has finished run_one()\n", pthread_self()));
416 if (!jack_is_realtime (AudioEngine::instance()->jack())) {
420 int priority
= jack_client_real_time_priority (AudioEngine::instance()->jack());
423 struct sched_param rtparam
;
425 memset (&rtparam
, 0, sizeof (rtparam
));
426 rtparam
.sched_priority
= priority
;
428 pthread_setschedparam (pthread_self(), SCHED_FIFO
, &rtparam
);
433 Graph::helper_thread()
435 suspend_rt_malloc_checks ();
436 ProcessThread
* pt
= new ProcessThread ();
437 resume_rt_malloc_checks ();
454 suspend_rt_malloc_checks ();
455 ProcessThread
* pt
= new ProcessThread ();
456 resume_rt_malloc_checks ();
462 _callback_start_sem
.wait ();
463 DEBUG_TRACE(DEBUG::ProcessThreads
, "main thread is awake\n");
471 if (_graph_empty
&& !_quit_threads
) {
472 _callback_done_sem
.signal ();
473 DEBUG_TRACE(DEBUG::ProcessThreads
, "main thread sees graph done, goes back to slee\n");
478 DEBUG_TRACE(DEBUG::ProcessThreads
, "main thread runs one graph node\n");
488 Graph::dump (int chain
)
491 node_list_t::iterator ni
;
492 node_set_t::iterator ai
;
494 chain
= _pending_chain
;
496 DEBUG_TRACE (DEBUG::Graph
, "--------------------------------------------Graph dump:\n");
497 for (ni
=_nodes_rt
[chain
].begin(); ni
!=_nodes_rt
[chain
].end(); ni
++) {
498 boost::shared_ptr
<Route
> rp
= boost::dynamic_pointer_cast
<Route
>( *ni
);
499 DEBUG_TRACE (DEBUG::Graph
, string_compose ("GraphNode: %1 refcount: %2\n", rp
->name().c_str(), (*ni
)->_init_refcount
[chain
]));
500 for (ai
=(*ni
)->_activation_set
[chain
].begin(); ai
!=(*ni
)->_activation_set
[chain
].end(); ai
++) {
501 DEBUG_TRACE (DEBUG::Graph
, string_compose (" triggers: %1\n", boost::dynamic_pointer_cast
<Route
>(*ai
)->name().c_str()));
505 DEBUG_TRACE (DEBUG::Graph
, "------------- trigger list:\n");
506 for (ni
=_init_trigger_list
[chain
].begin(); ni
!=_init_trigger_list
[chain
].end(); ni
++) {
507 DEBUG_TRACE (DEBUG::Graph
, string_compose ("GraphNode: %1 refcount: %2\n", boost::dynamic_pointer_cast
<Route
>(*ni
)->name().c_str(), (*ni
)->_init_refcount
[chain
]));
510 DEBUG_TRACE (DEBUG::Graph
, string_compose ("final activation refcount: %1\n", _init_finished_refcount
[chain
]));
515 Graph::silent_process_routes (pframes_t nframes
, framepos_t start_frame
, framepos_t end_frame
,
516 bool can_record
, bool rec_monitors_input
, bool& need_butler
)
518 _process_nframes
= nframes
;
519 _process_start_frame
= start_frame
;
520 _process_end_frame
= end_frame
;
521 _process_can_record
= can_record
;
522 _process_rec_monitors_input
= rec_monitors_input
;
524 _process_silent
= true;
525 _process_noroll
= false;
527 _process_need_butler
= false;
530 DEBUG_TRACE(DEBUG::ProcessThreads
, "wake graph for silent process\n");
531 _callback_start_sem
.signal ();
532 _callback_done_sem
.wait ();
535 need_butler
= _process_need_butler
;
537 return _process_retval
;
541 Graph::process_routes (pframes_t nframes
, framepos_t start_frame
, framepos_t end_frame
, int declick
,
542 bool can_record
, bool rec_monitors_input
, bool& need_butler
)
544 DEBUG_TRACE (DEBUG::ProcessThreads
, string_compose ("graph execution from %1 to %2 = %3\n", start_frame
, end_frame
, nframes
));
546 _process_nframes
= nframes
;
547 _process_start_frame
= start_frame
;
548 _process_end_frame
= end_frame
;
549 _process_can_record
= can_record
;
550 _process_rec_monitors_input
= rec_monitors_input
;
551 _process_declick
= declick
;
553 _process_silent
= false;
554 _process_noroll
= false;
556 _process_need_butler
= false;
558 DEBUG_TRACE(DEBUG::ProcessThreads
, "wake graph for non-silent process\n");
559 _callback_start_sem
.signal ();
560 _callback_done_sem
.wait ();
562 DEBUG_TRACE (DEBUG::ProcessThreads
, "graph execution complete\n");
564 need_butler
= _process_need_butler
;
566 return _process_retval
;
570 Graph::routes_no_roll (pframes_t nframes
, framepos_t start_frame
, framepos_t end_frame
,
571 bool non_rt_pending
, bool can_record
, int declick
)
573 DEBUG_TRACE (DEBUG::ProcessThreads
, string_compose ("no-roll graph execution from %1 to %2 = %3\n", start_frame
, end_frame
, nframes
));
575 _process_nframes
= nframes
;
576 _process_start_frame
= start_frame
;
577 _process_end_frame
= end_frame
;
578 _process_can_record
= can_record
;
579 _process_declick
= declick
;
580 _process_non_rt_pending
= non_rt_pending
;
582 _process_silent
= false;
583 _process_noroll
= true;
585 _process_need_butler
= false;
587 DEBUG_TRACE(DEBUG::ProcessThreads
, "wake graph for no-roll process\n");
588 _callback_start_sem
.signal ();
589 _callback_done_sem
.wait ();
591 return _process_retval
;
594 Graph::process_one_route (Route
* route
)
596 bool need_butler
= false;
601 DEBUG_TRACE (DEBUG::ProcessThreads
, string_compose ("%1 runs route %2\n", pthread_self(), route
->name()));
603 if (_process_silent
) {
604 retval
= route
->silent_roll (_process_nframes
, _process_start_frame
, _process_end_frame
, _process_can_record
, _process_rec_monitors_input
, need_butler
);
605 } else if (_process_noroll
) {
606 route
->set_pending_declick (_process_declick
);
607 retval
= route
->no_roll (_process_nframes
, _process_start_frame
, _process_end_frame
, _process_non_rt_pending
, _process_can_record
, _process_declick
);
609 route
->set_pending_declick (_process_declick
);
610 retval
= route
->roll (_process_nframes
, _process_start_frame
, _process_end_frame
, _process_declick
, _process_can_record
, _process_rec_monitors_input
, need_butler
);
614 _process_retval
= retval
;
618 _process_need_butler
= true;
623 Graph::in_process_thread () const
625 list
<pthread_t
>::const_iterator i
= _thread_list
.begin ();
626 while (i
!= _thread_list
.end() && *i
!= pthread_self ()) {
630 return i
!= _thread_list
.end ();