Author: ion Date: Thu Jul 13 10:23:34 2006 New Revision: 23039
URL: http://svn.reactos.org/svn/reactos?rev=23039&view=rev Log: - Add some TIMER values to the ddk. - Add DPC Settings (Queue Depths, Rates, etc) - Cleanup System/Run Time Update code. - Always increase kernel time in PRCB when inside kernel-mode code. - Get rid of superflous interlocked commands when not needed. - Improve detection of DPC vs non-DPC time. - Respect and apply DPC queue/rate rules. - Allow future use of non-fulltick time increments.
Modified: trunk/reactos/include/ddk/winddk.h trunk/reactos/ntoskrnl/ke/clock.c trunk/reactos/ntoskrnl/ke/dpc.c
Modified: trunk/reactos/include/ddk/winddk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=23... ============================================================================== --- trunk/reactos/include/ddk/winddk.h (original) +++ trunk/reactos/include/ddk/winddk.h Thu Jul 13 10:23:34 2006 @@ -1189,6 +1189,9 @@ }; } KGUARDED_MUTEX, *PKGUARDED_MUTEX;
+#define TIMER_TABLE_SIZE 512 +#define TIMER_TABLE_SHIFT 9 + typedef struct _KTIMER { DISPATCHER_HEADER Header; ULARGE_INTEGER DueTime; @@ -1196,6 +1199,10 @@ struct _KDPC *Dpc; LONG Period; } KTIMER, *PKTIMER, *RESTRICTED_POINTER PRKTIMER; + +#define ASSERT_TIMER(E) \ + ASSERT(((E)->Header.Type == TimerNotificationObject) || \ + ((E)->Header.Type == TimerSynchronizationObject))
typedef struct _KMUTANT { DISPATCHER_HEADER Header;
Modified: trunk/reactos/ntoskrnl/ke/clock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/clock.c?rev=230... ============================================================================== --- trunk/reactos/ntoskrnl/ke/clock.c (original) +++ trunk/reactos/ntoskrnl/ke/clock.c Thu Jul 13 10:23:34 2006 @@ -39,12 +39,17 @@ static KDPC KiExpireTimerDpc; static BOOLEAN KiClockSetupComplete = FALSE;
+extern ULONG KiMaximumDpcQueueDepth; +extern ULONG KiMinimumDpcRate; +extern ULONG KiAdjustDpcThreshold; +extern ULONG KiIdealDpcRate; + /* * Number of timer interrupts since initialisation */ volatile KSYSTEM_TIME KeTickCount = {0}; volatile ULONG KiRawTicks = 0; - +LONG KiTickOffset = 0; extern LIST_ENTRY KiTimerListHead;
/* @@ -237,73 +242,87 @@ */ VOID STDCALL -KeUpdateRunTime( - IN PKTRAP_FRAME TrapFrame, - IN KIRQL Irql - ) -{ - PKPRCB Prcb; - PKTHREAD CurrentThread; - PKPROCESS CurrentProcess; -#if 0 - ULONG DpcLastCount; -#endif - - Prcb = KeGetCurrentPrcb(); - - /* Make sure we don't go further if we're in early boot phase. */ - if (Prcb == NULL || Prcb->CurrentThread == NULL) - return; - - DPRINT("KernelTime %u, UserTime %u \n", Prcb->KernelTime, Prcb->UserTime); - - CurrentThread = Prcb->CurrentThread; - CurrentProcess = CurrentThread->ApcState.Process; - - /* - * Cs bit 0 is always set for user mode if we are in protected mode. - * V86 mode is counted as user time. - */ - if (TrapFrame->SegCs & MODE_MASK || - TrapFrame->EFlags & X86_EFLAGS_VM) - { - (void)InterlockedIncrementUL(&CurrentThread->UserTime); - (void)InterlockedIncrementUL(&CurrentProcess->UserTime); - Prcb->UserTime++; +KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, + IN KIRQL Irql) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD CurrentThread; + PKPROCESS CurrentProcess; + + /* Make sure we don't go further if we're in early boot phase. */ + if (!(Prcb) || !(Prcb->CurrentThread)) return; + + /* Get the current thread and process */ + CurrentThread = Prcb->CurrentThread; + CurrentProcess = CurrentThread->ApcState.Process; + + /* Check if we came from user mode */ + if (TrapFrame->PreviousPreviousMode != KernelMode) + { + /* Update user times */ + CurrentThread->UserTime++; + InterlockedIncrement(&CurrentProcess->UserTime); + Prcb->UserTime++; + } + else + { + /* Check IRQ */ + if (Irql > DISPATCH_LEVEL) + { + /* This was an interrupt */ + Prcb->InterruptTime++; + } + else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive)) + { + /* This was normal kernel time */ + CurrentThread->KernelTime++; + InterlockedIncrement(&CurrentProcess->KernelTime); + } + else if (Irql == DISPATCH_LEVEL) + { + /* This was DPC time */ + Prcb->DpcTime++; + } + + /* Update CPU kernel time in all cases */ + Prcb->KernelTime++; } - else - { - if (Irql > DISPATCH_LEVEL) - { - Prcb->InterruptTime++; - } - else if (Irql == DISPATCH_LEVEL) - { - Prcb->DpcTime++; - } - else - { - (void)InterlockedIncrementUL(&CurrentThread->KernelTime); - (void)InterlockedIncrementUL(&CurrentProcess->KernelTime); - Prcb->KernelTime++; - } - } - -#if 0 - DpcLastCount = Prcb->DpcLastCount; - Prcb->DpcLastCount = Prcb->DpcCount; - Prcb->DpcRequestRate = ((Prcb->DpcCount - DpcLastCount) + - Prcb->DpcRequestRate) / 2; -#endif - - if (Prcb->DpcData[0].DpcQueueDepth > 0 && - Prcb->DpcRoutineActive == FALSE && - Prcb->DpcInterruptRequested == FALSE) - { - HalRequestSoftwareInterrupt(DISPATCH_LEVEL); - } - - /* FIXME: Do DPC rate adjustments */ + + /* Set the last DPC Count and request rate */ + Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount; + Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) + + Prcb->DpcRequestRate) / 2; + + /* Check if we should request a DPC */ + if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive)) + { + /* Request one */ + HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + + /* Update the depth if needed */ + if ((Prcb->DpcRequestRate < KiIdealDpcRate) && + (Prcb->MaximumDpcQueueDepth > 1)) + { + /* Decrease the maximum depth by one */ + Prcb->MaximumDpcQueueDepth--; + } + } + else + { + /* Decrease the adjustment threshold */ + if (!(--Prcb->AdjustDpcThreshold)) + { + /* We've hit 0, reset it */ + Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; + + /* Check if we've hit queue maximum */ + if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth) + { + /* Increase maximum by one */ + Prcb->MaximumDpcQueueDepth++; + } + } + }
/* * If we're at end of quantum request software interrupt. The rest @@ -315,11 +334,11 @@ * we don't care about the quantum value anymore after the QuantumEnd * flag is set. */ - if ((CurrentThread->Quantum -= 3) <= 0) - { - Prcb->QuantumEnd = TRUE; - HalRequestSoftwareInterrupt(DISPATCH_LEVEL); - } + if ((CurrentThread->Quantum -= 3) <= 0) + { + Prcb->QuantumEnd = TRUE; + HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + } }
@@ -333,51 +352,56 @@ */ VOID STDCALL -KeUpdateSystemTime( - IN PKTRAP_FRAME TrapFrame, - IN KIRQL Irql - ) -/* - * FUNCTION: Handles a timer interrupt - */ -{ - LARGE_INTEGER Time; - - ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL); - - KiRawTicks++; - - if (KiClockSetupComplete == FALSE) return; - - /* - * Increment the number of timers ticks - */ - (*(PULONGLONG)&KeTickCount)++; - SharedUserData->TickCountLowDeprecated++; - - Time.u.LowPart = SharedUserData->InterruptTime.LowPart; - Time.u.HighPart = SharedUserData->InterruptTime.High1Time; - Time.QuadPart += CLOCK_INCREMENT; - SharedUserData->InterruptTime.High2Time = Time.u.HighPart; - SharedUserData->InterruptTime.LowPart = Time.u.LowPart; - SharedUserData->InterruptTime.High1Time = Time.u.HighPart; - - Time.u.LowPart = SharedUserData->SystemTime.LowPart; - Time.u.HighPart = SharedUserData->SystemTime.High1Time; - Time.QuadPart += CLOCK_INCREMENT; - SharedUserData->SystemTime.High2Time = Time.u.HighPart; - SharedUserData->SystemTime.LowPart = Time.u.LowPart; - SharedUserData->SystemTime.High1Time = Time.u.HighPart; - - /* FIXME: Here we should check for remote debugger break-ins */ - - /* Update process and thread times */ - KeUpdateRunTime(TrapFrame, Irql); - - /* - * Queue a DPC that will expire timers - */ - KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0); +KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, + IN KIRQL Irql) +{ + LONG OldOffset; + LARGE_INTEGER Time; + ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL); + if (!KiClockSetupComplete) return; + + /* Update interrupt time */ + Time.LowPart = SharedUserData->InterruptTime.LowPart; + Time.HighPart = SharedUserData->InterruptTime.High1Time; + Time.QuadPart += CLOCK_INCREMENT; + SharedUserData->InterruptTime.High2Time = Time.u.HighPart; + SharedUserData->InterruptTime.LowPart = Time.u.LowPart; + SharedUserData->InterruptTime.High1Time = Time.u.HighPart; + + /* Increase the tick offset */ + KiTickOffset -= CLOCK_INCREMENT; + OldOffset = KiTickOffset; + + /* Check if this isn't a tick yet */ + if (KiTickOffset > 0) + { + /* Expire timers */ + KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0); + } + else + { + /* This was a tick, calculate the next one */ + KiTickOffset += CLOCK_INCREMENT; + + /* Setup time structure for system time */ + Time.LowPart = SharedUserData->SystemTime.LowPart; + Time.HighPart = SharedUserData->SystemTime.High1Time; + Time.QuadPart += CLOCK_INCREMENT; + SharedUserData->SystemTime.High2Time = Time.HighPart; + SharedUserData->SystemTime.LowPart = Time.LowPart; + SharedUserData->SystemTime.High1Time = Time.HighPart; + + /* Update tick count */ + (*(PULONGLONG)&KeTickCount)++; + SharedUserData->TickCountLowDeprecated++; + KiRawTicks++; + + /* Queue a DPC that will expire timers */ + KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0); + } + + /* Update process and thread times */ + if (OldOffset <= 0) KeUpdateRunTime(TrapFrame, Irql); }
/*
Modified: trunk/reactos/ntoskrnl/ke/dpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=23039... ============================================================================== --- trunk/reactos/ntoskrnl/ke/dpc.c (original) +++ trunk/reactos/ntoskrnl/ke/dpc.c Thu Jul 13 10:23:34 2006 @@ -25,6 +25,10 @@ #pragma alloc_text(INIT, KeInitDpc) #endif
+ULONG KiMaximumDpcQueueDepth = 4; +ULONG KiMinimumDpcRate = 3; +ULONG KiAdjustDpcThreshold = 20; +ULONG KiIdealDpcRate = 20;
/* TYPES *******************************************************************/
@@ -49,8 +53,8 @@ KeInitializeEvent(Prcb->DpcEvent, 0, 0); #endif KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock); - Prcb->MaximumDpcQueueDepth = 4; - Prcb->MinimumDpcRate = 3; + Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; + Prcb->MinimumDpcRate = KiMinimumDpcRate; Prcb->DpcData[0].DpcQueueDepth = 0; }