mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 03:56:41 +00:00
- 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:
parent
ea0c0daec0
commit
38ca1d7d77
7 changed files with 280 additions and 348 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *************************************************************************/
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue