mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:03:12 +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;
|
LARGE_INTEGER CurrentPerfCounter;
|
||||||
ULONG CounterValue, ClockDelta;
|
ULONG CounterValue, ClockDelta;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* If caller wants performance frequency, return hardcoded value */
|
/* If caller wants performance frequency, return hardcoded value */
|
||||||
if (PerformanceFrequency) PerformanceFrequency->QuadPart = PIT_FREQUENCY;
|
if (PerformanceFrequency) PerformanceFrequency->QuadPart = PIT_FREQUENCY;
|
||||||
|
@ -263,6 +264,10 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency)
|
||||||
/* Check if interrupts are disabled */
|
/* Check if interrupts are disabled */
|
||||||
if(!(__readeflags() & EFLAGS_INTERRUPT_MASK)) return HalpPerfCounter;
|
if(!(__readeflags() & EFLAGS_INTERRUPT_MASK)) return HalpPerfCounter;
|
||||||
|
|
||||||
|
/* Raise irql to DISPATCH_LEVEL */
|
||||||
|
OldIrql = KeGetCurrentIrql();
|
||||||
|
if (OldIrql < DISPATCH_LEVEL) KfRaiseIrql(DISPATCH_LEVEL);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Get the current performance counter value */
|
/* Get the current performance counter value */
|
||||||
|
@ -287,13 +292,21 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency)
|
||||||
/* Add the clock delta */
|
/* Add the clock delta */
|
||||||
CurrentPerfCounter.QuadPart += ClockDelta;
|
CurrentPerfCounter.QuadPart += ClockDelta;
|
||||||
|
|
||||||
/* This must be true unless HalpPerfCounter has changed sign,
|
/* Check if the value is smaller then before, this means, we somehow
|
||||||
which takes approximately 245,118 years */
|
missed an interrupt. This is a sign that the timer interrupt
|
||||||
ASSERT(CurrentPerfCounter.QuadPart >= HalpLastPerfCounter.QuadPart);
|
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 */
|
/* Update the last counter value */
|
||||||
HalpLastPerfCounter = CurrentPerfCounter;
|
HalpLastPerfCounter = CurrentPerfCounter;
|
||||||
|
|
||||||
|
/* Restore previous irql */
|
||||||
|
if (OldIrql < DISPATCH_LEVEL) KfLowerIrql(OldIrql);
|
||||||
|
|
||||||
/* Return the result */
|
/* Return the result */
|
||||||
return CurrentPerfCounter;
|
return CurrentPerfCounter;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue