我一直在试图理解Linux内核中的try_to_wake_up()函数好一些。从概念上讲,我(认为)要唤醒一个进程,我们必须将其添加到 CPU 运行队列中,但我很难看出这种情况发生在哪里。
//try_to_wake_up()
if (p == current) {
/* I omitted some comments here*/
success = 1;
cpu = task_cpu(p); //task_cpu(p) returns READ_ONCE(p->cpu);
trace_sched_waking(p); //This is just a logging call
p->state = TASK_RUNNING;
trace_sched_wakeup(p); //Another logging call
goto out;
}
所以任务CPU()似乎根本没有修改CPU运行队列,所以我决定去看看标签,它正在调用ttwu_stat():
/*I omitted some intermediate code here*/
out:
if (success)
ttwu_stat(p, cpu, wake_flags);
preempt_enable();
return success;
但当我去看的时候ttwu_stat(),这似乎只是一堆对此的调用__schedstat_inc只是增加其输入参数的宏。
那么...我们实际上在哪里将 task_struct* p 添加到 CPU 运行队列中?
任何想法表示赞赏。
谢谢。
答案1
您引用的代码块是一种特殊情况,如省略的注释中所述:
* We're waking current, this means 'p->on_rq' and 'task_cpu(p)
* == smp_processor_id()'. Together this means we can special
* case the whole 'p->on_rq && ttwu_remote()' case below
* without taking any locks.
由于要唤醒的任务是当前任务,因此它已经在运行队列 ( p->on_rq
) 中,因此不需要将其添加到运行队列中。
处理将任务添加到运行队列再向下:
cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
这会将任务添加到运行队列并返回调度该任务的 CPU,因此可以在必要时处理迁移。
该#ifdef CONFIG_SMP
条件值得一些解释:如果不支持 SMP,则多个任务不能并发运行,并且由于我们知道我们不会唤醒当前任务,因此唯一需要处理的情况是 I/O 等待。