INIT_WORK

2021-02-05  本文已影响0人  xuefeng_apple

kernel 使用了很多工作队列。了解历史更好的理解INIT_WORK 参数

1- old kernel(2.6 之前) 如何使用INIT_WORK

#define INIT_WORK(_work, _func, _data) \
do { \
INIT_LIST_HEAD(&(_work)->entry); \
(_work)->pending = 0; \
PREPARE_WORK((_work), (_func), (_data)); \
init_timer(&(_work)->timer); \
} while (0)

#define PREPARE_WORK(_work, _func, _data) \
do { \
(_work)->func = _func; \
(_work)->data = _data; \
} while (0)

_work 实际就是
struct work_struct {
    unsigned long pending;
    struct list_head entry;
    void (*func)(void *);
    void *data;
    void *wq_data;
    struct timer_list timer;
};

从上面可以code 定义可以看出old kernel INIT_WORK 有三个参数,如果使用了container_of是否可以省一个参数 ,答案是肯定的

2- new kernel INIT_WORK

    #define INIT_WORK(_work, _func)                                                      /
              do {                                                                                              /
                     (_work)->data = (atomic_long_t) WORK_DATA_INIT();       /
                      INIT_LIST_HEAD(&(_work)->entry);                                    /
                     PREPARE_WORK((_work), (_func));                                    /
             } while (0)

例子1
使用最新的INIT_WORK 进行举例:
2.1. 在探测函数里goodix_ts_probe初始化
INIT_WORK(&ts->work, goodix_ts_work_func);//struct work_struct work,ts是client私有数据结构体
主要目的就是因为就算没有中断,在第一次开机时也有检测设备,所以这个任务一开始就执行,只不过到后来中断发生后就再执行.
2.2 goodix_ts_work_func 如何实现

static void goodix_ts_work_func(struct work_struct *work) {
    struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);
}

使用container_of这个函数来求出我们的data的指针

2.3.当然你不能忘记注册你的中断函数了

request_irq(client->irq, goodix_ts_irq_handler,pdata->irq_edge ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING,client->name, ts);

goodix_ts_irq_handler
{
    schedule_work(&ts->work) //这里就wakeup了goodix_ts_work_func
}

所以用一个结构体ts就可以把中断,任务,设备名等全部囊括进来
上面的例子使用了中断,进行了work wakeup的操作。不使用中断也是可以的。

例子2:qcom log dump reg 的操作

注册init workqueue:
kernel/msm-4.9/drivers/gpu/drm/msm/sde_dbg.c
--->sde_dbg_init
   --->INIT_WORK(&sde_dbg_base.dump_work, _sde_dump_work);
      --->_sde_dump_work
         --->_sde_dump_array
             sde_evtlog_dump_all ::这里修改了log信息

叫醒:dump_work
msm-4.9/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
---> sde_encoder_phys_vid_prepare_for_kickoff
    --->SDE_DBG_DUMP("panic");---->sde_dbg_dump[sde_dbg.c
       --->schedule_work(&sde_dbg_base.dump_work);

上面可以看出,如果发生调用了SDE_DBG_DUMP,就会调用到了dump_work workqueue

3- INIT_WORK 相关的函数,如果使用到,需要细查

INIT_DELAYED_WORK //这个work_struct 只是多了timer 进行了延时
schedule_delayed_work

cancel_delayed_work
flush_scheduled_work

REF:
https://blog.csdn.net/fcf1990501/article/details/8445441
https://blog.csdn.net/bingqingsuimeng/article/details/7891157

上一篇下一篇

猜你喜欢

热点阅读