> 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(;
{
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