以下代码是否保证delayed_work将尽快运行?
cancel_delayed_work(work); schedule_delayed_work(work,0);
在工作已经开始的情况下会发生什么? cancel_delayed_work将返回0,但如果工作当前正在运行或未安排,我不确定schedule_delayed_work将执行的操作.
解决方法
Documentation/workqueue.txt
中,但如果没有阅读并发管理工作队列(cmwq)子系统的整个规范,就没有明确说明,即便如此,有些信息已经过时了!
简答
Will [your code] guarantee that the delayed_work will run as soon as possible?
是的(以下警告)
What happens in a situation where the work is already running?
它将在当前运行的delayed_work函数退出后的某个时刻运行,并且在与最后一个函数相同的cpu上运行,尽管已经在该工作队列中排队的任何其他工作(或者应该延迟的工作)将首先运行.这假设您没有重新初始化delayed_work或work_struct对象,并且您没有更改work->函数指针.
答案很长
首先,struct delayed_work
通过嵌入struct work_struct作为其第一个成员,使用伪继承从struct work_struct
派生.这个子系统使用一些惊人的原子位frigging来获得一些严重的并发性.当work_struct的数据字段设置为WORK_STRUCT_PENDING
时,它“拥有”.当一个worker执行你的工作时,它是releases ownership并通过私有set_work_pool_and_clear_pending()函数记录最后一个工作池 – 这是API最后一次修改work_struct对象(当然,直到你重新安排它).拨打cancel_delayed_work()
完全一样.
因此,如果在工作函数已经开始执行时调用cancel_delayed_work(),它将返回false(如公布的那样),因为它不再由任何人拥有,即使它可能仍在运行.但是,当您尝试使用schedule_delayed_work()重新添加它时,它将在examine the work发现最后一个pool_workqueue,然后查明该pool_workqueue的任何工作者当前是否正在运行您的工作.如果它们(并且您没有更改work-> func指针),它只是将工作附加到该pool_workqueue的队列中,这就是它如何避免重入!否则,它会将其排队到当前cpu的池中. (work-gt; func指针检查的原因是允许重用work_struct对象.)
但是请注意,如果工作仍然排队,那么简单地调用schedule_delayed_work()而不首先取消它将导致没有变化,因此您必须首先取消它.
编辑:哦,是的,如果您对Documentation / workqueue.txt中关于WQ_NON_REENTRANT
的讨论感到困惑,请忽略它.不推荐使用此标志并将其忽略,并且所有工作队列现在都是非重新标记的.