• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: multithreaded mixer
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: multithreaded mixer


  • Subject: Re: multithreaded mixer
  • From: Philippe Wicker <email@hidden>
  • Date: Thu, 5 Feb 2004 11:37:40 +0100

On Wednesday, February 4, 2004, at 08:57 PM, Jeff Moore wrote:

Hi,

The original reply was too long and rejected, here is a snipped version.

On Feb 3, 2004, at 11:00 PM, Philippe Wicker wrote:


On Wednesday, February 4, 2004, at 12:56 AM, Jeff Moore wrote:

The reason why is that there is no "politically correct" way to block the IO thread.

On the other hand I cannot figure why it could have a negative impact on the MIDI threads. Could tell us more about this?

The way it works is that the IO thread will not be pre-emptible for a portion of it's cycle right after it wakes up. Then it becomes pre-emptible by other real time threads. By constantly blocking the IO thread, you are essentially putting it into a state where it won't ever be pre-emptible. This will prevent the real time MIDI threads from being able to sneak in for a few mics to do their thing and result in a degradation of MIDI timing which will have the natural consequence of making MIDI and audio go out of synch.

That's clear.


In short, don't ever block the IO thread. It is number one on the list of "bad things" you can do.

The question then is: is this scheduler the best one for the kind of applications we are all writing?

It is and the fact that lots of apps out there (like Logic, DP, etc) have already solved this problem is proof that things work if you cooperate with the system and are flexible with how you approach the solution to the problem.

I get what I deserve. My remark about the scheduler was out of line. I apologize for this.

I also want to suggest a nightmare scenario: what if everybody's AudioUnit did what you are suggesting? This is not an unreasonable suggestion at first blush considering that some of the synths and effects are pretty darn complicated and do a lot of work that wouldn't be too hard to parallelize. This would bring the system to it's knees with all the real time thread traffic and no one would get anything done.

I wasn't suggesting that everyone should try to split the dsp load between a plethora of threads (I wouldn't do it myself on my own AUs). I was *only* trying to give an answer to *one* question.

Also, let's not forget that in most applications, there is a whole lot more going on than just DSP. There's UI to update, data to read from the disk or the network, bookkeeping to do, MIDI data to read and write, etc. Trying to split your DSP tasks up to distribute to all the processors can easily get you into a situation where you just not able to respond to the user or get the data from the disk that you need in a timely fashion. This is another facet of why doing this won't necessarily have the beneficial effect you think it will.

It makes sense. This is the second part of the answer to the original question. To sum up: 2 guidelines, don't block the IO thread, *and* don't overload the machine with too much works within real time threads.


To go back to the original question (split the DSP work between different threads), the only solution I can see which satisfies the "don't ever block the IO thread" constraint is to make both subgraphs run in their own thread and "push" the audio into a private ring buffer. The code executed in the context of the IO thread has then to pull the audio from both ring buffers, mix it and return it to the HAL. When the IOProc is called, the code here could pass the IOProc parameters to these two threads using 2 non blocking queues (one for each thread). This solution adds a latency which may be as much as an IOProc buffer size. The other bad news is that the synchronization of the worker threads with the IOProc needs a mutex/condvar couple or a mach semaphore. In both cases, a lock must be taken either by the IO thread or the worker thread which may lead to block the IO thread (although for a very short amount of time). It is true however that in this particular case the probability of such a blocking is very low and may be neglected (???).

This is a common misconception about how pthreads work. One doesn't have to own the mutex associated with a condvar to signal it.

I think you misunderstood me here. I didn't mean that you need to take a lock to signal the condvar. The lock on the signaler side is necessary to avoid a race condition at the waiter side.

A signaler thread executes a code such as:
mutex_lock();
predicate = true;
mutex_unlock();
cond_signal(); // No need to take the lock to signal

A waiter thread executes a code such as:
mutex_lock();
while (! predicate) cond_wait(); // while (! predicate) to protect against spurious wake up
// Reset the predicate if needed
mutex_unlock();

If you don't bracket "predicate = true" with a lock/unlock pair then the following may occur:

Signaler thread Waiter thread
mutex_lock()
while (!predicate)

- waiter is pre-empted by signaler here before the call to cond_wait

predicate = true
cond_signal()

- no thread is waiting, so no actual signal
- waiter is yielded the cpu here
cond_wait()

- the predicate is true, but Waiter have to wait next cond_signal to wake up. It has missed one IO cycle.

I'm sure you're aware of this race condition, but maybe not all the readers. The lock I was thinking about is the one around "predicate = true". If the waiter is able to deal with such a miss, then the lock is not necessary.

I don't use mach semaphores, so I can't comment on them. Also, there is no reason why you have to use a signal to do this. You could just as easily wake the thread up on the decrementer and thus save a bit of overhead. After all, if it's good enough for the main IO thread, it should be good enough for any auxiliaries, right?

I'm not aware of this technique. Is it documented somewhere? IOKit? Available in user land?

--

Jeff Moore
Core Audio
Apple

Anyway, this discussion gives me a much better understanding of how the scheduler works. Thanks for that.


Philippe Wicker
email@hidden
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.

References: 
 >Re: multithreaded mixer (From: Jeff Moore <email@hidden>)

  • Prev by Date: [ANN] Sample-code: A 'cheap' oscilloscope
  • Next by Date: [NEWBIE] Starting...
  • Previous by thread: Re: multithreaded mixer
  • Next by thread: Re: multithreaded mixer
  • Index(es):
    • Date
    • Thread