[ros-diffs] [tkreuzer] 53496: [HAL] We cannot make any assumptions about the latency whith which the timer interrupt fires after a rollover, since VBox (other VMs probably as well) doesn't always meet this. Ad...

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Tue Aug 30 12:01:01 UTC 2011


Author: tkreuzer
Date: Tue Aug 30 12:01:01 2011
New Revision: 53496

URL: http://svn.reactos.org/svn/reactos?rev=53496&view=rev
Log:
[HAL]
We cannot make any assumptions about the latency whith which the timer interrupt fires after a rollover, since VBox (other VMs probably as well) doesn't always meet this. Add another check to KeQueryPerformanceCounter that gracefully handles missing interrupts. Also raise to DISPATCH_LEVEL, since the function is not reentrant.

Modified:
    trunk/reactos/hal/halx86/generic/timer.c

Modified: trunk/reactos/hal/halx86/generic/timer.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/timer.c?rev=53496&r1=53495&r2=53496&view=diff
==============================================================================
--- trunk/reactos/hal/halx86/generic/timer.c [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/timer.c [iso-8859-1] Tue Aug 30 12:01:01 2011
@@ -253,6 +253,7 @@
 {
     LARGE_INTEGER CurrentPerfCounter;
     ULONG CounterValue, ClockDelta;
+    KIRQL OldIrql;
 
     /* If caller wants performance frequency, return hardcoded value */
     if (PerformanceFrequency) PerformanceFrequency->QuadPart = PIT_FREQUENCY;
@@ -262,6 +263,10 @@
 
     /* Check if interrupts are disabled */
     if(!(__readeflags() & EFLAGS_INTERRUPT_MASK)) return HalpPerfCounter;
+
+    /* Raise irql to DISPATCH_LEVEL */
+    OldIrql = KeGetCurrentIrql();
+    if (OldIrql < DISPATCH_LEVEL) KfRaiseIrql(DISPATCH_LEVEL);
 
     do
     {
@@ -287,13 +292,21 @@
     /* Add the clock delta */
     CurrentPerfCounter.QuadPart += ClockDelta;
 
-    /* This must be true unless HalpPerfCounter has changed sign,
-       which takes approximately 245,118 years */
-    ASSERT(CurrentPerfCounter.QuadPart >= HalpLastPerfCounter.QuadPart);
+    /* Check if the value is smaller then before, this means, we somehow
+       missed an interrupt. This is a sign that the timer interrupt
+       is very inaccurate. Probably a virtual machine. */
+    if (CurrentPerfCounter.QuadPart < HalpLastPerfCounter.QuadPart)
+    {
+        /* We missed an interrupt. Assume we will receive it later */
+        CurrentPerfCounter.QuadPart += HalpCurrentRollOver;
+    }
 
     /* Update the last counter value */
     HalpLastPerfCounter = CurrentPerfCounter;
 
+    /* Restore previous irql */
+    if (OldIrql < DISPATCH_LEVEL) KfLowerIrql(OldIrql);
+
     /* Return the result */
     return CurrentPerfCounter;
 }




More information about the Ros-diffs mailing list