WHQL to detect rogue drivers

Looking at the following link it seems there *were* plans to have a WHQL
requirement for drivers not to spin too much time in their dpc/isr routines.
http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx

Curious if such has been implemented already for Windows XP?

thanks
banks

In fact may I follow up on this with another question, some of these aspects
are not very clear in Inside Windows 2000:

How does the whole dpc scheduling operation tie up with that of normal
thread scheduling.
So my understanding is that at a period `P’, the DPC queue will be flushed
of all its queued objects. Meaning,
at such time, the scheduler stops scheduling normal threads, raises system
to dispatch level and clears the dpc queue.
Question is when such takes place, is it atomic ? Meaning is it true that
once started *ALL* dpc objects will be executed
before normal thread scheduling takes place again?

**What can impact ‘P’? ( other than lenghty ISR routines ? ) Is there
such a ‘P’ at all?

thanks
banks

“bank kus” wrote in message news:xxxxx@ntdev…
> Looking at the following link it seems there were plans to have a WHQL
> requirement for drivers not to spin too much time in their dpc/isr
> routines.
> http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx
>
> Curious if such has been implemented already for Windows XP?
>
> thanks
> banks
>
>**

First, make sure you understand that the current DPC level is per-processor, not per-system. So, the scheduler doesn’t “stop scheduling normal threads” when the current processor raises to DPC_LEVEL or above. The scheduler simply guarantees that the current processor will not perform a context swap to another thread. Also, there is no such thing as a “normal thread” vs. a “non-normal thread”. To the scheduler, it’s all just… threads.

The scheduler is not some active entity in the system. It is a passive library of functions, and the associated system-wide data structures and per-processor data structures that those functions manipulate. Access to the system-wide data structures is synchronized. Access to the per-processor control block is mostly unsynchronized (hey, it’s just one processor, right?), although there are times when access to certain parts of that structure are synchronized as well.

There are no threads dedicated to “the scheduler” – they’re all owned by the scheduler. The scheduler is a set of mechanisms that control which thread will be run at a given time. It is not itself a thread, or a set of threads. (Unless you mean “all threads” by “a set of threads”.)

So, the general pattern is this. A user-mode thread lives most of its life at PASSIVE_LEVEL. When a hardware interrupt occurs, the processor executes an ISR, which sets the DPC level of the current processor to the device IRQL of the associated interrupt. Since this is always > DISPATCH_LEVEL, the current thread cannot change.

The main job of the device-specific ISR code is to 1) verify that the device associated with the ISR really is asserting its interrupt line, 2) turn off the interrupt line, and then 3) schedule a DPC to deal with the changed state of the device “later”.

The OS ISR code then attempts to lower the DPC level to what it was before the ISR fired. If lowering the DPC level would cause a transition from DPC_LEVEL or higher to a lower level (PASSIVE or APC), then the kernel scans the queued DPC list, and executes items in that list. The idea is that inserting into that list is cheap (no allocations, O(1)) and safe (non-paged pool for all participants, so safe no matter what thread is active on the processor).

The DPC list is part of the per-processor control block. So when you queue a DPC, by default, it will be queued for execution on the current processor. You can specify that a DPC should be executed on a preferred processor (affinitized DPCs, using KeSetTargetProcessorDpc), for special occasions.

“P” in your mail is controlled simply by how often DPCs are queued, and how long each individual DPC routine runs. On a given processor, no code will ever run at PASSIVE_LEVEL or APC_LEVEL until all DPCs queued on that processor have been completed. Which means that, as long as DPCs are queued on a processor, the thread on that processor will not be rescheduled. However, keep in mind that one processor can be at DPC_LEVEL (or device IRQL, or anything), while another processor is running at a completely different IRQL.

In other words, there is no periodic “P” time interval. The DPC queue (on the current processor) is drained by the time the IRQL level moves to APC_LEVEL or PASSIVE_LEVEL (on the current processor).

On the current processor.

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of bank kus
Sent: Wednesday, October 04, 2006 2:18 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] WHQL to detect rogue drivers

In fact may I follow up on this with another question, some of these aspects are not very clear in Inside Windows 2000:

How does the whole dpc scheduling operation tie up with that of normal thread scheduling.
So my understanding is that at a period `P’, the DPC queue will be flushed of all its queued objects. Meaning, at such time, the scheduler stops scheduling normal threads, raises system to dispatch level and clears the dpc queue.
Question is when such takes place, is it atomic ? Meaning is it true that once started *ALL* dpc objects will be executed before normal thread scheduling takes place again?

