Source code of Windows XP (NT5)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
dpcplt.c
Abstract:
This module implements platform specific code to support Deferred Procedure Calls (DPCs).
Author:
David N. Cutler (davec) 30-Aug-2000
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
VOID KiRetireDpcList ( PKPRCB Prcb )
/*++
Routine Description:
This function processes the DPC list for the specified processor.
N.B. This function is entered with interrupts disabled and exits with interrupts disabled.
Arguments:
Prcb - Supplies the address of the processor block.
Return Value:
None.
--*/
{
PKDPC Dpc; PVOID DeferredContext; PKDEFERRED_ROUTINE DeferredRoutine; PLIST_ENTRY Entry; PLIST_ENTRY ListHead; PVOID SystemArgument1; PVOID SystemArgument2; ULONG TimerHand;
//
// Loop processing DPC list entries until the specified DPC list is empty.
//
// N.B. This following code appears to have a redundant loop, but it does
// not. The point of this code is to avoid as many dispatch interrupts
// as possible.
//
ListHead = &Prcb->DpcListHead; do { Prcb->DpcRoutineActive = TRUE;
//
// If the timer hand value is nonzero, then process expired timers.
//
if ((TimerHand = Prcb->TimerHand) != 0) { Prcb->TimerHand = 0; _enable(); KiTimerExpiration(NULL, NULL, UlongToHandle(TimerHand - 1), NULL); _disable(); }
//
// If the DPC list is not empty, then process the DPC list.
//
if (Prcb->DpcQueueDepth != 0) {
//
// Acquire the DPC lock for the current processor and check if
// the DPC list is empty. If the DPC list is not empty, then
// remove the first entry from the DPC list, capture the DPC
// parameters, set the DPC inserted state false, decrement the
// DPC queue depth, release the DPC lock, enable interrupts, and
// call the specified DPC routine. Otherwise, release the DPC
// lock and enable interrupts.
//
do { KeAcquireSpinLockAtDpcLevel(&Prcb->DpcLock); Entry = Prcb->DpcListHead.Flink; if (Entry != ListHead) { RemoveEntryList(Entry); Dpc = CONTAINING_RECORD(Entry, KDPC, DpcListEntry); DeferredRoutine = Dpc->DeferredRoutine; DeferredContext = Dpc->DeferredContext; SystemArgument1 = Dpc->SystemArgument1; SystemArgument2 = Dpc->SystemArgument2; Dpc->Lock = NULL; Prcb->DpcQueueDepth -= 1; KeReleaseSpinLockFromDpcLevel(&Prcb->DpcLock); _enable(); (DeferredRoutine)(Dpc, DeferredContext, SystemArgument1, SystemArgument2);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
_disable();
} else {
ASSERT(Prcb->DpcQueueDepth == 0);
KeReleaseSpinLockFromDpcLevel(&Prcb->DpcLock); }
} while (ListHead != *((PLIST_ENTRY volatile *)&ListHead->Flink)); }
Prcb->DpcRoutineActive = FALSE; Prcb->DpcInterruptRequested = FALSE; } while (ListHead != *((PLIST_ENTRY volatile *)&ListHead->Flink));
return; }
|