2013-02-19 60 views
5

我使用的内核共享的工作队列会发生什么,我有一个delayed_work结构,我想重新安排立即运行。当内核delayed_work改期

请问下面的代码保证该delayed_work将尽快运行?

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

在工作已经运行的情况下会发生什么? cancel_delayed_work将返回0,但我不确定schedule_delayed_work会在作业当前正在运行或未计划时执行。

+0

uugh!这是我目前的困境。事实上,我在oops中找到的一个回溯表明,在做出上面的确切代码后,它可能会重新输入。我已经添加了一个原子计数器来阻止它,但我需要知道重新安排delayed_work的正确方法。 – 2013-06-27 03:13:56

回答

4

嗯,你知道他们怎么说需要是所有发明(或研究在这种情况下)的母亲是什么。我真的需要这个答案,并通过挖掘kernel/workqueue.c来获得它。虽然答案大多包含在doc commentsDocumentation/workqueue.txt结合,它不是明确规定不读的并发管理工作队列(cmwq)子系统的整体规范,即使是这样,一些信息是过时了!

简答

威尔[代码]保证该delayed_work将尽快运行?

是(与下面的警告)

在那里的工作已经在运行的情况下,会发生什么?

它会在某个时刻当前正在运行的delayed_work函数退出和相同的CPU作为最后一个上运行,虽然任何其他工作已经排队上的工作队列(或延迟的工作,是因为)会先跑步。这假设您没有重新初始化您的对象delayed_workwork_struct,并且您没有更改过指针。

长的答案

所以第一关,struct delayed_work使用伪继承通过嵌入struct work_struct作为它的第一个成员从struct work_struct派生。这个子系统使用了一些令人惊讶的原子位数来实现一些严重的并发。 A work_struct是字段设置为WORK_STRUCT_PENDING位时“拥有”。当工人执行你的工作,它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的工人正在运行的工作。如果它们(并且你没有改变指针),它只是简单地将工作追加到pool_workqueue的队列中,这就是它避免再次入侵的方法!否则,它会将其排列在当前CPU的池中。 (的原因work->func指针检查是允许work_struct对象的重用。)

然而要注意简单地调用schedule_delayed_work()不取消第一会导致没有变化,如果工作仍在排队,所以你肯定必须先取消它。

编辑:哦,是啊,如果你被Documentation/workqueue.txt关于WQ_NON_REENTRANT的讨论困惑,忽略它。此标志已被弃用且被忽略,所有工作队列现在都不可退货。