diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index ce1b6329482..4dffeee09a2 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -1079,16 +1079,25 @@ typedef struct _KLOCK_QUEUE_HANDLE { KIRQL OldIrql; } KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; -typedef struct _KDPC { - CSHORT Type; - UCHAR Number; - UCHAR Importance; - LIST_ENTRY DpcListEntry; - PKDEFERRED_ROUTINE DeferredRoutine; - PVOID DeferredContext; - PVOID SystemArgument1; - PVOID SystemArgument2; - PVOID DpcData; +#define DPC_NORMAL 0 +#define DPC_THREADED 1 + +#define ASSERT_DPC(Object) \ + ASSERT(((Object)->Type == 0) || \ + ((Object)->Type == DpcObject) || \ + ((Object)->Type == ThreadedDpcObject)) + +typedef struct _KDPC +{ + UCHAR Type; + UCHAR Importance; + USHORT Number; + LIST_ENTRY DpcListEntry; + PKDEFERRED_ROUTINE DeferredRoutine; + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + volatile PVOID DpcData; } KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC; typedef PVOID PKIPI_CONTEXT; diff --git a/reactos/include/ndk/i386/ketypes.h b/reactos/include/ndk/i386/ketypes.h index df4d7b47f18..b9e69261103 100644 --- a/reactos/include/ndk/i386/ketypes.h +++ b/reactos/include/ndk/i386/ketypes.h @@ -421,9 +421,9 @@ typedef struct _KPRCB ULONG KeSecondLevelTbFills; ULONG KeSystemCalls; #endif - ULONG IoReadOperationCount; - ULONG IoWriteOperationCount; - ULONG IoOtherOperationCount; + volatile ULONG IoReadOperationCount; + volatile ULONG IoWriteOperationCount; + volatile ULONG IoOtherOperationCount; LARGE_INTEGER IoReadTransferCount; LARGE_INTEGER IoWriteTransferCount; LARGE_INTEGER IoOtherTransferCount; @@ -464,37 +464,37 @@ typedef struct _KPRCB PP_LOOKASIDE_LIST PPLookasideList[16]; PP_LOOKASIDE_LIST PPNPagedLookasideList[32]; PP_LOOKASIDE_LIST PPPagedLookasideList[32]; - ULONG PacketBarrier; - ULONG ReverseStall; + volatile ULONG PacketBarrier; + volatile ULONG ReverseStall; PVOID IpiFrame; UCHAR PrcbPad2[52]; - PVOID CurrentPacket[3]; - ULONG TargetSet; - PKIPI_WORKER WorkerRoutine; - ULONG IpiFrozen; + volatile PVOID CurrentPacket[3]; + volatile ULONG TargetSet; + volatile PKIPI_WORKER WorkerRoutine; + volatile ULONG IpiFrozen; UCHAR PrcbPad3[40]; - ULONG RequestSummary; - struct _KPRCB *SignalDone; + volatile ULONG RequestSummary; + volatile struct _KPRCB *SignalDone; UCHAR PrcbPad4[56]; struct _KDPC_DATA DpcData[2]; PVOID DpcStack; ULONG MaximumDpcQueueDepth; ULONG DpcRequestRate; ULONG MinimumDpcRate; - UCHAR DpcInterruptRequested; - UCHAR DpcThreadRequested; - UCHAR DpcRoutineActive; - UCHAR DpcThreadActive; + volatile UCHAR DpcInterruptRequested; + volatile UCHAR DpcThreadRequested; + volatile UCHAR DpcRoutineActive; + volatile UCHAR DpcThreadActive; ULONG PrcbLock; ULONG DpcLastCount; - ULONG TimerHand; - ULONG TimerRequest; + volatile ULONG TimerHand; + volatile ULONG TimerRequest; PVOID DpcThread; KEVENT DpcEvent; UCHAR ThreadDpcEnable; - BOOLEAN QuantumEnd; + volatile BOOLEAN QuantumEnd; UCHAR PrcbPad50; - UCHAR IdleSchedule; + volatile UCHAR IdleSchedule; LONG DpcSetEventRequest; #if (NTDDI_VERSION >= NTDDI_LONGHORN) LONG Sleeping; @@ -535,19 +535,19 @@ typedef struct _KPRCB #endif PVOID ChainedInterruptList; LONG LookasideIrpFloat; - LONG MmPageFaultCount; - LONG MmCopyOnWriteCount; - LONG MmTransitionCount; - LONG MmCacheTransitionCount; - LONG MmDemandZeroCount; - LONG MmPageReadCount; - LONG MmPageReadIoCount; - LONG MmCacheReadCount; - LONG MmCacheIoCount; - LONG MmDirtyPagesWriteCount; - LONG MmDirtyWriteIoCount; - LONG MmMappedPagesWriteCount; - LONG MmMappedWriteIoCount; + volatile LONG MmPageFaultCount; + volatile LONG MmCopyOnWriteCount; + volatile LONG MmTransitionCount; + volatile LONG MmCacheTransitionCount; + volatile LONG MmDemandZeroCount; + volatile LONG MmPageReadCount; + volatile LONG MmPageReadIoCount; + volatile LONG MmCacheReadCount; + volatile LONG MmCacheIoCount; + volatile LONG MmDirtyPagesWriteCount; + volatile LONG MmDirtyWriteIoCount; + volatile LONG MmMappedPagesWriteCount; + volatile LONG MmMappedWriteIoCount; #if (NTDDI_VERSION >= NTDDI_LONGHORN) ULONG CachedCommit; ULONG CachedResidentAvailable; @@ -563,7 +563,7 @@ typedef struct _KPRCB ULONG MHz; ULONG FeatureBits; LARGE_INTEGER UpdateSignature; - LARGE_INTEGER IsrTime; + volatile LARGE_INTEGER IsrTime; LARGE_INTEGER SpareField1; FX_SAVE_AREA NpxSaveArea; PROCESSOR_POWER_STATE PowerState; diff --git a/reactos/include/ndk/ketypes.h b/reactos/include/ndk/ketypes.h index fc98ba91d6e..691b88a2e4f 100644 --- a/reactos/include/ndk/ketypes.h +++ b/reactos/include/ndk/ketypes.h @@ -487,7 +487,7 @@ typedef struct _KDPC_DATA { LIST_ENTRY DpcListHead; ULONG DpcLock; - ULONG DpcQueueDepth; + volatile ULONG DpcQueueDepth; ULONG DpcCount; } KDPC_DATA, *PKDPC_DATA; @@ -676,13 +676,13 @@ typedef struct _KTHREAD UCHAR ApcQueueable; }; }; - UCHAR NextProcessor; - UCHAR DeferredProcessor; + volatile UCHAR NextProcessor; + volatile UCHAR DeferredProcessor; UCHAR AdjustReason; UCHAR AdjustIncrement; KSPIN_LOCK ApcQueueLock; ULONG ContextSwitches; - UCHAR State; + volatile UCHAR State; UCHAR NpxState; UCHAR WaitIrql; UCHAR WaitMode; @@ -697,7 +697,7 @@ typedef struct _KTHREAD UCHAR WaitReason; UCHAR Priority; UCHAR EnableStackSwap; - UCHAR SwapBusy; + volatile UCHAR SwapBusy; UCHAR Alerted[2]; union { @@ -903,7 +903,7 @@ typedef struct _KPROCESS UCHAR Iopl; UCHAR Unused; #endif - ULONG ActiveProcessors; + volatile ULONG ActiveProcessors; ULONG KernelTime; ULONG UserTime; LIST_ENTRY ReadyListHead; diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index b92589660ee..66e455739e3 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -113,6 +113,9 @@ extern KSPIN_LOCK KiProfileLock; extern LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead; extern LIST_ENTRY KiStackInSwapListHead; extern KEVENT KiSwapEvent; +extern PKPRCB KiProcessorBlock[]; +extern ULONG KiMask32Array[MAXIMUM_PRIORITY]; +extern ULONG IdleProcessorMask; /* MACROS *************************************************************************/ diff --git a/reactos/ntoskrnl/ke/dpc.c b/reactos/ntoskrnl/ke/dpc.c index 615ccfa07fb..e893aec16ea 100644 --- a/reactos/ntoskrnl/ke/dpc.c +++ b/reactos/ntoskrnl/ke/dpc.c @@ -1,29 +1,22 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/dpc.c - * PURPOSE: Handle DPCs (Delayed Procedure Calls) - * - * PROGRAMMERS: David Welch (welch@mcmail.com) +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/cpu.c + * PURPOSE: Routines for CPU-level support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * Philip Susi (phreak@iag.net) * Eric Kohl (ekohl@abo.rhein-zeitung.de) - * Alex Ionescu (alex@relsoft.net) */ -/* - * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c - */ +/* INCLUDES ******************************************************************/ -/* INCLUDES ***************************************************************/ +#define NTDDI_VERSION NTDDI_WS03 #include #define NDEBUG -#include +#include -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, KeInitDpc) -#endif +/* GLOBALS *******************************************************************/ ULONG KiMaximumDpcQueueDepth = 4; ULONG KiMinimumDpcRate = 3; @@ -31,32 +24,17 @@ ULONG KiAdjustDpcThreshold = 20; ULONG KiIdealDpcRate = 20; KMUTEX KiGenericCallDpcMutex; -/* TYPES *******************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ -#define MAX_QUANTUM 0x7F - -/* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ VOID -STDCALL -KeInitializeThreadedDpc(PKDPC Dpc, - PKDEFERRED_ROUTINE DeferredRoutine, - PVOID DeferredContext) -/* - * FUNCTION: - * Initalizes a Threaded DPC and registers the DeferredRoutine for it. - * ARGUMENTS: - * Dpc = Pointer to a caller supplied DPC to be initialized. The caller must allocate this memory. - * DeferredRoutine = Pointer to associated DPC callback routine. - * DeferredContext = Parameter to be passed to the callback routine. - * NOTE: Callers can be running at any IRQL. - */ +NTAPI +KiInitializeDpc(IN PKDPC Dpc, + IN PKDEFERRED_ROUTINE DeferredRoutine, + IN PVOID DeferredContext, + IN KOBJECTS Type) { - DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine); - Dpc->Type = ThreadedDpcObject; + /* Setup the DPC Object */ + Dpc->Type = Type; Dpc->Number= 0; Dpc->Importance= MediumImportance; Dpc->DeferredRoutine = DeferredRoutine; @@ -64,275 +42,236 @@ KeInitializeThreadedDpc(PKDPC Dpc, Dpc->DpcData = NULL; } +/* PUBLIC FUNCTIONS **********************************************************/ + /* * @implemented - * - * FUNCTION: - * Initalizes a DPC and registers the DeferredRoutine for it. - * ARGUMENTS: - * Dpc = Pointer to a caller supplied DPC to be initialized. The caller must allocate this memory. - * DeferredRoutine = Pointer to associated DPC callback routine. - * DeferredContext = Parameter to be passed to the callback routine. - * NOTE: Callers can be running at any IRQL. */ VOID -STDCALL -KeInitializeDpc(PKDPC Dpc, - PKDEFERRED_ROUTINE DeferredRoutine, - PVOID DeferredContext) +NTAPI +KeInitializeThreadedDpc(IN PKDPC Dpc, + IN PKDEFERRED_ROUTINE DeferredRoutine, + IN PVOID DeferredContext) { - DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine); - Dpc->Type = DpcObject; - Dpc->Number= 0; - Dpc->Importance= MediumImportance; - Dpc->DeferredRoutine = DeferredRoutine; - Dpc->DeferredContext = DeferredContext; - Dpc->DpcData = NULL; + /* Call the internal routine */ + KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, ThreadedDpcObject); +} + +/* + * @implemented + */ +VOID +NTAPI +KeInitializeDpc(IN PKDPC Dpc, + IN PKDEFERRED_ROUTINE DeferredRoutine, + IN PVOID DeferredContext) +{ + /* Call the internal routine */ + KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject); } /* * @implemented - * - * FUNCTION: - * Queues a DPC for execution when the IRQL of a processor - * drops below DISPATCH_LEVEL - * ARGUMENTS: - * Dpc = Pointed to a DPC Object Initalized by KeInitializeDpc. - * SystemArgument1 = Driver Determined context data - * SystemArgument2 = Driver Determined context data - * RETURNS: - * TRUE if the DPC object wasn't already in the queue - * FALSE otherwise - * NOTES: - * If there is currently a DPC active on the target processor, or a DPC - * interrupt has already been requested on the target processor when a - * DPC is queued, then no further action is necessary. The DPC will be - * executed on the target processor when its queue entry is processed. - * - * If there is not a DPC active on the target processor and a DPC interrupt - * has not been requested on the target processor, then the exact treatment - * of the DPC is dependent on whether the host system is a UP system or an - * MP system. - * - * UP system. - * ---------- - * If the DPC is of medium or high importance, the current DPC queue depth - * is greater than the maximum target depth, or current DPC request rate is - * less the minimum target rate, then a DPC interrupt is requested on the - * host processor and the DPC will be processed when the interrupt occurs. - * Otherwise, no DPC interupt is requested and the DPC execution will be - * delayed until the DPC queue depth is greater that the target depth or the - * minimum DPC rate is less than the target rate. - * - * MP system. - * ---------- - * If the DPC is being queued to another processor and the depth of the DPC - * queue on the target processor is greater than the maximum target depth or - * the DPC is of high importance, then a DPC interrupt is requested on the - * target processor and the DPC will be processed when the interrupt occurs. - * Otherwise, the DPC execution will be delayed on the target processor until - * the DPC queue depth on the target processor is greater that the maximum - * target depth or the minimum DPC rate on the target processor is less than - * the target mimimum rate. - * - * If the DPC is being queued to the current processor and the DPC is not of - * low importance, the current DPC queue depth is greater than the maximum - * target depth, or the minimum DPC rate is less than the minimum target rate, - * then a DPC interrupt is request on the current processor and the DPV will - * be processed whne the interrupt occurs. Otherwise, no DPC interupt is - * requested and the DPC execution will be delayed until the DPC queue depth - * is greater that the target depth or the minimum DPC rate is less than the - * target rate. */ BOOLEAN -STDCALL -KeInsertQueueDpc(PKDPC Dpc, - PVOID SystemArgument1, - PVOID SystemArgument2) +NTAPI +KeInsertQueueDpc(IN PKDPC Dpc, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) { KIRQL OldIrql; - PKPRCB Prcb; - - DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n", - Dpc, SystemArgument1, SystemArgument2); + PKPRCB Prcb, CurrentPrcb = KeGetCurrentPrcb(); + ULONG Cpu; + PKDPC_DATA DpcData; + BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE; + ASSERT_DPC(Dpc); /* Check IRQL and Raise it to HIGH_LEVEL */ - ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL); KeRaiseIrql(HIGH_LEVEL, &OldIrql); - /* Check if this is a Thread DPC, which we don't support (yet) */ - if (Dpc->Type == ThreadedDpcObject) { - KeLowerIrql(OldIrql); - return FALSE; + /* Check if the DPC has more then the maximum number of CPUs */ + if (Dpc->Number >= MAXIMUM_PROCESSORS) + { + /* Then substract the maximum and get that PRCB. */ + Cpu = Dpc->Number - MAXIMUM_PROCESSORS; + Prcb = KiProcessorBlock[Cpu]; + } + else + { + /* Use the current one */ + Prcb = CurrentPrcb; + Cpu = Prcb->Number; } -#ifdef CONFIG_SMP - /* Get the right PCR for this CPU */ - if (Dpc->Number >= MAXIMUM_PROCESSORS) { - - ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors); - Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + ((Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE)))->Prcb; - - } else { - - ASSERT (Dpc->Number < KeNumberProcessors); - Prcb = KeGetCurrentPrcb(); - Dpc->Number = KeGetCurrentProcessorNumber(); + /* Check if this is a threaded DPC and threaded DPCs are enabled */ + if ((Dpc->Type = ThreadedDpcObject) && (Prcb->ThreadDpcEnable)) + { + /* Then use the threaded data */ + DpcData = &Prcb->DpcData[DPC_THREADED]; + } + else + { + /* Otherwise, use the regular data */ + DpcData = &Prcb->DpcData[DPC_NORMAL]; } - KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock); -#else - Prcb = ((PKPCR)KPCR_BASE)->Prcb; -#endif + /* Acquire the DPC lock */ + KiAcquireSpinLock(&DpcData->DpcLock); /* Get the DPC Data */ - if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Prcb->DpcData[0].DpcLock, 0)) { + if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL)) + { + /* Now we can play with the DPC safely */ + Dpc->SystemArgument1 = SystemArgument1; + Dpc->SystemArgument2 = SystemArgument2; + DpcData->DpcQueueDepth++; + DpcData->DpcCount++; + DpcConfigured = TRUE; - DPRINT("DPC Already Inserted\n"); -#ifdef CONFIG_SMP - KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock); -#endif - KeLowerIrql(OldIrql); - return(FALSE); - } + /* Check if this is a high importance DPC */ + if (Dpc->Importance == HighImportance) + { + /* Pre-empty other DPCs */ + InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry); + } + else + { + /* Add it at the end */ + InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry); + } - /* Make sure the lists are free if the Queue is 0 */ - if (Prcb->DpcData[0].DpcQueueDepth == 0) { + /* Check if this is the DPC on the threaded list */ + if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead) + { + /* Make sure a threaded DPC isn't already active */ + if (!(Prcb->DpcThreadActive) && (!Prcb->DpcThreadRequested)) + { + /* FIXME: Setup Threaded DPC */ + ASSERT(FALSE); + } + } + else + { + /* Make sure a DPC isn't executing already */ + if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) + { + /* Check if this is the same CPU */ + if (Prcb != CurrentPrcb) + { + /* + * Check if the DPC is of high importance or above the + * maximum depth. If it is, then make sure that the CPU + * isn't idle, or that it's sleeping. + */ + if (((Dpc->Importance == HighImportance) || + (DpcData->DpcQueueDepth >= + Prcb->MaximumDpcQueueDepth)) && + (!(AFFINITY_MASK(Cpu) & IdleProcessorMask) || + (Prcb->Sleeping))) + { + /* Set interrupt requested */ + Prcb->DpcInterruptRequested = TRUE; - ASSERT(IsListEmpty(&Prcb->DpcData[0].DpcListHead)); - } else { - - ASSERT(!IsListEmpty(&Prcb->DpcData[0].DpcListHead)); - } - - /* Now we can play with the DPC safely */ - Dpc->SystemArgument1=SystemArgument1; - Dpc->SystemArgument2=SystemArgument2; - Prcb->DpcData[0].DpcQueueDepth++; - Prcb->DpcData[0].DpcCount++; - - /* Insert the DPC into the list. HighImportance DPCs go at the beginning */ - if (Dpc->Importance == HighImportance) { - - InsertHeadList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry); - } else { - - InsertTailList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry); - } - DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink); - - /* Make sure a DPC isn't executing already and respect rules outlined above. */ - if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) { - -#ifdef CONFIG_SMP - /* Check if this is the same CPU */ - if (Prcb != KeGetCurrentPrcb()) { - - /* Send IPI if High Importance */ - if ((Dpc->Importance == HighImportance) || - (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth)) { - - if (Dpc->Number >= MAXIMUM_PROCESSORS) { - - KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_DPC); - } else { - - KiIpiSendRequest(1 << Dpc->Number, IPI_DPC); + /* Set DPC inserted */ + DpcInserted = TRUE; + } } + else + { + /* Check if the DPC is of anything but low importance */ + if ((Dpc->Importance != LowImportance) || + (DpcData->DpcQueueDepth >= + Prcb->MaximumDpcQueueDepth) || + (Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) + { + /* Set interrupt requested */ + Prcb->DpcInterruptRequested = TRUE; - } - } else { - - /* Request an Interrupt only if the DPC isn't low priority */ - if ((Dpc->Importance != LowImportance) || - (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) || - (Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) { - - /* Request Interrupt */ - HalRequestSoftwareInterrupt(DISPATCH_LEVEL); - Prcb->DpcInterruptRequested = TRUE; + /* Set DPC inserted */ + DpcInserted = TRUE; + } + } } } -#else - DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Prcb->DpcData[0].DpcQueueDepth, Prcb->MaximumDpcQueueDepth, Prcb->DpcRequestRate, Prcb->MinimumDpcRate); - - /* Request an Interrupt only if the DPC isn't low priority */ - if ((Dpc->Importance != LowImportance) || - (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) || - (Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) { - - /* Request Interrupt */ - DPRINT("Requesting Interrupt\n"); - HalRequestSoftwareInterrupt(DISPATCH_LEVEL); - Prcb->DpcInterruptRequested = TRUE; - } -#endif } -#ifdef CONFIG_SMP - KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock); -#endif + + /* Release the lock */ + KiReleaseSpinLock(&DpcData->DpcLock); + + /* Check if the DPC was inserted */ + if (DpcInserted) + { + /* Check if this was SMP */ + if (Prcb != CurrentPrcb) + { + /* It was, request and IPI */ + KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC); + } + else + { + /* It wasn't, request an interrupt from HAL */ + HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + } + } + /* Lower IRQL */ KeLowerIrql(OldIrql); - return(TRUE); + return DpcConfigured; } /* * @implemented - * - * FUNCTION: - * Removes DPC object from the system dpc queue - * ARGUMENTS: - * Dpc = Pointer to DPC to remove from the queue. - * RETURNS: - * TRUE if the DPC was in the queue - * FALSE otherwise */ BOOLEAN -STDCALL -KeRemoveQueueDpc(PKDPC Dpc) +NTAPI +KeRemoveQueueDpc(IN PKDPC Dpc) { - BOOLEAN WasInQueue; - KIRQL OldIrql; + PKDPC_DATA DpcData; + UCHAR DpcType; + ASSERT_DPC(Dpc); - /* Raise IRQL */ - DPRINT("Removing DPC: %x\n", Dpc); - KeRaiseIrql(HIGH_LEVEL, &OldIrql); -#ifdef CONFIG_SMP - KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); -#endif + /* Disable interrupts */ + Ke386DisableInterrupts(); - /* First make sure the DPC lock isn't being held */ - WasInQueue = Dpc->DpcData ? TRUE : FALSE; - if (Dpc->DpcData) { + /* Get DPC data and type */ + DpcType = Dpc->Type; + DpcData = Dpc->DpcData; + if (DpcData) + { + /* Acquire the DPC lock */ + KiAcquireSpinLock(&DpcData->DpcLock); - /* Remove the DPC */ - ((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--; - RemoveEntryList(&Dpc->DpcListEntry); + /* Make sure that the data didn't change */ + if (DpcData == Dpc->DpcData) + { + /* Remove the DPC */ + DpcData->DpcQueueDepth--; + RemoveEntryList(&Dpc->DpcListEntry); + Dpc->DpcData = NULL; + } + /* Release the lock */ + KiReleaseSpinLock(&DpcData->DpcLock); } -#ifdef CONFIG_SMP - KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); -#endif + + /* Re-enable interrupts */ + Ke386EnableInterrupts(); /* Return if the DPC was in the queue or not */ - KeLowerIrql(OldIrql); - return WasInQueue; + return DpcData ? TRUE : FALSE; } /* * @implemented */ VOID -STDCALL +NTAPI KeFlushQueuedDpcs(VOID) -/* - * FUNCTION: - * Called to Deliver DPCs if any are pending. - * NOTES: - * Called when deleting a Driver. - */ { + PAGED_CODE(); + /* Request an interrupt if needed */ + DPRINT1("%s - FIXME!!!\n", __FUNCTION__); if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL); } @@ -340,59 +279,37 @@ KeFlushQueuedDpcs(VOID) * @implemented */ BOOLEAN -STDCALL -KeIsExecutingDpc( - VOID -) +NTAPI +KeIsExecutingDpc(VOID) { /* Return if the Dpc Routine is active */ return KeGetCurrentPrcb()->DpcRoutineActive; } /* - * FUNCTION: Specifies the DPCs importance - * ARGUMENTS: - * Dpc = Initalizes DPC - * Importance = DPC importance - * RETURNS: None - * * @implemented */ VOID -STDCALL +NTAPI KeSetImportanceDpc (IN PKDPC Dpc, - IN KDPC_IMPORTANCE Importance) + IN KDPC_IMPORTANCE Importance) { /* Set the DPC Importance */ + ASSERT_DPC(Dpc); Dpc->Importance = Importance; } /* * @implemented - * - * FUNCTION: Specifies on which processor the DPC will run - * ARGUMENTS: - * Dpc = Initalizes DPC - * Number = Processor number - * RETURNS: None */ VOID -STDCALL +NTAPI KeSetTargetProcessorDpc(IN PKDPC Dpc, IN CCHAR Number) { - /* Check how many CPUs are on the system */ - if (Number >= MAXIMUM_PROCESSORS) { - - /* No CPU Number */ - Dpc->Number = 0; - - } else { - - /* Set the Number Specified */ - ASSERT(Number < KeNumberProcessors); - Dpc->Number = Number + MAXIMUM_PROCESSORS; - } + /* Set a target CPU */ + ASSERT_DPC(Dpc); + Dpc->Number = Number + MAXIMUM_PROCESSORS; } /* diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index 42e7f8c8784..e4623677204 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -17,11 +17,11 @@ /* GLOBALS *******************************************************************/ +PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS]; KNODE KiNode0; PKNODE KeNodeBlock[1]; UCHAR KeNumberNodes = 1; UCHAR KeProcessNodeSeed; -PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS]; ETHREAD KiInitialThread; EPROCESS KiInitialProcess; @@ -195,10 +195,10 @@ KiInitSpinLocks(IN PKPRCB Prcb, } /* Initialize DPC Fields */ - InitializeListHead(&Prcb->DpcData[0].DpcListHead); - KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock); - Prcb->DpcData[0].DpcQueueDepth = 0; - Prcb->DpcData[0].DpcCount = 0; + InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead); + KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock); + Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0; + Prcb->DpcData[DPC_NORMAL].DpcCount = 0; Prcb->DpcRoutineActive = FALSE; Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; Prcb->MinimumDpcRate = KiMinimumDpcRate; @@ -245,11 +245,14 @@ KiInitSpinLocks(IN PKPRCB Prcb, Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock; Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL; Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL; - for (i = LockQueueTimerTableLock; i < LockQueueMaximumLock; i++) + + /* Loop timer locks */ + for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++) { - KeInitializeSpinLock(&KiTimerTableLock[i - 16]); + /* Initialize the lock and setup the Queued Spinlock */ + KeInitializeSpinLock(&KiTimerTableLock[i]); Prcb->LockQueue[i].Next = NULL; - Prcb->LockQueue[i].Lock = &KiTimerTableLock[i - 16]; + Prcb->LockQueue[i].Lock = &KiTimerTableLock[i]; } /* Check if this is the boot CPU */ @@ -297,7 +300,7 @@ KiInitializePcr(IN ULONG ProcessorNumber, /* Set pointers to ourselves */ Pcr->Self = (PKPCR)Pcr; - Pcr->Prcb = &(Pcr->PrcbData); + Pcr->Prcb = &Pcr->PrcbData; /* Set the PCR Version */ Pcr->MajorVersion = PCR_MAJOR_VERSION; diff --git a/reactos/ntoskrnl/ke/ipi.c b/reactos/ntoskrnl/ke/ipi.c index a43593a0faf..8592d96eeb1 100644 --- a/reactos/ntoskrnl/ke/ipi.c +++ b/reactos/ntoskrnl/ke/ipi.c @@ -33,7 +33,7 @@ KiIpiSendRequest(KAFFINITY TargetSet, ULONG IpiRequest) if (TargetSet & Current) { Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE); - Ke386TestAndSetBit(IpiRequest, &Pcr->Prcb->IpiFrozen); + Ke386TestAndSetBit(IpiRequest, (PLONG)&Pcr->Prcb->IpiFrozen); HalRequestIpi(i); } } @@ -59,18 +59,18 @@ KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame, Prcb = KeGetCurrentPrcb(); - if (Ke386TestAndClearBit(IPI_APC, &Prcb->IpiFrozen)) + if (Ke386TestAndClearBit(IPI_APC, (PLONG)&Prcb->IpiFrozen)) { HalRequestSoftwareInterrupt(APC_LEVEL); } - if (Ke386TestAndClearBit(IPI_DPC, &Prcb->IpiFrozen)) + if (Ke386TestAndClearBit(IPI_DPC, (PLONG)&Prcb->IpiFrozen)) { Prcb->DpcInterruptRequested = TRUE; HalRequestSoftwareInterrupt(DISPATCH_LEVEL); } - if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, &Prcb->IpiFrozen)) + if (Ke386TestAndClearBit(IPI_SYNCH_REQUEST, (PLONG)&Prcb->IpiFrozen)) { (void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]); if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0)) @@ -91,7 +91,7 @@ KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame, } } ((VOID (STDCALL*)(PVOID))(Prcb->SignalDone->WorkerRoutine))(Prcb->SignalDone->CurrentPacket[0]); - Ke386TestAndClearBit(KeGetCurrentProcessorNumber(), &Prcb->SignalDone->TargetSet); + Ke386TestAndClearBit(KeGetCurrentProcessorNumber(), (PLONG)&Prcb->SignalDone->TargetSet); if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0)) { #ifdef DBG @@ -140,7 +140,7 @@ KiIpiSendPacket(KAFFINITY TargetSet, VOID (STDCALL*WorkerRoutine)(PVOID), PVOID { Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb; while(0 != InterlockedCompareExchangeUL(&Prcb->SignalDone, (LONG)CurrentPrcb, 0)); - Ke386TestAndSetBit(IPI_SYNCH_REQUEST, &Prcb->IpiFrozen); + Ke386TestAndSetBit(IPI_SYNCH_REQUEST, (PLONG)&Prcb->IpiFrozen); if (Processor != CurrentPrcb->SetMember) { HalRequestIpi(i);