调度器30—调度相关结构体成员赋值


一、task_struct

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使用。

二、struct rq

1. rq->curr 

赋值位置1:

__schedule //core.c
    RCU_INIT_POINTER(rq->curr, next) //当选出的next不等于prev时赋值

注意:在上面执行 pick_next_task 选核的流程中,rq->curr指向的还是prev任务

赋值位置2:

init_idle //core.c
    rcu_assign_pointer(rq->curr, idle);

初始化到时init_idle时将rq->curr制定为idle线程。