- Add missing volatile statements to KPROCESS, KTHREAD, KPRCB and KDPC_DATA.

- Fix KDPC definition in DDK. You can always count on the w32api to get even the simplest structures wrong.
- Fix memory overwrite bug in KiInitSpinlocks.
- Part 1 of 2: Cleanup and improve DPC implementation to add partial support for Threaded DPCs and remove SMP vs non-SMP ifdefs. (At the expense of, oh God, 5 wasted CPU cycles!).

svn path=/trunk/; revision=23886
This commit is contained in:
Alex Ionescu 2006-09-02 16:19:00 +00:00
parent ea0c0daec0
commit 38ca1d7d77
7 changed files with 280 additions and 348 deletions

View file

@ -1079,16 +1079,25 @@ typedef struct _KLOCK_QUEUE_HANDLE {
KIRQL OldIrql;
} KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE;
typedef struct _KDPC {
CSHORT Type;
UCHAR Number;
UCHAR Importance;
LIST_ENTRY DpcListEntry;
PKDEFERRED_ROUTINE DeferredRoutine;
PVOID DeferredContext;
PVOID SystemArgument1;
PVOID SystemArgument2;
PVOID DpcData;
#define DPC_NORMAL 0
#define DPC_THREADED 1
#define ASSERT_DPC(Object) \
ASSERT(((Object)->Type == 0) || \
((Object)->Type == DpcObject) || \
((Object)->Type == ThreadedDpcObject))
typedef struct _KDPC
{
UCHAR Type;
UCHAR Importance;
USHORT Number;
LIST_ENTRY DpcListEntry;
PKDEFERRED_ROUTINE DeferredRoutine;
PVOID DeferredContext;
PVOID SystemArgument1;
PVOID SystemArgument2;
volatile PVOID DpcData;
} KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC;
typedef PVOID PKIPI_CONTEXT;

View file

@ -421,9 +421,9 @@ typedef struct _KPRCB
ULONG KeSecondLevelTbFills;
ULONG KeSystemCalls;
#endif
ULONG IoReadOperationCount;
ULONG IoWriteOperationCount;
ULONG IoOtherOperationCount;
volatile ULONG IoReadOperationCount;
volatile ULONG IoWriteOperationCount;
volatile ULONG IoOtherOperationCount;
LARGE_INTEGER IoReadTransferCount;
LARGE_INTEGER IoWriteTransferCount;
LARGE_INTEGER IoOtherTransferCount;
@ -464,37 +464,37 @@ typedef struct _KPRCB
PP_LOOKASIDE_LIST PPLookasideList[16];
PP_LOOKASIDE_LIST PPNPagedLookasideList[32];
PP_LOOKASIDE_LIST PPPagedLookasideList[32];
ULONG PacketBarrier;
ULONG ReverseStall;
volatile ULONG PacketBarrier;
volatile ULONG ReverseStall;
PVOID IpiFrame;
UCHAR PrcbPad2[52];
PVOID CurrentPacket[3];
ULONG TargetSet;
PKIPI_WORKER WorkerRoutine;
ULONG IpiFrozen;
volatile PVOID CurrentPacket[3];
volatile ULONG TargetSet;
volatile PKIPI_WORKER WorkerRoutine;
volatile ULONG IpiFrozen;
UCHAR PrcbPad3[40];
ULONG RequestSummary;
struct _KPRCB *SignalDone;
volatile ULONG RequestSummary;
volatile struct _KPRCB *SignalDone;
UCHAR PrcbPad4[56];
struct _KDPC_DATA DpcData[2];
PVOID DpcStack;
ULONG MaximumDpcQueueDepth;
ULONG DpcRequestRate;
ULONG MinimumDpcRate;
UCHAR DpcInterruptRequested;
UCHAR DpcThreadRequested;
UCHAR DpcRoutineActive;
UCHAR DpcThreadActive;
volatile UCHAR DpcInterruptRequested;
volatile UCHAR DpcThreadRequested;
volatile UCHAR DpcRoutineActive;
volatile UCHAR DpcThreadActive;
ULONG PrcbLock;
ULONG DpcLastCount;
ULONG TimerHand;
ULONG TimerRequest;
volatile ULONG TimerHand;
volatile ULONG TimerRequest;
PVOID DpcThread;
KEVENT DpcEvent;
UCHAR ThreadDpcEnable;
BOOLEAN QuantumEnd;
volatile BOOLEAN QuantumEnd;
UCHAR PrcbPad50;
UCHAR IdleSchedule;
volatile UCHAR IdleSchedule;
LONG DpcSetEventRequest;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
LONG Sleeping;
@ -535,19 +535,19 @@ typedef struct _KPRCB
#endif
PVOID ChainedInterruptList;
LONG LookasideIrpFloat;
LONG MmPageFaultCount;
LONG MmCopyOnWriteCount;
LONG MmTransitionCount;
LONG MmCacheTransitionCount;
LONG MmDemandZeroCount;
LONG MmPageReadCount;
LONG MmPageReadIoCount;
LONG MmCacheReadCount;
LONG MmCacheIoCount;
LONG MmDirtyPagesWriteCount;
LONG MmDirtyWriteIoCount;
LONG MmMappedPagesWriteCount;
LONG MmMappedWriteIoCount;
volatile LONG MmPageFaultCount;
volatile LONG MmCopyOnWriteCount;
volatile LONG MmTransitionCount;
volatile LONG MmCacheTransitionCount;
volatile LONG MmDemandZeroCount;
volatile LONG MmPageReadCount;
volatile LONG MmPageReadIoCount;
volatile LONG MmCacheReadCount;
volatile LONG MmCacheIoCount;
volatile LONG MmDirtyPagesWriteCount;
volatile LONG MmDirtyWriteIoCount;
volatile LONG MmMappedPagesWriteCount;
volatile LONG MmMappedWriteIoCount;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
ULONG CachedCommit;
ULONG CachedResidentAvailable;
@ -563,7 +563,7 @@ typedef struct _KPRCB
ULONG MHz;
ULONG FeatureBits;
LARGE_INTEGER UpdateSignature;
LARGE_INTEGER IsrTime;
volatile LARGE_INTEGER IsrTime;
LARGE_INTEGER SpareField1;
FX_SAVE_AREA NpxSaveArea;
PROCESSOR_POWER_STATE PowerState;

View file

@ -487,7 +487,7 @@ typedef struct _KDPC_DATA
{
LIST_ENTRY DpcListHead;
ULONG DpcLock;
ULONG DpcQueueDepth;
volatile ULONG DpcQueueDepth;
ULONG DpcCount;
} KDPC_DATA, *PKDPC_DATA;
@ -676,13 +676,13 @@ typedef struct _KTHREAD
UCHAR ApcQueueable;
};
};
UCHAR NextProcessor;
UCHAR DeferredProcessor;
volatile UCHAR NextProcessor;
volatile UCHAR DeferredProcessor;
UCHAR AdjustReason;
UCHAR AdjustIncrement;
KSPIN_LOCK ApcQueueLock;
ULONG ContextSwitches;
UCHAR State;
volatile UCHAR State;
UCHAR NpxState;
UCHAR WaitIrql;
UCHAR WaitMode;
@ -697,7 +697,7 @@ typedef struct _KTHREAD
UCHAR WaitReason;
UCHAR Priority;
UCHAR EnableStackSwap;
UCHAR SwapBusy;
volatile UCHAR SwapBusy;
UCHAR Alerted[2];
union
{
@ -903,7 +903,7 @@ typedef struct _KPROCESS
UCHAR Iopl;
UCHAR Unused;
#endif
ULONG ActiveProcessors;
volatile ULONG ActiveProcessors;
ULONG KernelTime;
ULONG UserTime;
LIST_ENTRY ReadyListHead;

View file

@ -113,6 +113,9 @@ extern KSPIN_LOCK KiProfileLock;
extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
extern LIST_ENTRY KiStackInSwapListHead;
extern KEVENT KiSwapEvent;
extern PKPRCB KiProcessorBlock[];
extern ULONG KiMask32Array[MAXIMUM_PRIORITY];
extern ULONG IdleProcessorMask;
/* MACROS *************************************************************************/

View file

@ -1,29 +1,22 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/dpc.c
* PURPOSE: Handle DPCs (Delayed Procedure Calls)
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/i386/cpu.c
* PURPOSE: Routines for CPU-level support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Philip Susi (phreak@iag.net)
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
* Alex Ionescu (alex@relsoft.net)
*/
/*
* NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
*/
/* INCLUDES ******************************************************************/
/* INCLUDES ***************************************************************/
#define NTDDI_VERSION NTDDI_WS03
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#include <debug.h>
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, KeInitDpc)
#endif
/* GLOBALS *******************************************************************/
ULONG KiMaximumDpcQueueDepth = 4;
ULONG KiMinimumDpcRate = 3;
@ -31,32 +24,17 @@ ULONG KiAdjustDpcThreshold = 20;
ULONG KiIdealDpcRate = 20;
KMUTEX KiGenericCallDpcMutex;
/* TYPES *******************************************************************/
/* PRIVATE FUNCTIONS *********************************************************/
#define MAX_QUANTUM 0x7F
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
VOID
STDCALL
KeInitializeThreadedDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
/*
* FUNCTION:
* Initalizes a Threaded DPC and registers the DeferredRoutine for it.
* ARGUMENTS:
* Dpc = Pointer to a caller supplied DPC to be initialized. The caller must allocate this memory.
* DeferredRoutine = Pointer to associated DPC callback routine.
* DeferredContext = Parameter to be passed to the callback routine.
* NOTE: Callers can be running at any IRQL.
*/
NTAPI
KiInitializeDpc(IN PKDPC Dpc,
IN PKDEFERRED_ROUTINE DeferredRoutine,
IN PVOID DeferredContext,
IN KOBJECTS Type)
{
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = ThreadedDpcObject;
/* Setup the DPC Object */
Dpc->Type = Type;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
@ -64,275 +42,236 @@ KeInitializeThreadedDpc(PKDPC Dpc,
Dpc->DpcData = NULL;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*
* FUNCTION:
* Initalizes a DPC and registers the DeferredRoutine for it.
* ARGUMENTS:
* Dpc = Pointer to a caller supplied DPC to be initialized. The caller must allocate this memory.
* DeferredRoutine = Pointer to associated DPC callback routine.
* DeferredContext = Parameter to be passed to the callback routine.
* NOTE: Callers can be running at any IRQL.
*/
VOID
STDCALL
KeInitializeDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
NTAPI
KeInitializeThreadedDpc(IN PKDPC Dpc,
IN PKDEFERRED_ROUTINE DeferredRoutine,
IN PVOID DeferredContext)
{
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = DpcObject;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL;
/* Call the internal routine */
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, ThreadedDpcObject);
}
/*
* @implemented
*/
VOID
NTAPI
KeInitializeDpc(IN PKDPC Dpc,
IN PKDEFERRED_ROUTINE DeferredRoutine,
IN PVOID DeferredContext)
{
/* Call the internal routine */
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject);
}
/*
* @implemented
*
* FUNCTION:
* Queues a DPC for execution when the IRQL of a processor
* drops below DISPATCH_LEVEL
* ARGUMENTS:
* Dpc = Pointed to a DPC Object Initalized by KeInitializeDpc.
* SystemArgument1 = Driver Determined context data
* SystemArgument2 = Driver Determined context data
* RETURNS:
* TRUE if the DPC object wasn't already in the queue
* FALSE otherwise
* NOTES:
* If there is currently a DPC active on the target processor, or a DPC
* interrupt has already been requested on the target processor when a
* DPC is queued, then no further action is necessary. The DPC will be
* executed on the target processor when its queue entry is processed.
*
* If there is not a DPC active on the target processor and a DPC interrupt
* has not been requested on the target processor, then the exact treatment
* of the DPC is dependent on whether the host system is a UP system or an
* MP system.
*
* UP system.
* ----------
* If the DPC is of medium or high importance, the current DPC queue depth
* is greater than the maximum target depth, or current DPC request rate is
* less the minimum target rate, then a DPC interrupt is requested on the
* host processor and the DPC will be processed when the interrupt occurs.
* Otherwise, no DPC interupt is requested and the DPC execution will be
* delayed until the DPC queue depth is greater that the target depth or the
* minimum DPC rate is less than the target rate.
*
* MP system.
* ----------
* If the DPC is being queued to another processor and the depth of the DPC
* queue on the target processor is greater than the maximum target depth or
* the DPC is of high importance, then a DPC interrupt is requested on the
* target processor and the DPC will be processed when the interrupt occurs.
* Otherwise, the DPC execution will be delayed on the target processor until
* the DPC queue depth on the target processor is greater that the maximum
* target depth or the minimum DPC rate on the target processor is less than
* the target mimimum rate.
*
* If the DPC is being queued to the current processor and the DPC is not of
* low importance, the current DPC queue depth is greater than the maximum
* target depth, or the minimum DPC rate is less than the minimum target rate,
* then a DPC interrupt is request on the current processor and the DPV will
* be processed whne the interrupt occurs. Otherwise, no DPC interupt is
* requested and the DPC execution will be delayed until the DPC queue depth
* is greater that the target depth or the minimum DPC rate is less than the
* target rate.
*/
BOOLEAN
STDCALL
KeInsertQueueDpc(PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
NTAPI
KeInsertQueueDpc(IN PKDPC Dpc,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
KIRQL OldIrql;
PKPRCB Prcb;
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2);
PKPRCB Prcb, CurrentPrcb = KeGetCurrentPrcb();
ULONG Cpu;
PKDPC_DATA DpcData;
BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
ASSERT_DPC(Dpc);
/* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */
if (Dpc->Type == ThreadedDpcObject) {
KeLowerIrql(OldIrql);
return FALSE;
/* Check if the DPC has more then the maximum number of CPUs */
if (Dpc->Number >= MAXIMUM_PROCESSORS)
{
/* Then substract the maximum and get that PRCB. */
Cpu = Dpc->Number - MAXIMUM_PROCESSORS;
Prcb = KiProcessorBlock[Cpu];
}
else
{
/* Use the current one */
Prcb = CurrentPrcb;
Cpu = Prcb->Number;
}
#ifdef CONFIG_SMP
/* Get the right PCR for this CPU */
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + ((Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE)))->Prcb;
} else {
ASSERT (Dpc->Number < KeNumberProcessors);
Prcb = KeGetCurrentPrcb();
Dpc->Number = KeGetCurrentProcessorNumber();
/* Check if this is a threaded DPC and threaded DPCs are enabled */
if ((Dpc->Type = ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
{
/* Then use the threaded data */
DpcData = &Prcb->DpcData[DPC_THREADED];
}
else
{
/* Otherwise, use the regular data */
DpcData = &Prcb->DpcData[DPC_NORMAL];
}
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
#else
Prcb = ((PKPCR)KPCR_BASE)->Prcb;
#endif
/* Acquire the DPC lock */
KiAcquireSpinLock(&DpcData->DpcLock);
/* Get the DPC Data */
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Prcb->DpcData[0].DpcLock, 0)) {
if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL))
{
/* Now we can play with the DPC safely */
Dpc->SystemArgument1 = SystemArgument1;
Dpc->SystemArgument2 = SystemArgument2;
DpcData->DpcQueueDepth++;
DpcData->DpcCount++;
DpcConfigured = TRUE;
DPRINT("DPC Already Inserted\n");
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif
KeLowerIrql(OldIrql);
return(FALSE);
}
/* Check if this is a high importance DPC */
if (Dpc->Importance == HighImportance)
{
/* Pre-empty other DPCs */
InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
}
else
{
/* Add it at the end */
InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
}
/* Make sure the lists are free if the Queue is 0 */
if (Prcb->DpcData[0].DpcQueueDepth == 0) {
/* Check if this is the DPC on the threaded list */
if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead)
{
/* Make sure a threaded DPC isn't already active */
if (!(Prcb->DpcThreadActive) && (!Prcb->DpcThreadRequested))
{
/* FIXME: Setup Threaded DPC */
ASSERT(FALSE);
}
}
else
{
/* Make sure a DPC isn't executing already */
if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested))
{
/* Check if this is the same CPU */
if (Prcb != CurrentPrcb)
{
/*
* Check if the DPC is of high importance or above the
* maximum depth. If it is, then make sure that the CPU
* isn't idle, or that it's sleeping.
*/
if (((Dpc->Importance == HighImportance) ||
(DpcData->DpcQueueDepth >=
Prcb->MaximumDpcQueueDepth)) &&
(!(AFFINITY_MASK(Cpu) & IdleProcessorMask) ||
(Prcb->Sleeping)))
{
/* Set interrupt requested */
Prcb->DpcInterruptRequested = TRUE;
ASSERT(IsListEmpty(&Prcb->DpcData[0].DpcListHead));
} else {
ASSERT(!IsListEmpty(&Prcb->DpcData[0].DpcListHead));
}
/* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2;
Prcb->DpcData[0].DpcQueueDepth++;
Prcb->DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) {
InsertHeadList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else {
InsertTailList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) {
#ifdef CONFIG_SMP
/* Check if this is the same CPU */
if (Prcb != KeGetCurrentPrcb()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) ||
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth)) {
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_DPC);
/* Set DPC inserted */
DpcInserted = TRUE;
}
}
else
{
/* Check if the DPC is of anything but low importance */
if ((Dpc->Importance != LowImportance) ||
(DpcData->DpcQueueDepth >=
Prcb->MaximumDpcQueueDepth) ||
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate))
{
/* Set interrupt requested */
Prcb->DpcInterruptRequested = TRUE;
}
} else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Prcb->DpcInterruptRequested = TRUE;
/* Set DPC inserted */
DpcInserted = TRUE;
}
}
}
}
#else
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Prcb->DpcData[0].DpcQueueDepth, Prcb->MaximumDpcQueueDepth, Prcb->DpcRequestRate, Prcb->MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n");
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Prcb->DpcInterruptRequested = TRUE;
}
#endif
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif
/* Release the lock */
KiReleaseSpinLock(&DpcData->DpcLock);
/* Check if the DPC was inserted */
if (DpcInserted)
{
/* Check if this was SMP */
if (Prcb != CurrentPrcb)
{
/* It was, request and IPI */
KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);
}
else
{
/* It wasn't, request an interrupt from HAL */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
/* Lower IRQL */
KeLowerIrql(OldIrql);
return(TRUE);
return DpcConfigured;
}
/*
* @implemented
*
* FUNCTION:
* Removes DPC object from the system dpc queue
* ARGUMENTS:
* Dpc = Pointer to DPC to remove from the queue.
* RETURNS:
* TRUE if the DPC was in the queue
* FALSE otherwise
*/
BOOLEAN
STDCALL
KeRemoveQueueDpc(PKDPC Dpc)
NTAPI
KeRemoveQueueDpc(IN PKDPC Dpc)
{
BOOLEAN WasInQueue;
KIRQL OldIrql;
PKDPC_DATA DpcData;
UCHAR DpcType;
ASSERT_DPC(Dpc);
/* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* Disable interrupts */
Ke386DisableInterrupts();
/* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) {
/* Get DPC data and type */
DpcType = Dpc->Type;
DpcData = Dpc->DpcData;
if (DpcData)
{
/* Acquire the DPC lock */
KiAcquireSpinLock(&DpcData->DpcLock);
/* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
/* Make sure that the data didn't change */
if (DpcData == Dpc->DpcData)
{
/* Remove the DPC */
DpcData->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
Dpc->DpcData = NULL;
}
/* Release the lock */
KiReleaseSpinLock(&DpcData->DpcLock);
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* Re-enable interrupts */
Ke386EnableInterrupts();
/* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql);
return WasInQueue;
return DpcData ? TRUE : FALSE;
}
/*
* @implemented
*/
VOID
STDCALL
NTAPI
KeFlushQueuedDpcs(VOID)
/*
* FUNCTION:
* Called to Deliver DPCs if any are pending.
* NOTES:
* Called when deleting a Driver.
*/
{
PAGED_CODE();
/* Request an interrupt if needed */
DPRINT1("%s - FIXME!!!\n", __FUNCTION__);
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
@ -340,59 +279,37 @@ KeFlushQueuedDpcs(VOID)
* @implemented
*/
BOOLEAN
STDCALL
KeIsExecutingDpc(
VOID
)
NTAPI
KeIsExecutingDpc(VOID)
{
/* Return if the Dpc Routine is active */
return KeGetCurrentPrcb()->DpcRoutineActive;
}
/*
* FUNCTION: Specifies the DPCs importance
* ARGUMENTS:
* Dpc = Initalizes DPC
* Importance = DPC importance
* RETURNS: None
*
* @implemented
*/
VOID
STDCALL
NTAPI
KeSetImportanceDpc (IN PKDPC Dpc,
IN KDPC_IMPORTANCE Importance)
IN KDPC_IMPORTANCE Importance)
{
/* Set the DPC Importance */
ASSERT_DPC(Dpc);
Dpc->Importance = Importance;
}
/*
* @implemented
*
* FUNCTION: Specifies on which processor the DPC will run
* ARGUMENTS:
* Dpc = Initalizes DPC
* Number = Processor number
* RETURNS: None
*/
VOID
STDCALL
NTAPI
KeSetTargetProcessorDpc(IN PKDPC Dpc,
IN CCHAR Number)
{
/* Check how many CPUs are on the system */
if (Number >= MAXIMUM_PROCESSORS) {
/* No CPU Number */
Dpc->Number = 0;
} else {
/* Set the Number Specified */
ASSERT(Number < KeNumberProcessors);
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
/* Set a target CPU */
ASSERT_DPC(Dpc);
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
/*

View file

@ -17,11 +17,11 @@
/* GLOBALS *******************************************************************/
PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
KNODE KiNode0;
PKNODE KeNodeBlock[1];
UCHAR KeNumberNodes = 1;
UCHAR KeProcessNodeSeed;
PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
ETHREAD KiInitialThread;
EPROCESS KiInitialProcess;
@ -195,10 +195,10 @@ KiInitSpinLocks(IN PKPRCB Prcb,
}
/* Initialize DPC Fields */
InitializeListHead(&Prcb->DpcData[0].DpcListHead);
KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
Prcb->DpcData[0].DpcQueueDepth = 0;
Prcb->DpcData[0].DpcCount = 0;
InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
Prcb->DpcRoutineActive = FALSE;
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
Prcb->MinimumDpcRate = KiMinimumDpcRate;
@ -245,11 +245,14 @@ KiInitSpinLocks(IN PKPRCB Prcb,
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
for (i = LockQueueTimerTableLock; i < LockQueueMaximumLock; i++)
/* Loop timer locks */
for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
{
KeInitializeSpinLock(&KiTimerTableLock[i - 16]);
/* Initialize the lock and setup the Queued Spinlock */
KeInitializeSpinLock(&KiTimerTableLock[i]);
Prcb->LockQueue[i].Next = NULL;
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i - 16];
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
}
/* Check if this is the boot CPU */
@ -297,7 +300,7 @@ KiInitializePcr(IN ULONG ProcessorNumber,
/* Set pointers to ourselves */
Pcr->Self = (PKPCR)Pcr;
Pcr->Prcb = &(Pcr->PrcbData);
Pcr->Prcb = &Pcr->PrcbData;
/* Set the PCR Version */
Pcr->MajorVersion = PCR_MAJOR_VERSION;

View file

@ -33,7 +33,7 @@ KiIpiSendRequest(KAFFINITY TargetSet, ULONG IpiRequest)
if (TargetSet & Current)
{
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
Ke386TestAndSetBit(IpiRequest, &Pcr->Prcb->IpiFrozen);
Ke386TestAndSetBit(IpiRequest, (PLONG)&Pcr->Prcb->IpiFrozen);
HalRequestIpi(i);
}
}
@ -59,18 +59,18 @@ KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
Prcb = KeGetCurrentPrcb();
if (Ke386TestAndClearBit(IPI_APC, &Prcb->IpiFrozen))
if (Ke386TestAndClearBit(IPI_APC, (PLONG)&Prcb->IpiFrozen))
{
HalRequestSoftwareInterrupt(APC_LEVEL);
}
if (Ke386TestAndClearBit(IPI_DPC, &Prcb->IpiFrozen))
if (Ke386TestAndClearBit(IPI_DPC, (PLONG)&Prcb->IpiFrozen))
{
Prcb->DpcInterruptRequested = TRUE;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, &Prcb->IpiFrozen))
if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, (PLONG)&Prcb->IpiFrozen))
{
(void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]);
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
@ -91,7 +91,7 @@ KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
}
}
((VOID (STDCALL*)(PVOID))(Prcb->SignalDone->WorkerRoutine))(Prcb->SignalDone->CurrentPacket[0]);
Ke386TestAndClearBit(KeGetCurrentProcessorNumber(), &Prcb->SignalDone->TargetSet);
Ke386TestAndClearBit(KeGetCurrentProcessorNumber(), (PLONG)&Prcb->SignalDone->TargetSet);
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
{
#ifdef DBG
@ -140,7 +140,7 @@ KiIpiSendPacket(KAFFINITY TargetSet, VOID (STDCALL*WorkerRoutine)(PVOID), PVOID
{
Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
while(0 != InterlockedCompareExchangeUL(&Prcb->SignalDone, (LONG)CurrentPrcb, 0));
Ke386TestAndSetBit(IPI_SYNCH_REQUEST, &Prcb->IpiFrozen);
Ke386TestAndSetBit(IPI_SYNCH_REQUEST, (PLONG)&Prcb->IpiFrozen);
if (Processor != CurrentPrcb->SetMember)
{
HalRequestIpi(i);