我需要保护我的中断处理程序避免被相同的中断多次调用吗?
给定以下代码,我不确定应该进行哪些系统调用。我当前的实现偶尔会出现随机死锁情况:
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
中,应该使用spin_lock_irq
/spin_lock_irqsave
/local_irq_disable
替代down_interruptible
吗? - 在
set/clear_intr
方法中,应该使用spin_lock_irqsave
/local_irq_disable
替代spin_lock_irq
吗? - 在硬件产生的中断被内核处理程序处理并且驱动程序在处理它之前不清除它时,它们能持续产生/获取中断吗?当处理程序正在处理中断时,
interrupt_handler
是否会反复调用? - 如果当前实现的中断处理程序是可重入的,那么它会在
down_interruptible
上阻塞吗?
引用自LDD3:-
必须是可重入的——它必须能够同时在多个上下文中运行。
编辑1) 经过一些好帮助,我们得到以下建议 :-
- 从
interrupt_handler
中删除down_interruptible
- 将
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...
}
编辑2)在阅读了一些其他的SO帖子之后:阅读为什么内核代码/线程在中断上下文中无法睡眠?,其中链接到罗伯特·洛夫(article)的文章,我发现了这个:
一些中断处理程序(在Linux中称为快速中断处理程序)会禁用本地处理器上的所有中断。这样做是为了确保中断处理程序尽可能快地运行而不被打断。此外,所有中断处理程序都在所有处理器上禁用其当前中断线。这确保了同一中断线的两个中断处理程序不会并发运行。它还防止设备驱动程序编写人员处理递归中断,这会使编程变得复杂。
我启用了快速中断(SA_INTERRUPT)!因此不需要互斥锁/锁/信号量/自旋/等待/睡眠等等!
spin_lock_irq
。我建议你至少更改中断处理程序中的调用,改用spin_lock_irqsave
。 - Hasturkun