Fix fail to calculate CPU time since thread_group_times was added to .21. -ck --- kernel/sched_bfs.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) Index: linux-2.6.32.21/kernel/sched_bfs.c =================================================================== --- linux-2.6.32.21.orig/kernel/sched_bfs.c 2010-09-22 08:18:25.802987869 +1000 +++ linux-2.6.32.21/kernel/sched_bfs.c 2010-09-22 08:21:25.126546538 +1000 @@ -6743,7 +6743,52 @@ cputime_t task_stime(struct task_struct { return p->stime; } + +void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) +{ + struct task_cputime cputime; + + thread_group_cputime(p, &cputime); + + *ut = cputime.utime; + *st = cputime.stime; +} #else + +#ifndef nsecs_to_cputime +/** + * nsecs_to_jiffies - Convert nsecs in u64 to jiffies + * + * @n: nsecs in u64 + * + * Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64. + * And this doesn't return MAX_JIFFY_OFFSET since this function is designed + * for scheduler, not for use in device drivers to calculate timeout value. + * + * note: + * NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512) + * ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years + */ +static unsigned long nsecs_to_jiffies(u64 n) +{ +#if (NSEC_PER_SEC % HZ) == 0 + /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */ + return div_u64(n, NSEC_PER_SEC / HZ); +#elif (HZ % 512) == 0 + /* overflow after 292 years if HZ = 1024 */ + return div_u64(n * HZ / 512, NSEC_PER_SEC / 512); +#else + /* + * Generic case - optimized for cases where HZ is a multiple of 3. + * overflow after 64.99 years, exact for HZ = 60, 72, 90, 120 etc. + */ + return div_u64(n * 9, (9ull * NSEC_PER_SEC + HZ / 2) / HZ); +#endif +} + +# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) +#endif + cputime_t task_utime(struct task_struct *p) { clock_t utime = cputime_to_clock_t(p->utime), @@ -6774,11 +6819,38 @@ cputime_t task_stime(struct task_struct return p->prev_stime; } -#endif +/* + * Must be called with siglock held. + */ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) { + struct signal_struct *sig = p->signal; + struct task_cputime cputime; + cputime_t rtime, utime, total; + + thread_group_cputime(p, &cputime); + + total = cputime_add(cputime.utime, cputime.stime); + rtime = nsecs_to_cputime(cputime.sum_exec_runtime); + + if (total) { + u64 temp; + + temp = (u64)(rtime * cputime.utime); + do_div(temp, total); + utime = (cputime_t)temp; + } else + utime = rtime; + + sig->prev_utime = max(sig->prev_utime, utime); + sig->prev_stime = max(sig->prev_stime, + cputime_sub(rtime, sig->prev_utime)); + + *ut = sig->prev_utime; + *st = sig->prev_stime; } +#endif inline cputime_t task_gtime(struct task_struct *p) {