sched_entity의 초기화
새로운 태스크가 생성될 때 task_struct를 slab cache에서 새롭게 가져온다. 태스크의 sched_entity는 task_struct 구조체에 embedded되어 있으므로 sched_entity도 0으로 초기화되어 있다.
do_fork
-> _do_fork
->-> copy_process()
->->-> dup_task_struct()
->->->-> alloc_task_struct_node() <------ allocate new task_struct
task_struct의 sched_entity의 주요변수들은 __sched_fork()에서 다시한번 0으로 초기화된다.
do_fork
-> _do_fork
->-> copy_process()
->->-> sched_fork()
->->->-> __sched_fork()
kernel/sched/core.c
static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
{
p->on_rq = 0;
p->se.on_rq = 0;
p->se.exec_start = 0;
p->se.sum_exec_runtime = 0;
p->se.prev_sum_exec_runtime = 0;
p->se.nr_migrations = 0;
p->se.vruntime = 0;
INIT_LIST_HEAD(&p->se.group_node);
#ifdef CONFIG_FAIR_GROUP_SCHED
p->se.cfs_rq = NULL;
#endif
...
}
다만 sched_entity의 cfs_rq, parent 멤버변수는 set_task_rq()에서 의미있는 값으로 설정된다
kernel/sched/sched.h
static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
{
#if defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED)
struct task_group *tg = task_group(p);
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
set_task_rq_fair(&p->se, p->se.cfs_rq, tg->cfs_rq[cpu]);
p->se.cfs_rq = tg->cfs_rq[cpu];
p->se.parent = tg->se[cpu];
#endif
}
task_group()은 태스크 @p->sched_task_group이 가리키는 태스크그룹을 리턴해준다. 별도의 태스크그룹을 생성하지 않으면 root_task_group으로 설정되어 있다.
새로 생성되는 태스크의 sched_task_group 멤버변수는 dup_task_struct()에서 부모의 것으로 복사된다. sched_task_group은 태스크가 다른 태스크그룹으로 이동할 때(sched_move_task()) 변경된다.
root_task_group으로 설정되어 있다고 가정하면, 새로 생성된 태스크 p의 sched_entity는 아래와 같이 설정된다.
- @cpu의 rq->cfs_rq가 태스크가 enqueue될 cfs_rq로 설정됨
- 태스크의 부모 sched_entity로 NULL이 설정됨.
위 설정되는 값이 잘 이해가 가지 않을 경우 태스크그룹 계층도의 root - root_task_group 글의 그림을 참고한다.
새로 생성된 태스크의 sched_entity가 초기화된 모습을 그림으로 표현하면 아래와 같다.