- Make KeUpdateSystemTime independent, so that it returns and exits from the current ROSterrupt by itself.

- Make KeUpdateRunTime increase the interrupt count, check for V86 as well as for user-mode by using the CS and EFLAGS (isntead of PreviousMode), also only request DPCs if DpcInterruptRequested isn't already set, and only perform Quantum End if this isn't the idle thread.
- Add clock.S which will have the clock interrupt handlers of the kernel (UpdateSystemTime and UpdateRunTime) and ultimately replace the only reason irqhand.S is still around (the clock interrupt). Implement the current version of KeUpdateSystemTime in assembly, with stack optimizations since we'll be called from the HAL later.

svn path=/trunk/; revision=23680
This commit is contained in:
Alex Ionescu 2006-08-24 06:52:33 +00:00
parent 5e7ef1d665
commit 065837f112
4 changed files with 133 additions and 15 deletions

View file

@ -247,18 +247,15 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
IN KIRQL Irql)
{
PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD CurrentThread;
PKPROCESS CurrentProcess;
PKTHREAD CurrentThread = Prcb->CurrentThread;
PKPROCESS CurrentProcess = CurrentThread->ApcState.Process;
/* 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;
/* Increase interrupt count */
Prcb->InterruptCount++;
/* Check if we came from user mode */
if (TrapFrame->PreviousPreviousMode != KernelMode)
if ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
(TrapFrame->SegCs & MODE_MASK))
{
/* Update user times */
CurrentThread->UserTime++;
@ -267,6 +264,9 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
}
else
{
/* Update CPU kernel time in all cases */
Prcb->KernelTime++;
/* Check IRQ */
if (Irql > DISPATCH_LEVEL)
{
@ -284,9 +284,6 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
/* This was DPC time */
Prcb->DpcTime++;
}
/* Update CPU kernel time in all cases */
Prcb->KernelTime++;
}
/* Set the last DPC Count and request rate */
@ -295,7 +292,9 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
Prcb->DpcRequestRate) / 2;
/* Check if we should request a DPC */
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
if ((Prcb->DpcData[0].DpcQueueDepth) &&
!(Prcb->DpcRoutineActive) &&
!(Prcb->DpcInterruptRequested))
{
/* Request one */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
@ -335,7 +334,8 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
* we don't care about the quantum value anymore after the QuantumEnd
* flag is set.
*/
if ((CurrentThread->Quantum -= 3) <= 0)
if (((CurrentThread->Quantum -= 3) <= 0) &&
(Prcb->IdleThread != CurrentThread))
{
Prcb->QuantumEnd = TRUE;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
@ -414,6 +414,10 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
KiTickOffset += KeMaximumIncrement;
KeUpdateRunTime(TrapFrame, Irql);
}
/* Return from the interrupt */
Ke386DisableInterrupts();
HalEndSystemInterrupt(Irql, 0);
}
/*

View file

@ -0,0 +1,113 @@
/*
* FILE: ntoskrnl/ke/i386/clock.S
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: System Clock Management
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
#include <asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* GLOBALS *******************************************************************/
.extern _KeTimeAdjustment
.extern _KiTickOffset
.extern _KeTickCount
.extern _KeMaximumIncrement
/* FUNCTIONS ******************************************************************/
.globl _KeUpdateSystemTime2@0
.func KeUpdateSystemTime2@0
_KeUpdateSystemTime2@0:
/* Get shared data in ECX */
mov ecx, USER_SHARED_DATA
/* Get interrupt time */
mov edi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME]
mov esi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4]
/* Add the increment and get the carry */
add edi, eax
adc esi, 0
/* Now store the updated times */
mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+8], esi
mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME], edi
mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4], esi
/* Substract tick count and get the low count */
LOCK sub _KiTickOffset, eax
mov eax, _KeTickCount
mov ebx, eax
jg IncompleteTick
/* Get shared data in ECX */
mov ebx, USER_SHARED_DATA
/* Get system time */
mov edi, [ebx+USER_SHARED_DATA_SYSTEM_TIME]
mov esi, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]
/* Add the increment and get the carry */
add ecx, _KeTimeAdjustment
adc edx, 0
/* Now store the updated times */
mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+8], edx
mov [ebx+USER_SHARED_DATA_SYSTEM_TIME], ecx
mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+4], edx
/* Put tick count back in EBX */
mov ebx, eax
/* Copyit in ECX and get hich count */
mov ecx, eax
mov edx, _KeTickCount + 4
/* Add the increment and get the carry */
add ecx, 1
adc edx, 0
/* Now store the updated tick */
mov [_KeTickCount+8], edx
mov [_KeTickCount], ecx
mov [_KeTickCount+4], edx
/* Store in in shared data too */
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+8], edx
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx
IncompleteTick:
/* Queue DPC to handle registered timers */
/* Check if this was a full tick */
cmp dword ptr _KiTickOffset, 0
jg IncompleteTick2
/* Increase tick offset */
mov eax, _KeMaximumIncrement
add _KiTickOffset, eax
/* Update system run time */
push esp
call _KeUpdateRunTime@8
jmp Done
IncompleteTick2:
/* Increase interrupt count */
inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
Done:
/* Exit the interrupt */
mov esi, $
cli
call _HalEndSystemInterrupt@8
jmp _Kei386EoiHelper@0
.endfunc

View file

@ -156,7 +156,7 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
if (KiClockSetupComplete)
{
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
return KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
}
/*

View file

@ -29,6 +29,7 @@
<file first="true">main_asm.S</file>
<file>cpu.S</file>
<file>ctxswitch.S</file>
<file>clock.S</file>
<file>exp.c</file>
<file>fpu.c</file>
<file>gdt.c</file>