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

Reply via email to