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=2…
==============================================================================
--- 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=23…
==============================================================================
--- 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=2303…
==============================================================================
--- 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;
}