Ядро Linux в комментариях

       

Reschedule_idle_slow


Функция reschedule_idle_slow, как сказано в этих комментариях, пытается найти холостой процессор для размещения на нем процесса с идентификатором р. Алгоритм основан на том наблюдении, что первые n входов массива заданий представляют собой холостые системные процессы, по одному на каждый из n процессоров компьютера. Холостые процессы работают тогда (и только тогда), когда ни один другой процесс на данном процессоре не хочет получить к нему доступ. Холостой процесс обычно переводит процессор в режим ожидания с малым потреблением энергии с помощью команды hlt, если это возможно. Следовательно, просмотр в цикле первых n процессов в массиве задач— это все, что требуется для поиска холостого процессора, если он существует. Функция reschedule_idle_slow просто опрашивает каждый холостой процесс, выполняется ли он в настоящее время; если да, то процессор, на котором он работает, должен быть холостым и поэтому должен быть хорошим кандидатом для размещения на нем процесса р.

Безусловно, всегда возможно, что выбранный процессор, который с виду является холостым, является таковым только временно и вскоре должен быть загружен сверх меры десятками высокоприоритетных процессов, нуждающихся в большом количестве процессорного времени, которые активизируются через несколько наносекунд. Поэтому такой алгоритм не является идеальным, но он вполне приемлем с точки зрения статистических данных о загрузке процессора, и помните, что такой алгоритм выбран также потому, что он полностью соответствует принятому в планировщике принципу «забегаловки» — не заглядывать слишком далеко вперед и стараться все выполнить побыстрее.

Устанавливает локальные переменные. Здесь best_cpu представляет собой процессор, на котором сейчас работает процесс р; это — «наилучший» процессор, поскольку, если процесс р останется здесь, то не придется промывать кэш или нести другие издержки, a this_cpu обозначает процессор, на котором работает функция reschedule_idle_slow.


Переменные idle и tsk проходят по массиву задач, a target_tsk представляет собой последний найденный работающий холостой процесс (или NULL, если такового нет).

Переменная i инициализируется функцией smp_num_cpus (которая была вызвана за n итераций перед этим) и ведет обратный отсчет при каждой итерации.

Если установлен флажок has_cpu этой холостой задачи, она активно работает на своем процессоре (мы будем называть его «целевым процессором»). Если нет, то целевой процессор занят какой-то другой задачей, поэтому он не является холостым и функция reschedule_idle_slow не будет пытаться запланировать процесс р на него. Здесь проявляется оборотная сторона проблемы, упомянутой перед этим: тот факт, что процессор сейчас не является холостым, не означает, что вскоре на нем не закончат свою работу все его процессы и не сделают его холостым. Но функция reschedule_idle_slow не имеет способа узнать об этом, поэтому она вполне может предполагать, что целевой процессор на какое-то время будет занят. Во всяком случае, вполне вероятно, что так оно и будет, и даже если случится иное, то достаточно скоро на этот процессор, который только что стал холостым, будут запланированы какие-то другие процессы.

Однако, если целевой процессор является текущим процессором, он будет пропущен. Такое решение кажется неожиданным, но так или иначе это — «невероятный» случай: счетчик холостого процесса является отрицательным, поэтому проверка в строке должна была заранее предотвратить возможность достижения настоящей функцией данной точки.

Был найден подходящий холостой процессор; связанный с ним холостой процесс сохраняется с использованием переменной target_tsk. Почему бы теперь просто не прервать цикл, коль скоро найден подходящий целевой процессор? Дело в том, что продолжение цикла может выявить, что процессор, на котором находится процесс р, также холост, и лучше оставить процесс на его текущем процессоре, чем послать на другой, если оба процессора являются холостыми.



Здесь функция reschedule_idle_slow проверяет, является ли холостым процессор, на котором работает процесс р. Если только что найденный холостой процессор является именно тем процессором, на котором уже размещен процесс р, функция переходит вперед к метке send (строка ), чтобы запланировать процесс р на этот процессор.

Функция рассмотрела возможность применения другого процессора; она выполняет обратный отсчет.

Если в этом цикле обнаружены какие-либо холостые процессоры, холостая задача процессора отмечается для перепланирования и функция smp_send_reschedule (строка ) посылает на этот процессор прерывание IPI, чтобы он перепланировал свои процессы.

Можно видеть, что функция reschedule_idle_slow — это прекрасный пример работы по координации взаимодействия между процессорами, которая просто не нужна в однопроцессорной системе. В однопроцессорном компьютере задача определения процессора, который должен быть получен процессом, просто эквивалентна определению того, должен ли процесс получить единственный процессор системы или не должен получить ничего. Поэтому в компьютере с симметричной мультипроцессорной архитектурой нужно также приложить некоторые усилия для определения того, какой из процессоров системы в наибольшей степени подходит для данного процесса. Безусловно, полученное взамен невероятное повышение скорости вполне оправдывает это дополнительное усилие.


Содержание раздела