为什么级连中断不能线程化呢……
本文是原「蜗窝讨论区」的历史存档(2016-04-19),来自版块「Linux kernel技术问答」,共 6 帖。讨论区已停止服务,此处仅供查阅。
在3.18.12内核中,有如下代码:
void __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, const char name) { unsigned long flags; struct irq_desc desc = irq_get_desc_buslock(irq, &flags, 0);
if (!desc)
return;
if (!handle) {
handle = handle_bad_irq;
} else {
if (WARN_ON(desc->irq_data.chip == &no_irq_chip))
goto out;
}
/* Uninstall? */
if (handle == handle_bad_irq) {
if (desc->irq_data.chip != &no_irq_chip)
mask_ack_irq(desc);
irq_state_set_disabled(desc);
desc->depth = 1;
}
desc->handle_irq = handle;
desc->name = name;
if (handle != handle_bad_irq && is_chained) {
irq_settings_set_noprobe(desc);
irq_settings_set_norequest(desc);
irq_settings_set_nothread(desc);
irq_startup(desc, true);
}
out: irq_put_desc_busunlock(desc, flags); }
当是级联中断的时候(is_chained == true),会通过irq_settings_set_nothread函数将该中断描述符设定为no thread,也就是说该中断handler不能被线程化,为什么呢?
1、假设系统interrupt request line的拓扑结构如下:interrupt controller A-----》interrupt controller B-----》Devices 2、B使用了A的第x号中断线。
中断控制器A的第x号中断对应的IRQ应该就是传说中的级联的中断(chained)
我们首先假设B中断控制器使用的x中断是threaded(对于A中断控制器而言,B中断控制器也就是一个普通的设备而已),那么挂在B的那些设备会怎么解析IRQ呢?假设设备Q使用了B的第y号中断,一旦中断产生,最终会通过Q-->B-->A--->CPU进入中断处理过程,而对于中断处理软件而言,最重要的是将hardware interrupt ID翻译成virtual interrupt ID,也就是我们常说的IRQ number,得到了IRQ number就可以立刻调用其handler了。
整个翻译过程是这样的: 1、A的irq domain负责将x号hardware interrupt ID翻译成B使用的IRQ number从而找到了B对应的handler 2、执行B对应的handler,继续解析中断号。Q设备实际使用了B中断控制器的y号中断,它的翻译需要在B的interrupt handler中执行。 3、在B的irq domain中将y号hardware interrupt ID翻译成Q设备使用的IRQ number从而找到了Q设备对应的interrupt handler
如果B的interrupt handler是在线程中执行(上面的第二步),那么b上所有的hardware interrupt ID到IRQ number的翻译都是在线程环境中执行,因此,B上的所有的设备的中断处理都是经历了在线程中解析IRQ的过程,这是大部分系统不能接受的。
为什么不能在线程中处理呢??? 因为中断的初衷本就是讲究的异步 快速响应。 如果中断的到来,到handler这部分流程,经历一个thread的话,这才是系统所不能忍受的。
这么说对吗?@linuxer
hello_world 写道: 1、假设系统interrupt request line的拓扑结构如下:interrupt controller A-----》interrupt controller B-----》Devices 2、B使用了A的第x号中断线。
中断控制器A的第x号中断对应的IRQ应该就是传说中的级联的中断(chained)
我们首先假设B中断控制器使用的x中断是threaded(对于A中断控制器而言,B中断控制器也就是一个普通的设备而已),那么挂在B的那些设备会怎么解析IRQ呢?假设设备Q使用了B的第y号中断,一旦中断产生,最终会通过Q-->B-->A--->CPU进入中断处理过程,而对于中断处理软件而言,最重要的是将hardware interrupt ID翻译成virtual interrupt ID,也就是我们常说的IRQ number,得到了IRQ number就可以立刻调用其handler了。
整个翻译过程是这样的: 1、A的irq domain负责将x号hardware interrupt ID翻译成B使用的IRQ number从而找到了B对应的handler 2、执行B对应的handler,继续解析中断号。Q设备实际使用了B中断控制器的y号中断,它的翻译需要在B的interrupt handler中执行。 3、在B的irq domain中将y号hardware interrupt ID翻译成Q设备使用的IRQ number从而找到了Q设备对应的interrupt handler
如果B的interrupt handler是在线程中执行(上面的第二步),那么b上所有的hardware interrupt ID到IRQ number的翻译都是在线程环境中执行,因此,B上的所有的设备的中断处理都是经历了在线程中解析IRQ的过程,这是大部分系统不能接受的。
好吧,早晚有一天我会把名字该回到linuxer
BTW,这个问题是我在某个微信群里面讨论的问题,觉得也挺有意思,就分享出来,呵呵~~~
回linglongqion朋友:你说的对,我上面这段话表达的就是这个意思,handler可以线程化,但是发生中断到找到handler的入口的过程(就是找到对应中断描述符的过程)不能线程化。对于驱动工程师而言,当注册了一个非线程化的handler之后,缺省的行为是在中断上下文中执行这个handler的,并且全程关中断,尽快执行完毕。这一点应该是对于所有的硬件平台的要求是一样的(无论是否级联)。
因此,无论对于连接在A上的设备还是连接在B上的设备,其IRQ handler的行为应该是一致的(无论底层的interrupt controller的拓扑是多么复杂,这也是一种良好的封装和抽象)。
不过还是有一些特例,例如I2C接口的IO expander,这些expander也会有中断功能,从某种意义上说也是中断控制器。但是,在这种情况下,这种级联的中断是必须要线程化的。
哈哈,分析的简洁,透彻,支持linuxer和蜗窝创办这个论坛,让我们大家可以更方便的交流,讨论问题,另外X Project很赞,32个赞代表不了我的喜欢~~~
Daniel 写道: 哈哈,分析的简洁,透彻,支持linuxer和蜗窝创办这个论坛,让我们大家可以更方便的交流,讨论问题,另外X Project很赞,32个赞代表不了我的喜欢~~~
多谢Daniel的32个赞,大家一起加油努力
