mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:46:17 +00:00
[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. svn path=/trunk/; revision=53496
This commit is contained in:
parent
e03d0348d9
commit
ee0c854ff6
1 changed files with 16 additions and 3 deletions
|
@ -253,6 +253,7 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency)
|
|||
{
|
||||
LARGE_INTEGER CurrentPerfCounter;
|
||||
ULONG CounterValue, ClockDelta;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* If caller wants performance frequency, return hardcoded value */
|
||||
if (PerformanceFrequency) PerformanceFrequency->QuadPart = PIT_FREQUENCY;
|
||||
|
@ -263,6 +264,10 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency)
|
|||
/* 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
|
||||
{
|
||||
/* Get the current performance counter value */
|
||||
|
@ -287,13 +292,21 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency)
|
|||
/* 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue