Re: Threading/timer issues on Mach-O vs. OS 9
Re: Threading/timer issues on Mach-O vs. OS 9
- Subject: Re: Threading/timer issues on Mach-O vs. OS 9
- From: Kurt Revis <email@hidden>
- Date: Sun, 23 Apr 2006 20:01:38 -0700
First of all, if you haven't read this document, please do:
http://developer.apple.com/documentation/Cocoa/Conceptual/
Multithreading/index.html
This is the closest thing to a high-level description of how threads
work in OS X, as far as I now. There is some Cocoa-related stuff in
there but you can safely ignore it.
You need a basic understanding of how threads work, and what they can
do for you, in order to talk sensibly about them. This is one of
those areas where guessing will not help -- you're more likely to get
something that kind of works, but ends up breaking in different
circumstances (say a machine with 1 processor vs. multiprocessors).
There is nothing more terrifying than programmers who dabble in
threads without knowing what they're doing.
Also, please pardon any inaccuracies or overgeneralizations in the
following...
I think I was using what was a pretty common method of
creating a scheduler:
There is a 1 ms callback installed as a Timer function (i.e. using
NewTimerUPP() and InsXTime()). So I'm getting 1ms interrupts
They aren't interrupts anymore. Hardware-level interrupts are
entirely handled by the kernel and aren't your responsibility (or
problem). You'd say that your timer activates, instead.
(It probably used to be closer to a real interrupt in OS 9, but now
under Carbon you're going through some code that's just simulating
things for your benefit. It's probably making a thread for you and
setting up a timer on it using some other API.)
and having it process a list of queued tasks stored in a linked
list according to
execution time (the "ScheduledQueue") - for my purposes, this is
used to
generate MIDI data in real-time to create algorithmic music.
Are you sure you need to do this exactly the same way in OS X? You
can tell CoreMIDI to send a MIDI packet at a scheduled time in the
future, and let it (and the MIDI hardware drivers) do the hard work
of getting the timing accurate.
I bet you could get away with waking up far less frequently, which is
easier to do reliably. Are you reacting to external input in order
to figure out what MIDI to generate? How often does that input come
in, and what is it (MIDI input, keyboard/mouse, network, ...)?
(I guess this is what is known as a preemptive thread?)
All threads are preemptive on OS X.
There's another queue of tasks, the "DeferredQueue", that is *NOT*
performed
at interrupt level, such as redrawing blinking leds, GUI updating,
etc. This
tasklist is processed by the app's "idle time" mechanism, whenever
it's not
busy. (I guess this is the main app thread?)
Typically you do drawing and UI interaction in the main thread, yes.
There is a mechanism to set a "lockoutFlag" around "critical
sections" of
code that you don't want interrupted for any reason. The lockout flag
prevents interrupts while it is set to true.
What is your "lockoutFlag" exactly? Just a variable in memory that
you set to true during your critical section? Or is there some
function you have to call to change it?
Anyway, on OS X, user code can't turn off interrupts for the whole
machine, and can't prevent itself from being preempted. The system is
fully preemptive, and any of your code may be preempted at any time.
(You can give hints to the scheduler to try to change its behavior,
but it is free to ignore you.)
Turning off interrupts for the whole machine was almost certainly
total overkill, even under OS 9. You can't do it anymore anyway, so
you need to determine what it is that you really want to achieve.
Probably, you want a guarantee that one thread not run while the
other one is in the critical section ... but I'm just guessing, you
need to figure out the exact details.
If that is what you want, you'd set up a "mutex lock", then take the
lock when your critical section starts, and release the lock when the
critical section ends. Your other thread would do the same, using
the same lock. Since only one thread is allowed to hold the lock at
any time, the two critical sections would then never run
simultaneously. (If one thread tries to lock the lock while the
other thread holds the lock, the first thread will be blocked until
the other thread releases it.)
See:
http://developer.apple.com/documentation/Cocoa/Conceptual/
Multithreading/articles/POSIXLocks.html#//apple_ref/doc/uid/
TP40001522-132741
and the man pages for pthread_mutex_lock, pthread_mutex_unlock, etc.
2. I don't even know what kind of threading this is, now that its
on Mach-O.
I don't know what these ancient Time Manager functions do either. As
a start, set a breakpoint in your timer callback and see what thread
it's in when it gets hit. I assume it will be a different thread
than the main thread (one that Carbon started for you) but it's
important to actually know.
3. On another front, I see that this whole method of doing things
has been
deprecated (or has it?). The Time Manager Reference says
"Deprecated. Use
Carbon Event Loop timers or Cocoa NSTimers instead."
I don't know how much clearer it could be. Yes, this stuff is
incredibly deprecated. I haven't heard of anybody using it in years.
I'd prefer to rewrite as little of this as possible. It almost
works, except
for this lockout flag getting "stuck".
Like I said above, try using a plain old mutex around your critical
sections. I bet it will solve your problem.
--
Kurt Revis
email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden