Интеллектуальное распределение обработки таймерного такта
На рисунке ниже изображены процессоры, выполняющие ISR-процедуру обработки прерывания от часов и обрабатывающие истечение времени таймеров, показано, что процессор 1 привлекается несколько раз (сплошные стрелки), даже при отсутствии связанных с ним таймеров с истечением времени (пунктирные стрелки).
Хотя при работе процессора 1 такое поведение и требуется (для обновления времени выполнения потока или процесса и планирования состояния), что если процессор 1 простаивает (и не должен заниматься истечением времени таймеров)? Зачем ему по-прежнему обрабатывать прерывания от часов? Как уже ранее говорилось, для обновления всеобщего системного времени и такта системных часов требуется только одна дополнительная работа.
В качестве хронометра вполне достаточно назначить всего лишь один процессор (в данном случае процессор 0) и дать возможность другим процессорам оставаться в спящем состоянии. Если они будут разбужены, любые корректировки, связанные со временем, могут быть выполнены путем ресинхронизации с процессором 0.
Фактически Windows так и делает, реализуя данный принцип (который называется интеллигентным распределением обработки таймерного такта), и на следующем рисунке показаны состояния процессоров при выполнении сценария, по которому процессор 1 находится в спящем состоянии (в отличие от прежней картины, где мы предполагали, что он выполняет какой-нибудь код). Как видите, процессор 1 пробуждается только 5 раз для обработки своих таймеров с истечением времени, что создает намного более широкий разрыв (спящий период).
Ядро использует переменную KiPendingTimer, которая содержит массив из структур масок сходства, показывающих, какие логические процессоры нуждаются в получении тактового интервала для заданного исполнителя таймера (интервала такта часов). Затем оно может соответствующим образом запрограммировать контроллер прерываний, а также определить, какому процессору оно будет отправлять IPI для инициирования обработки таймеров.
Оставление как можно больших промежутков играет весьма важную роль, если взять в расчет способ управления электропитанием, применяемый в процессорах: как только процессор обнаружит, что нагрузка постоянно уменьшается, он уменьшает свою потребляемую мощность (P-состояние), пока в конечном итоге не войдет в состояние простоя. У процессора есть возможность выборочно выключать свои составные части и все глубже входить в состояния простоя или спячки, например, он может выключать блоки кэш-памяти.
Но если процессору снова придется пробудиться, на то чтобы включиться, будет затрачена энергия и время; поэтому разработчики процессоров, будут идти на риск, связанный с вводом этих состояний простоя и спячки (C-состояний), только если время, проводимое в этих состояниях, превосходит время и энергозатраты, затрачиваемые на вход в эти состояния и выход из них. Понятно, что нет никакого смысла потратить 10 мс на вход в спящее состояние, которое продлится всего 1 мс.
Мешая прерываниям от часов будить без надобности процессоры (из-за таймеров), можно добиться их более глубокого погружения в C-состояния и более продолжительного пребывания в этих состояниях.