Run_bottom_halves
Теперь ядро готово выполнить ждущие обработки нижние половины.
Сохраняет текущий набор активных — т.е. помеченных — нижних половин в локальной переменной active и с помощью макроса clear_active_bhs (строка ) очищает установленные разряды в глобальной переменной bh_active. Очистка этих разрядов в переменной bh_active одновременно удаляет метки со всех нижних половин.
Теперь читатели могут убедиться, что иногда нижние половины объединяются в пакеты, как и утверждалось ранее без доказательств. К этому моменту прерывания включены, поэтому если другое прерывание запускается и отмечает уже помеченную нижнюю половину раньше, чем функция run_bottom_halves успеет скопировать bh_active в active, верхняя половина будет выполнена дважды, а нижняя — только один раз. И, поскольку само прерывание также может быть прервано, верхняя половина могла бы быть выполнена трижды при однократном выполнении нижней половины, и т.д. Однако вероятность этого быстро уменьшается с увеличением количества рекурсивных прерываний.
Может ли данный код пропустить какие-либо нижние половины? Давайте предположим, что прерывание происходит в самый неудачный момент времени: между строками и — т.е. после копирования переменной bh_active но перед очисткой разрядов установки в ней. Возможны три случая:
Одновременно просматривает массив bh_base и разряды в переменной active. Если самый младший разряд в active установлен, соответствующая нижняя половина вызывается; затем цикл переходит к следующей записи массива bh_base и к следующему разряду в active.
Поскольку данный цикл является циклом do/while, он выполняется по меньшей мере один раз. Частично это связанно с тем, что вызывающая функция всегда, прежде чем вызывать функцию do_bottom_half, проверяет, нуждаются ли какие-либо нижние половины в обслуживании, и поэтому цикл должен быть выполнен по меньшей мере один раз. Кстати, та проверка могла бы быть помещена и внутрь самой функции do_bottom_half, но выполнение проверки прежде вызова функции предотвращает вызов, если никакие нижние половины не нуждаются в выполнении. В любом случае цикл будет выполняться правильно, даже если никакие нижние половины не нуждаются в выполнении; это привело бы к напрасной трате времени, но не принесло бы никакого иного вреда.
Цикл прерывается, когда в active не остается установленных разрядов. Поскольку по мере выполнения цикла выполняется сдвиг active, все остальные разряды проверяются одновременно, без необходимости выполнения цикла по каждому из них.