Re: MPNotifyQueue takes 500,000 nsec (worst case)
Re: MPNotifyQueue takes 500,000 nsec (worst case)
- Subject: Re: MPNotifyQueue takes 500,000 nsec (worst case)
- From: Philippe Wicker <email@hidden>
- Date: Tue, 22 Oct 2002 07:56:52 +0200
I don't know exactly how MPNotifyQueue works. I suppose that your
problem is that you are using between 2 threads a synchronization
mechanism which may be blocking. I mean that the queue itself may be a
protected structure, ie a structure which may be locked by either of
the two sides (the producer and/or the consumer) to atomically update
some data. If the locking thread is preempted (or suspended) while the
queue is locked (for instance when the system tick interrupt fires
every 10 ms - well I think the tick is 10 ms because this is a usual
value, but I'm not positively sure of that), or because the producer
tries to lock the queue while it is already locked by the consumer, and
this consumer is being preempted by a third thread (in real time lingo,
it's called an inversion of priority), then the queue will remain
locked until the preempted or suspended thread regains the CPU. The
solution to the priority inversion needs some kernel mechanism (such as
priority inheritance mutex or semaphore) which may not bet implemented
- please someone at Apple, correct me if I'm wrong here - within the
Mach kernel.
You cannot say that a "realtime thread should never be preempted, or at
the very least, not preempted by a lower priority thread". This would
only be true if the thread was using a FIFO scheduling policy. A "FIFO"
thread yields the CPU when it has finished its job (or when a higher
priority thread is given the CPU by the scheduler). However, this
scheduling policy is extremely dangerous (although sometimes
necessary), because it can easily lead to hang the whole system if its
code gets lost in an infinite loop. I don't think Apple guys have
chosen this policy. Another scheduling policy is the ROUND_ROBIN one.
Threads at the same level of priority behaves as FIFO threads regarding
lower priority threads, but the CPU is shared (on a time basis) between
them. This is also a dangerous policy which may still lead to hang the
system because lower priority threads will never be given the CPU
should a higher priority thread get lost in an infinite loop (believe
me, I often had to reset the computer when I was experimenting with
this on Linux machines). That's why I would think that the scheduling
mechanism used in the CoreAudio engine is based on a time sharing
policy, but with an important weigth assigned to critical threads. If
this is true - any remarks from the CoreAudio team ? - such a thread
may still be preempted in some occasions, either by an equal or higher
priority one, or when it has consumed all the ticks it has been
allocated (sorry for my english, not sure everything I write would
please Shakespeare fans...). If your application is mixing midi and
audio, you may encounter some similar problems because both midi and
audio threads are high priority threads and therefore will compete for
the CPU resource.
To go back to your problem, you should design the thread communication
using **NON** blocking mechanism. Kurt revis has posted some sources
included a non blocking FIFO (hi Kurt, maybe you should asks for some
royalties at the end :-) ).
These sources are available on his web site:
http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz
It is written in Objective C (well, it was the last time I had a look
at it) but it can easily be rewritten as a C++ class. Maybe I'll do
that sometime, any way I need it for my own projects. (Oh yes, I'm one
of the last dinosaurs still programming in C++ and not playing with
Cocoa ...).
Regards,
Philippe Wicker
email@hidden
On Tuesday, October 22, 2002, at 06:43 AM, EJ Campbell wrote:
How is everyone here communicating with other threads from within
your IOAudioProc? I've tried using both a MPQueue and a semaphore to
facilitate communication between threads, and they both result in the
same behaviour: occasionally the synchronization primitive takes an
extremely long time to complete. The problem is described in detail
below and was originally posted on the multiprocessing mailing list
without garnering a reply:
I'm having trouble reliably calling MPNotifyQueue from inside a
realtime thread on Mac OS 10.2. I'm using the queue to notify an
MPThread (operating at a lower priority) that a buffer of incoming
audio data is ready for processing.
I'm using the Sound Manager API, specifically SPBRecord with a Sound
Input Completion Proc, to record audio. My completion procedure is
called from within a realtime thread whenever a buffer of audio data
is ready for processing. In my completion procedure, I call
MPNotifyQueue to let my sound processing thread know that a buffer of
data is ready to be processed.
Most of the time everything works perfectly. However, occasionally, I
loose packets of audio. To track down the problem, I profiled my
entire input completion procedure. What I found was that occasionally
the call to MPNotifyQueue (or MPSignalSemaphore) takes a VERY long
time to complete. Normally the call takes approximately 1,500
nanoseconds. However, during times when I loose audio packets, this
call can take upwards of 500,000 nanoseconds, which unacceptable when
inside of a record completion procedure.
Does anyone have any clues as to what is going on? My queue has
plenty of room reserved to it by MPSetQueueReserve(), and there's no
more than one or two items in the queue at any time. I can't think of
anything else that is relevant. Does it matter that I'm still using
SPBRecord? Why would that affect the time it takes MPNotifyQueue to
complete. What seems to be happening is that the synchronization
primitives are causing the realtime thread that the completion proc is
run in to go to sleep and the processing thread to wake up and begin
processing. This seems like it's the wrong behavior since a realtime
thread should never be preempted, or at the very least, not preempted
by a lower priority thread.
I'd be extremely appreciative of any suggestions as to what I can do
to make MPNotifyQueue more reliable. The only alternative I see is to
completely decouple my processing thread from my completion proc.
Instead of using a semaphore or queue to notify the processing thread
that a buffer of data is ready, I could rely on the fact that data
arrives in a regular fashion, and use a timer that periodically wakes
the processing thread whenever data should be ready for it to
process. But this is not the right way to do it, and I'd like to not
have to rely on any polling whatsoever.
Thanks,
EJ
_______________________________________________
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.
_______________________________________________
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.