The most important clocks are the three first ones and of these the second is the most interesting.
The synchronous virtual clock is tied to the virtual clock except that it will take into account timer delivery lag caused by host scheduling. It will normally never advance beyond the head timer, and when lagging too far behind it will gradually speed up to catch up with the virtual clock. All devices implementing time sources accessible to and used by the guest is using this clock (for timers and other things). This ensures consistency between the time sources.
The virtual clock is implemented as an offset to a monotonic, high resolution, wall clock. The current time source is using the RTTimeNanoTS() machinery based upon the Global Info Pages (GIP), that is, we're using TSC deltas (usually 10 ms) to fill the gaps between GIP updates. The result is a fairly high res clock that works in all contexts and on all hosts. The virtual clock is paused when the VM isn't in the running state.
The CPU tick (TSC) is normally virtualized as a function of the synchronous virtual clock, where the frequency defaults to the host cpu frequency (as we measure it). In this mode it is possible to configure the frequency. Another (non-default) option is to use the raw unmodified host TSC values. And yet another, to tie it to time spent executing guest code. All these things are configurable should non-default behavior be desirable.
The real clock is a monotonic clock (when available) with relatively low resolution, though this a bit host specific. Note that we're currently not servicing timers using the real clock when the VM is not running, this is simply because it has not been needed yet therefore not implemented.VMM device. The principle is very simple, the guest additions periodically asks the VMM device what the current UTC time is and makes adjustments accordingly.
A complicating factor is that the synchronous virtual clock might be doing catchups and the guest perception is currently a little bit behind the world but it will (hopefully) be catching up soon as we're feeding timer interrupts at a slightly higher rate. Adjusting the guest clock to the current wall time in the real world would be a bad idea then because the guest will be advancing too fast and run ahead of world time (if the catchup works out). To solve this problem TM provides the VMM device with an UTC time source that gets adjusted with the current lag, so that when the guest eventually catches up the lag it will be showing correct real world time.TM clocks described in the previous section. Each clock has its own scheduling facility, or timer queue if you like. There are a few factors which makes it a bit complex. First, there is the usual R0 vs R3 vs. RC thing. Then there are multiple threads, and then there is the timer thread that periodically checks whether any timers has expired without EMT noticing. On the API level, all but the create and save APIs must be mulithreaded. EMT will always run the timers.
The design is using a doubly linked list of active timers which is ordered by expire date. This list is only modified by the EMT thread. Updates to the list are batched in a singly linked list, which is then processed by the EMT thread at the first opportunity (immediately, next time EMT modifies a timer on that clock, or next timer timeout). Both lists are offset based and all the elements are therefore allocated from the hyper heap.
For figuring out when there is need to schedule and run timers TM will: