diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 9a1ddb84e26d..cc1f81b50b82 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4179,6 +4179,65 @@ void account_steal_time(struct task_struct *p, cputime_t steal) | |||
4179 | } | 4179 | } |
4180 | 4180 | ||
4181 | /* | 4181 | /* |
4182 | * Use precise platform statistics if available: | ||
4183 | */ | ||
4184 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
4185 | cputime_t task_utime(struct task_struct *p) | ||
4186 | { | ||
4187 | return p->utime; | ||
4188 | } | ||
4189 | |||
4190 | cputime_t task_stime(struct task_struct *p) | ||
4191 | { | ||
4192 | return p->stime; | ||
4193 | } | ||
4194 | #else | ||
4195 | cputime_t task_utime(struct task_struct *p) | ||
4196 | { | ||
4197 | clock_t utime = cputime_to_clock_t(p->utime), | ||
4198 | total = utime + cputime_to_clock_t(p->stime); | ||
4199 | u64 temp; | ||
4200 | |||
4201 | /* | ||
4202 | * Use CFS's precise accounting: | ||
4203 | */ | ||
4204 | temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); | ||
4205 | |||
4206 | if (total) { | ||
4207 | temp *= utime; | ||
4208 | do_div(temp, total); | ||
4209 | } | ||
4210 | utime = (clock_t)temp; | ||
4211 | |||
4212 | p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); | ||
4213 | return p->prev_utime; | ||
4214 | } | ||
4215 | |||
4216 | cputime_t task_stime(struct task_struct *p) | ||
4217 | { | ||
4218 | clock_t stime; | ||
4219 | |||
4220 | /* | ||
4221 | * Use CFS's precise accounting. (we subtract utime from | ||
4222 | * the total, to make sure the total observed by userspace | ||
4223 | * grows monotonically - apps rely on that): | ||
4224 | */ | ||
4225 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - | ||
4226 | cputime_to_clock_t(task_utime(p)); | ||
4227 | |||
4228 | if (stime >= 0) | ||
4229 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | ||
4230 | |||
4231 | return p->prev_stime; | ||
4232 | } | ||
4233 | #endif | ||
4234 | |||
4235 | inline cputime_t task_gtime(struct task_struct *p) | ||
4236 | { | ||
4237 | return p->gtime; | ||
4238 | } | ||
4239 | |||
4240 | /* | ||
4182 | * This function gets called by the timer code, with HZ frequency. | 4241 | * This function gets called by the timer code, with HZ frequency. |
4183 | * We call it with interrupts disabled. | 4242 | * We call it with interrupts disabled. |
4184 | * | 4243 | * |
@@ -7637,24 +7696,27 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, | |||
7637 | * and partition_sched_domains() will fallback to the single partition | 7696 | * and partition_sched_domains() will fallback to the single partition |
7638 | * 'fallback_doms', it also forces the domains to be rebuilt. | 7697 | * 'fallback_doms', it also forces the domains to be rebuilt. |
7639 | * | 7698 | * |
7699 | * If doms_new==NULL it will be replaced with cpu_online_map. | ||
7700 | * ndoms_new==0 is a special case for destroying existing domains. | ||
7701 | * It will not create the default domain. | ||
7702 | * | ||
7640 | * Call with hotplug lock held | 7703 | * Call with hotplug lock held |
7641 | */ | 7704 | */ |
7642 | void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, | 7705 | void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, |
7643 | struct sched_domain_attr *dattr_new) | 7706 | struct sched_domain_attr *dattr_new) |
7644 | { | 7707 | { |
7645 | int i, j; | 7708 | int i, j, n; |
7646 | 7709 | ||
7647 | mutex_lock(&sched_domains_mutex); | 7710 | mutex_lock(&sched_domains_mutex); |
7648 | 7711 | ||
7649 | /* always unregister in case we don't destroy any domains */ | 7712 | /* always unregister in case we don't destroy any domains */ |
7650 | unregister_sched_domain_sysctl(); | 7713 | unregister_sched_domain_sysctl(); |
7651 | 7714 | ||
7652 | if (doms_new == NULL) | 7715 | n = doms_new ? ndoms_new : 0; |
7653 | ndoms_new = 0; | ||
7654 | 7716 | ||
7655 | /* Destroy deleted domains */ | 7717 | /* Destroy deleted domains */ |
7656 | for (i = 0; i < ndoms_cur; i++) { | 7718 | for (i = 0; i < ndoms_cur; i++) { |
7657 | for (j = 0; j < ndoms_new; j++) { | 7719 | for (j = 0; j < n; j++) { |
7658 | if (cpus_equal(doms_cur[i], doms_new[j]) | 7720 | if (cpus_equal(doms_cur[i], doms_new[j]) |
7659 | && dattrs_equal(dattr_cur, i, dattr_new, j)) | 7721 | && dattrs_equal(dattr_cur, i, dattr_new, j)) |
7660 | goto match1; | 7722 | goto match1; |
@@ -7667,7 +7729,6 @@ match1: | |||
7667 | 7729 | ||
7668 | if (doms_new == NULL) { | 7730 | if (doms_new == NULL) { |
7669 | ndoms_cur = 0; | 7731 | ndoms_cur = 0; |
7670 | ndoms_new = 1; | ||
7671 | doms_new = &fallback_doms; | 7732 | doms_new = &fallback_doms; |
7672 | cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map); | 7733 | cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map); |
7673 | dattr_new = NULL; | 7734 | dattr_new = NULL; |
@@ -7704,8 +7765,13 @@ match2: | |||
7704 | int arch_reinit_sched_domains(void) | 7765 | int arch_reinit_sched_domains(void) |
7705 | { | 7766 | { |
7706 | get_online_cpus(); | 7767 | get_online_cpus(); |
7768 | |||
7769 | /* Destroy domains first to force the rebuild */ | ||
7770 | partition_sched_domains(0, NULL, NULL); | ||
7771 | |||
7707 | rebuild_sched_domains(); | 7772 | rebuild_sched_domains(); |
7708 | put_online_cpus(); | 7773 | put_online_cpus(); |
7774 | |||
7709 | return 0; | 7775 | return 0; |
7710 | } | 7776 | } |
7711 | 7777 | ||
@@ -7789,7 +7855,7 @@ static int update_sched_domains(struct notifier_block *nfb, | |||
7789 | case CPU_ONLINE_FROZEN: | 7855 | case CPU_ONLINE_FROZEN: |
7790 | case CPU_DEAD: | 7856 | case CPU_DEAD: |
7791 | case CPU_DEAD_FROZEN: | 7857 | case CPU_DEAD_FROZEN: |
7792 | partition_sched_domains(0, NULL, NULL); | 7858 | partition_sched_domains(1, NULL, NULL); |
7793 | return NOTIFY_OK; | 7859 | return NOTIFY_OK; |
7794 | 7860 | ||
7795 | default: | 7861 | default: |