diff options
Diffstat (limited to 'kernel/sched/core.c')
-rw-r--r-- | kernel/sched/core.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 257002c13bb0..106167243d68 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -7159,7 +7159,6 @@ static void free_sched_group(struct task_group *tg) | |||
7159 | struct task_group *sched_create_group(struct task_group *parent) | 7159 | struct task_group *sched_create_group(struct task_group *parent) |
7160 | { | 7160 | { |
7161 | struct task_group *tg; | 7161 | struct task_group *tg; |
7162 | unsigned long flags; | ||
7163 | 7162 | ||
7164 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); | 7163 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); |
7165 | if (!tg) | 7164 | if (!tg) |
@@ -7171,6 +7170,17 @@ struct task_group *sched_create_group(struct task_group *parent) | |||
7171 | if (!alloc_rt_sched_group(tg, parent)) | 7170 | if (!alloc_rt_sched_group(tg, parent)) |
7172 | goto err; | 7171 | goto err; |
7173 | 7172 | ||
7173 | return tg; | ||
7174 | |||
7175 | err: | ||
7176 | free_sched_group(tg); | ||
7177 | return ERR_PTR(-ENOMEM); | ||
7178 | } | ||
7179 | |||
7180 | void sched_online_group(struct task_group *tg, struct task_group *parent) | ||
7181 | { | ||
7182 | unsigned long flags; | ||
7183 | |||
7174 | spin_lock_irqsave(&task_group_lock, flags); | 7184 | spin_lock_irqsave(&task_group_lock, flags); |
7175 | list_add_rcu(&tg->list, &task_groups); | 7185 | list_add_rcu(&tg->list, &task_groups); |
7176 | 7186 | ||
@@ -7180,12 +7190,6 @@ struct task_group *sched_create_group(struct task_group *parent) | |||
7180 | INIT_LIST_HEAD(&tg->children); | 7190 | INIT_LIST_HEAD(&tg->children); |
7181 | list_add_rcu(&tg->siblings, &parent->children); | 7191 | list_add_rcu(&tg->siblings, &parent->children); |
7182 | spin_unlock_irqrestore(&task_group_lock, flags); | 7192 | spin_unlock_irqrestore(&task_group_lock, flags); |
7183 | |||
7184 | return tg; | ||
7185 | |||
7186 | err: | ||
7187 | free_sched_group(tg); | ||
7188 | return ERR_PTR(-ENOMEM); | ||
7189 | } | 7193 | } |
7190 | 7194 | ||
7191 | /* rcu callback to free various structures associated with a task group */ | 7195 | /* rcu callback to free various structures associated with a task group */ |
@@ -7198,6 +7202,12 @@ static void free_sched_group_rcu(struct rcu_head *rhp) | |||
7198 | /* Destroy runqueue etc associated with a task group */ | 7202 | /* Destroy runqueue etc associated with a task group */ |
7199 | void sched_destroy_group(struct task_group *tg) | 7203 | void sched_destroy_group(struct task_group *tg) |
7200 | { | 7204 | { |
7205 | /* wait for possible concurrent references to cfs_rqs complete */ | ||
7206 | call_rcu(&tg->rcu, free_sched_group_rcu); | ||
7207 | } | ||
7208 | |||
7209 | void sched_offline_group(struct task_group *tg) | ||
7210 | { | ||
7201 | unsigned long flags; | 7211 | unsigned long flags; |
7202 | int i; | 7212 | int i; |
7203 | 7213 | ||
@@ -7209,9 +7219,6 @@ void sched_destroy_group(struct task_group *tg) | |||
7209 | list_del_rcu(&tg->list); | 7219 | list_del_rcu(&tg->list); |
7210 | list_del_rcu(&tg->siblings); | 7220 | list_del_rcu(&tg->siblings); |
7211 | spin_unlock_irqrestore(&task_group_lock, flags); | 7221 | spin_unlock_irqrestore(&task_group_lock, flags); |
7212 | |||
7213 | /* wait for possible concurrent references to cfs_rqs complete */ | ||
7214 | call_rcu(&tg->rcu, free_sched_group_rcu); | ||
7215 | } | 7222 | } |
7216 | 7223 | ||
7217 | /* change task's runqueue when it moves between groups. | 7224 | /* change task's runqueue when it moves between groups. |
@@ -7563,6 +7570,19 @@ static struct cgroup_subsys_state *cpu_cgroup_css_alloc(struct cgroup *cgrp) | |||
7563 | return &tg->css; | 7570 | return &tg->css; |
7564 | } | 7571 | } |
7565 | 7572 | ||
7573 | static int cpu_cgroup_css_online(struct cgroup *cgrp) | ||
7574 | { | ||
7575 | struct task_group *tg = cgroup_tg(cgrp); | ||
7576 | struct task_group *parent; | ||
7577 | |||
7578 | if (!cgrp->parent) | ||
7579 | return 0; | ||
7580 | |||
7581 | parent = cgroup_tg(cgrp->parent); | ||
7582 | sched_online_group(tg, parent); | ||
7583 | return 0; | ||
7584 | } | ||
7585 | |||
7566 | static void cpu_cgroup_css_free(struct cgroup *cgrp) | 7586 | static void cpu_cgroup_css_free(struct cgroup *cgrp) |
7567 | { | 7587 | { |
7568 | struct task_group *tg = cgroup_tg(cgrp); | 7588 | struct task_group *tg = cgroup_tg(cgrp); |
@@ -7570,6 +7590,13 @@ static void cpu_cgroup_css_free(struct cgroup *cgrp) | |||
7570 | sched_destroy_group(tg); | 7590 | sched_destroy_group(tg); |
7571 | } | 7591 | } |
7572 | 7592 | ||
7593 | static void cpu_cgroup_css_offline(struct cgroup *cgrp) | ||
7594 | { | ||
7595 | struct task_group *tg = cgroup_tg(cgrp); | ||
7596 | |||
7597 | sched_offline_group(tg); | ||
7598 | } | ||
7599 | |||
7573 | static int cpu_cgroup_can_attach(struct cgroup *cgrp, | 7600 | static int cpu_cgroup_can_attach(struct cgroup *cgrp, |
7574 | struct cgroup_taskset *tset) | 7601 | struct cgroup_taskset *tset) |
7575 | { | 7602 | { |
@@ -7925,6 +7952,8 @@ struct cgroup_subsys cpu_cgroup_subsys = { | |||
7925 | .name = "cpu", | 7952 | .name = "cpu", |
7926 | .css_alloc = cpu_cgroup_css_alloc, | 7953 | .css_alloc = cpu_cgroup_css_alloc, |
7927 | .css_free = cpu_cgroup_css_free, | 7954 | .css_free = cpu_cgroup_css_free, |
7955 | .css_online = cpu_cgroup_css_online, | ||
7956 | .css_offline = cpu_cgroup_css_offline, | ||
7928 | .can_attach = cpu_cgroup_can_attach, | 7957 | .can_attach = cpu_cgroup_can_attach, |
7929 | .attach = cpu_cgroup_attach, | 7958 | .attach = cpu_cgroup_attach, |
7930 | .exit = cpu_cgroup_exit, | 7959 | .exit = cpu_cgroup_exit, |