• 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: MPNotifyQueue takes 500,000 nsec (worst case)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

References: 
 >MPNotifyQueue takes 500,000 nsec (worst case) (From: EJ Campbell <email@hidden>)

  • Prev by Date: MPNotifyQueue takes 500,000 nsec (worst case)
  • Next by Date: MPNotifyQueue takes 500,000 nsec (worst case)
  • Previous by thread: MPNotifyQueue takes 500,000 nsec (worst case)
  • Next by thread: ANN: Rax
  • Index(es):
    • Date
    • Thread