если текущее значение goodness получается
если текущее значение goodness получается равным 0, то производится просмотр всего списка процессов (не только runqueue!) и производится перерасчет динамических приоритетов следуя простому алгоритму:
recalculate: { struct task_struct *p; spin_unlock_irq(&runqueue_lock); read_lock(&tasklist_lock); for_each_task(p) p->counter = (p->counter >> 1) + p->priority; read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); }
Следует отметить, что перед выполнением цикла перерасчета сбрасывается runqueue_lock, поскольку цикл может занять довольно продолжительное время, в течение которого schedule() может быть вызвана другим процессором, в результате чего может быть найдена задача с goodness достаточным для запуска на этом процессоре. По общему признанию это выглядит несколько непоследовательным, потому что в то время как один процессор отбирает задачи с наивысшим goodness, другой вынужден производить перерасчет динамических приоритетов.
В этой точке next указывает на задачу, которая должна быть запланирована, далее в next->has_cpu заносится 1 и в next->processor заносится значение this_cpu. Блокировка runqueue_lock
может быть снята.
Если происходит возврат к предыдущей задаче (next == prev) то просто повторно устанавливается блокировка ядра и производится возврат, т.е. минуя аппаратный уровень (регистры, стек и т.п.) и настройки VM (переключение каталога страницы, пересчет active_mm и т.п.).
Макрос switch_to() является платформо-зависимым. На i386 это имеет отношение к:
a) обработке FPU (Floating Point Unit - арифметический сопроцессор)
b) обработке LDT (Local Descriptor Table)
c) установке сегментных регистров
d) обработке TSS (Task State Segment) и
e) установке регистров отладки.
Содержание Назад Вперед