workqueue
#include <linux/workqueue.h>
struct work_struct {
unsigned long pending;
struct list_head entry; /* 将任务挂载到 queue 的挂载点 */
void (*func)(void *); /* 任务方法 */
void *data; /* 任务处理的数据 */
void *wq_data; /* work 的属主 */
strut timer_list timer; /* 任务延时处理定时器 */
};
简单的workqueue, 由kernel 自己内部调度
1、定义struct work_struct irq_queue;
2、初始化INIT_WORK(&irq_queue,do_irq_queuework);
3、调用方法:schedule_work(&rq_queue);
其中 work_func_t 的定义如下:
typedef void (*work_func_t)(struct work_struct *work);
work queue 主要的 API:
struct workqueue_struct *create_workqueue(const char *name);
struct workqueue_struct *create_singlethread_workqueue(const char *name);
DECLARE_WORK(name, void (*function)(void *), void *data);
set up work at run time
INIT_WORK(struct work_struct *work, work_func_t func)
PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data);
Schedule the work for execution
int schedule_work(struct work_struct *work)
void flush_scheduled_work(void)
int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
add work to workqueue
int queue_work(struct workqueue_struct *wq, struct work_struct *work)
int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay)
cancel a pending workqueue entry and must follow that call with a call to flush_workqueue()
int cancel_delayed_work(struct work_struct *work);
void flush_workqueue(struct workqueue_struct *wq)
if you have done a workqueue:
void destroy_workqueue(struct workqueue_struct *wq)
tasklet
#include <linux/interrupt.h>
struct tasklet_struct { struct tasklet_struct *next; unsigned long state; atomic_t count; void (*func)(unsigned long); unsigned long data; };
各成员的含义如下:
(1)next指针:指向下一个tasklet的指针。
(2)state:定义了这个tasklet的当前状态。这一个32位的无符号长整数,当前只使用了bit[1]和bit[0]两个状态位。其中,bit[1]=1表示这个tasklet当前正在某个CPU上被执行,它仅对SMP系统才有意义,其作用就是为了防止多个CPU同时执行一个tasklet的情形出现;bit[0]=1表示这个tasklet已经被调度去等待执行了。对这两个状态位的宏定义如下所示(interrupt.h):
enum { TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */ TASKLET_STATE_RUN /* Tasklet is running (SMP only) */ };
(3)原子计数count:对这个tasklet的引用计数值。NOTE!只有当count等于0时,tasklet代码段才能执行,也即此时tasklet是被使能的;如果count非零,则这个tasklet是被禁止的。任何想要执行一个tasklet代码段的人都首先必须先检查其count成员是否为0。
(4)函数指针func:指向以函数形式表现的可执行tasklet代码段。
(5)data:函数func的参数。这是一个32位的无符号整数,其具体含义可供func函数自行解释,比如将其解释成一个指向某个用户自定义数据结构的地址值。
初始化:
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data);
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data);
Linux在interrupt.h头文件中又定义了两个用来定义tasklet_struct结构变量的辅助宏:
#define DECLARE_TASKLET(name, func, data) struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data } #define DECLARE_TASKLET_DISABLED(name, func, data) struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
显然,从上述源代码可以看出,用DECLARE_TASKLET宏定义的tasklet在初始化时是被使能的(enabled),因为其count成员为0。而用DECLARE_TASKLET_DISABLED宏定义的tasklet在初始时是被禁止的(disabled),因为其count等于1。
enable and disable tasklet through atomic
void tasklet_disable(struct tasklet_struct *t);
void tasklet_disable_nosync(struct tasklet_struct *t);
void tasklet_enable(struct tasklet_struct *t);
Schedule the tasklet for execution
void tasklet_schedule(struct tasklet_struct *t);
void tasklet_hi_schedule(struct tasklet_struct *t);
void tasklet_kill(struct tasklet_struct *t);
BUG_ON(condition)
BUG_ON macro first checks for the condition and if condition is true then it calls BUG which do a printk of msg and call panic which halts the system.
The unlikely in BUG_ON macro is compiler directive which ask compiler to generate assembly such that the condition mentioned in unlikely isn't going to be met most-of-the time, which reduces jumps and speeds-up things, although if condition mentioned in unlikely met then there will be a long jump and speed will be effected, so must be used carefully. Same is with likely as it is the opposite of unlikely.