Description
Currently, the kernel uses the local APIC timer in oneshot mode. From Timer::schedule_timeout()
, the Tmr_initial
APIC register is set to _last_timeout_duration
in _start_one_shot()
. Afterwards, the APIC timer decrements the counter until it reaches 0, which triggers an interrupt. This is specified as follows.
In one-shot mode, the timer is started by programming its initial-count register. The initial count value is then copied into the current-count register and count-down begins. After the timer reaches zero, an timer interrupt is generated and the timer remains at its 0 value until reprogrammed.
The last part is crucial as the counter does not roll-over but remains 0. Further ticks are therefore lost until the timer is programmed again via _start_one_shot()
and _duration()
returns _last_timeout_duration
on any call.
Switching to APIC TSC deadline mode may be a valid fix.