Является ли in_irq() надежным?

Ненадежное руководство по взлому ядра Linux утверждает, что

Вы можете сказать, что находитесь в состоянии аппаратного прерывания, потому что функция in_irq() возвращает значение true.
Внимание. Помните, что это вернет ложное срабатывание, если прерывания отключены (см. ниже).

Действительно ли in_irq() может возвращать ненулевое значение не в контексте hardirq в ядрах Linux 2.6.32 или новее на x86?

В моих экспериментах с ядром 2.6.32 (Debian 6) и 3.4 (OpenSUSE 12.1) in_irq() всегда возвращал 0 при вызове из контекста процесса, даже если он вызывался между local_irq_disable() и local_irq_enable(). Результаты были такими же, когда я использовал функции спин-блокировки, которые отключают прерывания вместо local_irq*.

Из исходного кода ядра я в настоящее время не вижу, как in_irq() может возвращать ложное срабатывание. Может ли кто-нибудь прояснить это?

РЕДАКТИРОВАТЬ: я также пробовал API спин-блокировки *_irqsave() и *_irq(), а также local_irq_save()/local_irq_restore(), результаты были одинаковыми, то есть in_irq() возвращал 0, когда прерывания были отключены. Явное отключение прерываний с помощью машинной инструкции cli на x86 также не заставляло функцию in_irq() возвращать ненулевое значение.


person Eugene    schedule 04.02.2013    source источник


Ответы (1)


in_irq() — это оболочка, которая просматривает некоторые биты в preempt_count, который является целым числом в структуре thread_info, а значение 0 означает, что он не вытеснен, поэтому он не находится в прерывании.

local_irq_disable() сам по себе не влияет на этот подсчет, но spin_lock_irqsave() делает, что может привести к ложное срабатывание. Вы говорите, что использовали функции спин-блокировки, вы использовали эту? Если это так, посмотрите, не меняется ли значение preempt_count.

РЕДАКТИРОВАТЬ: Просто чтобы охватить все базы, убедитесь, что упреждение ядра включено.

person engineerC    schedule 12.02.2013
comment
CONFIG_PREEMPT, конечно же, 'y'. Да, я проверил *_irqsave, *_irq и *_bh варианты API спин-блокировки. В каждом случае in_irq() возвращал 0, даже если спин-блокировка была заблокирована. - person Eugene; 13.02.2013
comment
Да, я видел реализацию in_irq(). Вот почему я не понимаю, почему он не дает ложных срабатываний на моих машинах. - person Eugene; 13.02.2013
comment
Возвращает ли in_irq() ненулевое значение, когда спин-блокировка заблокирована или прерывания отключены другим способом в ваших экспериментах? - person Eugene; 13.02.2013
comment
Мне также не удалось получить ненулевое значение из in_irq() или из preempt_count. (3.2.0.31) - person engineerC; 15.02.2013
comment
Спасибо за информацию. Что ж, я попытаюсь углубиться в этот код ядра, когда у меня будет время. Можно предположить, что in_irq() надежна на x86; не уверен насчет ARM, нужно это тоже изучить. Но, возможно, это может быть ненадежно на некоторых других архитектурах. Посмотрим. В любом случае, спасибо за ваш вклад. - person Eugene; 15.02.2013