Albert Santoni wrote:
> Hi Bjorn and Pau,
> 
> Thanks for the enlightening responses. After thinking about what you've
> both written for a day, I have a few more questions:
> 
> 1) It looks like the watchdog thread attempts to run at higher priority
> than the callback thread, so it can do its job. However, when the
> callback thread is running with realtime priority, what priority does
> the watchdog thread run with? I'm wondering if the watchdog thread can't
> do its job if you have a realtime priority callback thread. If that's
> true, then if you have a series of callback underruns (ie. they don't
> finish in time), more and more callback threads might be created, and
> you might unintentionally end up with the equivalent of a fork-bomb.
> (Too many threads crashing the kernel... ?)
In Linux there are 99 priority levels for SCHED_FIFO (so called 
realtime) threads. It is common practice to run a watchdog thread with 
higher priority when you use SCHED_FIFO threads. The operating system 
will always make sure that a higher priority thread will preempt a lower 
one once it becomes runnable (e.g. when it's timer expires).


> 
> 2) Besides Ross Bencina's notes on lock-free and wait-free algorithms
> ( http://www.audiomulch.com/~rossb/code/lockfree/ ), are there any good
> resources people can recommend on the topic? (Books, websites, etc.)
http://www.google.com/search?q=yann+orlarey+lock+free
should give you a head start. Not easy material though.

> 
> 3) In Mixxx, there are two spots where we dump audio from the callback
> into a separate worker thread, and in order to notify the worker thread
> that there's data that needs processing, we use a QWaitCondtion. The
> QWaitCondition requires the use of a QMutex around calls to it, so we
> end up locking/unlocking this mutex in the callback thread (bad). Is
> using something like PortAudio's ringbuffer an appropriate solution for
> eliminating the mutex/wait condition in this situation?
QWaitCondition is probably some sort of wrapper around a phread 
conditional variable, which indeed needs a mutex to avoid problems. 
Although this is not strictly required if you have a single 
writer/single reader setup if I remember correctly.

The better way might be to use a semaphore that is increased by the 
realtime thread. Signaling a semaphore should be realtime safe, and the 
other thread can block on it. The combination of a lock-free ringbuffer 
and a semaphore can give you what you need.

In an answer to your original question: if portaudio kills the thread at 
underrun, it should also provide a cleanup callback to recover from the 
scenario you describel, or it has a broken design. Unless of course the 
API specifies that you're not allowed to do this stuff in the callback. 
It would be a very strange design if portaudio were to kill the thread 
and spawn a new one. OTOH it's a problem that is not solved in e.g. jack 
either: if an application decides not to return from a callback, jack 
completely messes up.

Greets,

Pieter

