一、p->wake_cpu
1. p->wake_cpu 的赋值位置
//kernel/sched/sched.h static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) { set_task_rq(p, cpu); #ifdef CONFIG_SMP /* * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be * successfully executed on another CPU. We must ensure that updates of * per-task data have been completed by this moment. */ smp_wmb(); #ifdef CONFIG_THREAD_INFO_IN_TASK WRITE_ONCE(p->cpu, cpu); #else WRITE_ONCE(task_thread_info(p)->cpu, cpu); #endif p->wake_cpu = cpu; //这里赋值 #endif }
2. p->wake_cpu 的赋值流程:
set_task_cpu(p, new_cpu) //kernel/sched/core.c __set_task_cpu(p, new_cpu);
显式调用set_task_cpu,p->wake_cpu 赋值为指定的cpu.
sched_fork //kernel/sched/core.c __set_task_cpu(p, smp_processor_id());
对于fork的新任务,p->wake_cpu 赋值为当前正在执行的cpu.
wake_up_new_task //kernel/sched/core.c __set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
对于唤醒的任务,p->wake_cpu 赋值为为其选择的cpu.
sched_init //kernel/sched/core.c 传参current, smp_processor_id(),也就是将当前线程认为是idle线程,当前cpu当做wake_cpu idle_init //将per-cpu的idle线程的wake_cpu赋值为自己的cpu fork_idle(cpu) //fork.c init_idle(idle, cpu) //kernel/sched/core.c __set_task_cpu(idle, cpu);
对于idle线程初始化的时候,其 p->wake_cpu 赋值为为其选择的cpu.
migration_cpu_stop //core.c 若 p->on_rq != TASK_ON_RQ_QUEUED 时赋值 p->wake_cpu = arg->dest_cpu; __migrate_swap_task //core.c 若 p->on_rq != TASK_ON_RQ_QUEUED 时赋值 p->wake_cpu = cpu;
TODO: 待叙
3. p->wake_cpu 的使用:
try_to_wake_up cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
在选核时 p->wake_cpu 作为 prev_cpu 来使用,也就是当做任务之前运行的CPU。
4. 总结
p->wake_cpu 赋值为给任务选定的CPU,在唤醒任务时作为任务之前运行的CPU使用。