Linux内核中断处理程序互斥保护?
我是否需要保护我的中断处理程序在同一中断中被多次调用 鉴于下面的代码,我不确定应该进行哪些系统调用。我在当前的实现中遇到了罕见的随机死锁:-Linux内核中断处理程序互斥保护?,linux,linux-kernel,linux-device-driver,interrupt,Linux,Linux Kernel,Linux Device Driver,Interrupt,我是否需要保护我的中断处理程序在同一中断中被多次调用 鉴于下面的代码,我不确定应该进行哪些系统调用。我在当前的实现中遇到了罕见的随机死锁:- void interrupt_handler(void) { down_interruptible(&sem); // or use a lock here ? clear_intr(); // clear interrupt source on H/W wake_up_interruptible(...);
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(...);
}
中断处理程序
:向下可中断
为旋转锁定irq
/旋转锁定irq保存
/本地irq禁用
set/clear\u intr
:spin\u lock\u irq
bespin\u lock\u irqsave
/local\u irq\u disable
interrupt\u处理程序
在其内部时能否继续被调用关闭\u interruptable
编辑1)在获得一些不错的帮助后,建议如下:-
interrupt\u处理程序中删除down\u interruptable
spin\u lock\u irq
外部设置/清除方法(不需要spin\u lock\u 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帖子:阅读了与Robert Loves的链接后,我读了以下内容: 一些中断处理程序(在 Linux(作为快速中断处理程序)运行 所有的中断都在本地 处理器已禁用。这样做是为了 确保中断处理程序运行 没有中断,尽快 可能的更何况,大家都打断了 处理程序使用其当前 所有设备上的中断线已禁用 处理器。这确保了两个 同样的中断处理程序 中断行不运行 同时它还可以防止设备损坏 驱动程序编写器不必处理 递归中断,使 编程
我启用了快速中断(SA_中断)!所以不需要互斥锁/锁/信号量/旋转/等待/睡眠/等等 不要在中断上下文中使用信号量,而是使用
spin\u lock\u irqsave
。引用LDD3:
如果你有一个旋转锁可以
由在(硬件)中运行的代码获取
或软件)中断上下文,您
必须使用旋转锁定的其中一种形式
这将禁用中断。做
否则会导致系统死锁,
迟早如果您不访问
你的锁在硬件中断
处理程序,但您可以通过软件执行
中断(在代码中,使用的是
例如,tasklet是一个涵盖的主题
在第7章),您可以使用
旋转锁以安全避免死锁
同时仍然允许硬件
需要维修的中断
至于第2点,让您的set_intr
和clear_intr
要求调用方锁定自旋锁,否则您会发现代码死锁。同样来自LDD3:
要使您的锁正常工作,
你必须用它来写一些函数
假设他们的来电者
已获取相关锁。
通常,只有你的内部,静态
函数可以用这种方式编写;
从外部调用的函数必须
显式处理锁定。当你
编写内部函数,使
关于锁定的假设,请自己动手
(还有其他与您合作的人
编码)一个帮助并记录这些
明确的假设。这可能是非常危险的
几个月后很难再回来
弄清楚你是否需要持有一张支票
锁定以调用特定函数或
不是
在中断上下文中使用spinlock,因为如果没有获得锁,您不想在中断上下文中睡眠。您发布的代码看起来不像设备驱动程序irq处理程序。 内核驱动程序中的irq处理程序返回irqreturn__t并将int irq_no、void*数据作为参数 您还没有指定是注册线程处理程序还是非线程处理程序。 无论您是否持有任何自旋锁,非线程irq处理程序都不能有任何休眠调用。 wait_事件、互斥、信号量等都是休眠调用,不能在非线程irq处理程序中使用。但是,您可以保持自旋锁以防止中断处理程序中断。这将确保可屏蔽IRQ和调度器不会中断中间的IRQ处理程序。
在线程化irq处理程序中,可以使用休眠调用(等待队列、互斥等),但仍不推荐使用。您回答了(LDD3引述)自己的第一个问题(以及其他一些问题的重新表述)。一般来说,防止锁定时间关键的东西(如中断处理)。很抱歉,我不能提供更多的答案,+1来自me@sehe是的,但是对
向下
/向上
的调用应该在那里吗?@sehe并且有了它,这个方法就不能说是可重入的@IanVaughan:只有当您确定在调用代码时没有中断被禁用时,才应该使用spin\u lock\u irq
。我建议您至少将中断处理程序中的调用更改为使用spin\u lock\u irqsave
。@Ian Vaughan-不允许在中断处理程序或原子上下文中使用down/up!!!你的意思是不要在中断处理程序中使用down\u interruptible
?@IanVaughan:是的,那是自找麻烦。我已经扩展了我的答案。你的意思是用旋转锁定irqsave
替换向下可中断的(这肯定会使它不可重入)?或者确保我在set/clear中使用spin\u lock\u irqsave
(而不是当前的spin\u lock\u irq
)重新编辑:我看不出将锁定/解锁移到方法之外有什么帮助,要么调用方为我执行,要么它为我完成,无论哪种方式都是一样的?除非我锁定了更大/更多的代码。@IanVaughan:我主要建议将锁定/解锁移到方法之外以避免