diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index b4fbbc440453..3f6bd1112900 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -172,6 +172,7 @@ struct task_group { | |||
172 | unsigned long shares; | 172 | unsigned long shares; |
173 | /* spinlock to serialize modification to shares */ | 173 | /* spinlock to serialize modification to shares */ |
174 | spinlock_t lock; | 174 | spinlock_t lock; |
175 | struct rcu_head rcu; | ||
175 | }; | 176 | }; |
176 | 177 | ||
177 | /* Default task group's sched entity on each cpu */ | 178 | /* Default task group's sched entity on each cpu */ |
@@ -258,7 +259,6 @@ struct cfs_rq { | |||
258 | */ | 259 | */ |
259 | struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */ | 260 | struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */ |
260 | struct task_group *tg; /* group that "owns" this runqueue */ | 261 | struct task_group *tg; /* group that "owns" this runqueue */ |
261 | struct rcu_head rcu; | ||
262 | #endif | 262 | #endif |
263 | }; | 263 | }; |
264 | 264 | ||
@@ -3355,7 +3355,7 @@ void account_user_time(struct task_struct *p, cputime_t cputime) | |||
3355 | * @p: the process that the cpu time gets accounted to | 3355 | * @p: the process that the cpu time gets accounted to |
3356 | * @cputime: the cpu time spent in virtual machine since the last update | 3356 | * @cputime: the cpu time spent in virtual machine since the last update |
3357 | */ | 3357 | */ |
3358 | void account_guest_time(struct task_struct *p, cputime_t cputime) | 3358 | static void account_guest_time(struct task_struct *p, cputime_t cputime) |
3359 | { | 3359 | { |
3360 | cputime64_t tmp; | 3360 | cputime64_t tmp; |
3361 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; | 3361 | struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; |
@@ -5365,7 +5365,7 @@ static struct ctl_table sd_ctl_dir[] = { | |||
5365 | .procname = "sched_domain", | 5365 | .procname = "sched_domain", |
5366 | .mode = 0555, | 5366 | .mode = 0555, |
5367 | }, | 5367 | }, |
5368 | {0,}, | 5368 | {0, }, |
5369 | }; | 5369 | }; |
5370 | 5370 | ||
5371 | static struct ctl_table sd_ctl_root[] = { | 5371 | static struct ctl_table sd_ctl_root[] = { |
@@ -5375,7 +5375,7 @@ static struct ctl_table sd_ctl_root[] = { | |||
5375 | .mode = 0555, | 5375 | .mode = 0555, |
5376 | .child = sd_ctl_dir, | 5376 | .child = sd_ctl_dir, |
5377 | }, | 5377 | }, |
5378 | {0,}, | 5378 | {0, }, |
5379 | }; | 5379 | }; |
5380 | 5380 | ||
5381 | static struct ctl_table *sd_alloc_ctl_entry(int n) | 5381 | static struct ctl_table *sd_alloc_ctl_entry(int n) |
@@ -7019,8 +7019,8 @@ err: | |||
7019 | /* rcu callback to free various structures associated with a task group */ | 7019 | /* rcu callback to free various structures associated with a task group */ |
7020 | static void free_sched_group(struct rcu_head *rhp) | 7020 | static void free_sched_group(struct rcu_head *rhp) |
7021 | { | 7021 | { |
7022 | struct cfs_rq *cfs_rq = container_of(rhp, struct cfs_rq, rcu); | 7022 | struct task_group *tg = container_of(rhp, struct task_group, rcu); |
7023 | struct task_group *tg = cfs_rq->tg; | 7023 | struct cfs_rq *cfs_rq; |
7024 | struct sched_entity *se; | 7024 | struct sched_entity *se; |
7025 | int i; | 7025 | int i; |
7026 | 7026 | ||
@@ -7041,7 +7041,7 @@ static void free_sched_group(struct rcu_head *rhp) | |||
7041 | /* Destroy runqueue etc associated with a task group */ | 7041 | /* Destroy runqueue etc associated with a task group */ |
7042 | void sched_destroy_group(struct task_group *tg) | 7042 | void sched_destroy_group(struct task_group *tg) |
7043 | { | 7043 | { |
7044 | struct cfs_rq *cfs_rq; | 7044 | struct cfs_rq *cfs_rq = NULL; |
7045 | int i; | 7045 | int i; |
7046 | 7046 | ||
7047 | for_each_possible_cpu(i) { | 7047 | for_each_possible_cpu(i) { |
@@ -7049,10 +7049,10 @@ void sched_destroy_group(struct task_group *tg) | |||
7049 | list_del_rcu(&cfs_rq->leaf_cfs_rq_list); | 7049 | list_del_rcu(&cfs_rq->leaf_cfs_rq_list); |
7050 | } | 7050 | } |
7051 | 7051 | ||
7052 | cfs_rq = tg->cfs_rq[0]; | 7052 | BUG_ON(!cfs_rq); |
7053 | 7053 | ||
7054 | /* wait for possible concurrent references to cfs_rqs complete */ | 7054 | /* wait for possible concurrent references to cfs_rqs complete */ |
7055 | call_rcu(&cfs_rq->rcu, free_sched_group); | 7055 | call_rcu(&tg->rcu, free_sched_group); |
7056 | } | 7056 | } |
7057 | 7057 | ||
7058 | /* change task's runqueue when it moves between groups. | 7058 | /* change task's runqueue when it moves between groups. |
@@ -7211,25 +7211,53 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft) | |||
7211 | return (u64) tg->shares; | 7211 | return (u64) tg->shares; |
7212 | } | 7212 | } |
7213 | 7213 | ||
7214 | static struct cftype cpu_shares = { | 7214 | static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft) |
7215 | .name = "shares", | 7215 | { |
7216 | .read_uint = cpu_shares_read_uint, | 7216 | struct task_group *tg = cgroup_tg(cgrp); |
7217 | .write_uint = cpu_shares_write_uint, | 7217 | unsigned long flags; |
7218 | u64 res = 0; | ||
7219 | int i; | ||
7220 | |||
7221 | for_each_possible_cpu(i) { | ||
7222 | /* | ||
7223 | * Lock to prevent races with updating 64-bit counters | ||
7224 | * on 32-bit arches. | ||
7225 | */ | ||
7226 | spin_lock_irqsave(&cpu_rq(i)->lock, flags); | ||
7227 | res += tg->se[i]->sum_exec_runtime; | ||
7228 | spin_unlock_irqrestore(&cpu_rq(i)->lock, flags); | ||
7229 | } | ||
7230 | /* Convert from ns to ms */ | ||
7231 | do_div(res, 1000000); | ||
7232 | |||
7233 | return res; | ||
7234 | } | ||
7235 | |||
7236 | static struct cftype cpu_files[] = { | ||
7237 | { | ||
7238 | .name = "shares", | ||
7239 | .read_uint = cpu_shares_read_uint, | ||
7240 | .write_uint = cpu_shares_write_uint, | ||
7241 | }, | ||
7242 | { | ||
7243 | .name = "usage", | ||
7244 | .read_uint = cpu_usage_read, | ||
7245 | }, | ||
7218 | }; | 7246 | }; |
7219 | 7247 | ||
7220 | static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont) | 7248 | static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont) |
7221 | { | 7249 | { |
7222 | return cgroup_add_file(cont, ss, &cpu_shares); | 7250 | return cgroup_add_files(cont, ss, cpu_files, ARRAY_SIZE(cpu_files)); |
7223 | } | 7251 | } |
7224 | 7252 | ||
7225 | struct cgroup_subsys cpu_cgroup_subsys = { | 7253 | struct cgroup_subsys cpu_cgroup_subsys = { |
7226 | .name = "cpu", | 7254 | .name = "cpu", |
7227 | .create = cpu_cgroup_create, | 7255 | .create = cpu_cgroup_create, |
7228 | .destroy = cpu_cgroup_destroy, | 7256 | .destroy = cpu_cgroup_destroy, |
7229 | .can_attach = cpu_cgroup_can_attach, | 7257 | .can_attach = cpu_cgroup_can_attach, |
7230 | .attach = cpu_cgroup_attach, | 7258 | .attach = cpu_cgroup_attach, |
7231 | .populate = cpu_cgroup_populate, | 7259 | .populate = cpu_cgroup_populate, |
7232 | .subsys_id = cpu_cgroup_subsys_id, | 7260 | .subsys_id = cpu_cgroup_subsys_id, |
7233 | .early_init = 1, | 7261 | .early_init = 1, |
7234 | }; | 7262 | }; |
7235 | 7263 | ||