Я поддерживаю драйвер, который разделяет некоторый ресурс между ISR (т.е. в контексте прерывания) и системным вызовом read()
.В обоих случаях используется spin_lock_irqsave()
, поскольку (очевидно) ресурс может быть получен в контексте прерывания.
Однако мне было интересно, необходимо ли использовать spin_lock_irqsave()
в контексте прерывания.А именно, Ненадежное руководство по блокировке (см. Здесь: https://kernel.readthedocs.io/en/sphinx-samples/kernel-locking.html) утверждает:
Обратите внимание, что spin_lock_irqsave()
отключит прерывания, если они включены, в противном случае ничего не делает (если мыуже в обработчике прерываний), следовательно, эти функции можно безопасно вызывать из любого контекста.
В результате, это обычная практика - использовать «нормальный» spin_lock()
в обработчике прерываний (так какопределенное прерывание уже отключено), а затем вызовите spin_lock_irqsave()
в контексте пользователя? В качестве альтернативы, лучше просто использовать spin_lock_irqsave()
везде? Я склоняюсь к последнему по двум причинам:
- Как только кто-то увидит, что блокировка получена с помощью
spin_lock_irqsave()
, становится очевидным, что блокировка предназначена для совместного использования с контекстом прерывания. - Поскольку кто-то поддерживает код, вам не нужноубедитесь, будет ли определенная функция вызываться в каком контексте. Сказано иначе, использование
spin_lock_irqsave()
работает в любом контексте, поэтому вам не нужно гарантировать, что функцияВызывается только в определенном контексте.
С учетом сказанного выше, мне интересно, что такое соглашение / лучшие практики для кода, который находится в пространстве ядра.Лучше ли использовать spin_lock_irqsave()
везде, где получена блокировка, даже если вы можете гарантировать, что блокировка получается из контекста прерывания?