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