Запрещение определенной линии прерывания
Запрещение определенной линии прерывания
В предыдущем разделе были рассмотрены функции, которые позволяют запретить доставку всех прерываний на определенном процессоре. В некоторых случаях полезным может оказаться запрещение определенной линии прерывания во всей системе. Это называется маскированием линии прерывания. Например, может потребоваться запрещение доставки прерывания от некоторого устройства перед манипуляциями с его состоянием. Для этой цели операционная система Linux предоставляет четыре интерфейса.
void disable_irq(unsigned int irq);
void disable_irq_nosync(unsigned int irq);
void enable_irq(unsigned int irq);
void synchronize_irq(unsigned int irq);
Первые две функции позволяют запретить указанную линию прерывания в контроллере прерываний. Это запрещает доставку данного прерывания всем процессорам в системе. Кроме того, функция disable_irq() не возвращается до тех пор, пока все обработчики прерываний, которые в данный момент выполняются, не закончат работу. Таким образом гарантируется не только то, что прерывания с данной линии не будут доставляться, но и то, что все выполняющиеся обработчики закончили работу. Функция disable_irq_nosync() не имеет последнего свойства.
Функция synchronize_irq() будет ожидать, пока не завершится указанный обработчик, если он, конечно, выполняется.
Вызовы этих функций должны быть сгруппированы, т.е. каждому вызову функции disable_irq() или disable_irq_nosync() должен соответствовать вызов функции enable_irq(). Только после последнего вызова функции enable_irq() линия запроса на прерывание будет снова разрешена. Например, если функция disable_irq() последовательно вызвана два раза, то линия запроса на прерывание не будет разрешена, пока функция enable_irq() тоже не будет вызвана два раза.
Эти три функции могут быть вызваны из контекста прерывания и из контекста процесса и не приводят к переходу в приостановленное состояние (sleep). При вызове из контекста прерывания следует быть осторожным! Например, нельзя разрешать линию прерывания во время выполнения обработчика прерывания (вспомним, что линия запроса на прерывание обработчика, который в данный момент выполняется, является замаскированной).
Было бы также плохим тоном запрещать линию прерывания, которая совместно используется несколькими обработчиками. Запрещение линии прерывания запрещает доставку прерываний для всех устройств, которые используют эту линию. Поэтому в драйверах новых устройств не рекомендуется использовать эти интерфейсы[33]. Так как устройства PCI должны согласно спецификации поддерживать совместное использование линий прерываний, они вообще не должны использовать эти интерфейсы. Поэтому функция disable_irq() и дружественные ей обычно используются для устаревших устройств, таких как параллельный порт персонального компьютера.