嘿,我在看内核源代码中的这个函数。我试图弄清楚Linux如何处理不能在本地CPU上调度任务的情况。
/**
* queue_delayed_work - queue work on a workqueue after delay
* @wq: workqueue to use
* @dwork: delayable work to queue
* @delay: number of jiffies to wait before queueing
*
* Equivalent to queue_delayed_work_on() but tries to use the local CPU.
*/
static inline bool queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *dwork,
unsigned long delay)
{
return queue_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
}这是queue_delayed_work_on
bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay)
{
struct work_struct *work = &dwork->work;
bool ret = false;
unsigned long flags;
/* read the comment in __queue_work() */
local_irq_save(flags);
if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
__queue_delayed_work(cpu, wq, dwork, delay);
ret = true;
}
local_irq_restore(flags);
return ret;
}假设您有4个CPU,并且它不能在CPU 1上安排任务,那么它选择哪一个?在源代码中这是在哪里处理的?我找了很久却找不到。即使你不明白它是如何工作的,我真的很想知道魔法发生的地方。
发布于 2015-07-24 14:18:51
如您所见,queue_delayed_work将cpu参数设置为WORK_CPU_UNBOUND。这个值被定义为大于内核支持的CPU的实际数量。此值将传递给__queue_delayed_work,如果delay为非零,则将使用计时器(在指定的时间后使用add_timer函数来触发回调函数delayed_work_timer_fn (此回调函数在工作队列初始化时定义)。这个回调函数所做的就是调用__queue_work,仍然将WORK_CPU_UNBOUND作为cpu参数传递。所以所有的“魔法”都发生在那里。
此函数将检查cpu参数是否设置为WORK_CPU_UNBOUND,并选择cpu作为当前处理器:
if (req_cpu == WORK_CPU_UNBOUND)
cpu = raw_smp_processor_id()因此,这项工作将在处理器上执行,处理器处理之前设置的定时器中断。现在我没有研究计时器代码,但是LDD3书中的IIRC,计时器中断将由它们注册的CPU来处理(当然,除非这个CPU在此期间被禁用,在这种情况下,计时器IRQ将被移到其他CPU),但是那本书很旧
内核代码中还有一个提示应该证明我所写的东西--参见queue_work函数的注释:“我们将工作排队到提交它的CPU,但是如果CPU死了,它可以由另一个CPU处理”。此函数还使用WORK_CPU_UNBOUND作为cpu参数。
计时器迁移细节
如前所述,如果某个处理器出现故障,它将无法再处理IRQ,因此它将无法处理已注册的计时器。因此,当CPU离线时,内核将将所有挂起的定时器迁移到其他CPU。此任务由migrate_timers()函数完成,该函数由timer_cpu_notify运行,该函数反过来是注册为cpu_notifier的回调。
当cpu状态更改为CPU_DEAD或CPU_DEAD_FROZEN时,将运行CPU_DEAD。此状态是在_cpu_down函数中通过以下方式设置的:
cpu_notify_nofail(CPU_DEAD | mod, hcpu);它是在__cpu_die(cpu)之后调用的,这确保了我们禁用的CPU不再工作,因此我们可以确保这段代码运行在其他CPU上。migrate_timers将把所有计时器重新分配到正在运行的CPU上。
那么,在哪一个CPU应该接管定时器的决定呢?可以说,这是由调度程序完成的:
cpu_down,而不是您想要禁用的CPU,那么这就是将要接管的CPU。cpu_down,它将在__cpu_die中调度自己,其余代码将在其他CPU上重新调度。发布于 2015-07-25 23:55:45
我不知道,但是看看LWN的调度器部门。
https://stackoverflow.com/questions/31601216
复制相似问题