Re: Audio threads scheduling
Re: Audio threads scheduling
- Subject: Re: Audio threads scheduling
- From: Shaun Wexler <email@hidden>
- Date: Mon, 5 Apr 2004 07:31:10 -0700
On Apr 5, 2004, at 2:12 AM, Stiphane Letz wrote:
As an example, my app runs multiple threads for drawing: a rendering
thread, and one or more threads per-screen for synchronization
purposes. The sync threads use extended policy with priority 63, and
the rendering thread is normal timeshare 31. While profiling a
certain DSP computation, its period would increase 150% when a flush
thread had more work to do, in which case it was blocked on
mach_msg_trap, while the window server of priority 79 would blit the
window backing store.
Where did you see this 79 priority? I always though the Windows server
had a 63 priority...
Darwin source. CGS runs at 76, and max pri is 79 unless it gets bumped
to realtime.
This means that a real time thread was indeed preempted by a lower
priority thread during its constraint (ie not during the computation
period).
You mean that your real time thread had still something to do? Quite
strange... In this case how can the scheduler guaranty your real time
thread *constraint* value?
The constraint value should be less than or equal to the total cycle
period minus the output latency and safety offset. The computation
value should be less than or equal to the actual unpreempted
computation time required by the ioProc. It's the minimum computation
that is tricky. The constraint minus the computation is the maximum
length of time in the thread can be preempted and safely blocked
without missing its deadline. How the scheduler determines when to
afford cycles to the thread is of course up to the scheduler. As long
as the thread receives no less than the computation's worth of cycles
per period, the scheduler is free to split that up in the constraint
period however it chooses. By careful selection of these parameters,
you can request or enforce nearly any timing behavior you require.
It's a well designed system.
Again, the problem is that you may end up "fooling" the HAL into
believing that your ioProc requires more unpreemptible cycles that it
really needs.
Why the HAL? The contraints and computation are going to be used by
the scheduler?
My understanding is that the HAL set the contraints and computation
parameters during the IO thread creation but not after.
It has to manage those constantly, to determine the exact wakeup time
each cycle, and base the computation and constraint on the current
total system load, ioProc durations, etc.
What happens if you block during the computation period?
It *will* block during the computation period... I mean if the thread
is preempted by the scheduler at the end of its computation slice,
we're in the normal case.
Maybe you're misunderstanding the problem. Do not assume that your
computation will be at the beginning of the constraint. The scheduler
can/will put higher priority and/or smaller computation threads ahead
of yours, as long as it can provide you the number of computation
cycles within your constraint cycle time window. What if your
computation time is allotted at the end of the constraint period? If
you block or in any other way overrun your computation period, you will
overload. Computation means computation. How many cycles do you need
to do your work? Is it always the same. Not necessarily. So the HAL
must measure the time it calls the ioProc until the time it returns,
and base its calculations on that delta. I assume that is how it
works. When we create our own realtime threads, they are not under the
HAL's management, so it is up to us to make them all play together
(with every other process, too).
In my audio graph execution case, the thread is going to bock during
its computation period because it has nothing to do more (the graph is
is a sequence subpart where there is no other parallel node to
compute) *but* the suspended thread may have to be resumed in the
*same* audio cycle because at some point later in the cycle, a
parallel part in the grah is reached.
The idea here is to try to alwys feed both processors when possible.
Rarely you will have the opportunity to have your threads running on
both processors simultaneously and continuously, much less start them
at the same time, etc. Lots more running in OS X than just your app.
How about a dependency queue, where you break your processing into
stages, which would each be enqueued for processing as soon as its
dependencies were satisfied. Thread(s) would drain the shared queue
until the whole series of stages in each of the graphs were processed,
regardless of which thread was processing which stage. The only time a
thread would block would be waiting on a dependency to be processed
where there were less than X stages remaining to process, in which case
the thread that was currently processing the critical stage would then
signal at completion. That would almost break the inter-thread
dependency (or completely break it if needed), and allow any number of
graphs to be processed concurrently by any number of threads. At least
that's how I'd approach it. ;)
--
Shaun Wexler
MacFOH
http://www.macfoh.com
_______________________________________________
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.