我是否需要保护我的中断处理程序被同一中断多次调用?
鉴于以下代码,我不确定应该进行的系统调用。我在当前的实现中遇到了罕见的随机死锁:-
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(...);
}
- Should
interrupt_handler
:down_interruptible
be spin_lock_irq
/ spin_lock_irqsave
/ local_irq_disable
?
- Should
set/clear_intr
:spin_lock_irq
be spin_lock_irqsave
/ local_irq_disable
?
- 它(硬件 -> 内核 -> 驱动程序处理程序)能否继续生成/获取中断直到其被清除?可以吗
interrupt_handler
在里面时不断接到电话吗?
- 如果当前实现的中断处理程序是可重入的,那么它会阻塞在
down_interruptible
?
来自LDD3:-
must be 可重入的——它必须能够同时在多个上下文中运行。
编辑1)经过一些很好的帮助后,建议是:-
- remove
down_interruptible
从内部interrupt_handler
- Move
spin_lock_irq
外部设置/清除方法(不需要spin_lock_irqsave
你说?)我实在看不出这样做有什么好处?!
Code :-
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帖子后:阅读为什么在中断上下文中执行的内核代码/线程无法休眠? https://stackoverflow.com/q/1053572/119790链接到罗伯特·洛夫斯article http://www.linuxjournal.com/article/6916,我读到了这个:
一些中断处理程序(已知
Linux 作为快速中断处理程序)运行
所有中断都在本地
处理器已禁用。这样做是为了
确保中断处理程序运行
不间断,尽快
可能的。更何况,全部中断
处理程序以其当前运行
所有中断线均禁用
处理器。这确保了两个
相同的中断处理程序
中断线不运行
同时。它还可以防止设备
驱动程序编写者不必处理
递归中断,这使情况变得复杂
编程。
我启用了快速中断(SA_INTERRUPT)!所以不需要互斥/锁/信号量/旋转/等待/睡眠/等等!
不要在中断上下文中使用信号量,使用spin_lock_irqsave
反而。引用LDD3:
如果你有一个自旋锁,可以
由运行在(硬件
或软件)中断上下文,你
必须使用 spin_lock 的一种形式
禁用中断。正在做
否则可能导致系统死锁,
迟早。如果您不访问
你的锁在硬件中断中
处理程序,但您可以通过软件来完成
中断(在代码中运行完
tasklet,例如,涵盖的主题
在第 7 章中),您可以使用
spin_lock_bh 以安全地避免死锁
同时仍然允许硬件
需要服务的中断。
至于第2点,让你的set_intr
and clear_intr
要求调用者锁定自旋锁,否则你会发现你的代码死锁。再次来自LDD3:
为了使您的锁定正常工作,
你必须写一些函数
假设他们的来电者有
已经获取了相关的锁。
通常,只有你内部的、静态的
函数可以这样写;
从外部调用的函数必须
显式处理锁定。当你
编写内部函数,使
关于锁定的假设,自己做
(以及与您一起工作的任何其他人
代码)一个忙并记录这些
明确的假设。它可以是非常
几个月后很难再回来
弄清楚你是否需要持有
锁定以调用特定函数或
不是。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)