中断线程

参考:2.6.34

 

看了下2.6.34中的中断线程,但是在《内核设计与实现》3ed_CN的p_90~p_130内并未提起中断线程,因此做下记录,其中关于kthread_create函数已在“工作队列”笔记中做了说明。

通常通过request_irq申请中断资源时并未注册中断线程处理函数,可以通过request_threaded_irq来注册中断线程处理函数。

注册中断线程处理函数:

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) 
    |---->struct irqaction *action;
    |     struct irq_desc *desc;
    |     des = irq_to_desc(irq); 
    |     action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
    |
    |----action->handler = handler;中断处理函数
    |    action->thread_fn = thread_fn; 中断线程处理函数
    |    action->name = devname;
    |    action->dev_id = dev_id;
    |
    |---->int retval = __setup_irq(irq, desc, action);


__setup_irq()中新建中断线程
static int __setup_irq(unsigned int irq,
                       struct irq_desc *desc, 
                       struct irqaction *new)
    |---->int nested = desc->status & IRQ_NESTED_THREAD;
    |
    |此处考虑创建中断线程;
    |关于IRQ_NESTED_THREAD的意义,我并没有理解,存疑
    |if (new->thread_fn && !nested) {
    |
    |----struct task_struct *t;
    |    t = kthread_create(irq_thread, new, "irq/%d-%s", irq, new->name);
    |    get_task_struct(t);
    |    new->thread = t;
    |}
    |
    |----int shared = 0;
    |    struct irqaction **old_ptr;
    |    通过遍历irq_desc中域irqaction*,获得可添加irqaction的位置;
    |    若为首次添加,则shared = 0;否则shared = 1;
    |    是否首次添加的区被至于在于对irq_desc实例的status域的影响,
    |    因为第一个irqaction将决定是否兼容后续的irqaction添加。
    |    在__setup_irq中有一系列的兼容性检查,此分析中省略了。
    |----若首次添加,则执行......
    |----new->irq = irq;
    |----*old_ptr = new;
    |
    |----if(new->thread) wake_up_process(new->thread); 见本记录最后对此的疑问


若首次在irq_desc中域irqaction*添加irqaction,则执行如下流程:
|---->irq_chip_set_defaults(desc->chip);
|---->init_waitqueue_head(&desc->wait_for_threads);
|---->if(new->flags & IRQF_TRIGGER_MASK)设置中断被触发的类型。
|---->desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_OENSHOT |
|                      IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
|---->new->flags & IRQF_ONESHOT ? desc->status |= IRQ_ONESHOT :(void)0;
|---->if(!desc->status & IRQ_NOAUTOEN){
|    desc->depth = 0;
|    desc->status &= ~IRQ_DISABLED;
|    desc->chip->startup(irq);
|     }else desc->depth = 1;

 

何时唤醒中断线程?

handle_IRQ_event中,若中断处理函数返回值为IRQ_WEAK_THREAD,则wake_up_process(action->thread)

中断处理线程的执行:

static int irq_thread(void *data)
{                                                                                                                   
        struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
        struct irqaction *action = data; 
        struct irq_desc *desc = irq_to_desc(action->irq);
        int wake, oneshot = desc->status & IRQ_ONESHOT;

        sched_setscheduler(current, SCHED_FIFO, &param);
        current->irqaction = action; 

        while (!irq_wait_for_interrupt(action)) {
+-- 18 lines: irq_thread_check_affinity(desc, action);--------------------------------------------------------------
                {       
                        raw_spin_unlock_irq(&desc->lock);

                        action->thread_fn(action->irq, action->dev_id);
+--  3 lines: if (oneshot)------------------------------------------------------------------------------------------
                }       
+--  3 lines: wake = atomic_dec_and_test(&desc->threads_active);----------------------------------------------------
                if (wake && waitqueue_active(&desc->wait_for_threads))
                        wake_up(&desc->wait_for_threads);
        }       
+--  5 lines: Clear irqaction. Otherwise exit_irq_thread() would make-----------------------------------------------
        current->irqaction = NULL; 
        return 0;
}

 

疑问:1、固然在__setup_irq的最后唤醒中断线程没有错误,但是为什么要在__setup_irq的最后唤醒中断线程,如果不唤醒会导致错误么?

          2、内核中既有中断线程,又有工作线程,为何同时应入这两种方法?两者的区别和各自的优势又是什么?

          3、当然,我们也注意到中断线程的调度策略总被设置为“SCHED_FIFO",而工作线程默认的调度策略是”SCHED_NORMAL", 为什么要把一个内核线程的调度策略设置成“SCHED_FIFO", SCHED_FIFO将一直持有cpu资源,要是在中断线程中做大量的工作,那系统的吞吐量将会大大降低?

 

posted on 2013-09-02 11:25  阿加  阅读(679)  评论(0编辑  收藏  举报

导航