diff -urN a/fs/proc/array.c b/fs/proc/array.c --- a/fs/proc/array.c 2002-12-16 03:08:11.000000000 +0100 +++ b/fs/proc/array.c 2002-12-20 15:40:41.000000000 +0100 @@ -597,3 +597,26 @@ out: return retval; } + +#ifdef CONFIG_SMP +int proc_pid_cpu(struct task_struct *task, char * buffer) +{ + int i, len; + + len = sprintf(buffer, + "cpu %lu %lu\n", + jiffies_to_clock_t(task->utime), + jiffies_to_clock_t(task->stime)); + + for (i = 0 ; i < NR_CPUS; i++) { + if (cpu_online(i)) + len += sprintf(buffer + len, "cpu%d %lu %lu\n", + i, + jiffies_to_clock_t(task->per_cpu_utime[i]), + jiffies_to_clock_t(task->per_cpu_stime[i])); + + } + len += sprintf(buffer + len, "current_cpu %d\n",task_cpu(task)); + return len; +} +#endif diff -urN a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c 2002-12-16 03:08:11.000000000 +0100 +++ b/fs/proc/base.c 2002-12-20 15:40:42.000000000 +0100 @@ -55,6 +55,7 @@ PROC_PID_STAT, PROC_PID_STATM, PROC_PID_MAPS, + PROC_PID_CPU, PROC_PID_MOUNTS, PROC_PID_WCHAN, PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */ @@ -75,6 +76,9 @@ E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO), E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO), +#ifdef CONFIG_SMP + E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO), +#endif E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO), E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO), @@ -1026,7 +1030,12 @@ case PROC_PID_MAPS: inode->i_fop = &proc_maps_operations; break; - +#ifdef CONFIG_SMP + case PROC_PID_CPU: + inode->i_fop = &proc_info_file_operations; + ei->op.proc_read = proc_pid_cpu; + break; +#endif case PROC_PID_MEM: inode->i_op = &proc_mem_inode_operations; inode->i_fop = &proc_mem_operations; diff -urN a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h 2002-12-18 16:54:40.000000000 +0100 +++ b/include/linux/sched.h 2002-12-20 15:40:42.000000000 +0100 @@ -354,6 +354,9 @@ struct timer_list real_timer; unsigned long utime, stime, cutime, cstime; unsigned long start_time; +#ifdef CONFIG_SMP + long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS]; +#endif /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1; diff -urN a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c 2002-12-16 03:07:44.000000000 +0100 +++ b/kernel/fork.c 2002-12-20 15:40:42.000000000 +0100 @@ -795,6 +795,14 @@ p->tty_old_pgrp = 0; p->utime = p->stime = 0; p->cutime = p->cstime = 0; +#ifdef CONFIG_SMP + { + int i; + + for(i = 0; i < NR_CPUS; i++) + p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0; + } +#endif p->array = NULL; p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; diff -urN a/kernel/timer.c b/kernel/timer.c --- a/kernel/timer.c 2002-12-16 03:07:52.000000000 +0100 +++ b/kernel/timer.c 2002-12-20 15:40:42.000000000 +0100 @@ -695,6 +695,10 @@ void update_one_process(struct task_struct *p, unsigned long user, unsigned long system, int cpu) { +#ifdef CONFIG_SMP + p->per_cpu_utime[cpu] += user; + p->per_cpu_stime[cpu] += system; +#endif do_process_times(p, user, system); do_it_virt(p, user); do_it_prof(p);