On Wed, Dec 02, 2009 at 01:15:08PM +0100, f...@kokkinizita.net wrote: > On Wed, Dec 02, 2009 at 12:32:12PM +0100, Arnold Krille wrote: > > > On Wednesday 02 December 2009 11:09:18 f...@kokkinizita.net wrote: > > > > > non-RT, while these extra threads remain at RT. So > > > they will pre-empts Jack's thread and will appear to > > > be always ready on time. Except when you have 2 CPUs: > > > then Jack's thread will be allowed to continue even > > > if some of the others have not yet completed their > > > work. > > > > Wouldn't the easiest solution be to wait for the worker-threads when in > > freewheeling mode? > > It's not the only solution but surely the easiest. > The semaphores that would be required are already > in place (they are used for checking readyness now).
hmm... but thats the trigger semaphore. and the worker thread blocks on it. so the process thread cant block on it. or are you talking about some non released code ? > > The complicated part could be switching between the > two regimes. I suspect this can't be done 'instantly', > it could require a multi-step process spread over a > series of periods. > > Maybe I'm overestimating the complexity, but I try > to step gently as organising the cooperation of these > threads was not a simple task. The code looks simple, > but that's the result of my usual irresistable urge > to simplify every algorithm down to its essentials. > > I've not really tried to solve this ATM, but will do > if some free time drops from the (currently) blue > Italian sky. i added a semaphore like construct built with pthread_cond the RT thread only decrements the counter and in sync mode wait for the counter to be zero. this allows instant switching. using more than 1 line for syncying clutters the code though, but as this kind of stuff is a matter of taste, i leave that up to you to move it into a separate method or class. patch is attached -- torben Hohn
diff --git a/jconvolver-0.8.4/source/jclient.cc b/jconvolver-0.8.4/source/jclient.cc index 5feb421..c57bd71 100644 --- a/jconvolver-0.8.4/source/jclient.cc +++ b/jconvolver-0.8.4/source/jclient.cc @@ -30,7 +30,8 @@ Jclient::Jclient (const char *name, Convproc *conv) : _mode (PM_CONVOL), _ninp (0), _nout (0), - _conv (conv) + _conv (conv), + _fweel (0) { init_jack (); } @@ -138,10 +139,16 @@ void Jclient::jack_static_shutdown (void *arg) void Jclient::jack_static_freewheel (int state, void *arg) { + Jclient *me = (Jclient *) arg; if (state) { - fprintf (stderr, "WARNING: jconvolver may not work correctly in freewheel mode.\n"); + if( me->_conv ) + me->_conv->drop_rt (); + } else { + if( me->_conv ) + me->_conv->get_rt (); } + me->_fweel = state ? true : false; } @@ -224,7 +231,7 @@ void Jclient::jack_process (void) } } - _conv->process (); + _conv->process ( false, _fweel ); for (i = 0; i < _nout; i++) { diff --git a/jconvolver-0.8.4/source/jclient.h b/jconvolver-0.8.4/source/jclient.h index 80240d0..998e188 100644 --- a/jconvolver-0.8.4/source/jclient.h +++ b/jconvolver-0.8.4/source/jclient.h @@ -69,6 +69,8 @@ private: unsigned int _ninp; unsigned int _nout; Convproc *_conv; + bool _fweel; + static void jack_static_shutdown (void *arg); static void jack_static_freewheel (int state, void *arg); diff --git a/zita-convolver-2.0.0/libs/zita-convolver.cc b/zita-convolver-2.0.0/libs/zita-convolver.cc index 9cb45ad..96fe319 100644 --- a/zita-convolver-2.0.0/libs/zita-convolver.cc +++ b/zita-convolver-2.0.0/libs/zita-convolver.cc @@ -282,7 +282,7 @@ int Convproc::cleanup (void) } -void Convproc::process (bool skip) +void Convproc::process (bool skip, bool sync) { unsigned int f, k; @@ -296,7 +296,7 @@ void Convproc::process (bool skip) { _outoffs = f = 0; for (k = 0; k < _nout; k++) memset (_outbuff [k], 0, _minpart * sizeof (float)); - for (k = 0; k < _nproc; k++) f |= _procs [k].readout (skip); + for (k = 0; k < _nproc; k++) f |= _procs [k].readout (skip, sync); if (f) { _flags |= f; @@ -327,7 +327,21 @@ void Convproc::print (void) for (k = 0; k < _nproc; k++) _procs [k].print (); } +int Convproc::get_rt () +{ + unsigned int k; + int f=0; + for (k = 0; k < _nproc; k++) f |= _procs [k].get_rt (); + return f; +} +int Convproc::drop_rt () +{ + unsigned int k; + int f=0; + for (k = 0; k < _nproc; k++) f |= _procs [k].drop_rt (); + return f; +} typedef float FV4 __attribute__ ((vector_size(16))); @@ -338,6 +352,7 @@ Convlevel::Convlevel (void) : _parsize (0), _vectopt (0), _pthr (0), + _done_count (0), _inp_list (0), _out_list (0), _plan_r2c (0), @@ -346,6 +361,8 @@ Convlevel::Convlevel (void) : _prep_data (0), _freq_data (0) { + pthread_mutex_init (&_sync_lock, NULL); + pthread_cond_init (&_done, NULL); } @@ -551,10 +568,10 @@ void Convlevel::start (int priority, int schclass) _pthr = 0; min = sched_get_priority_min (schclass); max = sched_get_priority_max (schclass); - priority += _prio; - if (priority > max) priority = max; - if (priority < min) priority = min; - parm.sched_priority = priority; + _priority = priority + _prio; + if (_priority > max) _priority = max; + if (_priority < min) _priority = min; + parm.sched_priority = _priority; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setschedpolicy (&attr, schclass); @@ -566,6 +583,37 @@ void Convlevel::start (int priority, int schclass) pthread_attr_destroy (&attr); } +int Convlevel::drop_rt () +{ + struct sched_param rtparam; + + if (_stat != ST_PROC) + return 0; + + memset (&rtparam, 0, sizeof (rtparam)); + rtparam.sched_priority = 0; + + if (pthread_setschedparam (_pthr, SCHED_OTHER, &rtparam) != 0) { + return -1; + } + return 0; +} + +int Convlevel::get_rt () +{ + struct sched_param rtparam; + + if (_stat != ST_PROC) + return 0; + + memset (&rtparam, 0, sizeof (rtparam)); + rtparam.sched_priority = _priority; + + if (pthread_setschedparam (_pthr, SCHED_FIFO, &rtparam) != 0) { + return -1; + } + return 0; +} void Convlevel::stop (void) { @@ -646,6 +694,7 @@ void Convlevel::main (void) while (true) { sem_wait (&_trig); + if (_stat == ST_TERM) { _stat = ST_IDLE; @@ -653,6 +702,11 @@ void Convlevel::main (void) return; } process (false); + + pthread_mutex_lock (&_sync_lock); + _done_count += 1; + pthread_cond_signal (&_done); + pthread_mutex_unlock (&_sync_lock); } } @@ -764,7 +818,7 @@ void Convlevel::process (bool skip) } -int Convlevel::readout (bool skip) +int Convlevel::readout (bool skip, bool sync) { unsigned int k; Outnode *Y; @@ -774,8 +828,27 @@ int Convlevel::readout (bool skip) if (_outoffs == _parsize) { _outoffs = 0; + + if (_stat == ST_PROC) { + if (sync) + { + pthread_mutex_lock (&_sync_lock); + while (_done_count < 0) + pthread_cond_wait (&_done, &_sync_lock); + _done_count -= 1; + pthread_mutex_unlock (&_sync_lock); + } else { + // this lock/unlock could be removed if the counter was atomic + // however atomic stuff is not really portable. and if the other thread + // holds this lock at this point, we could consider it late anyways. + // it doesnt do much while holding it. so this is probably better. + pthread_mutex_lock (&_sync_lock); + _done_count -= 1; + pthread_mutex_unlock (&_sync_lock); + } + k = _opi1; _opi1 = _opi2; _opi2 = _opi3; diff --git a/zita-convolver-2.0.0/libs/zita-convolver.h b/zita-convolver-2.0.0/libs/zita-convolver.h index cbc1e54..b069dbd 100644 --- a/zita-convolver-2.0.0/libs/zita-convolver.h +++ b/zita-convolver-2.0.0/libs/zita-convolver.h @@ -125,10 +125,12 @@ private: unsigned int out2); void reset (void); void cleanup (void); - int readout (bool skip); + int readout (bool skip, bool sync); void fftswap (fftwf_complex *p); bool idle (void) const { return _stat == ST_IDLE; } void print (void); + int get_rt(); + int drop_rt(); static void *static_main (void *arg); void main (void); @@ -138,6 +140,7 @@ private: volatile unsigned int _stat; // current processing state int _prio; // relative priority + int _priority; // absolute priority unsigned int _offs; // offset from start of impulse response unsigned int _npar; // number of partitions unsigned int _parsize; // partition and outbut buffer size @@ -154,6 +157,9 @@ private: int _late; pthread_t _pthr; sem_t _trig; + pthread_mutex_t _sync_lock; + pthread_cond_t _done; + volatile int _done_count; Inpnode *_inp_list; Outnode *_out_list; @@ -269,7 +275,11 @@ public: void print (void); - void process (bool skip = false); + void process (bool skip = false, bool sync = false); + + int get_rt(); + int drop_rt(); + private:
_______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev