235 lines
5.1 KiB
C
235 lines
5.1 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
dpcobj.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the kernel DPC object. Functions are provided
|
|||
|
to initialize, insert, and remove DPC objects.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David N. Cutler (davec) 6-Mar-1989
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ki.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The following assert macro is used to check that an input dpc is
|
|||
|
// really a kdpc and not something else, like deallocated pool.
|
|||
|
//
|
|||
|
|
|||
|
#define ASSERT_DPC(E) { \
|
|||
|
ASSERT((E)->Type == DpcObject); \
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KeInitializeDpc (
|
|||
|
IN PRKDPC Dpc,
|
|||
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
|||
|
IN PVOID DeferredContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function initializes a kernel DPC object. The deferred routine
|
|||
|
and context parameter are stored in the DPC object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Dpc - Supplies a pointer to a control object of type DPC.
|
|||
|
|
|||
|
DeferredRoutine - Supplies a pointer to a function that is called when
|
|||
|
the DPC object is removed from the current processor's DPC queue.
|
|||
|
|
|||
|
DeferredContext - Supplies a pointer to an arbitrary data structure which is
|
|||
|
to be passed to the function specified by the DeferredRoutine parameter.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Initialize standard control object header.
|
|||
|
//
|
|||
|
|
|||
|
Dpc->Type = DpcObject;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize deferred routine address and deferred context parameter.
|
|||
|
//
|
|||
|
|
|||
|
Dpc->DeferredRoutine = DeferredRoutine;
|
|||
|
Dpc->DeferredContext = DeferredContext;
|
|||
|
Dpc->Inserted = FALSE;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
KeInsertQueueDpc (
|
|||
|
IN PRKDPC Dpc,
|
|||
|
IN PVOID SystemArgument1,
|
|||
|
IN PVOID SystemArgument2
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function inserts a DPC object into the DPC queue. If the DPC object
|
|||
|
is already in the DPC queue, then no operation is performed. Otherwise,
|
|||
|
the DPC object is inserted in the DPC queue and a dispatch interrupt is
|
|||
|
requested.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Dpc - Supplies a pointer to a control object of type DPC.
|
|||
|
|
|||
|
SystemArgument1, SystemArgument2 - Supply a set of two arguments that
|
|||
|
contain untyped data provided by the executive.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the DPC object is already in a DPC queue, then a value of FALSE is
|
|||
|
returned. Otherwise a value of TRUE is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOLEAN Inserted;
|
|||
|
KIRQL OldIrql;
|
|||
|
PKPRCB Prcb;
|
|||
|
|
|||
|
ASSERT_DPC(Dpc);
|
|||
|
|
|||
|
//
|
|||
|
// Disable interrupts.
|
|||
|
//
|
|||
|
|
|||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// If the DPC object is not in a DPC queue, then store the system
|
|||
|
// arguments, insert the DPC object in the DPC queue, increment the
|
|||
|
// number of DPCs queued to the target processor, increment the DPC
|
|||
|
// queue depth, set the address of the DPC target DPC spinlock, and
|
|||
|
// request a dispatch interrupt if appropriate.
|
|||
|
//
|
|||
|
|
|||
|
Inserted = Dpc->Inserted;
|
|||
|
if (!Inserted) {
|
|||
|
|
|||
|
Dpc->Inserted = TRUE;
|
|||
|
Dpc->SystemArgument1 = SystemArgument1;
|
|||
|
Dpc->SystemArgument2 = SystemArgument2;
|
|||
|
|
|||
|
//
|
|||
|
// Insert the DPC at the end of the DPC queue.
|
|||
|
//
|
|||
|
|
|||
|
Prcb = KeGetCurrentPrcb();
|
|||
|
InsertTailList(&Prcb->DpcListHead, &Dpc->DpcListEntry);
|
|||
|
|
|||
|
//
|
|||
|
// If a DPC routine is not active on the target processor, then
|
|||
|
// request a dispatch interrupt if appropriate.
|
|||
|
//
|
|||
|
|
|||
|
if ((Prcb->DpcRoutineActive == FALSE) &&
|
|||
|
(Prcb->DpcInterruptRequested == FALSE)) {
|
|||
|
|
|||
|
//
|
|||
|
// Request a dispatch interrupt on the current processor.
|
|||
|
//
|
|||
|
|
|||
|
Prcb->DpcInterruptRequested = TRUE;
|
|||
|
KiRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Release the DPC lock, enable interrupts, and return whether the
|
|||
|
// DPC was queued or not.
|
|||
|
//
|
|||
|
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return (BOOLEAN)!Inserted;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
KeRemoveQueueDpc (
|
|||
|
IN PRKDPC Dpc
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function removes a DPC object from the DPC queue. If the DPC object
|
|||
|
is not in the DPC queue, then no operation is performed. Otherwise, the
|
|||
|
DPC object is removed from the DPC queue and its inserted state is set
|
|||
|
FALSE.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Dpc - Supplies a pointer to a control object of type DPC.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the DPC object is not in the DPC queue, then a value of FALSE is
|
|||
|
returned. Otherwise a value of TRUE is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOLEAN Inserted;
|
|||
|
|
|||
|
ASSERT_DPC(Dpc);
|
|||
|
|
|||
|
//
|
|||
|
// If the DPC object is in the DPC queue, then remove it from the queue
|
|||
|
// and set its inserted state to FALSE.
|
|||
|
//
|
|||
|
|
|||
|
_disable();
|
|||
|
Inserted = Dpc->Inserted;
|
|||
|
if (Inserted) {
|
|||
|
|
|||
|
//
|
|||
|
// If the specified DPC is still in the DPC queue, then remove it.
|
|||
|
//
|
|||
|
|
|||
|
RemoveEntryList(&Dpc->DpcListEntry);
|
|||
|
Dpc->Inserted = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enable interrupts and return whether the DPC was removed from a DPC
|
|||
|
// queue.
|
|||
|
//
|
|||
|
|
|||
|
_enable();
|
|||
|
return (BOOLEAN)Inserted;
|
|||
|
}
|