Шрифт:
На однопроцессорной машине показанный пример только лишь запретит прерывания, чтобы предотвратить доступ обработчика прерывания к совместно используемым данным, а механизм блокировок скомпилирован не будет. Функции захвата и освобождения блокировки также соответственно запрещают и разрешают преемптивность ядра.
Важно, чтобы каждая блокировка была четко связана с тем, что она блокирует. Еще более важно — это защищать данные, а не код. Несмотря на то что во всех примерах этой главы рассматриваются критические участки, в основе этих критических участков лежат данные, которые требуют защиты, а никак не код. Если блокировки просто блокируют участки кода, то такой код труднопонимаем и подвержен состояниям гонок. Необходимо ассоциировать данные с соответствующими блокировками. Например, структура
Если точно известно, что прерывания разрешены, то нет необходимости восстанавливать предыдущее состояние системы прерываний. Можно просто разрешить прерывания при освобождении блокировки. В этом случае оптимальным будет использование функций
Для любого участка кода очень сложно гарантировать, что прерывания всегда разрешены. В связи с этим не рекомендуется использовать функцию
Параметр конфигурации ядра
Другие средства работы со спин-блокировками
Функция
Функция
48
Использование этих функций может привести к тому, что код становится "грязным". Нет необходимости часто проверять значение спин-блокировок — код или всегда должен захватывать блокировку, или вызываться только, если блокировка захвачена. Однако существуют некоторые ситуации, когда такие функции логично использовать, поэтому эти интерфейсы и предоставляются.
В табл. 9.3 приведен полный список функций работы со спин-блокировками.
Таблица 9.3. Список функций работы со спин-блокировками
Функция | Описание |
---|---|
spin_lock | Захватить указанную блокировку |
spin_lock_irq | Запретить прерывания на локальном процессоре и захватить указанную блокировку |
spin_lock_irqsave | Сохранить текущее состояние системы прерываний, запретить прерывания на локальном процессоре и захватить указанную блокировку |
spin_unlock | Освободить указанную блокировку |
spin_unlock_irq | Освободить указанную блокировку и разрешить прерывания на локальном процессоре |
spin_unlock_irqrestore | Освободить указанную блокировку и восстановить состояние системы прерываний на локальном процессоре в указанное первоначальное значение |
spin_lock_init | Инициализировать объект типа spinlock_t в заданной области памяти |
spin_trylock | Выполнить попытку захвата указанной блокировки и в случае неудачи возвратить ненулевое значение |
spin_is_locked | Возвратить ненулевое значение, если указанная блокировка в данный момент захвачена, и нулевое значение в противном случае |
Спин-блокировки и обработчики нижних половин
Как было указано в главе 7, "Обработка нижних половин и отложенные действия", при использовании блокировок в работе с обработчиками нижних половин необходимо принимать некоторые меры предосторожности. Функция
Обработчик нижних половин может вытеснять код, который выполняется в контексте процесса, поэтому, если данные совместно используются обработчиком нижней половины и контекстом процесса, в контексте процесса эти данные необходимо защищать путем запрещения обработки нижних половин и захвата блокировки. Аналогично, поскольку обработчик прерывания может вытеснить обработчик нижней половины, необходимо запрещать прерывания и захватывать блокировку.
Вспомним, что два тасклета (tasklet) одного типа не могут выполняться параллельно. Поэтому нет необходимости защищать данные, которые используются только тасклетами одного типа.
Если данные используются тасклетами разных типов, то необходимо использовать обычную спин-блокировку перед тем, как обращаться к таким данным в обработчике нижней половины. В этом случае нет необходимости запрещать обработку нижних половин, так как тасклет никогда не вытесняет другой тасклет, выполняющийся на том же процессоре.
В случае отложенных прерываний (softirq), независимо от того, это отложенные прерывания одного типа или разных, данные, совместно используемые обработчиками отложенных прерываний, необходимо защищать с помощью блокировки. Вспомним, что обработчики отложенных прерываний, даже одного типа, могут выполняться одновременно на разных процессорах системы. Обработчик отложенного прерывания никогда не вытесняет другие обработчики отложенных прерываний, которые выполняются на одном процессоре с ним, поэтому запрещать обработку нижних половин в этом случае не нужно.