diff options
| -rw-r--r-- | include/linux/sched.h | 5 | ||||
| -rw-r--r-- | kernel/posix-cpu-timers.c | 34 | ||||
| -rw-r--r-- | kernel/sched.c | 36 |
3 files changed, 33 insertions, 42 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 995eb407c234..3e7f1890e55d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -482,7 +482,8 @@ struct signal_struct { | |||
| 482 | * from jiffies_to_ns(utime + stime) if sched_clock uses something | 482 | * from jiffies_to_ns(utime + stime) if sched_clock uses something |
| 483 | * other than jiffies.) | 483 | * other than jiffies.) |
| 484 | */ | 484 | */ |
| 485 | unsigned long long sched_time; | 485 | unsigned long sched_time; |
| 486 | unsigned long long sum_sched_runtime; | ||
| 486 | 487 | ||
| 487 | /* | 488 | /* |
| 488 | * We don't bother to synchronize most readers of this at all, | 489 | * We don't bother to synchronize most readers of this at all, |
| @@ -1308,7 +1309,7 @@ static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) | |||
| 1308 | 1309 | ||
| 1309 | extern unsigned long long sched_clock(void); | 1310 | extern unsigned long long sched_clock(void); |
| 1310 | extern unsigned long long | 1311 | extern unsigned long long |
| 1311 | current_sched_time(const struct task_struct *current_task); | 1312 | task_sched_runtime(struct task_struct *task); |
| 1312 | 1313 | ||
| 1313 | /* sched_exec is called by processes performing an exec */ | 1314 | /* sched_exec is called by processes performing an exec */ |
| 1314 | #ifdef CONFIG_SMP | 1315 | #ifdef CONFIG_SMP |
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 1de710e18373..b53c8fcd9d82 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
| @@ -161,7 +161,7 @@ static inline cputime_t virt_ticks(struct task_struct *p) | |||
| 161 | } | 161 | } |
| 162 | static inline unsigned long long sched_ns(struct task_struct *p) | 162 | static inline unsigned long long sched_ns(struct task_struct *p) |
| 163 | { | 163 | { |
| 164 | return (p == current) ? current_sched_time(p) : p->sched_time; | 164 | return task_sched_runtime(p); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) | 167 | int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) |
| @@ -246,10 +246,10 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx, | |||
| 246 | } while (t != p); | 246 | } while (t != p); |
| 247 | break; | 247 | break; |
| 248 | case CPUCLOCK_SCHED: | 248 | case CPUCLOCK_SCHED: |
| 249 | cpu->sched = p->signal->sched_time; | 249 | cpu->sched = p->signal->sum_sched_runtime; |
| 250 | /* Add in each other live thread. */ | 250 | /* Add in each other live thread. */ |
| 251 | while ((t = next_thread(t)) != p) { | 251 | while ((t = next_thread(t)) != p) { |
| 252 | cpu->sched += t->sched_time; | 252 | cpu->sched += t->se.sum_exec_runtime; |
| 253 | } | 253 | } |
| 254 | cpu->sched += sched_ns(p); | 254 | cpu->sched += sched_ns(p); |
| 255 | break; | 255 | break; |
| @@ -422,7 +422,7 @@ int posix_cpu_timer_del(struct k_itimer *timer) | |||
| 422 | */ | 422 | */ |
| 423 | static void cleanup_timers(struct list_head *head, | 423 | static void cleanup_timers(struct list_head *head, |
| 424 | cputime_t utime, cputime_t stime, | 424 | cputime_t utime, cputime_t stime, |
| 425 | unsigned long long sched_time) | 425 | unsigned long long sum_exec_runtime) |
| 426 | { | 426 | { |
| 427 | struct cpu_timer_list *timer, *next; | 427 | struct cpu_timer_list *timer, *next; |
| 428 | cputime_t ptime = cputime_add(utime, stime); | 428 | cputime_t ptime = cputime_add(utime, stime); |
| @@ -451,10 +451,10 @@ static void cleanup_timers(struct list_head *head, | |||
| 451 | ++head; | 451 | ++head; |
| 452 | list_for_each_entry_safe(timer, next, head, entry) { | 452 | list_for_each_entry_safe(timer, next, head, entry) { |
| 453 | list_del_init(&timer->entry); | 453 | list_del_init(&timer->entry); |
| 454 | if (timer->expires.sched < sched_time) { | 454 | if (timer->expires.sched < sum_exec_runtime) { |
| 455 | timer->expires.sched = 0; | 455 | timer->expires.sched = 0; |
| 456 | } else { | 456 | } else { |
| 457 | timer->expires.sched -= sched_time; | 457 | timer->expires.sched -= sum_exec_runtime; |
| 458 | } | 458 | } |
| 459 | } | 459 | } |
| 460 | } | 460 | } |
| @@ -467,7 +467,7 @@ static void cleanup_timers(struct list_head *head, | |||
| 467 | void posix_cpu_timers_exit(struct task_struct *tsk) | 467 | void posix_cpu_timers_exit(struct task_struct *tsk) |
| 468 | { | 468 | { |
| 469 | cleanup_timers(tsk->cpu_timers, | 469 | cleanup_timers(tsk->cpu_timers, |
| 470 | tsk->utime, tsk->stime, tsk->sched_time); | 470 | tsk->utime, tsk->stime, tsk->se.sum_exec_runtime); |
| 471 | 471 | ||
| 472 | } | 472 | } |
| 473 | void posix_cpu_timers_exit_group(struct task_struct *tsk) | 473 | void posix_cpu_timers_exit_group(struct task_struct *tsk) |
| @@ -475,7 +475,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk) | |||
| 475 | cleanup_timers(tsk->signal->cpu_timers, | 475 | cleanup_timers(tsk->signal->cpu_timers, |
| 476 | cputime_add(tsk->utime, tsk->signal->utime), | 476 | cputime_add(tsk->utime, tsk->signal->utime), |
| 477 | cputime_add(tsk->stime, tsk->signal->stime), | 477 | cputime_add(tsk->stime, tsk->signal->stime), |
| 478 | tsk->sched_time + tsk->signal->sched_time); | 478 | tsk->se.sum_exec_runtime + tsk->signal->sum_sched_runtime); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | 481 | ||
| @@ -536,7 +536,7 @@ static void process_timer_rebalance(struct task_struct *p, | |||
| 536 | nsleft = max_t(unsigned long long, nsleft, 1); | 536 | nsleft = max_t(unsigned long long, nsleft, 1); |
| 537 | do { | 537 | do { |
| 538 | if (likely(!(t->flags & PF_EXITING))) { | 538 | if (likely(!(t->flags & PF_EXITING))) { |
| 539 | ns = t->sched_time + nsleft; | 539 | ns = t->se.sum_exec_runtime + nsleft; |
| 540 | if (t->it_sched_expires == 0 || | 540 | if (t->it_sched_expires == 0 || |
| 541 | t->it_sched_expires > ns) { | 541 | t->it_sched_expires > ns) { |
| 542 | t->it_sched_expires = ns; | 542 | t->it_sched_expires = ns; |
| @@ -1004,7 +1004,7 @@ static void check_thread_timers(struct task_struct *tsk, | |||
| 1004 | struct cpu_timer_list *t = list_first_entry(timers, | 1004 | struct cpu_timer_list *t = list_first_entry(timers, |
| 1005 | struct cpu_timer_list, | 1005 | struct cpu_timer_list, |
| 1006 | entry); | 1006 | entry); |
| 1007 | if (!--maxfire || tsk->sched_time < t->expires.sched) { | 1007 | if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) { |
| 1008 | tsk->it_sched_expires = t->expires.sched; | 1008 | tsk->it_sched_expires = t->expires.sched; |
| 1009 | break; | 1009 | break; |
| 1010 | } | 1010 | } |
| @@ -1024,7 +1024,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
| 1024 | int maxfire; | 1024 | int maxfire; |
| 1025 | struct signal_struct *const sig = tsk->signal; | 1025 | struct signal_struct *const sig = tsk->signal; |
| 1026 | cputime_t utime, stime, ptime, virt_expires, prof_expires; | 1026 | cputime_t utime, stime, ptime, virt_expires, prof_expires; |
| 1027 | unsigned long long sched_time, sched_expires; | 1027 | unsigned long long sum_sched_runtime, sched_expires; |
| 1028 | struct task_struct *t; | 1028 | struct task_struct *t; |
| 1029 | struct list_head *timers = sig->cpu_timers; | 1029 | struct list_head *timers = sig->cpu_timers; |
| 1030 | 1030 | ||
| @@ -1044,12 +1044,12 @@ static void check_process_timers(struct task_struct *tsk, | |||
| 1044 | */ | 1044 | */ |
| 1045 | utime = sig->utime; | 1045 | utime = sig->utime; |
| 1046 | stime = sig->stime; | 1046 | stime = sig->stime; |
| 1047 | sched_time = sig->sched_time; | 1047 | sum_sched_runtime = sig->sum_sched_runtime; |
| 1048 | t = tsk; | 1048 | t = tsk; |
| 1049 | do { | 1049 | do { |
| 1050 | utime = cputime_add(utime, t->utime); | 1050 | utime = cputime_add(utime, t->utime); |
| 1051 | stime = cputime_add(stime, t->stime); | 1051 | stime = cputime_add(stime, t->stime); |
| 1052 | sched_time += t->sched_time; | 1052 | sum_sched_runtime += t->se.sum_exec_runtime; |
| 1053 | t = next_thread(t); | 1053 | t = next_thread(t); |
| 1054 | } while (t != tsk); | 1054 | } while (t != tsk); |
| 1055 | ptime = cputime_add(utime, stime); | 1055 | ptime = cputime_add(utime, stime); |
| @@ -1090,7 +1090,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
| 1090 | struct cpu_timer_list *t = list_first_entry(timers, | 1090 | struct cpu_timer_list *t = list_first_entry(timers, |
| 1091 | struct cpu_timer_list, | 1091 | struct cpu_timer_list, |
| 1092 | entry); | 1092 | entry); |
| 1093 | if (!--maxfire || sched_time < t->expires.sched) { | 1093 | if (!--maxfire || sum_sched_runtime < t->expires.sched) { |
| 1094 | sched_expires = t->expires.sched; | 1094 | sched_expires = t->expires.sched; |
| 1095 | break; | 1095 | break; |
| 1096 | } | 1096 | } |
| @@ -1182,7 +1182,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
| 1182 | virt_left = cputime_sub(virt_expires, utime); | 1182 | virt_left = cputime_sub(virt_expires, utime); |
| 1183 | virt_left = cputime_div_non_zero(virt_left, nthreads); | 1183 | virt_left = cputime_div_non_zero(virt_left, nthreads); |
| 1184 | if (sched_expires) { | 1184 | if (sched_expires) { |
| 1185 | sched_left = sched_expires - sched_time; | 1185 | sched_left = sched_expires - sum_sched_runtime; |
| 1186 | do_div(sched_left, nthreads); | 1186 | do_div(sched_left, nthreads); |
| 1187 | sched_left = max_t(unsigned long long, sched_left, 1); | 1187 | sched_left = max_t(unsigned long long, sched_left, 1); |
| 1188 | } else { | 1188 | } else { |
| @@ -1208,7 +1208,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
| 1208 | t->it_virt_expires = ticks; | 1208 | t->it_virt_expires = ticks; |
| 1209 | } | 1209 | } |
| 1210 | 1210 | ||
| 1211 | sched = t->sched_time + sched_left; | 1211 | sched = t->se.sum_exec_runtime + sched_left; |
| 1212 | if (sched_expires && (t->it_sched_expires == 0 || | 1212 | if (sched_expires && (t->it_sched_expires == 0 || |
| 1213 | t->it_sched_expires > sched)) { | 1213 | t->it_sched_expires > sched)) { |
| 1214 | t->it_sched_expires = sched; | 1214 | t->it_sched_expires = sched; |
| @@ -1300,7 +1300,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
| 1300 | 1300 | ||
| 1301 | if (UNEXPIRED(prof) && UNEXPIRED(virt) && | 1301 | if (UNEXPIRED(prof) && UNEXPIRED(virt) && |
| 1302 | (tsk->it_sched_expires == 0 || | 1302 | (tsk->it_sched_expires == 0 || |
| 1303 | tsk->sched_time < tsk->it_sched_expires)) | 1303 | tsk->se.sum_exec_runtime < tsk->it_sched_expires)) |
| 1304 | return; | 1304 | return; |
| 1305 | 1305 | ||
| 1306 | #undef UNEXPIRED | 1306 | #undef UNEXPIRED |
diff --git a/kernel/sched.c b/kernel/sched.c index 29eb227e33f7..0333abdda85e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -3156,28 +3156,23 @@ DEFINE_PER_CPU(struct kernel_stat, kstat); | |||
| 3156 | EXPORT_PER_CPU_SYMBOL(kstat); | 3156 | EXPORT_PER_CPU_SYMBOL(kstat); |
| 3157 | 3157 | ||
| 3158 | /* | 3158 | /* |
| 3159 | * This is called on clock ticks and on context switches. | 3159 | * Return p->sum_exec_runtime plus any more ns on the sched_clock |
| 3160 | * Bank in p->sched_time the ns elapsed since the last tick or switch. | 3160 | * that have not yet been banked in case the task is currently running. |
| 3161 | */ | 3161 | */ |
| 3162 | static inline void | 3162 | unsigned long long task_sched_runtime(struct task_struct *p) |
| 3163 | update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now) | ||
| 3164 | { | 3163 | { |
| 3165 | p->sched_time += now - p->last_ran; | ||
| 3166 | p->last_ran = rq->most_recent_timestamp = now; | ||
| 3167 | } | ||
| 3168 | |||
| 3169 | /* | ||
| 3170 | * Return current->sched_time plus any more ns on the sched_clock | ||
| 3171 | * that have not yet been banked. | ||
| 3172 | */ | ||
| 3173 | unsigned long long current_sched_time(const struct task_struct *p) | ||
| 3174 | { | ||
| 3175 | unsigned long long ns; | ||
| 3176 | unsigned long flags; | 3164 | unsigned long flags; |
| 3165 | u64 ns, delta_exec; | ||
| 3166 | struct rq *rq; | ||
| 3177 | 3167 | ||
| 3178 | local_irq_save(flags); | 3168 | rq = task_rq_lock(p, &flags); |
| 3179 | ns = p->sched_time + sched_clock() - p->last_ran; | 3169 | ns = p->se.sum_exec_runtime; |
| 3180 | local_irq_restore(flags); | 3170 | if (rq->curr == p) { |
| 3171 | delta_exec = rq_clock(rq) - p->se.exec_start; | ||
| 3172 | if ((s64)delta_exec > 0) | ||
| 3173 | ns += delta_exec; | ||
| 3174 | } | ||
| 3175 | task_rq_unlock(rq, &flags); | ||
| 3181 | 3176 | ||
| 3182 | return ns; | 3177 | return ns; |
| 3183 | } | 3178 | } |
| @@ -3360,14 +3355,11 @@ out_unlock: | |||
| 3360 | */ | 3355 | */ |
| 3361 | void scheduler_tick(void) | 3356 | void scheduler_tick(void) |
| 3362 | { | 3357 | { |
| 3363 | unsigned long long now = sched_clock(); | ||
| 3364 | struct task_struct *p = current; | 3358 | struct task_struct *p = current; |
| 3365 | int cpu = smp_processor_id(); | 3359 | int cpu = smp_processor_id(); |
| 3366 | int idle_at_tick = idle_cpu(cpu); | 3360 | int idle_at_tick = idle_cpu(cpu); |
| 3367 | struct rq *rq = cpu_rq(cpu); | 3361 | struct rq *rq = cpu_rq(cpu); |
| 3368 | 3362 | ||
| 3369 | update_cpu_clock(p, rq, now); | ||
| 3370 | |||
| 3371 | if (!idle_at_tick) | 3363 | if (!idle_at_tick) |
| 3372 | task_running_tick(rq, p); | 3364 | task_running_tick(rq, p); |
| 3373 | #ifdef CONFIG_SMP | 3365 | #ifdef CONFIG_SMP |
| @@ -3550,8 +3542,6 @@ switch_tasks: | |||
| 3550 | clear_tsk_need_resched(prev); | 3542 | clear_tsk_need_resched(prev); |
| 3551 | rcu_qsctr_inc(task_cpu(prev)); | 3543 | rcu_qsctr_inc(task_cpu(prev)); |
| 3552 | 3544 | ||
| 3553 | update_cpu_clock(prev, rq, now); | ||
| 3554 | |||
| 3555 | prev->sleep_avg -= run_time; | 3545 | prev->sleep_avg -= run_time; |
| 3556 | if ((long)prev->sleep_avg <= 0) | 3546 | if ((long)prev->sleep_avg <= 0) |
| 3557 | prev->sleep_avg = 0; | 3547 | prev->sleep_avg = 0; |
