DPC Guarantees

We all know that a DPC can only be queued once. A call to
KeInsertQueueDpc will do nothing and return FALSE if the DPC is not queued.

How far does that guarantee extend? Is it just until the DPC routine
starts, or is it until the DPC routine returns? The documentation is
not clear (to me). Specifically, if the DPC routine is executing, can
the DPC object be requeued, and presumably dequeued on a different
processor?

We seem to have run into a case where a DPC routine fired from our
interrupt handler is executing simultaneously on two processors. We
naively thought that to be impossible.

The guarantee is valid until the DPC object has been removed from the
DPC queue. It is removed before your DPC routine is called. That means
that you can easily have the same DPC routine fire on 2 different
processors if you call KeInsertQueueDpc in that window between dequeue
and routine call.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, April 04, 2005 4:46 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] DPC Guarantees

We all know that a DPC can only be queued once. A call to
KeInsertQueueDpc will do nothing and return FALSE if the DPC is not
queued.

How far does that guarantee extend? Is it just until the DPC routine
starts, or is it until the DPC routine returns? The documentation is
not clear (to me). Specifically, if the DPC routine is executing, can
the DPC object be requeued, and presumably dequeued on a different
processor?

We seem to have run into a case where a DPC routine fired from our
interrupt handler is executing simultaneously on two processors. We
naively thought that to be impossible.


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

You are currently subscribed to ntdev as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

it means exactly what it says (though i agree that can be confusing).
If your DPC is on a processor queue it will not be inserted into another
queue.

Once it’s been pulled off that queue in order to run (i.e. before it’s
ever called), the DPC could be requeued. You can potentially end up
with your DPC running on every processor in the system at the same time.

if you need to ensure mutual exclusion, then you’ll either need to add
that into your DPC. You can put a big spinlock around the whole thing.
Or keep more careful track of whether the DPC is running and whether one
is needed and use that to have each additional DPC just return while
there’s one running (and that one then loops picking up work to do)

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, April 04, 2005 4:46 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] DPC Guarantees

We all know that a DPC can only be queued once. A call to
KeInsertQueueDpc will do nothing and return FALSE if the DPC
is not queued.

How far does that guarantee extend? Is it just until the DPC
routine starts, or is it until the DPC routine returns? The
documentation is not clear (to me). Specifically, if the DPC
routine is executing, can the DPC object be requeued, and
presumably dequeued on a different processor?

We seem to have run into a case where a DPC routine fired
from our interrupt handler is executing simultaneously on two
processors. We naively thought that to be impossible.


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

You are currently subscribed to ntdev as:
xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The DPC could be running on two processors at the same time. The guarantee is only for queuing.
The DPC is dequeued before execution.

-----Original Message-----
From: xxxxx@lists.osr.com on behalf of Tim Roberts
Sent: Mon 4/4/2005 4:46 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] DPC Guarantees

We all know that a DPC can only be queued once. A call to
KeInsertQueueDpc will do nothing and return FALSE if the DPC is not queued.

How far does that guarantee extend? Is it just until the DPC routine
starts, or is it until the DPC routine returns? The documentation is
not clear (to me). Specifically, if the DPC routine is executing, can
the DPC object be requeued, and presumably dequeued on a different
processor?

We seem to have run into a case where a DPC routine fired from our
interrupt handler is executing simultaneously on two processors. We
naively thought that to be impossible.


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

You are currently subscribed to ntdev as: xxxxx@troikanetworks.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

In order to run the dpc routine associated with the dpc object the OS
removes the dpc object from the dpc queue. In doing so it allows the dpc to
be re-queued. Yes your dpc routine can be requeued while you are in your dpc
routine. Theoretically your dpc routine can be executing concurrently on
each logical processor on the system.

=====================
Mark Roddy
Windows .NET/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: Monday, April 04, 2005 7:46 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] DPC Guarantees

We all know that a DPC can only be queued once. A call to
KeInsertQueueDpc will do nothing and return FALSE if the DPC
is not queued.

How far does that guarantee extend? Is it just until the DPC
routine starts, or is it until the DPC routine returns? The
documentation is not clear (to me). Specifically, if the DPC
routine is executing, can the DPC object be requeued, and
presumably dequeued on a different processor?

We seem to have run into a case where a DPC routine fired
from our interrupt handler is executing simultaneously on two
processors. We naively thought that to be impossible.


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

You are currently subscribed to ntdev as: xxxxx@hollistech.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> How far does that guarantee extend? Is it just until the DPC routine

starts, or is it until the DPC routine returns? The documentation is
not clear (to me).

The DPC ceases to be queued exactly at the moment when the dispatcher starts
its execution. It can be re-queued just after this.

Specifically, if the DPC routine is executing, can
the DPC object be requeued, and presumably dequeued on a different
processor?

Yes.

We seem to have run into a case where a DPC routine fired from our
interrupt handler is executing simultaneously on two processors. We
naively thought that to be impossible.

This is possible.

One of the methods of dealing with this is disabling the device interrupts in
the ISR and re enabling them in the end of DPC. SCSIPORT provides the callbacks
for the miniports to do this.

Another way is more complex - like:

a) ISR:

DevExt->InterruptCause |= READ_REGISTER_ULONG(InterruptStatus);
WRITE_REGISTER_ULONG(InterruptStatus, 0);
KeInsertQueueDpc(…).

b) Helper structure:

typedef struct _SYNC_CONTEXT
{
ULONG InterruptCause;
PMY_DEVEXT DevExt;
} SYNC_CONTEXT, *PSYNC_CONTEXT;

c) SyncCritSection helper:

PSYNC_CONTEXT SyncContext;
SyncContext = (PSYNC_CONTEXT)Context;
SyncContext->InterruptCause = SyncContext->DevExt->InterruptCause;
SyncContext->DevExt->InterruptCause = 0;

d) the DPC:

SYNC_CONTEXT SyncContext;
for(;:wink:
{
KeSynchronizeExecution(MySyncCritSection, &SyncContext);
if( SyncContext.InterruptCause == 0 )
break;
// Handle the interrupt causes in SyncContext.InterruptCause

}

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