Как работает spin_lock_bh ()? - PullRequest
0 голосов
/ 16 мая 2018

У меня есть драйвер устройства, с которым я работаю, который имеет общий ресурс между ISR (точнее, нижней половиной ISR) и вызовом read().

ISR ничего не делает, кроме как звонит schedule_work(), чтобы получить нижнюю половину для выполнения тяжелой работы. Ресурс распределяется между read() (то есть пользовательским контекстом) и функцией, которая реализует нижнюю половину, поэтому я блокирую с spin_lock_bh().

Чего я не понимаю, так это механики блокировки. Скажем, кто-то в данный момент удерживает блокировку, что происходит, когда ISR достигает schedule_work() (то есть аппаратное прерывание сработало, пока мы удерживали блокировку)? Работы по-прежнему планируются, а затем выполняются позднее или же они падают на пол? Другими словами ... что на самом деле «заблокировано» или предотвращено (то есть очередь работ или выполнение работы)? Обновляется ли рабочая очередь?

Чтобы противопоставить мой вопрос, я понимаю, что, если бы я использовал spin_lock_irqsave(), ISR был бы отключен, удерживая блокировку, поэтому я бы не получил schedule_work(), во-первых, но учитывая, как ресурс поделился, я не думаю, что мне нужно или не нужно отключать аппаратные прерывания при удержании блокировки.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

spin_lock_bh отключает softirqs (bh - древний термин, который на самом деле относится к softirqs). Однако work_queues, запускаемые с schedule_work, на самом деле выполняются не в softirq, а в выделенном потоке, таким образом обрабатывая контекст.

Таким образом, вашему драйверу необходим простой spin_lock () для защиты от одновременных вызовов read ().

Возможно, потребуется отключить прерывания при доступе к ресурсам, которые используются совместно с «верхней половиной», но это не входит в сферу вашего вопроса.

0 голосов
/ 16 мая 2018

ISR не может ждать блокировки, если она может удерживаться кодом, который не отключает прерывания. Это приведет к тупику. spin_lock_irqsave сначала отключает прерывания, сохраняя предыдущее состояние, затем снимает блокировку. Восстановление отменяет это в обратном порядке.

Нижняя половина все еще является прерыванием. spin_lock_bh делает то же самое, отключая нижнюю половину выполнения, а затем снимая блокировку. Это предотвращает наступление нижней половины на наш код read.

Блокировка не позволяет нескольким потокам выполнять заблокированный код. Рабочая очередь защищена только тем, что ее удерживают, удерживая блокировку.

...