**What can impact ‘P’? ( other than lenghty ISR routines ? ) Is there such a ‘P’ at all?

thanks
banks

“bank kus” wrote in message news:xxxxx@ntdev…
> Looking at the following link it seems there were plans to have a
> WHQL requirement for drivers not to spin too much time in their
> dpc/isr routines.
> http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx
>
> Curious if such has been implemented already for Windows XP?
>
> thanks
> banks
>
>


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer**

bank kus wrote:

In fact may I follow up on this with another question, some of these aspects
are not very clear in Inside Windows 2000:

How does the whole dpc scheduling operation tie up with that of normal
thread scheduling.
So my understanding is that at a period `P’, the DPC queue will be flushed
of all its queued objects. Meaning,
at such time, the scheduler stops scheduling normal threads, raises system
to dispatch level and clears the dpc queue.

No. Remember that the system guarantees that it will always select the
highest-priority thread that is ready to run. A DPC has higher priority
than any passive thread, so every DPC will run before the system ever
goes back to user-mode.

Also remember that threads cannot pop up asynchronously (with the
exception of hardware interrupts!). The system does not have to stop
processing user-mode threads and say “OK, now do I have anything more
important to do?”, because a DPC cannot “pop up” in the middle of a
user-mode thread. A DPC cannot be waiting unless some kernel-mode
thread queued it. Ordinarily, that DPC will have been queued by an ISR
(which is higher priority yet). As soon as the ISR is done, the
operating system has to go find another thread to run. Again, it will
choose the highest priority thread, which in this example will be the
DPC. After all of the DPCs are drained, the highest priority thread is
probably a user-mode thread.

“Ah,” you say, being observant, “but what about a DPC queued with
KeSetTimer? Can’t that ‘pop up’ in the middle of a user-mode thread?”
No. Essentially, time is frozen while a user-mode thread runs. When
operating system gets a chance to do scheduling, either because of an
interrupt or because the user-mode thread did some I/O, THAT’S when it
checks the timer queues. If a timer has expired, then only at that
point will its DPC become “ready to run”. When the scheduler is
finished, it has to decide which thread to run next. If a DPC came
ready, then it will, of course, now be the highest priority thread, and
it will run.

It is not possible to have a DPC ready and waiting while the system is
running a “normal” thread. It cannot happen.

Question is when such takes place, is it atomic ? Meaning is it true that
once started *ALL* dpc objects will be executed
before normal thread scheduling takes place again?

ALL higher priority threads (including DPCs) will run before the system
chooses a normal thread. If you write a DPC which queues itself, your
system will never go back to user mode.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Arlie
Thanks, that was a very nice explanation. My takeaway from this is:
<1> the DPC queue is flushed before IRQL can be lowered to APC_LEVEL or
lower.

<2> All DPC queued objects will *run together * before any APC or PASSIVE
level code is executed.

banks

“Arlie Davis” wrote in message news:xxxxx@ntdev…
First, make sure you understand that the current DPC level is per-processor,
not per-system. So, the scheduler doesn’t “stop scheduling normal threads”
when the current processor raises to DPC_LEVEL or above. The scheduler
simply guarantees that the current processor will not perform a context swap
to another thread. Also, there is no such thing as a “normal thread” vs. a
“non-normal thread”. To the scheduler, it’s all just… threads.

The scheduler is not some active entity in the system. It is a passive
library of functions, and the associated system-wide data structures and
per-processor data structures that those functions manipulate. Access to
the system-wide data structures is synchronized. Access to the
per-processor control block is mostly unsynchronized (hey, it’s just one
processor, right?), although there are times when access to certain parts of
that structure are synchronized as well.

There are no threads dedicated to “the scheduler” – they’re all owned by
the scheduler. The scheduler is a set of mechanisms that control which
thread will be run at a given time. It is not itself a thread, or a set of
threads. (Unless you mean “all threads” by “a set of threads”.)

So, the general pattern is this. A user-mode thread lives most of its life
at PASSIVE_LEVEL. When a hardware interrupt occurs, the processor executes
an ISR, which sets the DPC level of the current processor to the device IRQL
of the associated interrupt. Since this is always > DISPATCH_LEVEL, the
current thread cannot change.

The main job of the device-specific ISR code is to 1) verify that the device
associated with the ISR really is asserting its interrupt line, 2) turn off
the interrupt line, and then 3) schedule a DPC to deal with the changed
state of the device “later”.

The OS ISR code then attempts to lower the DPC level to what it was before
the ISR fired. If lowering the DPC level would cause a transition from
DPC_LEVEL or higher to a lower level (PASSIVE or APC), then the kernel scans
the queued DPC list, and executes items in that list. The idea is that
inserting into that list is cheap (no allocations, O(1)) and safe (non-paged
pool for all participants, so safe no matter what thread is active on the
processor).

The DPC list is part of the per-processor control block. So when you queue
a DPC, by default, it will be queued for execution on the current processor.
You can specify that a DPC should be executed on a preferred processor
(affinitized DPCs, using KeSetTargetProcessorDpc), for special occasions.

“P” in your mail is controlled simply by how often DPCs are queued, and how
long each individual DPC routine runs. On a given processor, no code will
ever run at PASSIVE_LEVEL or APC_LEVEL until all DPCs queued on that
processor have been completed. Which means that, as long as DPCs are queued
on a processor, the thread on that processor will not be rescheduled.
However, keep in mind that one processor can be at DPC_LEVEL (or device
IRQL, or anything), while another processor is running at a completely
different IRQL.

In other words, there is no periodic “P” time interval. The DPC queue (on
the current processor) is drained by the time the IRQL level moves to
APC_LEVEL or PASSIVE_LEVEL (on the current processor).

On the current processor.

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of bank kus
Sent: Wednesday, October 04, 2006 2:18 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] WHQL to detect rogue drivers

In fact may I follow up on this with another question, some of these aspects
are not very clear in Inside Windows 2000:

How does the whole dpc scheduling operation tie up with that of normal
thread scheduling.
So my understanding is that at a period `P’, the DPC queue will be flushed
of all its queued objects. Meaning, at such time, the scheduler stops
scheduling normal threads, raises system to dispatch level and clears the
dpc queue.
Question is when such takes place, is it atomic ? Meaning is it true that
once started ALL dpc objects will be executed before normal thread
scheduling takes place again?

