组调度属于cgroup中的cpu子系统 cpu子系统的所有操作都在cpu_cgrp_subsys 中有定义 struct cgroup_subsys cpu_cgrp_subsys = { .css_alloc = cpu_cgroup_css_alloc, .css_online = cpu_cgroup_css_online, .css_released = cpu_cgroup_css_released, .css_free = cpu_cgroup_css_free, .css_extra_stat_show = cpu_extra_stat_show, .fork = cpu_cgroup_fork, .can_attach = cpu_cgroup_can_attach, .attach = cpu_cgroup_attach, .legacy_cftypes = cpu_legacy_files, .dfl_cftypes = cpu_files, .early_init = true, .threaded = true, }; 我们这里以css_alloc 为例 static struct cgroup_subsys_state * cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) { struct task_group *parent = css_tg(parent_css); struct task_group *tg; if (!parent) { /* This is early initialization for the top cgroup */ return &root_task_group.css; } #创建调度组 tg = sched_create_group(parent); if (IS_ERR(tg)) return ERR_PTR(-ENOMEM); return &tg->css; } struct task_group *sched_create_group(struct task_group *parent) { struct task_group *tg; tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO); if (!tg) return ERR_PTR(-ENOMEM); #可见这里分别为fair和rt申请调度组 if (!alloc_fair_sched_group(tg, parent)) goto err; if (!alloc_rt_sched_group(tg, parent)) goto err; return tg; err: sched_free_group(tg); return ERR_PTR(-ENOMEM); } int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) { struct sched_entity *se; struct cfs_rq *cfs_rq; int i; #分别问cfs_rq和se申请内存 tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL); if (!tg->cfs_rq) goto err; tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL); if (!tg->se) goto err; tg->shares = NICE_0_LOAD; init_cfs_bandwidth(tg_cfs_bandwidth(tg)); #为每个cpu 初始化cfs_rq和se for_each_possible_cpu(i) { cfs_rq = kzalloc_node(sizeof(struct cfs_rq), GFP_KERNEL, cpu_to_node(i)); if (!cfs_rq) goto err; se = kzalloc_node(sizeof(struct sched_entity), GFP_KERNEL, cpu_to_node(i)); if (!se) goto err_free_rq; #主要是初始化 init_cfs_rq(cfs_rq); init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]); init_entity_runnable_average(se); } } 当进程要加入组调度是会调用attach static void cpu_cgroup_attach(struct cgroup_taskset *tset) { struct task_struct *task; struct cgroup_subsys_state *css; #将cgroup_taskset 中的所有task通过sched_move_task 将进程迁移到组调度中 cgroup_taskset_for_each(task, css, tset) sched_move_task(task); } void sched_move_task(struct task_struct *tsk) { #分别调用调度器的dequeue_task函数迁出task,然后在调用enqueue_task加入调度组 if (queued) dequeue_task(rq, tsk, queue_flags); if (running) put_prev_task(rq, tsk); sched_change_group(tsk, TASK_MOVE_GROUP); if (queued) enqueue_task(rq, tsk, queue_flags); if (running) set_curr_task(rq, tsk); } 这里以enqueue_task 为例 static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags) { if (!(flags & ENQUEUE_NOCLOCK)) update_rq_clock(rq); if (!(flags & ENQUEUE_RESTORE)) sched_info_queued(rq, p); #这里最终调用fair的enqueue_task_fair 来加入组调度的fair的rq中 p->sched_class->enqueue_task(rq, p, flags); }
转载请标明出处:cpu子系统的组调度
文章来源: cpu子系统的组调度