!timer Abnormalities
The kernel debugger extension command !timer displays information about all outstanding timers in the system. This document explains some of the abnormalities in the output of this command.
Far out expiration times
Some timers in the system have expiration times (i.e. time when the timer will fire) set very far out in the future.
kd> !timer Dump system timers Interrupt time: 02e93b10 00000013 [10/22/2008 22:46:48.740] List Timer Interrupt Low/High Fire Time DPC/thread . . . 464 831d7378 e36e417f 7e36cb37 [ 9/13/30828 18:48:05.477] thread 831d72f0
Timeout specified to NtWaitForSingleObject() is in 100nS intervals and is expressed as a -ve number to denote relative time.
NTSTATUS
NtWaitForSingleObject(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL );
When the caller of this API specifies the Timeout value as 0x7fffffff'ffffffff, which is the largest +ve 64-bit signed integer, it translates to the time 9/13/30828 18:48:05.477. The mswsock.dll function SockWaitForSingleObject() uses this number to imply an INFINITE timeout. This is functionally still correct as the timer never expires as it is intended to.
Following is the assembler code snippet that calls NtWaitForSingleObject().
mswsock!SockWaitForSingleObject+0x12c:
75232220 83cfff or edi,0FFFFFFFFh
75232223 beffffff7f mov esi,7FFFFFFFh
.
.
.
75232232 897de8 mov dword ptr [ebp-18h],edi
75232235 8975ec mov dword ptr [ebp-14h],esi
.
.
.
75232274 8d45e8 lea eax,[ebp-18h] ;Timeout
75232277 50 push eax
75232278 6a01 push 1
7523227a ff7508 push dword ptr [ebp+8]
7523227d ff15d8102375 call dword ptr [mswsock!_imp__NtWaitForSingleObject (752310d8)]
Timers set to "NEVER" expire
Some timers in the system have expiration times set to never expire, so why would someone use a timer that will never expire?
Here is an example of 2 such timers that have threads waiting on them.
kd> !timer
Dump system timers
Interrupt time: 02e93b10 00000013 [10/22/2008 22:46:48.740]
List Timer Interrupt Low/High Fire Time DPC/thread
. . .
13 846d8ce8 cc154910 80000002 [ NEVER ] thread 846d8c60
. . .
830d0658 7a122690 80000001 [ NEVER ] thread 830d05d0
kd> !thread 846d8c60
THREAD 846d8c60 Cid 0424.044c Teb: 7ffde000 Win32Thread: 00000000 WAIT: (DelayExecution) UserMode Alertable
846d8ce8 NotificationTimer
kd> !thread 830d05d0
THREAD 830d05d0 Cid 054c.0994 Teb: 7ffaf000 Win32Thread: 00000000 WAIT: (DelayExecution) UserMode Alertable
830d0658 NotificationTimer
Below is the call stack for such a thread
kd> k ChildEBP RetAddr 98b2cc68 818b0943 nt!KiSwapContext+0x26 98b2ccac 818af6ee nt!KiSwapThread+0x433 98b2cd08 81a0dff3 nt!KeDelayExecutionThread+0x472 98b2cd54 8189c9aa nt!NtDelayExecution+0x8d 98b2cd54 773e9a94 nt!KiFastCallEntry+0x12a 0283fae4 773e83b4 ntdll!KiFastSystemCallRet 0283fae8 7755c350 ntdll!NtDelayExecution+0xc 0283fb50 6d48da2f kernel32!SleepEx+0x62
Both these threads are waiting in an alertable wait initiated from user mode with the call to SleepEx(). The caller invokes SleepEx() with a timeout of -1 (INFINITE) since the thread actually wants to wait for a user mode APC delivery without for any specific time out interval.
As seen in the code below SleepEx() is special cased for the timeout value of (-1) for which it actually sets up a timer with the maximum possible relative timeout i.e. 0x80000000`00000000. This is why the time shows up as "NEVER".
kernel32!SleepEx+0x24 :
7755c322 33ff xor edi,edi
. . .
77520168 897ddc mov dword ptr [ebp-24h],edi
7752016b c745e000000080 mov dword ptr [ebp-20h],80000000h
77520172 8d75dc lea esi,[ebp-24h]
. . .
7755c346 56 push esi ; Delay Interval
7755c347 ff750c push dword ptr [ebp+0Ch]
7755c34a ff15a8155177 call dword ptr [kernel32!_imp__NtDelayExecution (775115a8)]
NTSTATUS NtDelayExecution( IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval );