INIT_WORK

作者: xuefeng_apple | 来源:发表于2021-02-05 12:01 被阅读0次

    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

    相关文章

      网友评论

          本文标题:INIT_WORK

          本文链接:https://www.haomeiwen.com/subject/cavwtltx.html