> 
> Thanks again,
> Albert
> 
> 
> On Thu, 2008-04-24 at 09:28 -0400, Bjorn Roche wrote:
>> Albert,
>>
>>      I'm not sure I understand exactly what you're wanting to know, and  
>> I'm no longer an expert on the watchdog thread since I don't work on  
>> the platforms that use it anymore, so you'll have to take what I say  
>> with a grain of salt. The watchdog thread, IIRC, only kills the  
>> callback thread if the callback is overrunning the CPU, and seriously  
>> blocking lower priority threads from getting anything done at all for  
>> a significant period of time, as detected by the so-called "canary"  
>> thread. This is not the standard buffer underrun scenario. It's really  
>> a disaster-prevention scenario, eg if your callback gets stuck in a  
>> loop, making the computer completely unresponsive. The only time I've  
>> seen it kill my thread is when I've made a programming error resulting  
>> in a total system freeze up for three (?) seconds (including mouse  
>> movements), in which case it's a real godsend. It may not be necessary  
>> in the future, because of design improvements in Linux, which will  
>> hopefully be picked up by other OSes:
>>
>> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/scheduler/sched-rt-group.txt;h=1c6332f4543c350889eae9ba2b4c766270c1b65e;hb=HEAD#l38
>>
>> As for what happens when an underrun occurs, it's possible that a new  
>> thread is launched on some platforms and the old one is killed, I  
>> don't know. This doesn't happen on Linux (OSS, ALSA or JACK) AFAIK,  
>> but I could be wrong. It's possible that this does happens on the mac  
>> OS -- I wrote the code and couldn't tell you because, AFAIK, it  
>> doesn't say in the Core Audio docs -- but creating a new thread is  
>> expensive and unbounded and I don't know why they would do it when  
>> they are already falling behind. Older platforms don't even use  
>> "threads", they use interrupts, so you should not expect each callback  
>> to occur on the same thread unless you know something about your  
>> platform. I imagine other techniques are possible as well, so I  
>> suspect newer OSes may not use threads either, but I am having a hard  
>> time imagining what that would be (still, I wouldn't rule it out  
>> unless an OS expert knows better). It seems to me that it's possible  
>> that on such platforms, you could have multiple simultaneous callbacks  
>> during an underrun condition, at least in theory, but I think I would  
>> consider such a platform broken.
>>
>> That said, it is widely known to be bad multithreaded programming to  
>> kill a thread at random (unless a seeming disaster has occurred, like  
>> a thread has caused your machine to deadlock, in which case you should  
>> probably exit right away because something really bad just happened)  
>> rather than wait for the thread to complete, so if an implementation  
>> was not waiting for your callback to complete for any reason other  
>> than disaster avoidance I would consider that a bug in the  
>> implementation. I can't say there are no bugs in any of the  
>> implementations, but my assumption has always been that callbacks will  
>> complete, because if they didn't I would file a bug report.
>>
>> I assume you are aware of the issues relating to using mutexes in a  
>> realtime thread.
>>
>> I hope that answers your question.
>>
>>      bjorn
>>
>>
>> On Apr 24, 2008, at 4:50 AM, Pau Arumí Albó wrote:
>>> (This mail was already sent to mixxx-devel. I realized that portaudio
>>> was also at the Cc when received an "subscribers-only" bounce.
>>> So now resending it now after subscription)
>>>
>>>
>>> El dc 23 de 04 del 2008 a les 10:11 -0400, en/na Albert Santoni va
>>> escriure:
>>>> Hi guys,
>>>>
>>>> I've got a question that I haven't been able to conclusively  
>>>> answer, and
>>>> I was wondering if someone could shed some light on an answer.
>>>>
>>>> When a buffer underrun occurs, what happens to that instance of the
>>>> callback thread?
>>>>
>>>> To elaborate, consider a case where the soundcard has requested  
>>>> audio,
>>>> so the PA callback function gets called and your program runs off and
>>>> processes whatever audio it has to as quickly as it can. If your  
>>>> program
>>>> can't process quickly enough, what happens exactly? Does the initial
>>>> callback thread get killed, and another one started immediately  
>>>> after?
>>>> Does another callback thread simply get called?
>>>>
>>>> The reason this concerns me is because if the callback thread gets
>>>> killed (if that's what happens during a buffer underrun) while it is
>>>> waiting on a mutex, I'm afraid it could leave the mutex in some
>>>> undetermined state, deadlocking my application.
>>>>
>>>> If anyone could offer any advice or insight, it would be much
>>>> appreciated.
>>>>
>>>> Thanks,
>>>> Albert
>>> I've always guessed that in that case the audio process terminated
>>> somehow. Being curious about it i've looked at PortAudio code to see  
>>> the
>>> details. (this code from track corresponds to an old version, but i
>>> guess that the same technique also applies to the trunk)
>>>
>>> http://www.portaudio.com/trac/browser/portaudio/trunk/pa_unix_oss/pa_unix_oss.c?rev=115#L563
>>>
>>> So what happens is that a watchdog thread running with higher priority
>>> is set up and it kills the audio thread ONLY if it is reading/writing
>>> audio from 3 seconds behind the audio driver time.
>>>
>>> Ok, but during these 3 long seconds you can have underruns anyway.  
>>> What
>>> i _deduce_ is that while in this 3 sec safety window callbacks are not
>>> killed, and at termination, the new callback will contain the more
>>> recent buffers. Then the callback flags will tell you if something  
>>> nasty
>>> happened: skipped a writing deadline, skipped an input buffer...
>>>
>>> That's how i understand it - but a PortAudio developer could be more
>>> assertive.
>>>
>>> So i believe you can be confident on the state of the mutex. But  
>>> anyway,
>>> why to use a mutex inside a real-time thread?? Couldn't this be done
>>> with lock-free techniques?
>>>
>>> Regards,
>>>
>>> Pau
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> Portaudio mailing list
>>> [EMAIL PROTECTED]
>>> http://techweb.rfa.org/mailman/listinfo/portaudio
>> -----------------------------
>> Bjorn Roche
>> XO Wave
>> Digital Audio Production and Post-Production Software
>> http://www.xowave.com
>> http://blog.bjornroche.com
>> http://myspace.com/xowave
>>
>>
> 
> 
> -------------------------------------------------------------------------
> This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
> Don't miss this year's exciting event. There's still time to save $100. 
> Use priority code J8TL2D2. 
> http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
> _______________________________________________
> Mixxx-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mixxx-devel


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to