下半部机制之微线程

微线程(tasklet)是一种更通用的下半部机制,大多数情况下应该优先使用微线程,只有在对性能要求非常高的时候才考虑使用软中断。然而,微线程是基于软中断的,它实际上是一个软中断。内核中的微线程用两个软中断表示:HI_SOFTIRQTASKLET_SOFTIRQ。两者唯一的区别在于HI_SOFTIRQ优先级要高些。

数据结构

struct tasklet_struct {


struct tasklet_struct *next;

/*next tasklet in the list */

unsigned long state;

/*state of the tasklet */

atomic_t count;

/*reference counter */

void(*func)(unsigned long);

/*tasklet handler function */

unsigned long data;

/*argument to the tasklet function */

};


状态state的值可为0TASKLET_STATE_SCHED,TASKLET_STATE_RUNTASKLET_STATE_SCHED表示某个微线程将被调度运行,而TASKLET_STATE_RUN表示某个微线程正在运行。

count为微线程的引用计数,为非0时表示微线程被禁用,不能运行。为0时表示微线程可以运行,且如果标记为未决状态,将可以运行。

调度微线程

被调度的微线程存储于两个每-CPU结构中:tasklet_vec(对于普通微线程)tasklet_hi_vec(对于高优先级微线程)。这两个结构都是tasklet_struct结构构成的链表。链表表中的每个结点代表不同的微线程。调度微线程分别采用tasklet_schedule()tasklet_hi_schedule()。大致步骤如下:

1.检查微线程的状态是否为TASKLET_STATE_SCHED。如果是,该微线程已经被调度,函数立即返回。

2.调用__tasklet_schedule()

3.保存中断系统的状态,然后禁用所有本地中断。

4.将被调度的微线程添加到tasklet_vectasklet_hi_vec链表的头部。这些链表对每个处理器来说是唯一的。

5.触发TASKLET_SOFTIRQHI_SOFTIRQ软中断,这样使得do_softirq()能在将来的某个时刻执行该微线程。(实质上就是将微线程标记为一个未决的软中断

6.恢复中断到之前的状态,然后返回。

这样,do_softirq()在某个时刻会运行这些未决的软中断,并执行相关的处理函数,即tasklet_action()tasklet_hi_action()。这两个函数是微线程处理的核心。执行的步骤如下:

1.禁用本地中断,获取本处理器上的tasklet_vectasklet_hi_vec链表。

2.清除链表。

3.启动本地中断。

4.遍历链表中的每个未决微线程。

5.如果是处理器空闲,检测微线程是否运行于另外一个处理器,即检测TASKLET_STATE_RUN标志。如果是,跳过,处理下一个微线程。

6.如果否,设置TASKLET_STATE_RUN,这样就不会在另一个处理器上运行。

7.检测微线程的引用数是否为0,以确认微线程是否使能。如果否,跳过,处理下一个微线程。

8.执行微线程处理函数。

9.清除微线程state域的TASKLET_STATE_RUN标记。

10.重复上述过程,直到完毕。

使用微线程

静态声明

DECLARE_TASKLET(name,func, data)

DECLARE_TASKLET_DISABLED(name,func, data);

例子如下:

DECLARE_TASKLET(my_tasklet,my_tasklet_handler, dev);

等价于:

struct tasklet_struct my_tasklet = { NULL, 0, ATOMIC_INIT(0),

my_tasklet_handler,dev };

动态声明

tasklet_init(t,tasklet_handler, dev); /* dynamically as opposed to statically */

编写自己的微线程处理函数

函数原型:void tasklet_handler(unsigned long data)

跟软中断一样,微线程不能睡眠,所以不能使用户信号量等机制。

调度微线程

调度微线程使用如下函数:

tasklet_schedule(&my_tasklet);/* mark my_tasklet as pending */

其实质就是将微线程标记为未决状态。

通过函数tasklet_disable()来禁用一个微线程,如果被禁用的微线程正在运行,函数将等待微线程执行完毕后,返回。函数tasklet_disable_nosync()将立即返回。函数tasklet_enable()使能一个微线程。


        tasklet使用模板

UsingTasklets to Offload Work from Interrupt Handlers

struct roller_device_struct{

/*… */

struct tasklet_struct tsklt;

/*… */

};


void__init roller_init()

{

struct roller_device_struct *dev_struct;

/*… */

/*Initialize tasklet */

tasklet_init(&dev_struct->tsklt,roller_analyze, dev);

}


/*The bottom half */

void

roller_analyze()

{

/*… */

}


/*The interrupt handler */

static irqreturn_t

roller_interrupt(int irq, void *dev_id)

{

/*… */

/*Mark tasklet as pending */

tasklet_schedule(&dev_struct->tsklt);

return IRQ_HANDLED;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值