MPNotifyQueue takes 500,000 nsec (worst case)
MPNotifyQueue takes 500,000 nsec (worst case)
- Subject: MPNotifyQueue takes 500,000 nsec (worst case)
- From: EJ Campbell <email@hidden>
- Date: Tue, 22 Oct 2002 00:01:56 -0700
Thanks so much for the reply! I knew posting here would be a good
idea. My reply to you is inline.
On Monday, October 21, 2002, at 10:56 PM, Philippe Wicker wrote:
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.
This is absolutely what seems to be happening. I've noticed that as my
system load goes up, the chances increase dramatically that a call to
MPNotifyQueue will take an inordinate amount of time.
However, it seems that there should be a way for MPNotifyQueue (or at
least one of the more primitive synchronization primitives) to not fall
victim to this problem. If the guarded structures used by the
Multiprocessing services to synchronize its internal data structures
were managed by the scheduler or some other system that couldn't be
preempted, then there would be no way that a signaling primitive (like
MPNotifyQueue or MPSignalSemaphore) could encounter a locked data
structure. Are there any synchronization primitives that don't rely on
a user level lock like the ones that the multiprocessing services
apparently use?
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.
Your warning about FIFO scheduling is right on. However, I was under
the impression that the kernel had a way of putting misbehaving threads
in jail. I've noticed that if I accidently enter into an infinite loop
in one of my IO Procs, the system will lock up momentarily, but then
after a few seconds, responsiveness will return. I think this behavior
corresponds to the kernel punishing the errant thread.
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 what I meant when I said, "At the very least, a lower priority
thread should not preempt a higher priority thread." Thanks for the
terminology referesher. It's been a while since my OS course.
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).
Again, I think the Kernel has a way of timing these threads out by
removing their privileged status if they misbehave. So, this probably
isn't too much of a worry.
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 :-) ).
Kurt uses what I described at the end of my original message as my
solution of last resort . Instead of relying on the consumer to wake up
the producer when its ready for more data, Kurt's producer simply
regularly feeds the consumer so that it will never go hungry. From what
you've described this is not only my solution of last resort, but also
probably the only solution to my problem :).
Thanks a lot!
Sincerely,
EJ Campbell
_______________________________________________
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.