2017-01-18

1. 中断流程

假定 CONFIGMULTIIRQHANDLER=y, handlearchirq 为 gichandle_irq.
linux-3.10.86/arch/arm/kernel/setup.c

__irq_svc @entry-armv.S
|   |--svc_entry    保存spsr_<exception> 到r5
|   |--irq_handler
|   |   |--handle_arch_irq => gic_handle_irq
|   |   |   |--irq_find_mapping  完成 an hw irq number到a linux irq的转换
|   |   |   |--handle_IRQ(irqnr, regs) if not IPI 
|   |   |   |       |--generic_handle_irq  -> generic_handle_irq_desc -> handle_fasteoi_irq
|   |   |   |       |   |--raw_spin_lock(&desc->lock);
|   |   |   |       |   |--handle_irq_event
|   |   |   |       |   |   |--raw_spin_unlock(&desc->lock);
|   |   |   |       |   |   |--handle_irq_event_percpu -> action->handler
|   |   |   |       |   |   |--raw_spin_lock(&desc->lock);
|   |   |   |       |   |--chip->irq_eoi
|   |   |   |       |   |--raw_spin_unlock(&desc->lock);
|   |   |   |       |--irq_exit();  这里中断还是禁用的吗? 答:是的, ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
|   |   |   |       |   |--WARN_ON_ONCE(!irqs_disabled());
|   |   |   |       |   |--if( ... ) invoke_softirq() 
|   |   |   |       |   |    |--do_softirq -> __do_softirq
|   |   |   |       |   |    |    |--local_irq_enable   //修改CPSR I bit, 打开中断
|   |   |   |       |   |    |    |--h->action(h)
|   |   |   |       |   |    |    |--local_irq_disable  //这里为何又禁止中断???
|   |   |   |       |--set_irq_regs(old_regs)  这里开启中断? 答:不是.
|   |--svc_exit r5, irq = 1  @entry-header.S

假定发生中断前, 是处于svc模式的, 所以, 上面流程为_irqsvc. 中断上半部分 中断是关闭的, 何时重新使能中断, 上面都已标出. 使能之后, 就开始处理软中断了.

2. tasklet的特点

两个类型相同的tasklet不能同时运行, 即使在不同的处理器上也是如此, 因为代码上检查的并不是per cpu的变量.

void __init softirq_init(void)
{
...
    open_softirq(TASKLET_SOFTIRQ, tasklet_action);
    open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}

代码:linux-3.10/kernel/softirq.c

static void tasklet_action(struct softirq_action *a)
{
        struct tasklet_struct *t
        ...
        if (tasklet_trylock(t)) {
            ...
            t->func(t->data);
        }

}

#ifdef CONFIG_SMP
static inline int tasklet_trylock(struct tasklet_struct *t)
{
    return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);
}
#endif

3. softirq的特点

softirq的pending变量是per-cpu的, 并不会阻止相同的handler同时运行在不同的cpu上.

linux-3.10.86/kernel/softirq.c

__do_softirq
{

    pending = local_softirq_pending();
    set_softirq_pending(0);

    do {
        if (pending & 1) {

            ->action
        }

        pending >>= 1;
    }while (pending);

}

本文地址: https://awakening-fong.github.io/posts/arm/interrupt_softirq_in_arm

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus