[ros-diffs] [ion] 23886: - 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!).

ion at svn.reactos.org ion at svn.reactos.org
Sat Sep 2 18:19:01 CEST 2006


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=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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?rev=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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/ke.h?rev=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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 at 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 at reactos.org)
  *                  Philip Susi (phreak at iag.net)
  *                  Eric Kohl (ekohl at abo.rhein-zeitung.de)
- *                  Alex Ionescu (alex at 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?rev=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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=23886&r1=23885&r2=23886&view=diff
==============================================================================
--- 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);




More information about the Ros-diffs mailing list