Linux RT(二)-硬实时Linux(RT-Preempt Patch)的中断线程化

Linux RT(2)-硬实时Linux(RT-Preempt Patch)的中断线程化

特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。by  @宋宝华Barry

底半部:线程化IRQ

线程化中断的支持在2009年已经进入Linux官方内核,详见Thomas Gleixner的patch:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3aa551c9b4c40018f0e261a178e3d25478dc04a9

该patch提供一个能力,驱动可以通过

int request_threaded_irq(unsigned int irq, irq_handler_t handler,
                         irq_handler_t thread_fn, unsigned long irqflags,
                         const char *devname, void *dev_id)

申请一个线程化的IRQ,kernel会为中断的底版本创建一个名字为irq/%d-%s的线程,%d对应着中断号。其中顶半部(硬中断)handler在做完必要的处理工作之后,会返回IRQ_WAKE_THREAD,之后kernel会唤醒irq/%d-%s线程,而该kernel线程会调用thread_fn函数,因此,该线程成为底半部。在后续维护的过程中,笔者曾参与进一步完善该功能的讨论,后续patch包括nested、oneshot等的支持,详见patch:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=399b5da29b9f851eb7b96e2882097127f003e87c

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=70aedd24d20e75198f5a0b11750faabbb56924e2

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b25c340c195447afb1860da580fe2a85a6b652c5

该机制目前在kernel中使用已经十分广泛,可以认为是继softirq(含tasklet)和workqueue之后的又一大中断底半部方式。

顶半部:强制线程化

在使能Linux RT-Preempt后,默认情况下会强制透过request_irq()申请的IRQ的顶半部函数在线程中执行,我们都知道request_irq的原型为:

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
            const char *name, void *dev)
{                        
        return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}      

这意味着通过request_irq()申请的IRQ,在没有Rt-Preepmt的情况下,kernel并不会为其创建irq线程,因为它在最终调用request_threaded_irq()的时候传递的thread_fnNULL

如果使能了RT-Preempt Patch的情况下,其中的genirq-force-threading.patch会强制ARM使用threaded irq:

Index: linux-stable/arch/arm/Kconfig
===================================================================
--- linux-stable.orig/arch/arm/Kconfig
+++ linux-stable/arch/arm/Kconfig
@@ -40,6 +40,7 @@ config ARM
        select GENERIC_IRQ_SHOW
        select ARCH_WANT_IPC_PARSE_VERSION
        select HARDIRQS_SW_RESEND
+       select IRQ_FORCED_THREADING
        select CPU_PM if (SUSPEND || CPU_IDLE)
        select GENERIC_PCI_IOMAP
        select HAVE_BPF_JIT

在RT-Preempt Patch中,会针对使能了IRQ_FORCED_THREADING的情况,对这一原先没有线程化IRQ的case进行强制线程化,代码见__setup_irq():

 887 static int
888 __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
889 {
890 ...
903
904 /*
905 * Check whether the interrupt nests into another interrupt
906 * thread.
907 */
908 nested = irq_settings_is_nested_thread(desc);
909 if (nested) {
910 ...
920 } else {
921 if (irq_settings_can_thread(desc))
922 irq_setup_forced_threading(new);
923 }
925 /*
926 * Create a handler thread when a thread function is supplied
927 * and the interrupt does not nest into another interrupt
928 * thread.
929 */
930 if (new->thread_fn && !nested) {
931 struct task_struct *t;
932
933 t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
934 new->name);
935 ...
939 /*
940 * We keep the reference to the task struct even if
941 * the thread dies to avoid that the interrupt code
942 * references an already freed task_struct.
943 */
944 get_task_struct(t);
945 new->thread = t;
946

Linux RT(二)-硬实时Linux(RT-Preempt Patch)的中断线程化

相关文章:

你感兴趣的文章:

标签云: