Эти функции обычно реализуются в виде одной инструкции на языке ассемблера (что, конечно, зависит от аппаратной платформы). Для платформы x86 функция local_irq_disable()
— это просто машинная инструкция cli
, а функция local_irq_enable()
— просто инструкция sti
. Для хакеров, не знакомых с платформой x86, sti
и cli
— это ассемблерные вызовы, которые соответственно позволяют установить (
Функция local_irq_disable()
является опасной в случае, когда local_irq_enable()
разрешит прерывания независимо от того, были они запрещены первоначально (до вызова local_irq_disable()
) или нет. Для того чтобы избежать такой ситуации, необходим механизм, который позволяет восстанавливать состояние системы обработки прерывании в первоначальное значение. Это требование имеет общий характер, потому что некоторый участок кода ядра в одном случае может выполняться при разрешенных прерываниях, а в другом случае— при запрещенных, в зависимости от последовательности вызовов функций. Например, пусть показанный фрагмент кода является частью функции. Эта функция вызывается двумя другими функциями, и в первом случае перед вызовом прерывания запрещаются, а во втором — нет. Так как при увеличении объема кода ядра становится сложно отслеживать все возможные варианты вызова функции, значительно безопаснее сохранять состояние системы прерываний перед тем, как запрещать прерывания. Вместо разрешения прерываний просто восстанавливается первоначальное состояние системы обработки прерываний следующим образом.
unsigned long flags;
local_irq_save(flags);
/* прерывания запрещены . . */
local_irq_restore(flags);
/* состояние системы прерываний восстановлено
в первоначальное значение ... */
Нужно заметить, что эти функции являются макросами, поэтому передача параметра flags
выглядит как передача по значению. Этот параметр содержит зависящие от аппаратной платформы данные, которые в свою очередь содержат состояние системы прерываний. Так как, по крайней мере для одной аппаратной платформы (SPARC), в этой переменной хранится информация о стеке, то параметр flags
нельзя передавать в другие функции (другими словами, он должен оставаться в одном и том же стековом фрейме). По этой причине вызовы функций сохранения и восстановления должны выполняться в теле одной функции.
Все описанные функции могут вызываться как из обработчика прерываний, так и из контекста процесса.