diff options
-rw-r--r-- | libs/ardour/ardour/audio_backend.h | 18 | ||||
-rw-r--r-- | libs/ardour/ardour/audioengine.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/graph.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 10 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 26 | ||||
-rw-r--r-- | libs/ardour/graph.cc | 30 | ||||
-rw-r--r-- | libs/backends/jack/jack_audiobackend.cc | 64 | ||||
-rw-r--r-- | libs/backends/jack/jack_audiobackend.h | 8 |
8 files changed, 114 insertions, 55 deletions
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index 9052acd530..0e39625e8c 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -399,13 +399,25 @@ class AudioBackend : public PortEngine { * stacksize. The thread will begin executing @param func, and will exit * when that function returns. */ - virtual int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize) = 0; + virtual int create_process_thread (boost::function<void()> func) = 0; - /** Wait for the thread specified by @param thread to exit. + /** Wait for all processing threads to exit. * * Return zero on success, non-zero on failure. */ - virtual int wait_for_process_thread_exit (AudioBackendNativeThread thread) = 0; + virtual int join_process_threads () = 0; + + /** Return true if execution context is in a backend thread + */ + virtual bool in_process_thread () = 0; + + /** Return the minimum stack size of audio threads in bytes + */ + static size_t thread_stack_size () { return 100000; } + + /** Return number of processing threads + */ + virtual uint32_t process_thread_count () = 0; virtual void update_latencies () = 0; diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 201d960479..1bf4be3243 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -100,8 +100,12 @@ public: pframes_t sample_time_at_cycle_start (); pframes_t samples_since_cycle_start (); bool get_sync_offset (pframes_t& offset) const; - int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize); - int wait_for_process_thread_exit (AudioBackendNativeThread); + + int create_process_thread (boost::function<void()> func); + int join_process_threads (); + bool in_process_thread (); + uint32_t process_thread_count (); + bool is_realtime() const; bool connected() const; diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h index 08af6fb721..763723c792 100644 --- a/libs/ardour/ardour/graph.h +++ b/libs/ardour/ardour/graph.h @@ -31,8 +31,6 @@ #include <glib.h> #include <cassert> -#include <pthread.h> - #include "pbd/semutils.h" #include "ardour/types.h" @@ -59,8 +57,6 @@ class Graph : public SessionHandleRef public: Graph (Session & session); - uint32_t threads_in_use () const { return _thread_list.size(); } - void prep(); void trigger (GraphNode * n); void rechain (boost::shared_ptr<RouteList>, GraphEdges const &); @@ -93,7 +89,6 @@ protected: virtual void session_going_away (); private: - std::list<AudioBackendNativeThread> _thread_list; volatile bool _quit_threads; void reset_thread_list (); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 526a71c58b..ee43d1f30f 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -615,16 +615,6 @@ namespace ARDOUR { uint32_t max; //< samples }; -/* PLATFORM SPECIFIC #ifdef's here */ - - /** Define the native thread type used on the platform */ - typedef pthread_t AudioBackendNativeThread; - static inline bool self_thread_equal (AudioBackendNativeThread thr) { - return pthread_equal (thr, pthread_self()); - } - -/* PLATFORM SPECIFIC #endif's here */ - } // namespace ARDOUR diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 465f88de56..631a861741 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -826,21 +826,39 @@ AudioEngine::get_sync_offset (pframes_t& offset) const } int -AudioEngine::create_process_thread (boost::function<void()> func, AudioBackendNativeThread* thr, size_t stacksize) +AudioEngine::create_process_thread (boost::function<void()> func) { if (!_backend) { return -1; } - return _backend->create_process_thread (func, thr, stacksize); + return _backend->create_process_thread (func); } int -AudioEngine::wait_for_process_thread_exit (AudioBackendNativeThread thr) +AudioEngine::join_process_threads () +{ + if (!_backend) { + return -1; + } + return _backend->join_process_threads (); +} + +bool +AudioEngine::in_process_thread () +{ + if (!_backend) { + return false; + } + return _backend->in_process_thread (); +} + +uint32_t +AudioEngine::process_thread_count () { if (!_backend) { return 0; } - return _backend->wait_for_process_thread_exit (thr); + return _backend->process_thread_count (); } int diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index c8e374cddc..71eeee41ea 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -96,29 +96,24 @@ Graph::reset_thread_list () number of threads. */ - if (_thread_list.size() == num_threads) { + if (AudioEngine::instance()->process_thread_count() == num_threads) { return; } Glib::Threads::Mutex::Lock lm (_session.engine().process_lock()); - AudioBackendNativeThread a_thread; - if (!_thread_list.empty()) { + if (AudioEngine::instance()->process_thread_count() != 0) { drop_threads (); } - if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this)) != 0) { throw failed_constructor (); } - _thread_list.push_back (a_thread); - for (uint32_t i = 1; i < num_threads; ++i) { - if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), &a_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this))) { throw failed_constructor (); } - - _thread_list.push_back (a_thread); } } @@ -140,17 +135,15 @@ Graph::drop_threads () { _quit_threads = true; - for (unsigned int i=0; i< _thread_list.size(); i++) { + uint32_t thread_count = AudioEngine::instance()->process_thread_count (); + + for (unsigned int i=0; i < thread_count; i++) { _execution_sem.signal (); } _callback_start_sem.signal (); - for (list<AudioBackendNativeThread>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { - AudioEngine::instance()->wait_for_process_thread_exit (*i); - } - - _thread_list.clear (); + AudioEngine::instance()->join_process_threads (); _execution_tokens = 0; @@ -583,10 +576,5 @@ Graph::process_one_route (Route* route) bool Graph::in_process_thread () const { - for (list<AudioBackendNativeThread>::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) { - if (self_thread_equal (*i)) { - return true; - } - } - return false; + return AudioEngine::instance()->in_process_thread (); } diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc index c6a523f4d2..a651f2522d 100644 --- a/libs/backends/jack/jack_audiobackend.cc +++ b/libs/backends/jack/jack_audiobackend.cc @@ -45,6 +45,7 @@ using namespace PBD; using std::string; using std::vector; + #define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; } #define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; } @@ -825,25 +826,72 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar } int -JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize) +JACKAudioBackend::create_process_thread (boost::function<void()> f) { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); - ThreadData* td = new ThreadData (this, f, stacksize); - if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack), + jack_native_thread_t thread_id; + ThreadData* td = new ThreadData (this, f, thread_stack_size()); + + if (jack_client_create_thread (_priv_jack, &thread_id, jack_client_real_time_priority (_priv_jack), jack_is_realtime (_priv_jack), _start_process_thread, td)) { return -1; } - return 0; + _jack_threads.push_back(thread_id); + return 0; } int -JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr) +JACKAudioBackend::join_process_threads () +{ + GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); + + int ret = 0; + + for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin (); + i != _jack_threads.end(); i++) { + +#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS) + if (jack_client_stop_thread (_priv_jack, *i) != 0) { +#else + void* status; + if (pthread_join (*i, &status) != 0) { +#endif + error << "AudioEngine: cannot stop process thread" << endmsg; + ret += -1; + } + } + + _jack_threads.clear(); + + return ret; +} + +bool +JACKAudioBackend::in_process_thread () +{ + for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin (); + i != _jack_threads.end(); i++) { + +#ifdef COMPILER_MINGW + if (*i == GetCurrentThread()) { + return true; + } +#else // pthreads + if (pthread_equal (*i, pthread_self()) != 0) { + return true; + } +#endif + } + + return false; +} + +uint32_t +JACKAudioBackend::process_thread_count () { - void* status; - /* this doesn't actively try to stop the thread, it just waits till it exits */ - return pthread_join (thr, &status); + return _jack_threads.size(); } void* diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h index 9ab545f3ee..b8d8b3b3f1 100644 --- a/libs/backends/jack/jack_audiobackend.h +++ b/libs/backends/jack/jack_audiobackend.h @@ -103,8 +103,10 @@ class JACKAudioBackend : public AudioBackend { size_t raw_buffer_size (DataType t); - int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize); - int wait_for_process_thread_exit (AudioBackendNativeThread); + int create_process_thread (boost::function<void()> func); + int join_process_threads (); + bool in_process_thread (); + uint32_t process_thread_count (); void transport_start (); void transport_stop (); @@ -184,6 +186,8 @@ class JACKAudioBackend : public AudioBackend { bool _freewheeling; std::map<DataType,size_t> _raw_buffer_sizes; + std::vector<jack_native_thread_t> _jack_threads; + static int _xrun_callback (void *arg); static void* _process_thread (void *arg); static int _sample_rate_callback (pframes_t nframes, void *arg); |