Функция | Описание |
---|---|
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, "Обработка нижних половин и отложенные действия", при использовании блокировок в работе с обработчиками нижних половин необходимо принимать некоторые меры предосторожности. Функция spin_lock_bh()
позволяет захватить указанную блокировку и запретить все обработчики нижних половин. Функция spin_unlock_bh()
выполняет обратные действия.
Обработчик нижних половин может вытеснять код, который выполняется в контексте процесса, поэтому, если данные совместно используются обработчиком нижней половины и контекстом процесса, в контексте процесса эти данные необходимо защищать путем запрещения обработки нижних половин и захвата блокировки. Аналогично, поскольку обработчик прерывания может вытеснить обработчик нижней половины, необходимо запрещать прерывания и захватывать блокировку.
Вспомним, что два тасклета (tasklet) одного типа не могут выполняться параллельно. Поэтому нет необходимости защищать данные, которые используются только тасклетами одного типа.
Если данные используются тасклетами разных типов, то необходимо использовать обычную спин-блокировку перед тем, как обращаться к таким данным в обработчике нижней половины. В этом случае нет необходимости запрещать обработку нижних половин, так как тасклет никогда не вытесняет другой тасклет, выполняющийся на том же процессоре.
В случае отложенных прерываний (softirq), независимо от того, это отложенные прерывания одного типа или разных, данные, совместно используемые обработчиками отложенных прерываний, необходимо защищать с помощью блокировки. Вспомним, что обработчики отложенных прерываний, даже одного типа, могут выполняться одновременно на разных процессорах системы. Обработчик отложенного прерывания никогда не вытесняет другие обработчики отложенных прерываний, которые выполняются на одном процессоре с ним, поэтому запрещать обработку нижних половин в этом случае не нужно.
Спин-блокировки чтения-записи
Иногда в соответствии с целью использования блокировок их можно разделить два типа — блокировки чтения (reader lock) и блокировки записи (writer lock). Рассмотрим некоторый список, который может обновляться и в котором может выполняться поиск. Когда список обновляется (в него осуществляется запись), никакой другой код не может параллельно осуществлять запись или чтение этого списка. Запись означает исключительный доступ. С другой стороны, если в списке выполняется поиск (чтение информации), важно только, чтобы никто другой не выполнял записи в список. Работа со списком заданий в системе (как обсуждалось в главе 3, "Управление процессами") аналогична только что описанной ситуации. Не удивительно, что список заданий в системе защищен с помощью спин-блокировки чтения- записи (reader-writer spin lock).