Нужно ли мне защищать мой обработчик прерываний, вызываемый много раз для одного и того же прерывания?
Учитывая следующий код, я не уверен, какие системные вызовы мне следует делать . Я получаю редкие случайные блокировки с этой текущей реализацией: -
void interrupt_handler(void)
{
down_interruptible(&sem); // or use a lock here ?
clear_intr(); // clear interrupt source on H/W
wake_up_interruptible(...);
up(&sem); // unlock?
return IRQ_HANDLED;
}
void set/clear_intr()
{
spin_lock_irq(&lock);
RMW(x); // set/clear a bit by read/modify/write the H/W interrupt routing register
spin_unlock_irq(&lock);
}
void read()
{
set_intr(); // same as clear_intr, but sets a bit
wait_event_interruptible(...);
}
interrupt_handler
: down_interruptible
быть spin_lock_irq
/ spin_lock_irq67save / local_irq_disable
?
установить / clear_intr
: spin_lock_irq
быть spin_lock_irqsave
/ local_irq77] ? Может ли он (H / W -> ядро -> обработчик драйвера) продолжать генерировать / получать прерывания, пока он не будет очищен? Может ли interrupt_handler
продолжать вызываться, пока он находится внутри него?
down_interruptible
? Из LDD3: -
должен быть реентерабельным - он должен быть способен работать в более чем одном контексте одновременно.
Изменить 1) после некоторой хорошей помощи предлагаются следующие варианты: -
down_interruptible
изнутри interrupt_handler
spin_lock_irq
вне методов set / clear (не нужны spin_lock_irqsave
вы говорите?) Я правда не вижу выгода от этого?! Код: -
void interrupt_handler(void)
{
read_reg(y); // eg of other stuff in the handler
spin_lock_irq(&lock);
clear_intr(); // clear interrupt source on H/W
spin_unlock_irq(&lock);
wake_up_interruptible(...);
return IRQ_HANDLED;
}
void set/clear_intr()
{
RMW(x);
}
void read()
{
error_checks(); // eg of some other stuff in the read method
spin_lock_irq(&lock);
set_intr(); // same as clear_intr, but sets a bit
spin_unlock_irq(&lock);
wait_event_interruptible(...);
// more code here...
}
Edit2) После прочтения еще нескольких сообщений SO: чтение Почему код ядра / поток, выполняющийся в контексте прерывания, не может спать? , который ссылается на Роберт Лавс ] статью , я прочитал это:
некоторые обработчики прерываний (известные в Linux как обработчики быстрых прерываний) со всеми прерываниями на локальном процессор отключен. Это сделано для убедитесь, что обработчик прерывания работает без перерыва, так быстро, как возможное. Более того, все перебивают обработчики работают со своими текущими линия прерывания отключена на всех процессоры. Это гарантирует, что два обработчики прерываний для того же линия прерывания не работает одновременно. Это также предотвращает устройство писатели драйверов от необходимости обрабатывать рекурсивные прерывания, которые усложняют программирование.
И у меня включены быстрые прерывания (SA_INTERRUPT)! Так что нет необходимости в мьютексах / блокировках / семафорах / вращениях / ожиданиях / засыпании / и т.д. / и т.д.!