Re: [linux-audio-dev] priority inversion & inheritance

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] priority inversion & inheritance
From: Martijn Sipkema (msipkema_AT_sipkema-digital.com)
Date: Thu Jul 11 2002 - 17:13:25 EEST


> One simple reason, whether a valid design or not, is that there\'s a lot of
> code that handles audio in constant size blocks.

Ok. I give up. It\'s clear that most find this more important that the
issue with hardware.

> For instance if you have
> a mixer element in the signal graph, it is just easier if all the inputs
> deliver the same amount of data at every iteration.

Hmm, why? I can see that it is a requirement that at every iteration there
is the same data available at the input(s) as is requested on the output(s).
I don\'t see what makes a mixer that much easier to implement if the amount
of data to process is the same for every iteration.

> In ecasound the trickiest part is that the i/o subsystem uses buffer
> objecs to store audio. Each buffer object contains nframes of audio.
> These audio slots are allocated before real-time processing is started and
> cannot be resized on-the-fly.
>
> But the important point is that for low-latency processing, the design
> described above has no real negative sides and I see no need to change it.

And my problem is that if JACK goes over to constant nframes there will be
no need to change it. Even worse, new applications will also use assume
nframes == constant.

> With the current JACK implementation this design delivers optimal results
> both in terms of efficiency and latency... _if_ I ignore the
> non-const-nframes issue.

And you could still for all the cards that have nframes == const. Just add
some buffering for nframes != const.

> If I want to add correct support for the current API, I either have to a)
> change the engine design (basicly from using ringbuffers of audio blocks
> into ringbuffers of audio samples), which involves making changes to
> majority of the interfaces in ecasound\'s codebase (multiple MBs of code!),
> or b), make a compromise on efficicient&latency and add a intermediary
> buffer between the JACK process() and ecasound engine.

Or, only use the intermediate buffer when nframes != constant, assuming there
will be a way to determine that.

[...]
> >> read/write ops or driven by select/poll. In this case the easiest way to
> >> add JACK support is to put a FIFO between the engine and the process()
> >> callbacks. Although priority inheritance could be used here, it\\\'s
doesn\\\'t
> > If the FIFO uses a mutex, it should use some priority inversion prevention
> > mechanism, unless both threads run at the same priority. Otherwise there
> > is a potential unbounded block on the mutex.
>
> The two threads must run with SCHED_FIFO as they both need to complete
> their cycle before the next soundcard interrupt.

What I meant was a traditional application not running SCHED_FIFO but using
a large FIFO to communicate with JACK\'s process() callback.
And even if they both run SCHED_FIFO, they should then also run at the same
priority.

> As Linux is not a
> real-time OS (and probably even if it was), priority inheritance would
> only solve half of the problem. Calls to disk i/o, network, user i/o and
> other subsystems block without deterministic worst-case bounds. No amount
> of priority (given by priority inheritance) will save your butt if the
> disk head is physically in the wrong place when you need it. On a
> dedicated system you can reserve a separate disk for the audio i/o or
> prevent other processes from using the disk, but in a GPOS like Linux, it
> is always possible that some other process can affect the kernel
> subsystems (for instance, access a file and cause the disk head to move at
> the worst possible time).

When the disk is not able to supply the samples in time, then there is a
problem :)
Using a fast disk and buffering will normally be sufficient.

> The correct solution is to partition your audio code into real-time
> capable and non-realtime parts and make sure that the non-real-time part
> is never ever able to block the real-time part. In essence this very close
> to the RT<->non-RT separation advocated by RTLinux, just done on a
> different level (between interrupt-driven SCHED_FIFO code and
> timer-interrupt/scheduler driver SCHED_OTHER code).

As I see it, it isn\'t a problem when the non-realtime part blocks the
real-time part, as long as there is a worst case bounded block time for it.

> > There is hardware that just interrupts at a constant rate. With this
hardware
> > the frames that or ready isn\'t exactly constant. You might assume some
value,
> > but if it isn\'t exactly correct then you\'ll drift.
>
> Yes, the interrupt intervals and how much data actually is available when
> the software is woken up are two different things. But as the nframes
> count in any case has an upper bound, you are not free to directly use the
> avail_samples count anyways. And natural choice is to always use the
> period_count. I\'ve posted one alternative approach to this to
> jackit-devel, but at least to me it really didn\'t seem like a viable
> approach.

It is not that easy. Say period_count is constantly smaller than the available
data on each interrupt, you will start to get behind and will have to
eventually
do an extra callback that then has more samples/time to process.

> >> And nframes should be equal to the period size.
> > This hardware doesn\\\'t have a period size in samples, but time based.
> > And so I think it is wrong to have the driver export an interface that
> > is not used by the hardware.
>
> Hmm, ok, now we\'re talking! :) Still, you can always calculate the
> theoretical period size in samples and use that as the nframes
> count. Like I already mentioned above, in any case you need to honor the
> upper bound.

As I said, this will not work very well.

> > And besides that, I\'m pretty sure there is hardware that doesn\'t use
power
> > of 2 sized periods. Should that be a requirment too?
>
> Not a problem as there\'s no 2^x limitation.

Isn\'t there? for FFT?

--martijn

Powered by ASHosting


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Thu Jul 11 2002 - 17:00:33 EEST