netlib.narod.ru | < Назад | Оглавление | Далее > |
Эта функция является применяемым в симметричной мультипроцессорной системе аналогом функции update_process_times (строка 27382), применяемой только в однопроцессорных системах. Она выполняет все, что выполняет update_process_times (обновляет статистическую информацию процесса и ядра об использовании процессора), а также кое-что еще. Необычно то, что мультипроцессорная версия этих средств не была введена в однопроцессорную функцию, а была создана полностью отдельная функция такого же назначения. После изучения этой функции легко понять, почему было сделано именно так: она настолько отличается от однопроцессорной версии, что попытка объединить две версии для разных архитектур была бы бессмысленной. Функция smp_local_timer_interrupt может быть вызвана из двух мест:
5059: Счетчик prof_counter (строка 4610) следит за тем, как долго ядро должно ждать до обновления статистической информации процесса и ядра; если этот счетчик еще не достиг 0, управление фактически переходит к концу функции. Как описано в комментариях в этом коде, входы prof_counter начинают обратный отсчет с 1, если это значение не увеличено оператором root и, в связи с этим, эта работа по умолчанию выполняется при каждом импульсе сигнала таймера. Впоследствии, счетчик prof_counter[cpu] инициализируется из prof_multiplier[cpu].
Это, безусловно, оптимизация, поскольку выполнение всей работы внутри этого блока if при каждом импульсе сигнала времени привело бы к значительному замедлению, поэтому мы можем предпочесть пожертвовать некоторой точностью и выполнять эту работу с применением пакетной организации. Поскольку множитель профилирования является настраиваемым, можно выбрать желаемый коэффициент компромисса между быстродействием и точностью.
Однако автора в этом коде смущает одна тонкость: безусловно, после того, как счетчик prof_multiplier[cpu] будет исчерпан, статистические данные должны быть обновлены, как при истечении интервала, обозначенного величиной prof_multiplier[cpu], поскольку так и должно быть. (За исключением того случая, когда было просто изменено само значение prof_multiplier[cpu], но это мы пока не рассматриваем.) Вместо этого, код действует так, как если бы прошел интервал величиной только в один импульс таймера. Может быть, разработчики ядра намеревалась позднее где-то умножить число зарегистрированных импульсов таймера на величину prof_multiplier[cpu], но это в настоящее время не сделано.
5068: Если система во время активизации прерывания от таймера работала в режиме пользователя, то функция smp_local_timer_interrupt исходит из того, что весь этот импульс таймера был передан в режиме пользователя; в ином случае, она исходит из того, что весь импульс таймера был передан в режиме системы.
5073: Захватывает глобальную блокировку прерывания с помощью функции irq_enter (строка 1792). Это еще одна причина, по которой может потребоваться применение пакетной организации этой работы, поскольку вместо приобретения глобальной блокировки прерывания при каждом импульсе сигнала таймера, что может стать значительным источником конкуренции между процессорами, эта функция может захватывать его менее часто. Поэтому она действительно захватывает блокировку чаще, но в связи с этим, ей не приходится владеть этой блокировкой в течение более продолжительного времени при каждом ее захвате. Здесь опять возникает компромисс между повышением эффективности и потерей точности.
5074: Не заботится о ведении статистики для холостых процессов, поскольку это привело бы просто к бесполезному расходованию циклов процессора. Тем не менее, ядро отслеживает суммарное время простоя системы и любая более подробная статистическая информация об этом холостом процессе имела бы не очень большую ценность (например, мы знаем, что они всегда выполняются в режиме системы, поэтому нет необходимости явно вычислять интервалы времени их работы в системе).
5075: В этом функции update_process_times и smp_local_timer_interrupt имеют много общего: они обе вызывают функцию update_one_process для выполнения работы по обновлению статистической информации об использовании процессора отдельным процессом.
5077: Уменьшает значение счетчика процесса (его динамический приоритет), отмечая его для перепланирования, если он исчерпан.
5082: Обновление статистической информации ядра. Как и в функции update_process_times, время, израсходованное в режиме пользователя, будет отнесено либо к отсчету в ядре «времени пребывания в режиме с высоким значением nice» (с низким приоритетом), либо к отсчету обычного времени пользователя, в зависимости от того, находился ли приоритет данного процесса ниже DEF_PRIORITY.
5094: Повторная инициализация счетчика prof_counter процессора и освобождение глобальной блокировки прерывания. Безусловно, это должно выполняться именно в таком порядке, поскольку в другой последовательности выполнения перед повторной инициализацией значения prof_counter могло бы возникнуть еще одно прерывание от таймера.
netlib.narod.ru | < Назад | Оглавление | Далее > |