- Make KeUpdateSystemTime independent, so that it returns and exits from the current...
authorAlex Ionescu <aionescu@gmail.com>
Thu, 24 Aug 2006 06:52:33 +0000 (06:52 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Thu, 24 Aug 2006 06:52:33 +0000 (06:52 +0000)
- 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
reactos/ntoskrnl/ke/i386/clock.S [new file with mode: 0644]
reactos/ntoskrnl/ke/i386/irq.c
reactos/ntoskrnl/ntoskrnl.rbuild

index 401fc6b..f2eb528 100644 (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);
 }
 
 /*
diff --git a/reactos/ntoskrnl/ke/i386/clock.S b/reactos/ntoskrnl/ke/i386/clock.S
new file mode 100644 (file)
index 0000000..ee90fd3
--- /dev/null
@@ -0,0 +1,113 @@
+/*\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
index 5833443..158cd16 100644 (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);
    }
 
    /*
index 54aa934..784f7d0 100644 (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>