Chinaunix

标题: bh,tasklet, softirq [打印本页]

作者: xpyzyf    时间: 2008-10-27 23:38
标题: bh,tasklet, softirq
古老的BH、tasklet、softirq
古老的BH:作为一种特殊的tasklet
kernel/softirq.c : static void
(*bh_base[32])(void);
             struct tasklet_struct bh_task_vec[32];
在softirq_init中,注册32个bh_task_vec的函数指针为
bh_action;
TASKLET_SOFTIRQ : tasklet_action;
HI_SOFTIRQ :              
tasklet_hi_action;
NET_RX_SOFTIRQ :   net_rx_action;  
[net_dev_init]
NET_TX_SOFTIRQ:    net_tx_action;
在sched_init中注册
TIMER_BH的处理函数指针为 timer_bh;
init_bh(TIMER_BH,
timer_bh);
对于数据包的接收发送,标志对应的 NET_RX_SOFTIRQ / NET_TX_SOFTIRQ;
对于应用的
tasklet ,标志对应的 TASKLET_SOFTIRQ;
对于古老的BH,例如时钟中断,在do_IRQ -> timer_interrupt
-> do_timer_interrupt -> do_timer :
  mark_bh(TIMER_BH) ->
tasklet_hi_schedule(bh_task_vec+TIMER_BH)
  即将 TIMER_BH 所对应的 bh_task_vec
结构体挂接到对应的CPU的 tasklet_hi_vec
链表中,并标志HI_SOFTIRQ。
  do_softirq时,tasklet_hi_action 遍历对应CPU上的 tasklet_hi_vec
链表中的 tasklet_struct,执行其相应的action,也就是 bh_action 函数。
  bh_action 函数是个包装体,用于实际调用
bh_base 数组中的函数。对于时钟中断也就是 sched_init 中注册的 timer_bh 函数。
  
               
               
                void __init softirq_init()
{
    int i;
    for (i=0; i32; i++)
        tasklet_init(bh_task_vec+i, bh_action, i);
    open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);
    open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
}
void tasklet_init(struct tasklet_struct *t,
          void (*func)(unsigned long), unsigned long data)
{
    t->next = NULL;
    t->state = 0;
    atomic_set(&t->count, 0);
    t->func = func;
    t->data = data;
}
void fastcall __tasklet_hi_schedule(struct tasklet_struct *t)
{
    int cpu = smp_processor_id();
    unsigned long flags;
    local_irq_save(flags);
    t->next = tasklet_hi_vec[cpu].list;
    tasklet_hi_vec[cpu].list = t;
    cpu_raise_softirq(cpu, HI_SOFTIRQ);
    local_irq_restore(flags);
}
static void tasklet_hi_action(struct softirq_action *a)
{
    int cpu = smp_processor_id();
    struct tasklet_struct *list;
    local_irq_disable();
    list = tasklet_hi_vec[cpu].list;
    tasklet_hi_vec[cpu].list = NULL;
    local_irq_enable();
    while (list) {
        struct tasklet_struct *t = list;
        list = list->next;
        if (tasklet_trylock(t)) {
            if (!atomic_read(&t->count)) {
                if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
                    BUG();
                t->func(t->data);
                tasklet_unlock(t);
                continue;
            }
            tasklet_unlock(t);
        }
        local_irq_disable();
        t->next = tasklet_hi_vec[cpu].list;
        tasklet_hi_vec[cpu].list = t;
        __cpu_raise_softirq(cpu, HI_SOFTIRQ);
        local_irq_enable();
    }
}
static void bh_action(unsigned long nr)
{
    int cpu = smp_processor_id();
    if (!spin_trylock(&global_bh_lock))
        goto resched;
    if (!hardirq_trylock(cpu))
        goto resched_unlock;
    if (bh_base[nr])
        bh_base[nr]();
    hardirq_endlock(cpu);
    spin_unlock(&global_bh_lock);
    return;
resched_unlock:
    spin_unlock(&global_bh_lock);
resched:
    mark_bh(nr);
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/83556/showart_1342220.html




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2