当kernel delayed_work被重新安排时会发生什么

时间:2013-02-19 19:12:26

标签: linux-kernel

我正在使用内核共享工作队列,我有一个delayed_work结构,我想重新安排立即运行。

以下代码是否可以保证delayed_work能够尽快运行?

cancel_delayed_work(work);
schedule_delayed_work(work, 0);

在工作已经开始的情况下会发生什么? cancel_delayed_work将返回0,但如果作品当前正在投放或未安排,我不确定schedule_delayed_work会做什么。

1 个答案:

答案 0 :(得分:6)

嗯,你知道他们所说的必要性是所有发明的母亲(或在这种情况下的研究)。我真的需要这个答案,并通过挖掘kernel / workqueue.c得到它。虽然答案主要包含在doc commentsDocumentation/workqueue.txt中,但如果没有阅读并发管理工作队列(cmwq)子系统的整个规范,那么就没有明确说明,即使这样,一些信息也是如此。已经过时了!

简答

  

[您的代码]会保证delayed_work会尽快运行吗?

是(以下警告)

  

在工作已经开始的情况下会发生什么?

当前正在运行的delayed_work函数退出并且在与最后一个函数相同的CPU上时,它会在某个时刻运行,尽管任何其他工作已在该工作队列中排队(或延迟工作)即将到期)将首先运行。这假设您没有重新初始化delayed_workwork_struct对象,并且您没有更改work->func指针。

长答案

首先,struct delayed_work使用伪继承通过嵌入struct work_struct作为其第一个成员来从struct work_struct派生。该子系统使用一些惊人的原子位frigging来实现一些严重的并发性。当work_struct字段设置为WORK_STRUCT_PENDING时,data为“拥有”。当工作人员执行您的工作时,它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->func指针检查的原因是允许重用work_struct对象。)

但是请注意,如果工作仍然排队,只需调用schedule_delayed_work()而不首先取消它将导致 no 更改,因此您必须先取消它。

编辑:哦,是的,如果您对Documentation/workqueue.txt关于WQ_NON_REENTRANT的讨论感到困惑,请忽略它。不推荐使用和忽略此标志,并且所有工作队列现在都是非重新注册的。