Author: ion
Date: Sat Sep 2 20:19:00 2006
New Revision: 23886
URL:
http://svn.reactos.org/svn/reactos?rev=23886&view=rev
Log:
- 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!).
Modified:
trunk/reactos/include/ddk/winddk.h
trunk/reactos/include/ndk/i386/ketypes.h
trunk/reactos/include/ndk/ketypes.h
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/ke/dpc.c
trunk/reactos/ntoskrnl/ke/i386/kernel.c
trunk/reactos/ntoskrnl/ke/ipi.c
Modified: trunk/reactos/include/ddk/winddk.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=2…
==============================================================================
--- trunk/reactos/include/ddk/winddk.h (original)
+++ trunk/reactos/include/ddk/winddk.h Sat Sep 2 20:19:00 2006
@@ -1079,16 +1079,25 @@
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;
Modified: trunk/reactos/include/ndk/i386/ketypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/i386/ketypes.h…
==============================================================================
--- trunk/reactos/include/ndk/i386/ketypes.h (original)
+++ trunk/reactos/include/ndk/i386/ketypes.h Sat Sep 2 20:19:00 2006
@@ -421,9 +421,9 @@
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 @@
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 @@
#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 @@
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;
Modified: trunk/reactos/include/ndk/ketypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/ketypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/ketypes.h (original)
+++ trunk/reactos/include/ndk/ketypes.h Sat Sep 2 20:19:00 2006
@@ -487,7 +487,7 @@
{
LIST_ENTRY DpcListHead;
ULONG DpcLock;
- ULONG DpcQueueDepth;
+ volatile ULONG DpcQueueDepth;
ULONG DpcCount;
} KDPC_DATA, *PKDPC_DATA;
@@ -676,13 +676,13 @@
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 @@
UCHAR WaitReason;
UCHAR Priority;
UCHAR EnableStackSwap;
- UCHAR SwapBusy;
+ volatile UCHAR SwapBusy;
UCHAR Alerted[2];
union
{
@@ -903,7 +903,7 @@
UCHAR Iopl;
UCHAR Unused;
#endif
- ULONG ActiveProcessors;
+ volatile ULONG ActiveProcessors;
ULONG KernelTime;
ULONG UserTime;
LIST_ENTRY ReadyListHead;
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h Sat Sep 2 20:19:00 2006
@@ -113,6 +113,9 @@
extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
extern LIST_ENTRY KiStackInSwapListHead;
extern KEVENT KiSwapEvent;
+extern PKPRCB KiProcessorBlock[];
+extern ULONG KiMask32Array[MAXIMUM_PRIORITY];
+extern ULONG IdleProcessorMask;
/* MACROS *************************************************************************/
Modified: trunk/reactos/ntoskrnl/ke/dpc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=2388…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/dpc.c (original)
+++ trunk/reactos/ntoskrnl/ke/dpc.c Sat Sep 2 20:19:00 2006
@@ -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(a)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(a)reactos.org)
* Philip Susi (phreak(a)iag.net)
* Eric Kohl (ekohl(a)abo.rhein-zeitung.de)
- * Alex Ionescu (alex(a)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>
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, KeInitDpc)
-#endif
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
ULONG KiMaximumDpcQueueDepth = 4;
ULONG KiMinimumDpcRate = 3;
@@ -31,32 +24,17 @@
ULONG KiIdealDpcRate = 20;
KMUTEX KiGenericCallDpcMutex;
-/* TYPES *******************************************************************/
-
-#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.
- */
-{
- DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc,
DeferredRoutine);
- Dpc->Type = ThreadedDpcObject;
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+KiInitializeDpc(IN PKDPC Dpc,
+ IN PKDEFERRED_ROUTINE DeferredRoutine,
+ IN PVOID DeferredContext,
+ IN KOBJECTS Type)
+{
+ /* Setup the DPC Object */
+ Dpc->Type = Type;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
@@ -64,275 +42,236 @@
Dpc->DpcData = NULL;
}
-/*
- * @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)
-{
- 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;
-}
-
-/*
- * @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.
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeInitializeThreadedDpc(IN PKDPC Dpc,
+ IN PKDEFERRED_ROUTINE DeferredRoutine,
+ IN PVOID DeferredContext)
+{
+ /* 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
*/
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;
- }
-
-#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();
- }
-
- KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
-#else
- Prcb = ((PKPCR)KPCR_BASE)->Prcb;
-#endif
+ /* 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;
+ }
+
+ /* 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];
+ }
+
+ /* Acquire the DPC lock */
+ KiAcquireSpinLock(&DpcData->DpcLock);
/* Get the DPC Data */
- if (InterlockedCompareExchangeUL(&Dpc->DpcData,
&Prcb->DpcData[0].DpcLock, 0)) {
-
- DPRINT("DPC Already Inserted\n");
-#ifdef CONFIG_SMP
- KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
-#endif
- KeLowerIrql(OldIrql);
- return(FALSE);
- }
-
- /* Make sure the lists are free if the Queue is 0 */
- if (Prcb->DpcData[0].DpcQueueDepth == 0) {
-
- 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);
+ 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;
+
+ /* 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);
+ }
+
+ /* 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;
+
+ /* 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;
+
+ /* Set DPC inserted */
+ DpcInserted = 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;
- }
- }
-#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");
+ }
+ }
+
+ /* 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);
- Prcb->DpcInterruptRequested = TRUE;
- }
-#endif
- }
-#ifdef CONFIG_SMP
- KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
-#endif
+ }
+ }
+
/* Lower IRQL */
KeLowerIrql(OldIrql);
- return(TRUE);
-}
-
-/*
- * @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
+ return DpcConfigured;
+}
+
+/*
+ * @implemented
*/
BOOLEAN
-STDCALL
-KeRemoveQueueDpc(PKDPC Dpc)
-{
- BOOLEAN WasInQueue;
- KIRQL OldIrql;
-
- /* Raise IRQL */
- DPRINT("Removing DPC: %x\n", Dpc);
- KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-#ifdef CONFIG_SMP
- KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
-#endif
-
- /* First make sure the DPC lock isn't being held */
- WasInQueue = Dpc->DpcData ? TRUE : FALSE;
- if (Dpc->DpcData) {
-
- /* Remove the DPC */
- ((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
- RemoveEntryList(&Dpc->DpcListEntry);
-
- }
-#ifdef CONFIG_SMP
- KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
-#endif
+NTAPI
+KeRemoveQueueDpc(IN PKDPC Dpc)
+{
+ PKDPC_DATA DpcData;
+ UCHAR DpcType;
+ ASSERT_DPC(Dpc);
+
+ /* Disable interrupts */
+ Ke386DisableInterrupts();
+
+ /* Get DPC data and type */
+ DpcType = Dpc->Type;
+ DpcData = Dpc->DpcData;
+ if (DpcData)
+ {
+ /* Acquire the DPC lock */
+ KiAcquireSpinLock(&DpcData->DpcLock);
+
+ /* 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);
+ }
+
+ /* Re-enable interrupts */
+ Ke386EnableInterrupts();
/* Return if the DPC was in the queue or not */
- KeLowerIrql(OldIrql);
- return WasInQueue;
-}
-
-/*
- * @implemented
- */
-VOID
-STDCALL
+ return DpcData ? TRUE : FALSE;
+}
+
+/*
+ * @implemented
+ */
+VOID
+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 @@
* @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
+ * @implemented
+ */
+VOID
+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
+ */
+VOID
+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;
}
/*
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kernel.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/kernel.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/kernel.c Sat Sep 2 20:19:00 2006
@@ -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 @@
}
/* 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 @@
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
- for (i = LockQueueTimerTableLock; i < LockQueueMaximumLock; i++)
- {
- KeInitializeSpinLock(&KiTimerTableLock[i - 16]);
+
+ /* Loop timer locks */
+ for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
+ {
+ /* 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 @@
/* 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;
Modified: trunk/reactos/ntoskrnl/ke/ipi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/ipi.c?rev=2388…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/ipi.c (original)
+++ trunk/reactos/ntoskrnl/ke/ipi.c Sat Sep 2 20:19:00 2006
@@ -33,7 +33,7 @@
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 @@
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 @@
}
}
((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 @@
{
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);