Планировщик Windows - как работает разделение по времени? - PullRequest
1 голос
/ 25 марта 2019

Внутренние компоненты Windows ( перейдите к разделу Quantum End ), в котором говорится, как в предыдущих версиях Windows использовалось несправедливое наказание за потоки, но, начиная с Vista, теперь она дольше заряжает потоки, которые запускаются на полпути через тактовый интервал или для обработки прерываний. ,

Я знаком с ядром ReactOS и исходным кодом ядра исследований Windows. Функция KiQuantumEnd вызывается с помощью KiDispatchinterrupt, который, скорее всего, вызывается программным прерыванием, которое запрашивается, когда истекает квант, т. Е. Поток начинается с 6 квантовых единиц, а 3 вычитаются при каждом тактовом прерывании и когда оно больше или равно до 0 ISR прерывания тактовой частоты (KiUpdateRunTime) запрашивает Self IPI. KiQuantumEnd документируется только в ReactOS, и поскольку ReactOS демонстрирует поведение XP, он не проверяет несправедливое наказание, а просто планирует и отправляет новый поток.

Очевидно, что в Windows Vista и далее она будет реализована по-другому, но WRK не предоставляет эту функцию, поэтому я не могу ее изучить. Хотелось бы мне знать, как на самом деле он реализует разделение по времени, которое указано на внутреннем устройстве Windows.

Единственный способ, которым я могу думать, - это общий обработчик прерываний (недокументированный KiInterruptDispatch), который регистрируется во всех нецепных записях ISR, которые вызывают ISR из объекта прерывания, потенциально может сделать RDTSC, если уровень вложенности равен 1 затем увеличивают уровень вложенности и в конце прерывания, когда возвращается KiInterruptDispatch, уменьшают уровень вложенности, и если он равен 1, он может сделать еще один RDTSC и сохранить разницу между ними в элементе объекта потока ( таким образом, внешнее прерывание сохраняет время). Это, конечно, не будет учитываться для SMI, и это противоречит формулировке раздела о внутренних окнах, который предполагает, что записанное потоком записано общее количество циклов, но это звучит гораздо менее практично, чем предложенный мной метод. Имеет смысл записать в объекте потока количество потерянных циклов, а не циклов, загруженных в поток, и я не могу придумать никакого практического способа, которым он отслеживал бы это.

Что касается сценария, в котором поток запланирован в середине тактового интервала, то я могу думать только о том, как он это делает, путем планирования кода, принимающего RDTSC и сохраняющего его в отдельном элементе потока, а затем KiQuantumEnd выполнение RDTSC, вычитание исходного значения, записанного, когда оно было запланировано, и затем вычитание другого члена, который записывает потерянные циклы, а затем сравнение с целевым количеством циклов.

В структуре KTHREAD есть интересные поля, такие как «CycleTime» и «CurrentRunTime».

Если кто-нибудь знает о какой-либо другой реализации или фактической реализации, пожалуйста, дайте мне знать.

...