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 |
