whole-process CPU usage
Subsystems (9)
PATCH 1/1 whole-process CPU usage
This looks like it ought to work. Due to undocumented locking, it may need a bit of work. The two ungreppable old names are replaced with these six:
->task_sys_time Per-thread CPU usage ->signal->proc_sys_time Per-process CPU usage ->signal->dead_sys_time CPU usage of dead children
(and 3 more, with "usr" in place of "sys")
Some of the changes appear to fix UNIX non-compliance. For example, times() and getrusage() are per-process. I assume that the OOM killer wants per-process data too. BSD accounting appears to be per-thread, so that's what I gave it for now, but per-process accounting makes more sense.
Context switch and fault counts can get this treatment in some future patch.
It's long past time for "signal" to get renamed. Ideas?
arch/alpha/kernel/osf_sys.c +6 -6
@@ -1073,21 +1073,21 @@memset (&r,0 ,sizeof (r));switch (who) {case RUSAGE_SELF : -jiffies_to_timeval32 (current->utime, &r.ru_utime); -jiffies_to_timeval32 (current->stime, &r.ru_stime); +jiffies_to_timeval32 (current->signal->proc_usr_time, &r.ru_utime); +jiffies_to_timeval32 (current->signal->proc_sys_time, &r.ru_stime); r.ru_minflt = current->min_flt; r.ru_majflt = current->maj_flt;break ;case RUSAGE_CHILDREN : -jiffies_to_timeval32 (current->cutime, &r.ru_utime); -jiffies_to_timeval32 (current->cstime, &r.ru_stime); +jiffies_to_timeval32 (current->signal->dead_usr_time, &r.ru_utime); +jiffies_to_timeval32 (current->signal->dead_sys_time, &r.ru_stime); r.ru_minflt = current->cmin_flt; r.ru_majflt = current->cmaj_flt;break ;default : -jiffies_to_timeval32 (current->utime + current->cutime, +jiffies_to_timeval32 (current->signal->proc_usr_time + current->signal->dead_usr_time, &r.ru_utime); -jiffies_to_timeval32 (current->stime + current->cstime, +jiffies_to_timeval32 (current->signal->proc_sys_time + current->signal->dead_sys_time, &r.ru_stime); r.ru_minflt = current->min_flt + current->cmin_flt; r.ru_majflt = current->maj_flt + current->cmaj_flt;
arch/i386/kernel/apm.c +3 -3
@@ -837,18 +837,18 @@if (jiffies_since_last_check >IDLE_CALC_LIMIT ) { use_apm_idle =0 ; last_jiffies = jiffies; - last_stime = current->stime; + last_stime = current->task_sys_time; }else if (jiffies_since_last_check > idle_period) {unsigned int idle_percentage; - idle_percentage = current->stime - last_stime; + idle_percentage = current->task_sys_time - last_stime; idle_percentage *=100 ; idle_percentage /= jiffies_since_last_check; use_apm_idle = (idle_percentage > idle_threshold);if (apm_info.forbid_idle) use_apm_idle =0 ; last_jiffies = jiffies; - last_stime = current->stime; + last_stime = current->task_sys_time; } bucket =IDLE_LEAKY_MAX ;
fs/binfmt_elf.c +4 -4
@@ -1176,10 +1176,10 @@ prstatus->pr_ppid = p->parent->pid; prstatus->pr_pgrp =process_group (p); prstatus->pr_sid = p->signal->session; -jiffies_to_timeval (p->utime, &prstatus->pr_utime); -jiffies_to_timeval (p->stime, &prstatus->pr_stime); -jiffies_to_timeval (p->cutime, &prstatus->pr_cutime); -jiffies_to_timeval (p->cstime, &prstatus->pr_cstime); +jiffies_to_timeval (p->task_usr_time, &prstatus->pr_utime); +jiffies_to_timeval (p->task_sys_time, &prstatus->pr_stime); +jiffies_to_timeval (p->signal->dead_usr_time, &prstatus->pr_cutime); +jiffies_to_timeval (p->signal->dead_sys_time, &prstatus->pr_cstime); } static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
fs/proc/array.c +55 -18
142 lines not on this page · raw message
fs/proc/proc_misc.c +1 -1
@@ -136,7 +136,7 @@struct timespec uptime;struct timespec idle;int len; -u64 idle_jiffies = init_task.utime + init_task.stime; +u64 idle_jiffies = init_task.task_usr_time + init_task.task_sys_time;do_posix_clock_monotonic_gettime (&uptime);jiffies_to_timespec (idle_jiffies, &idle);
include/linux/sched.h +4 -1
@@ -284,6 +284,9 @@int leader;struct tty_struct *tty;/* NULL if no tty */ + +unsigned long proc_sys_time, proc_usr_time;/* whole process */ +unsigned long dead_sys_time, dead_usr_time;/* dead children */ };/*
@@ -460,7 +463,7 @@unsigned long it_real_value, it_prof_value, it_virt_value;unsigned long it_real_incr, it_prof_incr, it_virt_incr;struct timer_list real_timer; -unsigned long utime, stime, cutime, cstime; +unsigned long task_sys_time, task_usr_time;unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;/* context switch counts */ u64 start_time;/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
kernel/acct.c +8 -2
@@ -418,8 +418,14 @@#endif do_div (elapsed,AHZ ); ac.ac_btime = xtime.tv_sec - elapsed; - ac.ac_utime =encode_comp_t (jiffies_to_AHZ (current->utime)); - ac.ac_stime =encode_comp_t (jiffies_to_AHZ (current->stime)); + +/* +* accounting is called once per thread -- maybe not the best +* (if that changes, use current->signal->proc_usr_time, etc.) +*/ + ac.ac_utime =encode_comp_t (jiffies_to_AHZ (current->task_usr_time)); + ac.ac_stime =encode_comp_t (jiffies_to_AHZ (current->task_sys_time)); +/* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid;
kernel/compat.c +4 -4
@@ -160,10 +160,10 @@*/ if (tbuf) {struct compat_tms tmp; - tmp.tms_utime =compat_jiffies_to_clock_t (current->utime); - tmp.tms_stime =compat_jiffies_to_clock_t (current->stime); - tmp.tms_cutime =compat_jiffies_to_clock_t (current->cutime); - tmp.tms_cstime =compat_jiffies_to_clock_t (current->cstime); + tmp.tms_utime =compat_jiffies_to_clock_t (current->signal->proc_usr_time); + tmp.tms_stime =compat_jiffies_to_clock_t (current->signal->proc_sys_time); + tmp.tms_cutime =compat_jiffies_to_clock_t (current->signal->dead_usr_time); + tmp.tms_cstime =compat_jiffies_to_clock_t (current->signal->dead_sys_time);if (copy_to_user (tbuf, &tmp,sizeof (tmp)))return -EFAULT ; }
kernel/cpu.c +1 -1
@@ -49,7 +49,7 @@write_lock_irq (&tasklist_lock);for_each_process (p) { -if (task_cpu (p) == cpu && (p->utime !=0 || p->stime !=0 )) +if (task_cpu (p) == cpu && (p->signal->proc_usr_time || p->signal->proc_sys_time))printk (KERN_WARNING "Task %s (pid = %d) is on cpu %d\ (state = %ld, flags = %lx) \n" , p->comm, p->pid, cpu, p->state, p->flags);
kernel/exit.c +8 -2
@@ -90,12 +90,18 @@ zap_leader = (leader->exit_signal ==-1 ); } - p->parent->cutime += p->utime + p->cutime; - p->parent->cstime += p->stime + p->cstime; +/* credit parent's dead-child stats (proper: when parent waits) */ +if (leader == p &&thread_group_empty (leader)) { + p->parent->signal->dead_usr_time += p->signal->proc_usr_time + p->signal->dead_usr_time; + p->parent->signal->dead_sys_time += p->signal->proc_sys_time + p->signal->dead_sys_time; + } + +/* TODO: these should get the same treatment as CPU time */ p->parent->cmin_flt += p->min_flt + p->cmin_flt; p->parent->cmaj_flt += p->maj_flt + p->cmaj_flt; p->parent->cnvcsw += p->nvcsw + p->cnvcsw; p->parent->cnivcsw += p->nivcsw + p->cnivcsw; +sched_exit (p);write_unlock_irq (&tasklist_lock);spin_unlock (&p->proc_lock);
kernel/fork.c +3 -2
@@ -822,6 +822,8 @@if (!sig)return -ENOMEM ;atomic_set (&sig->count,1 ); + sig->proc_usr_time = sig->proc_sys_time =0 ; + sig->dead_usr_time = sig->dead_sys_time =0 ; sig->group_exit =0 ; sig->group_exit_code =0 ; sig->group_exit_task =NULL ;
@@ -959,8 +961,7 @@init_timer (&p->real_timer); p->real_timer.data = (unsigned long ) p; - p->utime = p->stime =0 ; - p->cutime = p->cstime =0 ; + p->task_usr_time = p->task_sys_time =0 ; p->lock_depth =-1 ;/* -1 = no lock */ p->start_time =get_jiffies_64 (); p->security =NULL ;
kernel/signal.c +4 -4
@@ -1445,8 +1445,8 @@ info.si_uid = tsk->uid;/* FIXME: find out whether or not this is supposed to be c*time. */ - info.si_utime = tsk->utime; - info.si_stime = tsk->stime; + info.si_utime = tsk->signal->proc_usr_time + tsk->signal->dead_usr_time; + info.si_stime = tsk->signal->proc_sys_time + tsk->signal->dead_sys_time; status = tsk->exit_code &0x7f ; why =SI_KERNEL ;/* shouldn't happen */
@@ -1534,8 +1534,8 @@ info.si_uid = tsk->uid;/* FIXME: find out whether or not this is supposed to be c*time. */ - info.si_utime = tsk->utime; - info.si_stime = tsk->stime; + info.si_utime = tsk->signal->proc_usr_time + tsk->signal->dead_usr_time; + info.si_stime = tsk->signal->proc_sys_time + tsk->signal->dead_sys_time; info.si_status = tsk->exit_code &0x7f ; info.si_code =CLD_STOPPED ;
kernel/sys.c +17 -16
@@ -944,13 +944,14 @@* the times increment as we use it. Since the value is an * atomically safe type this is just fine. Conceptually its * as if the syscall took an instant longer to occur. +* The UNIX spec seems to indicate that these are per-process. */ if (tbuf) {struct tms tmp; - tmp.tms_utime =jiffies_to_clock_t (current->utime); - tmp.tms_stime =jiffies_to_clock_t (current->stime); - tmp.tms_cutime =jiffies_to_clock_t (current->cutime); - tmp.tms_cstime =jiffies_to_clock_t (current->cstime); + tmp.tms_utime =jiffies_to_clock_t (current->signal->proc_usr_time); + tmp.tms_stime =jiffies_to_clock_t (current->signal->proc_sys_time); + tmp.tms_cutime =jiffies_to_clock_t (current->signal->dead_usr_time); + tmp.tms_cstime =jiffies_to_clock_t (current->signal->dead_sys_time);if (copy_to_user (tbuf, &tmp,sizeof (struct tms )))return -EFAULT ; }
@@ -1526,12 +1527,9 @@ }/* -* It would make sense to put struct rusage in the task_struct, -* except that would make the task_struct be *really big*. After -* task_struct gets moved into malloc'ed memory, it would -* make sense to do this. It will make moving the rest of the information -* a lot simpler! (Which we're not doing right now because we're not -* measuring them yet). +* It would make sense to put struct rusage in the signal_struct, +* except that would make the signal_struct be *really big*. +* TODO: Perhaps a thread-specific rusage value would be useful. * * This is SMP safe. Either we are called from sys_getrusage on ourselves * below (we know we aren't going to exit/disappear and only we change our
@@ -1547,24 +1545,27 @@memset ((char *) &r,0 ,sizeof (r));switch (who) {case RUSAGE_SELF : -jiffies_to_timeval (p->utime, &r.ru_utime); -jiffies_to_timeval (p->stime, &r.ru_stime); +jiffies_to_timeval (p->signal->proc_usr_time, &r.ru_utime); +jiffies_to_timeval (p->signal->proc_sys_time, &r.ru_stime); +/* these are still broken -- should be per-process */ r.ru_nvcsw = p->nvcsw; r.ru_nivcsw = p->nivcsw; r.ru_minflt = p->min_flt; r.ru_majflt = p->maj_flt;break ;case RUSAGE_CHILDREN : -jiffies_to_timeval (p->cutime, &r.ru_utime); -jiffies_to_timeval (p->cstime, &r.ru_stime); +jiffies_to_timeval (p->signal->dead_usr_time, &r.ru_utime); +jiffies_to_timeval (p->signal->dead_sys_time, &r.ru_stime); +/* these are still broken -- should be per-process */ r.ru_nvcsw = p->cnvcsw; r.ru_nivcsw = p->cnivcsw; r.ru_minflt = p->cmin_flt; r.ru_majflt = p->cmaj_flt;break ;default : -jiffies_to_timeval (p->utime + p->cutime, &r.ru_utime); -jiffies_to_timeval (p->stime + p->cstime, &r.ru_stime); +jiffies_to_timeval (p->signal->proc_usr_time + p->signal->dead_usr_time, &r.ru_utime); +jiffies_to_timeval (p->signal->proc_sys_time + p->signal->dead_sys_time, &r.ru_stime); +/* these are still broken -- should be per-process */ r.ru_nvcsw = p->nvcsw + p->cnvcsw; r.ru_nivcsw = p->nivcsw + p->cnivcsw; r.ru_minflt = p->min_flt + p->cmin_flt;
kernel/timer.c +4 -2
@@ -790,8 +790,10 @@ {unsigned long psecs; - psecs = (p->utime += user); - psecs += (p->stime += system); + p->task_usr_time += user; + p->task_sys_time += system; + psecs = (p->signal->proc_usr_time += user); + psecs += (p->signal->proc_sys_time += system);if (psecs /HZ >= p->rlim[RLIMIT_CPU ].rlim_cur) {/* Send SIGXCPU every second.. */ if (!(psecs %HZ ))
mm/oom_kill.c +1 -1
@@ -60,7 +60,7 @@* particular reason for this other than that it turned out to work * very well in practice. */ - cpu_time = (p->utime + p->stime) >> (SHIFT_HZ +3 ); + cpu_time = (p->signal->proc_usr_time + p->signal->proc_sys_time) >> (SHIFT_HZ +3 ); run_time = (get_jiffies_64 () - p->start_time) >> (SHIFT_HZ +10 ); s =int_sqrt (cpu_time);