What can impact ‘P’? ( other than lenghty ISR routines ? ) Is there
such a ‘P’ at all?

thanks
banks

“bank kus” wrote in message news:xxxxx@ntdev…
> Looking at the following link it seems there were plans to have a
> WHQL requirement for drivers not to spin too much time in their
> dpc/isr routines.
> http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx
>
> Curious if such has been implemented already for Windows XP?
>
> thanks
> banks
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>>If you write a DPC which queues itself, your

> system will never go back to user mode.

Nice, that is a one-line statement that answers all my doubts.

Thanks
banks

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> bank kus wrote:
>
>>In fact may I follow up on this with another question, some of these
>>aspects
>>are not very clear in Inside Windows 2000:
>>
>> How does the whole dpc scheduling operation tie up with that of normal
>>thread scheduling.
>>So my understanding is that at a period `P’, the DPC queue will be flushed
>>of all its queued objects. Meaning,
>>at such time, the scheduler stops scheduling normal threads, raises system
>>to dispatch level and clears the dpc queue.
>>
>>
>
> No. Remember that the system guarantees that it will always select the
> highest-priority thread that is ready to run. A DPC has higher priority
> than any passive thread, so every DPC will run before the system ever
> goes back to user-mode.
>
> Also remember that threads cannot pop up asynchronously (with the
> exception of hardware interrupts!). The system does not have to stop
> processing user-mode threads and say “OK, now do I have anything more
> important to do?”, because a DPC cannot “pop up” in the middle of a
> user-mode thread. A DPC cannot be waiting unless some kernel-mode
> thread queued it. Ordinarily, that DPC will have been queued by an ISR
> (which is higher priority yet). As soon as the ISR is done, the
> operating system has to go find another thread to run. Again, it will
> choose the highest priority thread, which in this example will be the
> DPC. After all of the DPCs are drained, the highest priority thread is
> probably a user-mode thread.
>
> “Ah,” you say, being observant, “but what about a DPC queued with
> KeSetTimer? Can’t that ‘pop up’ in the middle of a user-mode thread?”
> No. Essentially, time is frozen while a user-mode thread runs. When
> operating system gets a chance to do scheduling, either because of an
> interrupt or because the user-mode thread did some I/O, THAT’S when it
> checks the timer queues. If a timer has expired, then only at that
> point will its DPC become “ready to run”. When the scheduler is
> finished, it has to decide which thread to run next. If a DPC came
> ready, then it will, of course, now be the highest priority thread, and
> it will run.
>
> It is not possible to have a DPC ready and waiting while the system is
> running a “normal” thread. It cannot happen.
>
>>Question is when such takes place, is it atomic ? Meaning is it true that
>>once started ALL dpc objects will be executed
>>before normal thread scheduling takes place again?
>>
>>
>
> ALL higher priority threads (including DPCs) will run before the system
> chooses a normal thread. If you write a DPC which queues itself, your
> system will never go back to user mode.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

> So my understanding is that at a period `P’, the DPC queue will be flushed

