mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 07:56:59 +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;
|
KIRQL OldIrql;
|
||||||
} KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE;
|
} KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE;
|
||||||
|
|
||||||
typedef struct _KDPC {
|
#define DPC_NORMAL 0
|
||||||
CSHORT Type;
|
#define DPC_THREADED 1
|
||||||
UCHAR Number;
|
|
||||||
UCHAR Importance;
|
#define ASSERT_DPC(Object) \
|
||||||
LIST_ENTRY DpcListEntry;
|
ASSERT(((Object)->Type == 0) || \
|
||||||
PKDEFERRED_ROUTINE DeferredRoutine;
|
((Object)->Type == DpcObject) || \
|
||||||
PVOID DeferredContext;
|
((Object)->Type == ThreadedDpcObject))
|
||||||
PVOID SystemArgument1;
|
|
||||||
PVOID SystemArgument2;
|
typedef struct _KDPC
|
||||||
PVOID DpcData;
|
{
|
||||||
|
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;
|
} KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC;
|
||||||
|
|
||||||
typedef PVOID PKIPI_CONTEXT;
|
typedef PVOID PKIPI_CONTEXT;
|
||||||
|
|
|
@ -421,9 +421,9 @@ typedef struct _KPRCB
|
||||||
ULONG KeSecondLevelTbFills;
|
ULONG KeSecondLevelTbFills;
|
||||||
ULONG KeSystemCalls;
|
ULONG KeSystemCalls;
|
||||||
#endif
|
#endif
|
||||||
ULONG IoReadOperationCount;
|
volatile ULONG IoReadOperationCount;
|
||||||
ULONG IoWriteOperationCount;
|
volatile ULONG IoWriteOperationCount;
|
||||||
ULONG IoOtherOperationCount;
|
volatile ULONG IoOtherOperationCount;
|
||||||
LARGE_INTEGER IoReadTransferCount;
|
LARGE_INTEGER IoReadTransferCount;
|
||||||
LARGE_INTEGER IoWriteTransferCount;
|
LARGE_INTEGER IoWriteTransferCount;
|
||||||
LARGE_INTEGER IoOtherTransferCount;
|
LARGE_INTEGER IoOtherTransferCount;
|
||||||
|
@ -464,37 +464,37 @@ typedef struct _KPRCB
|
||||||
PP_LOOKASIDE_LIST PPLookasideList[16];
|
PP_LOOKASIDE_LIST PPLookasideList[16];
|
||||||
PP_LOOKASIDE_LIST PPNPagedLookasideList[32];
|
PP_LOOKASIDE_LIST PPNPagedLookasideList[32];
|
||||||
PP_LOOKASIDE_LIST PPPagedLookasideList[32];
|
PP_LOOKASIDE_LIST PPPagedLookasideList[32];
|
||||||
ULONG PacketBarrier;
|
volatile ULONG PacketBarrier;
|
||||||
ULONG ReverseStall;
|
volatile ULONG ReverseStall;
|
||||||
PVOID IpiFrame;
|
PVOID IpiFrame;
|
||||||
UCHAR PrcbPad2[52];
|
UCHAR PrcbPad2[52];
|
||||||
PVOID CurrentPacket[3];
|
volatile PVOID CurrentPacket[3];
|
||||||
ULONG TargetSet;
|
volatile ULONG TargetSet;
|
||||||
PKIPI_WORKER WorkerRoutine;
|
volatile PKIPI_WORKER WorkerRoutine;
|
||||||
ULONG IpiFrozen;
|
volatile ULONG IpiFrozen;
|
||||||
UCHAR PrcbPad3[40];
|
UCHAR PrcbPad3[40];
|
||||||
ULONG RequestSummary;
|
volatile ULONG RequestSummary;
|
||||||
struct _KPRCB *SignalDone;
|
volatile struct _KPRCB *SignalDone;
|
||||||
UCHAR PrcbPad4[56];
|
UCHAR PrcbPad4[56];
|
||||||
struct _KDPC_DATA DpcData[2];
|
struct _KDPC_DATA DpcData[2];
|
||||||
PVOID DpcStack;
|
PVOID DpcStack;
|
||||||
ULONG MaximumDpcQueueDepth;
|
ULONG MaximumDpcQueueDepth;
|
||||||
ULONG DpcRequestRate;
|
ULONG DpcRequestRate;
|
||||||
ULONG MinimumDpcRate;
|
ULONG MinimumDpcRate;
|
||||||
UCHAR DpcInterruptRequested;
|
volatile UCHAR DpcInterruptRequested;
|
||||||
UCHAR DpcThreadRequested;
|
volatile UCHAR DpcThreadRequested;
|
||||||
UCHAR DpcRoutineActive;
|
volatile UCHAR DpcRoutineActive;
|
||||||
UCHAR DpcThreadActive;
|
volatile UCHAR DpcThreadActive;
|
||||||
ULONG PrcbLock;
|
ULONG PrcbLock;
|
||||||
ULONG DpcLastCount;
|
ULONG DpcLastCount;
|
||||||
ULONG TimerHand;
|
volatile ULONG TimerHand;
|
||||||
ULONG TimerRequest;
|
volatile ULONG TimerRequest;
|
||||||
PVOID DpcThread;
|
PVOID DpcThread;
|
||||||
KEVENT DpcEvent;
|
KEVENT DpcEvent;
|
||||||
UCHAR ThreadDpcEnable;
|
UCHAR ThreadDpcEnable;
|
||||||
BOOLEAN QuantumEnd;
|
volatile BOOLEAN QuantumEnd;
|
||||||
UCHAR PrcbPad50;
|
UCHAR PrcbPad50;
|
||||||
UCHAR IdleSchedule;
|
volatile UCHAR IdleSchedule;
|
||||||
LONG DpcSetEventRequest;
|
LONG DpcSetEventRequest;
|
||||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||||
LONG Sleeping;
|
LONG Sleeping;
|
||||||
|
@ -535,19 +535,19 @@ typedef struct _KPRCB
|
||||||
#endif
|
#endif
|
||||||
PVOID ChainedInterruptList;
|
PVOID ChainedInterruptList;
|
||||||
LONG LookasideIrpFloat;
|
LONG LookasideIrpFloat;
|
||||||
LONG MmPageFaultCount;
|
volatile LONG MmPageFaultCount;
|
||||||
LONG MmCopyOnWriteCount;
|
volatile LONG MmCopyOnWriteCount;
|
||||||
LONG MmTransitionCount;
|
volatile LONG MmTransitionCount;
|
||||||
LONG MmCacheTransitionCount;
|
volatile LONG MmCacheTransitionCount;
|
||||||
LONG MmDemandZeroCount;
|
volatile LONG MmDemandZeroCount;
|
||||||
LONG MmPageReadCount;
|
volatile LONG MmPageReadCount;
|
||||||
LONG MmPageReadIoCount;
|
volatile LONG MmPageReadIoCount;
|
||||||
LONG MmCacheReadCount;
|
volatile LONG MmCacheReadCount;
|
||||||
LONG MmCacheIoCount;
|
volatile LONG MmCacheIoCount;
|
||||||
LONG MmDirtyPagesWriteCount;
|
volatile LONG MmDirtyPagesWriteCount;
|
||||||
LONG MmDirtyWriteIoCount;
|
volatile LONG MmDirtyWriteIoCount;
|
||||||
LONG MmMappedPagesWriteCount;
|
volatile LONG MmMappedPagesWriteCount;
|
||||||
LONG MmMappedWriteIoCount;
|
volatile LONG MmMappedWriteIoCount;
|
||||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||||
ULONG CachedCommit;
|
ULONG CachedCommit;
|
||||||
ULONG CachedResidentAvailable;
|
ULONG CachedResidentAvailable;
|
||||||
|
@ -563,7 +563,7 @@ typedef struct _KPRCB
|
||||||
ULONG MHz;
|
ULONG MHz;
|
||||||
ULONG FeatureBits;
|
ULONG FeatureBits;
|
||||||
LARGE_INTEGER UpdateSignature;
|
LARGE_INTEGER UpdateSignature;
|
||||||
LARGE_INTEGER IsrTime;
|
volatile LARGE_INTEGER IsrTime;
|
||||||
LARGE_INTEGER SpareField1;
|
LARGE_INTEGER SpareField1;
|
||||||
FX_SAVE_AREA NpxSaveArea;
|
FX_SAVE_AREA NpxSaveArea;
|
||||||
PROCESSOR_POWER_STATE PowerState;
|
PROCESSOR_POWER_STATE PowerState;
|
||||||
|
|
|
@ -487,7 +487,7 @@ typedef struct _KDPC_DATA
|
||||||
{
|
{
|
||||||
LIST_ENTRY DpcListHead;
|
LIST_ENTRY DpcListHead;
|
||||||
ULONG DpcLock;
|
ULONG DpcLock;
|
||||||
ULONG DpcQueueDepth;
|
volatile ULONG DpcQueueDepth;
|
||||||
ULONG DpcCount;
|
ULONG DpcCount;
|
||||||
} KDPC_DATA, *PKDPC_DATA;
|
} KDPC_DATA, *PKDPC_DATA;
|
||||||
|
|
||||||
|
@ -676,13 +676,13 @@ typedef struct _KTHREAD
|
||||||
UCHAR ApcQueueable;
|
UCHAR ApcQueueable;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
UCHAR NextProcessor;
|
volatile UCHAR NextProcessor;
|
||||||
UCHAR DeferredProcessor;
|
volatile UCHAR DeferredProcessor;
|
||||||
UCHAR AdjustReason;
|
UCHAR AdjustReason;
|
||||||
UCHAR AdjustIncrement;
|
UCHAR AdjustIncrement;
|
||||||
KSPIN_LOCK ApcQueueLock;
|
KSPIN_LOCK ApcQueueLock;
|
||||||
ULONG ContextSwitches;
|
ULONG ContextSwitches;
|
||||||
UCHAR State;
|
volatile UCHAR State;
|
||||||
UCHAR NpxState;
|
UCHAR NpxState;
|
||||||
UCHAR WaitIrql;
|
UCHAR WaitIrql;
|
||||||
UCHAR WaitMode;
|
UCHAR WaitMode;
|
||||||
|
@ -697,7 +697,7 @@ typedef struct _KTHREAD
|
||||||
UCHAR WaitReason;
|
UCHAR WaitReason;
|
||||||
UCHAR Priority;
|
UCHAR Priority;
|
||||||
UCHAR EnableStackSwap;
|
UCHAR EnableStackSwap;
|
||||||
UCHAR SwapBusy;
|
volatile UCHAR SwapBusy;
|
||||||
UCHAR Alerted[2];
|
UCHAR Alerted[2];
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -903,7 +903,7 @@ typedef struct _KPROCESS
|
||||||
UCHAR Iopl;
|
UCHAR Iopl;
|
||||||
UCHAR Unused;
|
UCHAR Unused;
|
||||||
#endif
|
#endif
|
||||||
ULONG ActiveProcessors;
|
volatile ULONG ActiveProcessors;
|
||||||
ULONG KernelTime;
|
ULONG KernelTime;
|
||||||
ULONG UserTime;
|
ULONG UserTime;
|
||||||
LIST_ENTRY ReadyListHead;
|
LIST_ENTRY ReadyListHead;
|
||||||
|
|
|
@ -113,6 +113,9 @@ extern KSPIN_LOCK KiProfileLock;
|
||||||
extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
|
extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
|
||||||
extern LIST_ENTRY KiStackInSwapListHead;
|
extern LIST_ENTRY KiStackInSwapListHead;
|
||||||
extern KEVENT KiSwapEvent;
|
extern KEVENT KiSwapEvent;
|
||||||
|
extern PKPRCB KiProcessorBlock[];
|
||||||
|
extern ULONG KiMask32Array[MAXIMUM_PRIORITY];
|
||||||
|
extern ULONG IdleProcessorMask;
|
||||||
|
|
||||||
/* MACROS *************************************************************************/
|
/* MACROS *************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
* PROJECT: ReactOS Kernel
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* FILE: ntoskrnl/ke/i386/cpu.c
|
||||||
* FILE: ntoskrnl/ke/dpc.c
|
* PURPOSE: Routines for CPU-level support
|
||||||
* PURPOSE: Handle DPCs (Delayed Procedure Calls)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*
|
|
||||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
|
||||||
* Philip Susi (phreak@iag.net)
|
* Philip Susi (phreak@iag.net)
|
||||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||||
* Alex Ionescu (alex@relsoft.net)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* INCLUDES ******************************************************************/
|
||||||
* NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ***************************************************************/
|
#define NTDDI_VERSION NTDDI_WS03
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#if defined (ALLOC_PRAGMA)
|
/* GLOBALS *******************************************************************/
|
||||||
#pragma alloc_text(INIT, KeInitDpc)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ULONG KiMaximumDpcQueueDepth = 4;
|
ULONG KiMaximumDpcQueueDepth = 4;
|
||||||
ULONG KiMinimumDpcRate = 3;
|
ULONG KiMinimumDpcRate = 3;
|
||||||
|
@ -31,32 +24,17 @@ ULONG KiAdjustDpcThreshold = 20;
|
||||||
ULONG KiIdealDpcRate = 20;
|
ULONG KiIdealDpcRate = 20;
|
||||||
KMUTEX KiGenericCallDpcMutex;
|
KMUTEX KiGenericCallDpcMutex;
|
||||||
|
|
||||||
/* TYPES *******************************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
#define MAX_QUANTUM 0x7F
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInitializeThreadedDpc(PKDPC Dpc,
|
KiInitializeDpc(IN PKDPC Dpc,
|
||||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
||||||
PVOID DeferredContext)
|
IN PVOID DeferredContext,
|
||||||
/*
|
IN KOBJECTS Type)
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
/* Setup the DPC Object */
|
||||||
Dpc->Type = ThreadedDpcObject;
|
Dpc->Type = Type;
|
||||||
Dpc->Number= 0;
|
Dpc->Number= 0;
|
||||||
Dpc->Importance= MediumImportance;
|
Dpc->Importance= MediumImportance;
|
||||||
Dpc->DeferredRoutine = DeferredRoutine;
|
Dpc->DeferredRoutine = DeferredRoutine;
|
||||||
|
@ -64,275 +42,236 @@ KeInitializeThreadedDpc(PKDPC Dpc,
|
||||||
Dpc->DpcData = NULL;
|
Dpc->DpcData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @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
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInitializeDpc(PKDPC Dpc,
|
KeInitializeThreadedDpc(IN PKDPC Dpc,
|
||||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
||||||
PVOID DeferredContext)
|
IN PVOID DeferredContext)
|
||||||
{
|
{
|
||||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
/* Call the internal routine */
|
||||||
Dpc->Type = DpcObject;
|
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, ThreadedDpcObject);
|
||||||
Dpc->Number= 0;
|
}
|
||||||
Dpc->Importance= MediumImportance;
|
|
||||||
Dpc->DeferredRoutine = DeferredRoutine;
|
/*
|
||||||
Dpc->DeferredContext = DeferredContext;
|
* @implemented
|
||||||
Dpc->DpcData = NULL;
|
*/
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
KeInitializeDpc(IN PKDPC Dpc,
|
||||||
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
||||||
|
IN PVOID DeferredContext)
|
||||||
|
{
|
||||||
|
/* Call the internal routine */
|
||||||
|
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @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
|
BOOLEAN
|
||||||
STDCALL
|
NTAPI
|
||||||
KeInsertQueueDpc(PKDPC Dpc,
|
KeInsertQueueDpc(IN PKDPC Dpc,
|
||||||
PVOID SystemArgument1,
|
IN PVOID SystemArgument1,
|
||||||
PVOID SystemArgument2)
|
IN PVOID SystemArgument2)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKPRCB Prcb;
|
PKPRCB Prcb, CurrentPrcb = KeGetCurrentPrcb();
|
||||||
|
ULONG Cpu;
|
||||||
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
PKDPC_DATA DpcData;
|
||||||
Dpc, SystemArgument1, SystemArgument2);
|
BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
|
||||||
|
ASSERT_DPC(Dpc);
|
||||||
|
|
||||||
/* Check IRQL and Raise it to HIGH_LEVEL */
|
/* Check IRQL and Raise it to HIGH_LEVEL */
|
||||||
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
/* Check if this is a Thread DPC, which we don't support (yet) */
|
/* Check if the DPC has more then the maximum number of CPUs */
|
||||||
if (Dpc->Type == ThreadedDpcObject) {
|
if (Dpc->Number >= MAXIMUM_PROCESSORS)
|
||||||
KeLowerIrql(OldIrql);
|
{
|
||||||
return FALSE;
|
/* 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
|
/* Check if this is a threaded DPC and threaded DPCs are enabled */
|
||||||
/* Get the right PCR for this CPU */
|
if ((Dpc->Type = ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
|
||||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
{
|
||||||
|
/* Then use the threaded data */
|
||||||
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
|
DpcData = &Prcb->DpcData[DPC_THREADED];
|
||||||
Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + ((Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE)))->Prcb;
|
}
|
||||||
|
else
|
||||||
} else {
|
{
|
||||||
|
/* Otherwise, use the regular data */
|
||||||
ASSERT (Dpc->Number < KeNumberProcessors);
|
DpcData = &Prcb->DpcData[DPC_NORMAL];
|
||||||
Prcb = KeGetCurrentPrcb();
|
|
||||||
Dpc->Number = KeGetCurrentProcessorNumber();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
/* Acquire the DPC lock */
|
||||||
#else
|
KiAcquireSpinLock(&DpcData->DpcLock);
|
||||||
Prcb = ((PKPCR)KPCR_BASE)->Prcb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get the DPC Data */
|
/* 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");
|
/* Check if this is a high importance DPC */
|
||||||
#ifdef CONFIG_SMP
|
if (Dpc->Importance == HighImportance)
|
||||||
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
{
|
||||||
#endif
|
/* Pre-empty other DPCs */
|
||||||
KeLowerIrql(OldIrql);
|
InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
|
||||||
return(FALSE);
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
/* Add it at the end */
|
||||||
|
InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure the lists are free if the Queue is 0 */
|
/* Check if this is the DPC on the threaded list */
|
||||||
if (Prcb->DpcData[0].DpcQueueDepth == 0) {
|
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));
|
/* Set DPC inserted */
|
||||||
} else {
|
DpcInserted = TRUE;
|
||||||
|
}
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
}
|
/* Set DPC inserted */
|
||||||
} else {
|
DpcInserted = TRUE;
|
||||||
|
}
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#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);
|
/* Release the lock */
|
||||||
#endif
|
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 */
|
/* Lower IRQL */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
return(TRUE);
|
return DpcConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @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
|
BOOLEAN
|
||||||
STDCALL
|
NTAPI
|
||||||
KeRemoveQueueDpc(PKDPC Dpc)
|
KeRemoveQueueDpc(IN PKDPC Dpc)
|
||||||
{
|
{
|
||||||
BOOLEAN WasInQueue;
|
PKDPC_DATA DpcData;
|
||||||
KIRQL OldIrql;
|
UCHAR DpcType;
|
||||||
|
ASSERT_DPC(Dpc);
|
||||||
|
|
||||||
/* Raise IRQL */
|
/* Disable interrupts */
|
||||||
DPRINT("Removing DPC: %x\n", Dpc);
|
Ke386DisableInterrupts();
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* First make sure the DPC lock isn't being held */
|
/* Get DPC data and type */
|
||||||
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
DpcType = Dpc->Type;
|
||||||
if (Dpc->DpcData) {
|
DpcData = Dpc->DpcData;
|
||||||
|
if (DpcData)
|
||||||
|
{
|
||||||
|
/* Acquire the DPC lock */
|
||||||
|
KiAcquireSpinLock(&DpcData->DpcLock);
|
||||||
|
|
||||||
/* Remove the DPC */
|
/* Make sure that the data didn't change */
|
||||||
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
|
if (DpcData == Dpc->DpcData)
|
||||||
RemoveEntryList(&Dpc->DpcListEntry);
|
{
|
||||||
|
/* 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);
|
/* Re-enable interrupts */
|
||||||
#endif
|
Ke386EnableInterrupts();
|
||||||
|
|
||||||
/* Return if the DPC was in the queue or not */
|
/* Return if the DPC was in the queue or not */
|
||||||
KeLowerIrql(OldIrql);
|
return DpcData ? TRUE : FALSE;
|
||||||
return WasInQueue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeFlushQueuedDpcs(VOID)
|
KeFlushQueuedDpcs(VOID)
|
||||||
/*
|
|
||||||
* FUNCTION:
|
|
||||||
* Called to Deliver DPCs if any are pending.
|
|
||||||
* NOTES:
|
|
||||||
* Called when deleting a Driver.
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Request an interrupt if needed */
|
/* Request an interrupt if needed */
|
||||||
|
DPRINT1("%s - FIXME!!!\n", __FUNCTION__);
|
||||||
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,59 +279,37 @@ KeFlushQueuedDpcs(VOID)
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
NTAPI
|
||||||
KeIsExecutingDpc(
|
KeIsExecutingDpc(VOID)
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/* Return if the Dpc Routine is active */
|
/* Return if the Dpc Routine is active */
|
||||||
return KeGetCurrentPrcb()->DpcRoutineActive;
|
return KeGetCurrentPrcb()->DpcRoutineActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Specifies the DPCs importance
|
|
||||||
* ARGUMENTS:
|
|
||||||
* Dpc = Initalizes DPC
|
|
||||||
* Importance = DPC importance
|
|
||||||
* RETURNS: None
|
|
||||||
*
|
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeSetImportanceDpc (IN PKDPC Dpc,
|
KeSetImportanceDpc (IN PKDPC Dpc,
|
||||||
IN KDPC_IMPORTANCE Importance)
|
IN KDPC_IMPORTANCE Importance)
|
||||||
{
|
{
|
||||||
/* Set the DPC Importance */
|
/* Set the DPC Importance */
|
||||||
|
ASSERT_DPC(Dpc);
|
||||||
Dpc->Importance = Importance;
|
Dpc->Importance = Importance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*
|
|
||||||
* FUNCTION: Specifies on which processor the DPC will run
|
|
||||||
* ARGUMENTS:
|
|
||||||
* Dpc = Initalizes DPC
|
|
||||||
* Number = Processor number
|
|
||||||
* RETURNS: None
|
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeSetTargetProcessorDpc(IN PKDPC Dpc,
|
KeSetTargetProcessorDpc(IN PKDPC Dpc,
|
||||||
IN CCHAR Number)
|
IN CCHAR Number)
|
||||||
{
|
{
|
||||||
/* Check how many CPUs are on the system */
|
/* Set a target CPU */
|
||||||
if (Number >= MAXIMUM_PROCESSORS) {
|
ASSERT_DPC(Dpc);
|
||||||
|
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
||||||
/* No CPU Number */
|
|
||||||
Dpc->Number = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Set the Number Specified */
|
|
||||||
ASSERT(Number < KeNumberProcessors);
|
|
||||||
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
|
||||||
KNODE KiNode0;
|
KNODE KiNode0;
|
||||||
PKNODE KeNodeBlock[1];
|
PKNODE KeNodeBlock[1];
|
||||||
UCHAR KeNumberNodes = 1;
|
UCHAR KeNumberNodes = 1;
|
||||||
UCHAR KeProcessNodeSeed;
|
UCHAR KeProcessNodeSeed;
|
||||||
PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
|
|
||||||
ETHREAD KiInitialThread;
|
ETHREAD KiInitialThread;
|
||||||
EPROCESS KiInitialProcess;
|
EPROCESS KiInitialProcess;
|
||||||
|
|
||||||
|
@ -195,10 +195,10 @@ KiInitSpinLocks(IN PKPRCB Prcb,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize DPC Fields */
|
/* Initialize DPC Fields */
|
||||||
InitializeListHead(&Prcb->DpcData[0].DpcListHead);
|
InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
|
||||||
KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
|
KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
|
||||||
Prcb->DpcData[0].DpcQueueDepth = 0;
|
Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
|
||||||
Prcb->DpcData[0].DpcCount = 0;
|
Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
|
||||||
Prcb->DpcRoutineActive = FALSE;
|
Prcb->DpcRoutineActive = FALSE;
|
||||||
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
||||||
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
||||||
|
@ -245,11 +245,14 @@ KiInitSpinLocks(IN PKPRCB Prcb,
|
||||||
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
|
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
|
||||||
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
|
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
|
||||||
Prcb->LockQueue[LockQueueUnusedSpare16].Lock = 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].Next = NULL;
|
||||||
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i - 16];
|
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is the boot CPU */
|
/* Check if this is the boot CPU */
|
||||||
|
@ -297,7 +300,7 @@ KiInitializePcr(IN ULONG ProcessorNumber,
|
||||||
|
|
||||||
/* Set pointers to ourselves */
|
/* Set pointers to ourselves */
|
||||||
Pcr->Self = (PKPCR)Pcr;
|
Pcr->Self = (PKPCR)Pcr;
|
||||||
Pcr->Prcb = &(Pcr->PrcbData);
|
Pcr->Prcb = &Pcr->PrcbData;
|
||||||
|
|
||||||
/* Set the PCR Version */
|
/* Set the PCR Version */
|
||||||
Pcr->MajorVersion = PCR_MAJOR_VERSION;
|
Pcr->MajorVersion = PCR_MAJOR_VERSION;
|
||||||
|
|
|
@ -33,7 +33,7 @@ KiIpiSendRequest(KAFFINITY TargetSet, ULONG IpiRequest)
|
||||||
if (TargetSet & Current)
|
if (TargetSet & Current)
|
||||||
{
|
{
|
||||||
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
||||||
Ke386TestAndSetBit(IpiRequest, &Pcr->Prcb->IpiFrozen);
|
Ke386TestAndSetBit(IpiRequest, (PLONG)&Pcr->Prcb->IpiFrozen);
|
||||||
HalRequestIpi(i);
|
HalRequestIpi(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,18 +59,18 @@ KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
|
||||||
Prcb = KeGetCurrentPrcb();
|
Prcb = KeGetCurrentPrcb();
|
||||||
|
|
||||||
if (Ke386TestAndClearBit(IPI_APC, &Prcb->IpiFrozen))
|
if (Ke386TestAndClearBit(IPI_APC, (PLONG)&Prcb->IpiFrozen))
|
||||||
{
|
{
|
||||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ke386TestAndClearBit(IPI_DPC, &Prcb->IpiFrozen))
|
if (Ke386TestAndClearBit(IPI_DPC, (PLONG)&Prcb->IpiFrozen))
|
||||||
{
|
{
|
||||||
Prcb->DpcInterruptRequested = TRUE;
|
Prcb->DpcInterruptRequested = TRUE;
|
||||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, &Prcb->IpiFrozen))
|
if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, (PLONG)&Prcb->IpiFrozen))
|
||||||
{
|
{
|
||||||
(void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]);
|
(void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]);
|
||||||
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
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]);
|
((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))
|
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
||||||
{
|
{
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
|
@ -140,7 +140,7 @@ KiIpiSendPacket(KAFFINITY TargetSet, VOID (STDCALL*WorkerRoutine)(PVOID), PVOID
|
||||||
{
|
{
|
||||||
Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
|
Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
|
||||||
while(0 != InterlockedCompareExchangeUL(&Prcb->SignalDone, (LONG)CurrentPrcb, 0));
|
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)
|
if (Processor != CurrentPrcb->SetMember)
|
||||||
{
|
{
|
||||||
HalRequestIpi(i);
|
HalRequestIpi(i);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue