aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/array.c3
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/sched.c70
-rw-r--r--kernel/sched_fair.c2
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
364static cputime_t task_stime(struct task_struct *p) 365static 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 */
3358void account_guest_time(struct task_struct *p, cputime_t cputime) 3358static 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
5371static struct ctl_table sd_ctl_root[] = { 5371static 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
5381static struct ctl_table *sd_alloc_ctl_entry(int n) 5381static 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 */
7020static void free_sched_group(struct rcu_head *rhp) 7020static 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 */
7042void sched_destroy_group(struct task_group *tg) 7042void 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
7214static struct cftype cpu_shares = { 7214static 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
7236static 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
7220static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont) 7248static 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
7225struct cgroup_subsys cpu_cgroup_subsys = { 7253struct 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