of all its queued objects. Meaning,
at such time, the scheduler stops scheduling normal threads, raises system
to dispatch level and clears the dpc queue.

The ‘P’ period occurs:

  • immediately on DPC being queued if the CPU is currently running an idle
    thread (is idle).
  • on a timer tick, if the DPC queue length reached some limit (governed by
    IdealDpcRate registry value)
  • on each thread context switch.

All of this is for Low importance DPCs. Normal and High importance DPCs are
fired on each IRQL lower to < DISPATCH, first High, then Normal.

So, if you have the high-CPU-load thread which never leaves the CPU idle and is
of a high priority (so it is never context-switched from), then the Low
imporance DPCs only interrupt it at timer ticks sometimes.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

The presence of a DPC to be executed on a particular processor will stop
thread scheduling. DPCs end up in the queue as a result (directly or
indirectly) of interrupt delivery, either from a device or from another
processor. DPCs will then be executed until the DPC queue is empty. Then
thread scheduling will resume.

You can assume that if you schedule a DPC from a thread, it will run to
completion before the next instruction of the function runs. This happens
because the scheduling of that DPC sends an interrupt to the processor
(self-directed.) Sometimes that interrupt is simulated, but the semantics
are the same as an actual hardware interrupt.

  • Jake Oshins
    Windows Kernel Team

“bank kus” wrote in message news:xxxxx@ntdev…
> In fact may I follow up on this with another question, some of these
> aspects are not very clear in Inside Windows 2000:
>
> How does the whole dpc scheduling operation tie up with that of normal
> thread scheduling.
> So my understanding is that at a period `P’, the DPC queue will be flushed
> of all its queued objects. Meaning,
> at such time, the scheduler stops scheduling normal threads, raises system
> to dispatch level and clears the dpc queue.
> Question is when such takes place, is it atomic ? Meaning is it true that
> once started ALL dpc objects will be executed
> before normal thread scheduling takes place again?
>
> What can impact ‘P’? ( other than lenghty ISR routines ? ) Is there
> such a ‘P’ at all?
>
> thanks
> banks
>
>
> “bank kus” wrote in message news:xxxxx@ntdev…
>> Looking at the following link it seems there were plans to have a WHQL
>> requirement for drivers not to spin too much time in their dpc/isr
>> routines.
>> http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx
>>
>> Curious if such has been implemented already for Windows XP?
>>
>> thanks
>> banks
>>
>>
>
>
>

I disagree with some of the statements below, if not the conclusions drawn
from them.

I think that it’s helpful to realize that DPCs are interrupts, and that DPCs
and ISRs are executed essentially outside of the threading model. They
aren’t “high-priority threads.” They are interrupts. They are not
scheduled. They happen asychronously and they are arbitrated by the
hardware. (Small exceptions happen when you’re using an interrupt
controller that isn’t expressive enough to match the NT IRQL concept and
then the hardware interrupts that would have happened for DPCs are simulated
by the HAL.)

Thread priority has nothing to do with IRQL. IRQL is separate
hardware-enforced priority mechanism for interrupt delivery, effectively
allowing some interrupts to be masked while others are unmasked.

I suggest reading the following:

http://www.microsoft.com/whdc/driver/kernel/IRQL.mspx

  • Jake Oshins
    Windows Kernel Team

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> bank kus wrote:
>
>>In fact may I follow up on this with another question, some of these
>>aspects
>>are not very clear in Inside Windows 2000:
>>
>> How does the whole dpc scheduling operation tie up with that of normal
>>thread scheduling.
>>So my understanding is that at a period `P’, the DPC queue will be flushed
>>of all its queued objects. Meaning,
>>at such time, the scheduler stops scheduling normal threads, raises system
>>to dispatch level and clears the dpc queue.
>>
>>
>
> No. Remember that the system guarantees that it will always select the
> highest-priority thread that is ready to run. A DPC has higher priority
> than any passive thread, so every DPC will run before the system ever
> goes back to user-mode.
>
> Also remember that threads cannot pop up asynchronously (with the
> exception of hardware interrupts!). The system does not have to stop
> processing user-mode threads and say “OK, now do I have anything more
> important to do?”, because a DPC cannot “pop up” in the middle of a
> user-mode thread. A DPC cannot be waiting unless some kernel-mode
> thread queued it. Ordinarily, that DPC will have been queued by an ISR
> (which is higher priority yet). As soon as the ISR is done, the
> operating system has to go find another thread to run. Again, it will
> choose the highest priority thread, which in this example will be the
> DPC. After all of the DPCs are drained, the highest priority thread is
> probably a user-mode thread.
>
> “Ah,” you say, being observant, “but what about a DPC queued with
> KeSetTimer? Can’t that ‘pop up’ in the middle of a user-mode thread?”
> No. Essentially, time is frozen while a user-mode thread runs. When
> operating system gets a chance to do scheduling, either because of an
> interrupt or because the user-mode thread did some I/O, THAT’S when it
> checks the timer queues. If a timer has expired, then only at that
> point will its DPC become “ready to run”. When the scheduler is
> finished, it has to decide which thread to run next. If a DPC came
> ready, then it will, of course, now be the highest priority thread, and
> it will run.
>
> It is not possible to have a DPC ready and waiting while the system is
> running a “normal” thread. It cannot happen.
>
>>Question is when such takes place, is it atomic ? Meaning is it true that
>>once started ALL dpc objects will be executed
>>before normal thread scheduling takes place again?
>>
>>
>
> ALL higher priority threads (including DPCs) will run before the system
> chooses a normal thread. If you write a DPC which queues itself, your
> system will never go back to user mode.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

