From 065837f1123796ec053669a4178203caaac79a83 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 24 Aug 2006 06:52:33 +0000 Subject: [PATCH] - 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 --- reactos/ntoskrnl/ke/clock.c | 32 +++++---- reactos/ntoskrnl/ke/i386/clock.S | 113 +++++++++++++++++++++++++++++++ reactos/ntoskrnl/ke/i386/irq.c | 2 +- reactos/ntoskrnl/ntoskrnl.rbuild | 1 + 4 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 reactos/ntoskrnl/ke/i386/clock.S diff --git a/reactos/ntoskrnl/ke/clock.c b/reactos/ntoskrnl/ke/clock.c index 401fc6b0b12..f2eb528a618 100644 --- a/reactos/ntoskrnl/ke/clock.c +++ b/reactos/ntoskrnl/ke/clock.c @@ -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); } /* diff --git a/reactos/ntoskrnl/ke/i386/clock.S b/reactos/ntoskrnl/ke/i386/clock.S new file mode 100644 index 00000000000..ee90fd31408 --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/clock.S @@ -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 +#include +.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 diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 58334437dff..158cd165bd8 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -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); } /* diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 54aa934f475..784f7d02183 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -29,6 +29,7 @@ main_asm.S cpu.S ctxswitch.S + clock.S exp.c fpu.c gdt.c