diff -rup /home/fmayhar/Static/linux-2.6.18.5/fs/binfmt_elf.c linux-2.6.18.5/fs/binfmt_elf.c --- /home/fmayhar/Static/linux-2.6.18.5/fs/binfmt_elf.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/fs/binfmt_elf.c 2008-03-06 15:05:34.000000000 -0800 @@ -1302,17 +1302,17 @@ static void fill_prstatus(struct elf_prs if (thread_group_leader(p)) { /* * This is the record for the group leader. Add in the - * cumulative times of previous dead threads. This total - * won't include the time of each live thread whose state - * is included in the core dump. The final total reported - * to our parent process when it calls wait4 will include - * those sums as well as the little bit more time it takes - * this and each other thread to finish dying after the - * core dump synchronization phase. + * cumulative times of all threads. This total includes + * the time of each live thread whose state is included in + * the core dump. The final total reported to our parent + * process when it calls wait4 will include those sums as + * well as the little bit more time it takes this and each + * other thread to finish dying after the core dump + * synchronization phase. */ - cputime_to_timeval(cputime_add(p->utime, p->signal->utime), + cputime_to_timeval(p->signal->shared_utime, &prstatus->pr_utime); - cputime_to_timeval(cputime_add(p->stime, p->signal->stime), + cputime_to_timeval(p->signal->shared_stime, &prstatus->pr_stime); } else { cputime_to_timeval(p->utime, &prstatus->pr_utime); diff -rup /home/fmayhar/Static/linux-2.6.18.5/fs/proc/array.c linux-2.6.18.5/fs/proc/array.c --- /home/fmayhar/Static/linux-2.6.18.5/fs/proc/array.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/fs/proc/array.c 2008-03-06 17:43:19.000000000 -0800 @@ -359,8 +359,6 @@ static int do_task_stat(struct task_stru do { min_flt += t->min_flt; maj_flt += t->maj_flt; - utime = cputime_add(utime, t->utime); - stime = cputime_add(stime, t->stime); t = next_thread(t); } while (t != task); } @@ -382,8 +380,8 @@ static int do_task_stat(struct task_stru if (whole) { min_flt += task->signal->min_flt; maj_flt += task->signal->maj_flt; - utime = cputime_add(utime, task->signal->utime); - stime = cputime_add(stime, task->signal->stime); + utime = task->signal->shared_utime; + stime = task->signal->shared_stime; } } ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; diff -rup /home/fmayhar/Static/linux-2.6.18.5/include/linux/sched.h linux-2.6.18.5/include/linux/sched.h --- /home/fmayhar/Static/linux-2.6.18.5/include/linux/sched.h 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/include/linux/sched.h 2008-03-07 13:45:35.000000000 -0800 @@ -413,6 +413,7 @@ struct signal_struct { /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */ cputime_t it_prof_expires, it_virt_expires; cputime_t it_prof_incr, it_virt_incr; + unsigned long long it_sched_expires; /* job control IDs */ pid_t pgrp; @@ -429,17 +430,22 @@ struct signal_struct { * Live threads maintain their own counters and add to these * in __exit_signal, except for the group leader. */ - cputime_t utime, stime, cutime, cstime; + cputime_t cutime, cstime; unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; /* + * Cumulative CPU time for all threads in the group including the + * group leader. + */ + cputime_t shared_utime, shared_stime; + /* * Cumulative ns of scheduled CPU time for dead threads in the * group, not including a zombie group leader. (This only differs * from jiffies_to_ns(utime + stime) if sched_clock uses something * other than jiffies.) */ - unsigned long long sched_time; + unsigned long long shared_schedtime; /* * We don't bother to synchronize most readers of this at all, diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/exit.c linux-2.6.18.5/kernel/exit.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/exit.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/exit.c 2008-03-06 15:48:37.000000000 -0800 @@ -103,13 +103,10 @@ static void __exit_signal(struct task_st * We won't ever get here for the group leader, since it * will have been the last reference on the signal_struct. */ - sig->utime = cputime_add(sig->utime, tsk->utime); - sig->stime = cputime_add(sig->stime, tsk->stime); sig->min_flt += tsk->min_flt; sig->maj_flt += tsk->maj_flt; sig->nvcsw += tsk->nvcsw; sig->nivcsw += tsk->nivcsw; - sig->sched_time += tsk->sched_time; sig = NULL; /* Marker for below. */ } @@ -1165,14 +1162,12 @@ static int wait_task_zombie(struct task_ sig = p->signal; psig->cutime = cputime_add(psig->cutime, - cputime_add(p->utime, - cputime_add(sig->utime, - sig->cutime))); + cputime_add(sig->shared_utime, + sig->cutime)); psig->cstime = cputime_add(psig->cstime, - cputime_add(p->stime, - cputime_add(sig->stime, - sig->cstime))); + cputime_add(sig->shared_stime, + sig->cstime)); psig->cmin_flt += p->min_flt + sig->min_flt + sig->cmin_flt; psig->cmaj_flt += diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/fork.c linux-2.6.18.5/kernel/fork.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/fork.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/fork.c 2008-03-07 14:23:22.000000000 -0800 @@ -855,14 +855,18 @@ static inline int copy_signal(unsigned l sig->it_virt_incr = cputime_zero; sig->it_prof_expires = cputime_zero; sig->it_prof_incr = cputime_zero; + sig->it_sched_expires = 0; sig->leader = 0; /* session leadership doesn't inherit */ sig->tty_old_pgrp = 0; - sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; + sig->shared_utime = cputime_zero; + sig->shared_stime = cputime_zero; + sig->shared_schedtime = 0; + + sig->cutime = sig->cstime = cputime_zero; sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; - sig->sched_time = 0; INIT_LIST_HEAD(&sig->cpu_timers[0]); INIT_LIST_HEAD(&sig->cpu_timers[1]); INIT_LIST_HEAD(&sig->cpu_timers[2]); @@ -877,7 +881,7 @@ static inline int copy_signal(unsigned l * New sole thread in the process gets an expiry time * of the whole CPU time limit. */ - tsk->it_prof_expires = + tsk->signal->it_prof_expires = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); } acct_init_pacct(&sig->pacct); @@ -1204,21 +1208,6 @@ static struct task_struct *copy_process( if (clone_flags & CLONE_THREAD) { p->group_leader = current->group_leader; list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); - - if (!cputime_eq(current->signal->it_virt_expires, - cputime_zero) || - !cputime_eq(current->signal->it_prof_expires, - cputime_zero) || - current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY || - !list_empty(¤t->signal->cpu_timers[0]) || - !list_empty(¤t->signal->cpu_timers[1]) || - !list_empty(¤t->signal->cpu_timers[2])) { - /* - * Have child wake up on its first tick to check - * for process CPU timers. - */ - p->it_prof_expires = jiffies_to_cputime(1); - } } /* diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/itimer.c linux-2.6.18.5/kernel/itimer.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/itimer.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/itimer.c 2008-03-06 15:49:17.000000000 -0800 @@ -61,12 +61,7 @@ int do_getitimer(int which, struct itime cval = tsk->signal->it_virt_expires; cinterval = tsk->signal->it_virt_incr; if (!cputime_eq(cval, cputime_zero)) { - struct task_struct *t = tsk; - cputime_t utime = tsk->signal->utime; - do { - utime = cputime_add(utime, t->utime); - t = next_thread(t); - } while (t != tsk); + cputime_t utime = tsk->signal->shared_utime; if (cputime_le(cval, utime)) { /* about to fire */ cval = jiffies_to_cputime(1); } else { @@ -84,15 +79,8 @@ int do_getitimer(int which, struct itime cval = tsk->signal->it_prof_expires; cinterval = tsk->signal->it_prof_incr; if (!cputime_eq(cval, cputime_zero)) { - struct task_struct *t = tsk; - cputime_t ptime = cputime_add(tsk->signal->utime, - tsk->signal->stime); - do { - ptime = cputime_add(ptime, - cputime_add(t->utime, - t->stime)); - t = next_thread(t); - } while (t != tsk); + cputime_t ptime = cputime_add(tsk->signal->shared_utime, + tsk->signal->shared_stime); if (cputime_le(cval, ptime)) { /* about to fire */ cval = jiffies_to_cputime(1); } else { diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/posix-cpu-timers.c linux-2.6.18.5/kernel/posix-cpu-timers.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/posix-cpu-timers.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/posix-cpu-timers.c 2008-03-07 12:57:23.000000000 -0800 @@ -164,6 +164,15 @@ static inline unsigned long long sched_n return (p == current) ? current_sched_time(p) : p->sched_time; } +static inline cputime_t prof_shared_ticks(struct task_struct *p) +{ + return cputime_add(p->signal->shared_utime, p->signal->shared_stime); +} +static inline cputime_t virt_shared_ticks(struct task_struct *p) +{ + return p->signal->shared_utime; +} + int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) { int error = check_clock(which_clock); @@ -227,31 +236,17 @@ static int cpu_clock_sample_group_locked struct task_struct *p, union cpu_time_count *cpu) { - struct task_struct *t = p; switch (clock_idx) { default: return -EINVAL; case CPUCLOCK_PROF: - cpu->cpu = cputime_add(p->signal->utime, p->signal->stime); - do { - cpu->cpu = cputime_add(cpu->cpu, prof_ticks(t)); - t = next_thread(t); - } while (t != p); + cpu->cpu = cputime_add(p->signal->shared_utime, p->signal->shared_stime); break; case CPUCLOCK_VIRT: - cpu->cpu = p->signal->utime; - do { - cpu->cpu = cputime_add(cpu->cpu, virt_ticks(t)); - t = next_thread(t); - } while (t != p); + cpu->cpu = p->signal->shared_utime; break; case CPUCLOCK_SCHED: - cpu->sched = p->signal->sched_time; - /* Add in each other live thread. */ - while ((t = next_thread(t)) != p) { - cpu->sched += t->sched_time; - } - cpu->sched += sched_ns(p); + cpu->sched = p->signal->shared_schedtime; break; } return 0; @@ -468,79 +463,9 @@ void posix_cpu_timers_exit(struct task_s void posix_cpu_timers_exit_group(struct task_struct *tsk) { cleanup_timers(tsk->signal->cpu_timers, - cputime_add(tsk->utime, tsk->signal->utime), - cputime_add(tsk->stime, tsk->signal->stime), - tsk->sched_time + tsk->signal->sched_time); -} - - -/* - * Set the expiry times of all the threads in the process so one of them - * will go off before the process cumulative expiry total is reached. - */ -static void process_timer_rebalance(struct task_struct *p, - unsigned int clock_idx, - union cpu_time_count expires, - union cpu_time_count val) -{ - cputime_t ticks, left; - unsigned long long ns, nsleft; - struct task_struct *t = p; - unsigned int nthreads = atomic_read(&p->signal->live); - - if (!nthreads) - return; - - switch (clock_idx) { - default: - BUG(); - break; - case CPUCLOCK_PROF: - left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), - nthreads); - do { - if (likely(!(t->flags & PF_EXITING))) { - ticks = cputime_add(prof_ticks(t), left); - if (cputime_eq(t->it_prof_expires, - cputime_zero) || - cputime_gt(t->it_prof_expires, ticks)) { - t->it_prof_expires = ticks; - } - } - t = next_thread(t); - } while (t != p); - break; - case CPUCLOCK_VIRT: - left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), - nthreads); - do { - if (likely(!(t->flags & PF_EXITING))) { - ticks = cputime_add(virt_ticks(t), left); - if (cputime_eq(t->it_virt_expires, - cputime_zero) || - cputime_gt(t->it_virt_expires, ticks)) { - t->it_virt_expires = ticks; - } - } - t = next_thread(t); - } while (t != p); - break; - case CPUCLOCK_SCHED: - nsleft = expires.sched - val.sched; - do_div(nsleft, nthreads); - nsleft = max_t(unsigned long long, nsleft, 1); - do { - if (likely(!(t->flags & PF_EXITING))) { - ns = t->sched_time + nsleft; - if (t->it_sched_expires == 0 || - t->it_sched_expires > ns) { - t->it_sched_expires = ns; - } - } - t = next_thread(t); - } while (t != p); - break; - } + tsk->signal->shared_utime, + tsk->signal->shared_stime, + tsk->signal->shared_schedtime); } static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now) @@ -637,7 +562,8 @@ static void arm_timer(struct k_itimer *t cputime_lt(p->signal->it_virt_expires, timer->it.cpu.expires.cpu)) break; - goto rebalance; + p->signal->it_virt_expires = timer->it.cpu.expires.cpu; + break; case CPUCLOCK_PROF: if (!cputime_eq(p->signal->it_prof_expires, cputime_zero) && @@ -648,13 +574,10 @@ static void arm_timer(struct k_itimer *t if (i != RLIM_INFINITY && i <= cputime_to_secs(timer->it.cpu.expires.cpu)) break; - goto rebalance; + p->signal->it_prof_expires = timer->it.cpu.expires.cpu; + break; case CPUCLOCK_SCHED: - rebalance: - process_timer_rebalance( - timer->it.cpu.task, - CPUCLOCK_WHICH(timer->it_clock), - timer->it.cpu.expires, now); + p->signal->it_sched_expires = timer->it.cpu.expires.sched; break; } } @@ -1020,7 +943,6 @@ static void check_process_timers(struct struct signal_struct *const sig = tsk->signal; cputime_t utime, stime, ptime, virt_expires, prof_expires; unsigned long long sched_time, sched_expires; - struct task_struct *t; struct list_head *timers = sig->cpu_timers; /* @@ -1037,16 +959,10 @@ static void check_process_timers(struct /* * Collect the current process totals. */ - utime = sig->utime; - stime = sig->stime; - sched_time = sig->sched_time; - t = tsk; - do { - utime = cputime_add(utime, t->utime); - stime = cputime_add(stime, t->stime); - sched_time += t->sched_time; - t = next_thread(t); - } while (t != tsk); + utime = sig->shared_utime; + stime = sig->shared_stime; + sched_time = sig->shared_schedtime; + ptime = cputime_add(utime, stime); maxfire = 20; @@ -1156,60 +1072,18 @@ static void check_process_timers(struct } } - if (!cputime_eq(prof_expires, cputime_zero) || - !cputime_eq(virt_expires, cputime_zero) || - sched_expires != 0) { - /* - * Rebalance the threads' expiry times for the remaining - * process CPU timers. - */ - - cputime_t prof_left, virt_left, ticks; - unsigned long long sched_left, sched; - const unsigned int nthreads = atomic_read(&sig->live); - - if (!nthreads) - return; - - prof_left = cputime_sub(prof_expires, utime); - prof_left = cputime_sub(prof_left, stime); - prof_left = cputime_div_non_zero(prof_left, nthreads); - virt_left = cputime_sub(virt_expires, utime); - virt_left = cputime_div_non_zero(virt_left, nthreads); - if (sched_expires) { - sched_left = sched_expires - sched_time; - do_div(sched_left, nthreads); - sched_left = max_t(unsigned long long, sched_left, 1); - } else { - sched_left = 0; - } - t = tsk; - do { - if (unlikely(t->flags & PF_EXITING)) - continue; - - ticks = cputime_add(cputime_add(t->utime, t->stime), - prof_left); - if (!cputime_eq(prof_expires, cputime_zero) && - (cputime_eq(t->it_prof_expires, cputime_zero) || - cputime_gt(t->it_prof_expires, ticks))) { - t->it_prof_expires = ticks; - } - - ticks = cputime_add(t->utime, virt_left); - if (!cputime_eq(virt_expires, cputime_zero) && - (cputime_eq(t->it_virt_expires, cputime_zero) || - cputime_gt(t->it_virt_expires, ticks))) { - t->it_virt_expires = ticks; - } - - sched = t->sched_time + sched_left; - if (sched_expires && (t->it_sched_expires == 0 || - t->it_sched_expires > sched)) { - t->it_sched_expires = sched; - } - } while ((t = next_thread(t)) != tsk); - } + if (!cputime_eq(prof_expires, cputime_zero) && + (cputime_eq(sig->it_prof_expires, cputime_zero) || + cputime_gt(sig->it_prof_expires, prof_expires))) + sig->it_prof_expires = prof_expires; + if (!cputime_eq(virt_expires, cputime_zero) && + (cputime_eq(sig->it_virt_expires, cputime_zero) || + cputime_gt(sig->it_virt_expires, virt_expires))) + sig->it_virt_expires = virt_expires; + if (sched_expires != 0 && + (sig->it_sched_expires == 0 || + sig->it_sched_expires > sched_expires)) + sig->it_sched_expires = sched_expires; } /* @@ -1289,13 +1163,16 @@ void run_posix_cpu_timers(struct task_st BUG_ON(!irqs_disabled()); + if (!tsk->signal) + return; + #define UNEXPIRED(clock) \ - (cputime_eq(tsk->it_##clock##_expires, cputime_zero) || \ - cputime_lt(clock##_ticks(tsk), tsk->it_##clock##_expires)) + (cputime_eq(tsk->signal->it_##clock##_expires, cputime_zero) || \ + cputime_lt(clock##_shared_ticks(tsk), tsk->signal->it_##clock##_expires)) if (UNEXPIRED(prof) && UNEXPIRED(virt) && - (tsk->it_sched_expires == 0 || - tsk->sched_time < tsk->it_sched_expires)) + (tsk->signal->it_sched_expires == 0 || + tsk->signal->shared_schedtime < tsk->signal->it_sched_expires)) return; #undef UNEXPIRED @@ -1398,13 +1275,14 @@ void set_process_cpu_timer(struct task_s cputime_ge(list_entry(head->next, struct cpu_timer_list, entry)->expires.cpu, *newval)) { - /* - * Rejigger each thread's expiry time so that one will - * notice before we hit the process-cumulative expiry time. - */ - union cpu_time_count expires = { .sched = 0 }; - expires.cpu = *newval; - process_timer_rebalance(tsk, clock_idx, expires, now); + switch (clock_idx) { + case CPUCLOCK_PROF: + tsk->signal->it_prof_expires = *newval; + break; + case CPUCLOCK_VIRT: + tsk->signal->it_virt_expires = *newval; + break; + } } } diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/sched.c linux-2.6.18.5/kernel/sched.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/sched.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/sched.c 2008-03-07 09:36:43.000000000 -0800 @@ -2901,7 +2901,13 @@ EXPORT_PER_CPU_SYMBOL(kstat); static inline void update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now) { - p->sched_time += now - max(p->timestamp, rq->timestamp_last_tick); + unsigned long long tmp; + + tmp = now - max(p->timestamp, rq->timestamp_last_tick); + p->sched_time += tmp; + /* Add our time to the shared field. */ + if (p->signal) + p->signal->shared_schedtime += tmp; } /* @@ -2955,6 +2961,10 @@ void account_user_time(struct task_struc p->utime = cputime_add(p->utime, cputime); + /* Add our time to the shared field. */ + if (p->signal) + p->signal->shared_utime = cputime_add(p->signal->shared_utime, cputime); + /* Add user time to cpustat. */ tmp = cputime_to_cputime64(cputime); if (TASK_NICE(p) > 0) @@ -2978,6 +2988,10 @@ void account_system_time(struct task_str p->stime = cputime_add(p->stime, cputime); + /* Add our time to the shared field. */ + if (p->signal) + p->signal->shared_stime = cputime_add(p->signal->shared_stime, cputime); + /* Add system time to cpustat. */ tmp = cputime_to_cputime64(cputime); if (hardirq_count() - hardirq_offset) diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/signal.c linux-2.6.18.5/kernel/signal.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/signal.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/signal.c 2008-03-06 15:50:31.000000000 -0800 @@ -1447,10 +1447,8 @@ void do_notify_parent(struct task_struct info.si_uid = tsk->uid; /* FIXME: find out whether or not this is supposed to be c*time. */ - info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime, - tsk->signal->utime)); - info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime, - tsk->signal->stime)); + info.si_utime = cputime_to_jiffies(tsk->signal->shared_utime); + info.si_stime = cputime_to_jiffies(tsk->signal->shared_stime); info.si_status = tsk->exit_code & 0x7f; if (tsk->exit_code & 0x80) diff -rup /home/fmayhar/Static/linux-2.6.18.5/kernel/sys.c linux-2.6.18.5/kernel/sys.c --- /home/fmayhar/Static/linux-2.6.18.5/kernel/sys.c 2006-12-01 16:13:05.000000000 -0800 +++ linux-2.6.18.5/kernel/sys.c 2008-03-06 15:51:37.000000000 -0800 @@ -1207,18 +1207,11 @@ asmlinkage long sys_times(struct tms __u if (tbuf) { struct tms tmp; struct task_struct *tsk = current; - struct task_struct *t; cputime_t utime, stime, cutime, cstime; spin_lock_irq(&tsk->sighand->siglock); - utime = tsk->signal->utime; - stime = tsk->signal->stime; - t = tsk; - do { - utime = cputime_add(utime, t->utime); - stime = cputime_add(stime, t->stime); - t = next_thread(t); - } while (t != tsk); + utime = tsk->signal->shared_utime; + stime = tsk->signal->shared_stime; cutime = tsk->signal->cutime; cstime = tsk->signal->cstime; @@ -1910,16 +1903,14 @@ static void k_getrusage(struct task_stru break; case RUSAGE_SELF: - utime = cputime_add(utime, p->signal->utime); - stime = cputime_add(stime, p->signal->stime); + utime = cputime_add(utime, p->signal->shared_utime); + stime = cputime_add(stime, p->signal->shared_stime); r->ru_nvcsw += p->signal->nvcsw; r->ru_nivcsw += p->signal->nivcsw; r->ru_minflt += p->signal->min_flt; r->ru_majflt += p->signal->maj_flt; t = p; do { - utime = cputime_add(utime, t->utime); - stime = cputime_add(stime, t->stime); r->ru_nvcsw += t->nvcsw; r->ru_nivcsw += t->nivcsw; r->ru_minflt += t->min_flt;