> You can assume that if you schedule a DPC from a thread, it will run to

completion before the next instruction of the function runs. This happens
because the scheduling of that DPC sends an interrupt to the processor
(self-directed.) Sometimes that interrupt is simulated, but the semantics
are the same as an actual hardware interrupt.

Am I correct that with Low importance DPCs, this interrupt can be delayed till
the CPU will become idle or till the clock tick?

Am I correct that the interrupt is sent via HalRequestSoftwareInterrupt, and
the simulation, if any, is done within HAL?

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Jake Oshins wrote:

I think that it’s helpful to realize that DPCs are interrupts, and that DPCs
and ISRs are executed essentially outside of the threading model. They
aren’t “high-priority threads.” They are interrupts. They are not
scheduled. They happen asychronously and they are arbitrated by the
hardware.

I guess I don’t understand why one would implement DPCs in this way.
What does this scheme provide that wouldn’t be accomplished just as well
through the threading model?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

DPC’s can run in an arbitrary context. They don’t require switching
address spaces or any (additional) saving of context - heck they don’t
even require the thread system to be running.

If you need to use something thread-like in your driver then NT has an
excellent option already: threads. :slight_smile:

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Friday, October 06, 2006 8:55 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] WHQL to detect rogue drivers

Jake Oshins wrote:

I think that it’s helpful to realize that DPCs are interrupts, and that
DPCs
and ISRs are executed essentially outside of the threading model. They

aren’t “high-priority threads.” They are interrupts. They are not
scheduled. They happen asychronously and they are arbitrated by the
hardware.

I guess I don’t understand why one would implement DPCs in this way.
What does this scheme provide that wouldn’t be accomplished just as well
through the threading model?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Just think of DPCs as very high priority threads :slight_smile:

=====================
Mark Roddy DDK MVP
Windows 2003/XP/2000 Consulting
Hollis Technology Solutions 603-321-1032
www.hollistech.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Friday, October 06, 2006 11:55 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] WHQL to detect rogue drivers

Jake Oshins wrote:

>I think that it’s helpful to realize that DPCs are
interrupts, and that
>DPCs and ISRs are executed essentially outside of the
threading model.
>They aren’t “high-priority threads.” They are interrupts. They are
>not scheduled. They happen asychronously and they are arbitrated by
>the hardware.
>

I guess I don’t understand why one would implement DPCs in this way.
What does this scheme provide that wouldn’t be accomplished
just as well through the threading model?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer

Mark Roddy wrote:

Just think of DPCs as very high priority threads :slight_smile:

No, that’s what got me in trouble in the first place…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

The fact that there are now “threaded DPCs” on Vista probably isn’t going to
make you feel much better then :slight_smile:

-scott


Scott Noone
Software Engineer
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> Mark Roddy wrote:
>
>>Just think of DPCs as very high priority threads :slight_smile:
>>
>>
>
> No, that’s what got me in trouble in the first place…
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> I guess I don’t understand why one would implement DPCs in this way.
> What does this scheme provide that wouldn’t be accomplished just as well
> through the threading model?
>

In Windows CE DPCs are high priority threads, and interrupts
basically are events that wake up these threads.
Everything has already been invented…

–PA