免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 996 | 回复: 0
打印 上一主题 下一主题

bh,tasklet, softirq [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-27 23:38 |只看该作者 |倒序浏览
古老的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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP