use JACK thread creation functions to create process-graph threads; provide GUI control over number of threads-relative-to-number-of-CPUS

git-svn-id: svn://localhost/ardour2/branches/3.0@7296 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-06-24 14:13:45 +00:00
parent fe229a830e
commit 0f5bdd666f
11 changed files with 183 additions and 34 deletions

View file

@ -2256,8 +2256,8 @@ MidiRegionView::trim_note (CanvasNoteEvent* event, Evoral::MusicalTime front_del
{
bool change_start = false;
bool change_length = false;
Evoral::MusicalTime new_start;
Evoral::MusicalTime new_length;
Evoral::MusicalTime new_start = 0;
Evoral::MusicalTime new_length = 0;
/* NOTE: the semantics of the two delta arguments are slightly subtle:
@ -2685,7 +2685,7 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
Evoral::MusicalTime beat_delta;
Evoral::MusicalTime paste_pos_beats;
Evoral::MusicalTime duration;
Evoral::MusicalTime end_point;
Evoral::MusicalTime end_point = 0;
duration = (*mcb.notes().rbegin())->end_time() - (*mcb.notes().begin())->time();
paste_pos_beats = frames_to_beats (pos - _region->position());

View file

@ -5,6 +5,7 @@
#include <gtkmm2ext/slider_controller.h>
#include "pbd/fpu.h"
#include "pbd/cpus.h"
#include "midi++/manager.h"
#include "midi++/factory.h"
@ -930,6 +931,28 @@ RCOptionEditor::RCOptionEditor ()
{
/* MISC */
uint32_t hwcpus = hardware_concurrency ();
if (hwcpus > 1) {
add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
ComboOption<uint32_t>* procs = new ComboOption<uint32_t> (
"processor-usage",
_("Signal processing uses: "),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
);
procs->add (-1, _("All but one"));
procs->add (0, _("All available processors"));
for (uint32_t i = 2; i < hwcpus; ++i) {
procs->add (1, string_compose (_("%1 processors"), i));
}
add_option (_("Misc"), procs);
}
add_option (_("Misc"), new OptionEditorHeading (_("Metering")));
ComboOption<float>* mht = new ComboOption<float> (

View file

@ -245,6 +245,8 @@ _ the regular process() call to session->process() is not made.
static AudioEngine* instance() { return _instance; }
void died ();
pthread_t create_process_thread (boost::function<void()>, size_t stacksize);
private:
static AudioEngine* _instance;
@ -316,6 +318,17 @@ _ the regular process() call to session->process() is not made.
static gint m_meter_exit;
ProcessThread* _main_thread;
struct ThreadData {
AudioEngine* engine;
boost::function<void()> f;
size_t stacksize;
ThreadData (AudioEngine* ae, boost::function<void()> fp, size_t stacksz)
: engine (ae) , f (fp) , stacksize (stacksz) {}
};
static void* _start_process_thread (void*);
};
} // namespace ARDOUR

View file

@ -85,7 +85,7 @@ class Graph : public SessionHandleRef
virtual void session_going_away ();
private:
std::list<Glib::Thread *> _thread_list;
std::list<pthread_t> _thread_list;
volatile bool _quit_threads;
node_list_t _nodes_rt[2];

View file

@ -153,6 +153,7 @@ CONFIG_VARIABLE (bool, show_waveforms_while_recording, "show-waveforms-while-rec
CONFIG_VARIABLE (WaveformScale, waveform_scale, "waveform-scale", Linear)
CONFIG_VARIABLE (WaveformShape, waveform_shape, "waveform-shape", Traditional)
CONFIG_VARIABLE (bool, allow_special_bus_removal, "allow-special-bus-removal", false)
CONFIG_VARIABLE (int32_t, processor_usage, "processor-usage", -1)
/* denormal management */

View file

@ -25,6 +25,9 @@
#include <sstream>
#include <glibmm/timer.h>
#include <jack/jack.h>
#include <jack/thread.h>
#include "pbd/pthread_utils.h"
#include "pbd/stacktrace.h"
#include "pbd/unknown_type.h"
@ -1480,3 +1483,30 @@ AudioEngine::is_realtime () const
GET_PRIVATE_JACK_POINTER_RET (_jack,false);
return jack_is_realtime (_priv_jack);
}
pthread_t
AudioEngine::create_process_thread (boost::function<void()> f, size_t stacksize)
{
GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
pthread_t thread;
ThreadData* td = new ThreadData (this, f, stacksize);
if (jack_client_create_thread (_priv_jack, &thread, jack_client_real_time_priority (_priv_jack),
jack_is_realtime (_priv_jack), _start_process_thread, td)) {
return -1;
}
return thread;
}
void*
AudioEngine::_start_process_thread (void* arg)
{
ThreadData* td = reinterpret_cast<ThreadData*> (arg);
boost::function<void()> f = td->f;
delete td;
f ();
return 0;
}

View file

@ -481,7 +481,7 @@ Delivery::target_gain ()
return 0.0;
}
MuteMaster::MutePoint mp;
MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
switch (_role) {
case Main:

View file

@ -18,17 +18,11 @@
*/
#ifdef __linux__
#include <unistd.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#include <stdio.h>
#include <cmath>
#include "pbd/compose.h"
#include "pbd/cpus.h"
#include "ardour/debug.h"
#include "ardour/graph.h"
@ -45,22 +39,6 @@
using namespace ARDOUR;
using namespace PBD;
static unsigned int
hardware_concurrency()
{
#if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
#elif defined(__APPLE__) || defined(__FreeBSD__)
int count;
size_t size=sizeof(count);
return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
#elif defined(HAVE_UNISTD) && defined(_SC_NPROCESSORS_ONLN)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
#else
return 0;
#endif
}
Graph::Graph (Session & session)
: SessionHandleRef (session)
@ -81,10 +59,34 @@ Graph::Graph (Session & session)
_graph_empty = true;
int num_cpu = hardware_concurrency();
info << string_compose (_("Using %1 CPUs via %1 threads\n"), num_cpu) << endmsg;
_thread_list.push_back( Glib::Thread::create( sigc::mem_fun( *this, &Graph::main_thread), 100000, true, true, Glib::THREAD_PRIORITY_NORMAL) );
for (int i=1; i<num_cpu; i++)
_thread_list.push_back( Glib::Thread::create( sigc::mem_fun( *this, &Graph::helper_thread), 100000, true, true, Glib::THREAD_PRIORITY_NORMAL) );
int num_threads = num_cpu;
int pu = Config->get_processor_usage ();
if (pu < 0) {
/* use "pu" less cores for DSP than appear to be available
*/
if (pu < num_threads) {
num_threads += pu; // pu is negative
} else {
num_threads = 1;
}
} else {
/* use "pu" cores, if available
*/
if (pu <= num_threads) {
num_threads = pu;
}
}
info << string_compose (_("Using %2 threads on %1 CPUs"), num_cpu, num_threads) << endmsg;
_thread_list.push_back (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), 100000));
for (int i = 1; i < num_threads; ++i) {
_thread_list.push_back (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), 100000));
}
}
void
@ -98,8 +100,9 @@ Graph::session_going_away()
sem_post( &_callback_start_sem);
for (std::list<Glib::Thread *>::iterator i=_thread_list.begin(); i!=_thread_list.end(); i++) {
(*i)->join();
for (std::list<pthread_t>::iterator i = _thread_list.begin(); i != _thread_list.end(); i++) {
void* status;
pthread_join (*i, &status);
}
// now drop all references on the nodes.

49
libs/pbd/cpus.cc Normal file
View file

@ -0,0 +1,49 @@
/*
Copyright (C) 2010 Paul Davis
Author: Torben Hohn
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef WAF_BUILD
#include "libpbd-config.h"
#endif
#ifdef __linux__
#include <unistd.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#include "pbd/cpus.h"
uint32_t
hardware_concurrency()
{
#if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
#elif defined(__APPLE__) || defined(__FreeBSD__)
int count;
size_t size=sizeof(count);
return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
#elif defined(HAVE_UNISTD) && defined(_SC_NPROCESSORS_ONLN)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
#else
return 0;
#endif
}

28
libs/pbd/pbd/cpus.h Normal file
View file

@ -0,0 +1,28 @@
/*
Copyright (C) 2010 Paul Davis
Author: Torben Hohn
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __libpbd_cpus_h__
#define __libpbd_cpus_h__
#include <stdint.h>
extern uint32_t hardware_concurrency ();
#endif /* __libpbd_cpus_h__ */

View file

@ -40,6 +40,7 @@ def configure(conf):
conf.check(function_name='getmntent', header_name='mntent.h', define_name='HAVE_GETMNTENT')
conf.check(header_name='execinfo.h', define_name='HAVE_EXECINFO')
conf.check(header_name='unistd.h', define_name='HAVE_UNISTD')
conf.write_config_header('libpbd-config.h')
@ -59,6 +60,7 @@ def build(bld):
controllable.cc
controllable_descriptor.cc
crossthread.cc
cpus.cc
debug.cc
enumwriter.cc
event_loop.cc