Спин-блокировка
Спин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть другие прерывания того же типа, и другие процессоры могут приступить к их обработке. Без спин-блокировки к главному дескриптору прерывания могли бы обратиться сразу несколько процессоров. Как мы увидим, избежать этого абсолютно необходимо.
Получив спин-блокировку, функция вызывает метод аск главного дескриптора прерывания. При работе со старым программируемым контроллером прерываний 8259А соответствующая функция mask_and_ack_8259A подтверждает прерывание и отключает IRQ-линию. Маскировка IRQ-линии гарантирует, что процессор не станет принимать последующие прерывания этого типа, пока не завершится обработчик прерывания. Вспомним, что функция
do iRQO работает при отключенных внешних прерываниях.
Управляющий
Блок процессора автоматически сбрасывает флаг if в регистре ef lags, потому что обработчик прерывания вызывается с помощью шлюза прерывания, хранящегося в таблице дескрипторов прерываний. Однако мы вскоре увидим, что ядро может снова включить локальные прерывания перед выполнением служебных процедур обработки данного прерывания.
Ситуация намного усложняется при использовании усовершенствованного программируемого контроллера ввода/вывода прерываний. В зависимости от типа прерывания его подтверждение может быть либо произведено с помощью метода аск, либо отложено до завершения обработчика прерываний (то есть подтверждение может быть выполнено методом end). В любом случае мы принимаем как само собой разумеющееся то, что локальный APIC- контроллер не будет воспринимать последующие прерывания этого типа, пока не завершится обработчик прерываний, хотя эти прерывания могут быть приняты другими процессорами.
Затем функция do iRQ инициализирует несколько флагов главного дескриптора прерывания. Она устанавливает флаг irq pending, потому что прерывание было подтверждено (в определенном смысле), но фактически еще не обработано. Кроме того, функция сбрасывает флаги irq waiting и irq replay
Далее функция do iRQ проверяет, действительно ли она должна обработать прерывание.
Существует три случая, в которых ничего не нужно предпринимать:
— Флаг irq disabled установлен — процессор, возможно, вызвал функцию
do iRQ, хотя соответствующая IRQ-линия отключена.
Описание этого
Кроме того, материнские платы с дефектами могут генерировать ложные прерывания, даже если IRQ-линия в программируемом контроллере прерываний отключена.
— Флаг irq inprogress установлен — в многопроцессорной системе другой процессор, возможно, обрабатывает предыдущее возникновение того же прерывания. Почему бы не переложить обработку данного прерывания на тот процессор? Именно так и поступает Linux. Этот подход упрощает архитектуру ядра, потому что служебным процедурам обработки прерываний от драйверов устройств не нужно быть реентерабельными (их выполнение сериализуется). Кроме того, освободившийся процессор может быстро вернуться к своим прежним делам, не загрязняя свой аппаратный кэш, а это способствует повышению производительности системы. Флаг irq inprogress устанавливается, когда процессор собирается выполнить служебные процедуры обработки прерывания, и поэтому функция do iRQ проверяет его до начала реальной работы.
— Поле irq desc [irq]. action содержит null — эта ситуация возникает, когда с прерыванием не ассоциировано никакой служебной процедуры. Обычно это случается, только когда ядро зондирует аппаратное устройство.
Предположим, что ни один из трех случаев не имеет места, и прерывание должно быть обслужено. Функция do iRQ устанавливает флаг irq inprogress и входит в цикл. На каждом шаге цикла она сбрасывает флаг irq pending, освобождает спин-блокировку прерывания и выполняет служебные процедуры обработки прерывания, для чего вызывает функцию handie iRQ event.
Когда последняя возвратит управление, функция do iRQ снова получает спин-блокировку и проверяет состояние флага irq pending. Если он сброшен, значит, последующие сигналы этого прерывания не были доставлены другому процессору, так что цикл завершается. Если же флаг irq pending установлен, значит, другой процессор вызвал функцию do iRQ для этого типа прерывания, пока этот процессор ВЫПОЛНЯЛ фуНКЦИЮ handie iRQ event. Тогда фуНКЦИЯ do iRQ ВЫ- полняет еще один шаг цикла, обслуживая новое возникновение этого прерывания.
Теперь наша функция do iRQ готова завершить свою работу, либо потому что она уже выполнила служебные процедуры обработки прерывания, либо потому что ей ничего не надо было делать. Функция вызывает метод end главного дескриптора прерывания. При работе со старым программируемым КОНТрОЛЛерОМ Прерываний 8259А соответствующая фуНКЦИЯ end_8259A_irq снова включает IRQ-линию (если прерывание не было ложным). При использовании усовершенствованного программируемого контроллера ввода/вывода прерываний метод end подтверждает прерывание (если этого не сделал метод аск).
Наконец, функция do iRQO освобождает спин-блокировку— самая трудная часть работы закончена!