diff options
-rw-r--r-- | fs/proc/array.c | 3 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | kernel/fork.c | 1 | ||||
-rw-r--r-- | kernel/sched.c | 70 | ||||
-rw-r--r-- | kernel/sched_fair.c | 2 |
5 files changed, 54 insertions, 23 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 63c95afb561f..d80baaabf835 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -358,7 +358,8 @@ static cputime_t task_utime(struct task_struct *p) | |||
358 | } | 358 | } |
359 | utime = (clock_t)temp; | 359 | utime = (clock_t)temp; |
360 | 360 | ||
361 | return clock_t_to_cputime(utime); | 361 | p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); |
362 | return p->prev_utime; | ||
362 | } | 363 | } |
363 | 364 | ||
364 | static cputime_t task_stime(struct task_struct *p) | 365 | static cputime_t task_stime(struct task_struct *p) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c07d595979f..b0b1fe6e0b17 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1009,6 +1009,7 @@ struct task_struct { | |||
1009 | unsigned int rt_priority; | 1009 | unsigned int rt_priority; |
1010 | cputime_t utime, stime, utimescaled, stimescaled; | 1010 | cputime_t utime, stime, utimescaled, stimescaled; |
1011 | cputime_t gtime; | 1011 | cputime_t gtime; |
1012 | cputime_t prev_utime; | ||
1012 | unsigned long nvcsw, nivcsw; /* context switch counts */ | 1013 | unsigned long nvcsw, nivcsw; /* context switch counts */ |
1013 | struct timespec start_time; /* monotonic time */ | 1014 | struct timespec start_time; /* monotonic time */ |
1014 | struct timespec real_start_time; /* boot based time */ | 1015 | struct timespec real_start_time; /* boot based time */ |
diff --git a/kernel/fork.c b/kernel/fork.c index ddafdfac9456..a65bfc47177c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1056,6 +1056,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1056 | p->gtime = cputime_zero; | 1056 | p->gtime = cputime_zero; |
1057 | p->utimescaled = cputime_zero; | 1057 | p->utimescaled = cputime_zero; |
1058 | p->stimescaled = cputime_zero; | 1058 | p->stimescaled = cputime_zero; |
1059 | p->prev_utime = cputime_zero; | ||
1059 | 1060 | ||
1060 | #ifdef CONFIG_TASK_XACCT | 1061 | #ifdef CONFIG_TASK_XACCT |
1061 | p->rchar = 0; /* I/O counter: bytes read */ | 1062 | p->rchar = 0; /* I/O counter: bytes read */ |
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 | ||
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 9971831b560e..01859f662ab7 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -1025,7 +1025,7 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr) | |||
1025 | } | 1025 | } |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | #define swap(a,b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0) | 1028 | #define swap(a, b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0) |
1029 | 1029 | ||
1030 | /* | 1030 | /* |
1031 | * Share the fairness runtime between parent and child, thus the | 1031 | * Share the fairness runtime between parent and child, thus the |