Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell which process set the high timer resolution in Windows

My system is suffering from a high timer resolution (NtQueryTimerResolution returns 0.5ms).

Maximum timer interval: 15.600 ms
Minimum timer interval: 0.500 ms
Current timer interval: 0.500 ms

Some process must be calling NtSetTimerResolution with a value of 5000 (0.5ms), but how can I determine which one? I saw Intel has a tool called Battery Life Analyzer that shows the current timer resolution per process, but that tool is only available to Intel partners. Is there another tool or a way to see it via WinDbg? Note: It seems to happen at boot time as setting a breakpoint isn't working (the resolution is already high when the debugger starts).

like image 557
rustyx Avatar asked May 05 '14 11:05

rustyx


People also ask

Does timer resolution increase FPS?

If you ever wondered how to change your Windows timer default resolution to have better accuracy while using various software or playing FPS games, we have the answer. It is called Timer Resolution.

What is the time resolution of the system time function?

The SystemTime function's resolution is dependent upon the operating system's timer resolution, which is typically 15.625 ms in Windows (equivalent to a 64 Hz timer frequency).

What does timer resolution mean?

Timer resolution is the smallest unit of time that can be accurately measured by that timer. Timer resolution for the CPU (which is the RTC or Real Time Clock resolution) differs from that of the API made available to the programmer by the operating system.


2 Answers

I found that Windows 7 keeps track of timer resolution per process in the _EPROCESS kernel structure.

With debugging enabled (boot with /debug) it is possible to browse the ExpTimerResolutionListHead list with windbg (run windbg -kl) and extract timer information like this:

lkd> !list "-e -x \"dt nt!_EPROCESS @$extret-@@(#FIELD_OFFSET(nt!_EPROCESS,TimerResolutionLink)) ImageFileName UniqueProcessId SmallestTimerResolution RequestedTimerResolution\" nt!ExpTimerResolutionListHead"

In my case however the process ID was NULL (probably because a driver made the request), and I still couldn't figure out which driver it was.

like image 164
rustyx Avatar answered Oct 14 '22 15:10

rustyx


The only way I know and have used so far is injecting into each of running processes and inside that process calling timeEndPeriod for each increased resolution (values 1-15) in a loop over these resolutions and checking whether the timeEndPeriod call for a current resolution returns TIMERR_NOCANDO or TIMERR_NOERROR (note: these return values are NOT correspondingly false and true). And if it returns TIMERR_NOERROR then concluding that the program is using that frequency, and then calling again timeBeginPeriod to restore the original resolution requested by the program.

Unfortunately this method does not detect the 0.5 ms timer resolutions that can be set by undocumented NtSetTimerResolution function.

If you want to continuously monitor the new timer resolutions then hooking calls to undocumented NtSetTimerResolution function in ntdll.dll is the way I use currently (the function's signature can be taken for example from here).

Unfortunately hooking does not detect timer resolutions that were requested before the hook was installed, so you need to combine it with the above timeEndPeriod trick and note also that the 0.5 ms resolution requests before the hooking stay undetected.

And I agree, this method seems cumbersome. Moreover, it is a bit intrusive since it modifies the state of the process, and also assumes that you are able to inject into all processes.

If anybody has better methods, I would be interested knowing about them too.

like image 23
Roland Pihlakas Avatar answered Oct 14 '22 13:10

Roland Pihlakas