Geoff Chappell - Software Analyst
In a DISPATCHER_HEADER that begins a KTIMER, the Type at offset 0x00 is TimerNotificationObject (0x08) or TimerSynchronizationObject (0x09). The byte at offset 0x01 is historically the single member Absolute, ever since version 4.0 started recording that the due time had been set as an absolute system time rather than as relative to the current interrupt time. To accommodate the TolerableDelay argument of the new KeSetCoalescableTimer function without changing the size of the KTIMER, Windows 7 reworked the byte into bit fields in union with a UCHAR member named TimerControlFlags. The old Absolute survives as one of the bit fields.
Mask | Definition | Versions |
---|---|---|
0x01 |
UCHAR Absolute : 1; |
6.1 and higher |
0x02 |
UCHAR Coalescable : 1; |
6.1 only |
UCHAR Wake : 1; |
6.2 and higher | |
0x04 (6.1) |
UCHAR KeepShifting : 1; |
6.1 only |
0xF8 (6.1); 0xFC |
UCHAR EncodedTolerableDelay : 5; |
6.1 only |
UCHAR EncodedTolerableDelay : 6; |
6.2 and higher |
If a timer is set though KeSetCoalescableTimer with a non-zero TolerableDelay, then Coalescable is set. If a non-zero Period is specified too, then in Windows 7 KeepShifting is set and the EncodedTolerableDelay is the binary logarithm of the TolerableDelay. Perhaps this was thought too coarse, at least for long tolerances on long periods. For instance, of the documentation’s suggestions, 150 and 250ms both get treated as 128. Windows 8 changed to a proportional encoding: specifically, the EncodedTolerableDelay is the TolerableDelay (in milliseconds) multiplied by 10,000 and shifted right by 18 bits, truncated to a maximum of 0x3F.
Starting with the Windows Driver Kit (WDK) for Windows 8, the bit width of EncodedTolerableDelay is defined symbolically as TIMER_TOLERABLE_DELAY_BITS.