I think the problem is that QPC is broken on Windows XP and Vista. The CPU
guides clearly state that RDTSC is not a serializing instruction and is
subject to out of order execution among other things and the various
implementations on Windows don’t do that. (On Win7 RDTSC is no longer used
possibly depending on available hardware features).
On XP SP3:
hal!KeQueryPerformanceCounter:
806ebb94 8bff mov edi,edi
806ebb96 55 push ebp
806ebb97 8bec mov ebp,esp
806ebb99 5d pop ebp
806ebb9a ff2548156f80 jmp dword ptr [hal!HalpHeapStart+0xc
(806f1548)]
0: kd> t
hal!HalpAcpiTimerQueryPerfCount:
806e4c78 a0dcd06e80 mov al,byte ptr [hal!HalpUse8254 (806ed0dc)]
806e4c78 a0dcd06e80 mov al,byte ptr [hal!HalpUse8254 (806ed0dc)]
806e4c7d 0ac0 or al,al
806e4c7f 752d jne hal!HalpAcpiTimerQueryPerfCount+0x36
(806e4cae)
806e4c81 8b4c2404 mov ecx,dword ptr [esp+4]
806e4c85 0bc9 or ecx,ecx
806e4c87 7412 je hal!HalpAcpiTimerQueryPerfCount+0x23
(806e4c9b)
806e4c89 64a1a4000000 mov eax,dword ptr fs:[000000A4h]
806e4c8f 648b15a8000000 mov edx,dword ptr fs:[0A8h]
806e4c96 8901 mov dword ptr [ecx],eax
806e4c98 895104 mov dword ptr [ecx+4],edx
806e4c9b 0f31 rdtsc
806e4c9d 640305ac000000 add eax,dword ptr fs:[0ACh]
806e4ca4 641315b0000000 adc edx,dword ptr fs:[0B0h]
806e4cab c20400 ret 4
There is no serializing instruction here making RDTSC subject to out of
order execution among other things.
What I would try is issue a CPUID serializing instruction before calling QPC
(__CPUID is included in intrin.h) and see if that solves the problem.
You can read more about the difficulties getting RDTSC right in this
article:
http://www.ccsl.carleton.ca/~jamuir/rdtscpm1.pdf
but you can read about these as well in the latest intel and AMD manuals.
//Daniel
“Gianluca Varenni” wrote in message
news:xxxxx@ntdev…
> Hi all.
>
> A customer of mine reported a strange issue, and I tracked the issue down
> to wrong values returned by KeQueryPerformanceCounter (or the user
> counterpart QueryPerformanceCounter/Frequency).
>
> The MSDN docs clearly state that
>
> KeQueryPerformanceCounter always returns a 64-bit integer that represents
> the current value of a monotonically nondecreasing counter. The resolution
> of the timer used to accumulate the current count can be obtained by
> specifying a pointer value for PerformanceFrequency. The value that is
> returned is the number of ticks per second. The count starts accumulating
> when the computer is started up.
>
>
> What I get on some specific customer machine is something that is not
> “ticks per second”. Either the frequency is bogus, or the counter itself.
>
> I wrote a small user app to test it:
>
> int _tmain(int argc, _TCHAR* argv)
> {
> int i;
> LARGE_INTEGER freq, counter;
> SYSTEMTIME systemTime;
>
> for (i = 0; i < 10; i++)
> {
> GetSystemTime(&systemTime);
>
> if (QueryPerformanceCounter(&counter) == FALSE ||
> QueryPerformanceFrequency(&freq) == FALSE)
> {
> printf(“Error getting performance counters\n”);
> }
>
> printf(“Counter = %I64d Freq = %I64d”, counter.QuadPart, freq.QuadPart);
> printf(" system: %02d:%02d:%02d\n",
> systemTime.wHour,
> systemTime.wMinute,
> systemTime.wSecond);
>
> Sleep(1000);
> }
>
> return 0;
> }
>
> And this is the output on the failing machine:
>
> Counter = 56497408135970 Freq = 3158750000 system: 01:18:57
> Counter = 56497818110218 Freq = 3158750000 system: 01:18:58
> Counter = 56498206404250 Freq = 3158750000 system: 01:18:59
> Counter = 56498715528269 Freq = 3158750000 system: 01:19:00
> Counter = 56499113984213 Freq = 3158750000 system: 01:19:01
> Counter = 56499489120527 Freq = 3158750000 system: 01:19:02
> Counter = 56499867623469 Freq = 3158750000 system: 01:19:03
> Counter = 56500252073478 Freq = 3158750000 system: 01:19:04
> Counter = 56500713252945 Freq = 3158750000 system: 01:19:05
> Counter = 56501096560332 Freq = 3158750000 system: 01:19:06
>
> If you make some computations, the counter seems to say that every
> iteration is about 0.12 seconds apart from the previous one, while it
> should be more or less 1 second.
> The failing machine is running XP SP3 (hal.dll 5.1.2600.5687, ntoskrnl.exe
> 5.1.2600.5938) on an Intel Core 2 Duo E8500.
>
> Has anyone ever seen this?
>
>
> Have a nice day
> GV
>
>
>
>