I am writing a virtual audio driver (currently for Vista, eventually for
XP as well).
The core of my driver is a KTIMER and DPC which notify the WaveCyclic
miniport as well as copy audio data to the output. I need to run my
process at least once per millisecond, so to provide headroom I have
adjusted the timer resolution to 0.5ms and scheduled the timer every 0.5ms.
When the PC is otherwise idle, this all works just fine. However, doing
anything mildly processor intensive (such as opening the sounds dialog
with the recording and playback tabs) will repeatably cause my timer/dpc
to be starved for 20-30ms. This doesn’t play very nicely with my driver,
as you can imagine.
Of course I am aware that Windows is not an RTOS and makes no claims to
be, but without a hardware clock like other sound-card drivers I am at
somewhat of a disadvantage.
I have experimented with using a thread and KeWaitForSingleObject with a
timeout but I am sure that this has a very similar timer under the covers,
and in any case it still exhibits the same issues.
I have also tried setting my DPC to high priority, but this also doesn’t
make any difference. I would expect this to be the case since it is the
timer scheduling that seems to have the issue, before the DPC gets
involved at all.
Is there any other way that I can increase the priority of my timer so
that it doesn’t get starved?
Joe.
Hi Joe,
Unfortunately you may not be in luck. First off, unless you adjust the system timer resolution (there are APIs which do this as a side effect now, but they may change soon because of the impact on power consumption), your timer can never expire more often than once every 10-15 ms depending on your system time source.
Assuming you can deal with that you have the second problem of how timers are actually processed.
There is currently a loop in the kernel that sorta goes like this on one of the processors at DISPATCH_LEVEL:
while(TimersOrDpcsPresent) {
if (ExpiredTimersPresent) ProcessTimers(); <— Unwaits threads that are waiting on timers (including the one that is implied in Sleep()/KeDelayExecution calls) and queues timer DPCs.
if (DpcsPresent) ExecuteAllDpcs();
}
If anyone has a long running DPC, yours could get delayed for quite some time, even with high priority DPCs (which just go to the front of the queue) because you may already be processing a set of DPCs in the bottom part of the loop when your timer tick comes in, so you don’t get to process the timers and queue their DPCs.
You can get a clear view of what DPCs are running on your system and how long they take using the “DPC/ISR analysis action” of the recently-released xperf toolkit.
Good luck,
Neeraj
Kernel Services Test.
Hi Neeraj, everyone,
Thanks for your reply.
On Fri, 27 Jun 2008 01:47:15 +1000, wrote:
> First off, unless you adjust the system timer resolution (there are APIs
> which do this as a side effect now, but they may change soon because of
> the impact on power consumption), your timer can never expire more often
> than once every 10-15 ms depending on your system time source.
I have discovered this API, and have successfully got my timer/DPC running
at 0.5ms intervals, most of the time. Unfortunately, when it doesn’t hit
0.5ms it is often around 20ms which causes my audio to glitch.
> If anyone has a long running DPC, yours could get delayed for quite some
> time, even with high priority DPCs (which just go to the front of the
> queue) because you may already be processing a set of DPCs in the bottom
> part of the loop when your timer tick comes in, so you don’t get to
> process the timers and queue their DPCs.
> You can get a clear view of what DPCs are running on your system and how
> long they take using the “DPC/ISR analysis action” of the
> recently-released xperf toolkit.
This definitely fits with my observations. I have had a fiddle with xperf
but haven’t succeeded in getting anything meaningful from it as yet.
It sounds like what you are saying is that I can’t use software timers to
do precision timing. Hardware sound cards do this with interrupts. I am
wondering, is there a a clock interrupt from one of the system buses of
sub-ms precision that I can attach an ISR to? I don’t know whether the ISR
architecture permits multiple routines for a single interrupt - I suspect
not…
Another thought that I had is that my audio data is being transmitted and
received over the network at >1000 packets/sec, so I am hoping that the
TDI callback may be triggered from the NIC hardware interrupt, but again,
I am not confident that this is the case.
Any insights would be appreciated.
With regards,
Joe.
Joseph Thomas-Kerr wrote:
It sounds like what you are saying is that I can’t use software timers
to do precision timing. Hardware sound cards do this with interrupts.
I am wondering, is there a a clock interrupt from one of the system
buses of sub-ms precision that I can attach an ISR to? I don’t know
whether the ISR architecture permits multiple routines for a single
interrupt - I suspect not…
Hardware sound cards have buffers, typically several seconds worth. The
operating system tries to feed 10ms at a time. Nothing in the system
that operates at a sub-millisecond level.
Another thought that I had is that my audio data is being transmitted
and received over the network at >1000 packets/sec, so I am hoping
that the TDI callback may be triggered from the NIC hardware
interrupt, but again, I am not confident that this is the case.
Again, that’s all buffered. You don’t get one interrupt per packet.
You wouldn’t get any work done.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
The most obvious solution I can think of is to buffer your audio data
and play it, lets say, 50ms behind the actual data stream (or even 20ms
if you’re feeling brave). Do you expect that any human would be able to
tell the difference? Unless maybe you’re trying to be sync’d to video or
something… but if that’s the case presumably you could buffer that too.
Joseph Thomas-Kerr wrote:
Hi Neeraj, everyone,
Thanks for your reply.
On Fri, 27 Jun 2008 01:47:15 +1000, wrote:
>
>> First off, unless you adjust the system timer resolution (there are
>> APIs which do this as a side effect now, but they may change soon
>> because of the impact on power consumption), your timer can never
>> expire more often than once every 10-15 ms depending on your system
>> time source.
>
> I have discovered this API, and have successfully got my timer/DPC
> running at 0.5ms intervals, most of the time. Unfortunately, when it
> doesn’t hit 0.5ms it is often around 20ms which causes my audio to glitch.
>
>
>> If anyone has a long running DPC, yours could get delayed for quite
>> some time, even with high priority DPCs (which just go to the front of
>> the queue) because you may already be processing a set of DPCs in the
>> bottom part of the loop when your timer tick comes in, so you don’t
>> get to process the timers and queue their DPCs.
>> You can get a clear view of what DPCs are running on your system and
>> how long they take using the “DPC/ISR analysis action” of the
>> recently-released xperf toolkit.
>
> This definitely fits with my observations. I have had a fiddle with
> xperf but haven’t succeeded in getting anything meaningful from it as yet.
>
> It sounds like what you are saying is that I can’t use software timers
> to do precision timing. Hardware sound cards do this with interrupts. I
> am wondering, is there a a clock interrupt from one of the system buses
> of sub-ms precision that I can attach an ISR to? I don’t know whether
> the ISR architecture permits multiple routines for a single interrupt -
> I suspect not…
>
> Another thought that I had is that my audio data is being transmitted
> and received over the network at >1000 packets/sec, so I am hoping that
> the TDI callback may be triggered from the NIC hardware interrupt, but
> again, I am not confident that this is the case.
>
> Any insights would be appreciated.
>
> With regards,
> Joe.
>
–
Ray
(If you want to reply to me off list, please remove “spamblock.” from my
email address)
On Tue, 01 Jul 2008 10:07:17 +1000, Tim Roberts wrote:
> Hardware sound cards have buffers, typically several seconds worth.
> The operating system tries to feed 10ms at a time. Nothing in the
> system that operates at a sub-millisecond level.
I think that perhaps we are talking at cross-purposes. I realise that
hardware
sound cards all run on 10ms chunks. But my measurements have me missing
out on my software “interrupt” for 20ms or more.
When I said “system” I was referring to the whole of the PC. I’m pretty
sure that there are numerous peripheral buses generating interrupts at
>1kHz, eg. memory, AGP or possibly firewire. I was hoping (probably more
like dreaming) that I could trigger my periodic code from one of these
interrupts. But the more I think about it the less confidence I have that
this would be possible.
Regards,
Joe.
Joseph Thomas-Kerr wrote:
…
When I said “system” I was referring to the whole of the PC. I’m
pretty sure that there are numerous peripheral buses generating
interrupts at
> 1kHz, eg. memory, AGP or possibly firewire.
Memory doesn’t interrupt. Most graphics cards do not; the ones that do
only interrupt at the refresh rate (75 Hz). USB can interrupt at 1 kHz
if a periodic device is running. Firewire won’t interrupt if it’s not
active.
Interrupt handling is expensive. No good hardware design would count on
steady state handling of thousands of interrupts per second.
You can verify this yourself. Bring up perfmon – there’s a counter for
interrupts/second. When my machine is idle, I get 1,150 per second.
The maximum over the last 2 minutes is 3,000.
> I was hoping (probably more
like dreaming) that I could trigger my periodic code from one of these
interrupts. But the more I think about it the less confidence I have
that this would be possible.
You are coming to the correct conclusion.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
> sure that there are numerous peripheral buses generating interrupts at
>1kHz, eg. memory, AGP or possibly firewire.
Memory never interrupts, firewire’s host controller is very smart and only
interrupts on chain DMA descriptor list completion.
–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com