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++;
}
else
{
+ /* Update CPU kernel time in all cases */
+ Prcb->KernelTime++;
+
/* Check IRQ */
if (Irql > DISPATCH_LEVEL)
{
/* This was DPC time */
Prcb->DpcTime++;
}
-
- /* Update CPU kernel time in all cases */
- Prcb->KernelTime++;
}
/* Set the last DPC Count and request rate */
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);
* 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);
KiTickOffset += KeMaximumIncrement;
KeUpdateRunTime(TrapFrame, Irql);
}
+
+ /* Return from the interrupt */
+ Ke386DisableInterrupts();
+ HalEndSystemInterrupt(Irql, 0);
}
/*
--- /dev/null
+/*\r
+ * FILE: ntoskrnl/ke/i386/clock.S\r
+ * COPYRIGHT: See COPYING in the top level directory\r
+ * PURPOSE: System Clock Management\r
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)\r
+ */\r
+\r
+/* INCLUDES ******************************************************************/\r
+\r
+#include <asm.h>\r
+#include <internal/i386/asmmacro.S>\r
+.intel_syntax noprefix\r
+\r
+/* GLOBALS *******************************************************************/\r
+\r
+.extern _KeTimeAdjustment\r
+.extern _KiTickOffset\r
+.extern _KeTickCount\r
+.extern _KeMaximumIncrement\r
+\r
+/* FUNCTIONS ******************************************************************/\r
+\r
+.globl _KeUpdateSystemTime2@0\r
+.func KeUpdateSystemTime2@0\r
+_KeUpdateSystemTime2@0:\r
+\r
+ /* Get shared data in ECX */\r
+ mov ecx, USER_SHARED_DATA\r
+\r
+ /* Get interrupt time */\r
+ mov edi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME]\r
+ mov esi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4]\r
+\r
+ /* Add the increment and get the carry */\r
+ add edi, eax\r
+ adc esi, 0\r
+\r
+ /* Now store the updated times */\r
+ mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+8], esi\r
+ mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME], edi\r
+ mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4], esi\r
+\r
+ /* Substract tick count and get the low count */\r
+ LOCK sub _KiTickOffset, eax\r
+ mov eax, _KeTickCount\r
+ mov ebx, eax\r
+ jg IncompleteTick\r
+\r
+ /* Get shared data in ECX */\r
+ mov ebx, USER_SHARED_DATA\r
+\r
+ /* Get system time */\r
+ mov edi, [ebx+USER_SHARED_DATA_SYSTEM_TIME]\r
+ mov esi, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]\r
+\r
+ /* Add the increment and get the carry */\r
+ add ecx, _KeTimeAdjustment\r
+ adc edx, 0\r
+\r
+ /* Now store the updated times */\r
+ mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+8], edx\r
+ mov [ebx+USER_SHARED_DATA_SYSTEM_TIME], ecx\r
+ mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+4], edx\r
+\r
+ /* Put tick count back in EBX */\r
+ mov ebx, eax\r
+\r
+ /* Copyit in ECX and get hich count */\r
+ mov ecx, eax\r
+ mov edx, _KeTickCount + 4\r
+\r
+ /* Add the increment and get the carry */\r
+ add ecx, 1\r
+ adc edx, 0\r
+\r
+ /* Now store the updated tick */\r
+ mov [_KeTickCount+8], edx\r
+ mov [_KeTickCount], ecx\r
+ mov [_KeTickCount+4], edx\r
+\r
+ /* Store in in shared data too */\r
+ mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+8], edx\r
+ mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx\r
+ mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx\r
+\r
+IncompleteTick:\r
+\r
+ /* Queue DPC to handle registered timers */\r
+\r
+ /* Check if this was a full tick */\r
+ cmp dword ptr _KiTickOffset, 0\r
+ jg IncompleteTick2\r
+\r
+ /* Increase tick offset */\r
+ mov eax, _KeMaximumIncrement\r
+ add _KiTickOffset, eax\r
+\r
+ /* Update system run time */\r
+ push esp\r
+ call _KeUpdateRunTime@8\r
+ jmp Done\r
+\r
+IncompleteTick2:\r
+ /* Increase interrupt count */\r
+ inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]\r
+\r
+Done:\r
+ /* Exit the interrupt */\r
+ mov esi, $\r
+ cli\r
+ call _HalEndSystemInterrupt@8\r
+ jmp _Kei386EoiHelper@0\r
+.endfunc\r