From: Albert Cahalan <albert@users.sourceforge.net>

This patch adjusts /proc/*/stat to have distinct per-process and per-thread
CPU usage, faults, and wchan.

Signed-off-by: Albert Cahalan <albert@users.sf.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/proc/array.c |   44 +++++++++++++++++++++++++++++++++-----------
 25-akpm/fs/proc/base.c  |    8 ++++++--
 2 files changed, 39 insertions(+), 13 deletions(-)

diff -puN fs/proc/array.c~distinct-tgid-tid-cpu-usage fs/proc/array.c
--- 25/fs/proc/array.c~distinct-tgid-tid-cpu-usage	2004-09-11 17:24:39.245911184 -0700
+++ 25-akpm/fs/proc/array.c	2004-09-11 17:24:39.251910272 -0700
@@ -300,9 +300,9 @@ int proc_pid_status(struct task_struct *
 	return buffer - orig;
 }
 
-int proc_pid_stat(struct task_struct *task, char * buffer)
+static int do_task_stat(struct task_struct *task, char * buffer, int whole)
 {
-	unsigned long vsize, eip, esp, wchan;
+	unsigned long vsize, eip, esp, wchan = ~0UL;
 	long priority, nice;
 	int tty_pgrp = -1, tty_nr = 0;
 	sigset_t sigign, sigcatch;
@@ -313,6 +313,7 @@ int proc_pid_stat(struct task_struct *ta
 	struct mm_struct *mm;
 	unsigned long long start_time;
 	unsigned long cmin_flt = 0, cmaj_flt = 0, cutime = 0, cstime = 0;
+	unsigned long  min_flt = 0,  maj_flt = 0,  utime = 0,  stime = 0;
 	char tcomm[sizeof(task->comm)];
 
 	state = *get_task_state(task);
@@ -325,7 +326,6 @@ int proc_pid_stat(struct task_struct *ta
 	}
 
 	get_task_comm(tcomm, task);
-	wchan = get_wchan(task);
 
 	sigemptyset(&sigign);
 	sigemptyset(&sigcatch);
@@ -347,18 +347,30 @@ int proc_pid_stat(struct task_struct *ta
 		cmaj_flt = task->signal->cmaj_flt;
 		cutime = task->signal->cutime;
 		cstime = task->signal->cstime;
+		if (whole) {
+			min_flt = task->signal->min_flt;
+			maj_flt = task->signal->maj_flt;
+			utime = task->signal->utime;
+			stime = task->signal->stime;
+		}
 	}
+	ppid = task->pid ? task->real_parent->pid : 0;
 	read_unlock(&tasklist_lock);
 
+	if (!whole || num_threads<2)
+		wchan = get_wchan(task);
+	if (!whole) {
+		min_flt = task->min_flt;
+		maj_flt = task->maj_flt;
+		utime = task->utime;
+		stime = task->stime;
+	}
+
 	/* scale priority and nice values from timeslices to -20..20 */
 	/* to make it look like a "normal" Unix priority/nice value  */
 	priority = task_prio(task);
 	nice = task_nice(task);
 
-	read_lock(&tasklist_lock);
-	ppid = task->pid ? task->real_parent->pid : 0;
-	read_unlock(&tasklist_lock);
-
 	/* Temporary variable needed for gcc-2.96 */
 	start_time = jiffies_64_to_clock_t(task->start_time - INITIAL_JIFFIES);
 
@@ -374,12 +386,12 @@ int proc_pid_stat(struct task_struct *ta
 		tty_nr,
 		tty_pgrp,
 		task->flags,
-		task->min_flt,
+		min_flt,
 		cmin_flt,
-		task->maj_flt,
+		maj_flt,
 		cmaj_flt,
-		jiffies_to_clock_t(task->utime),
-		jiffies_to_clock_t(task->stime),
+		jiffies_to_clock_t(utime),
+		jiffies_to_clock_t(stime),
 		jiffies_to_clock_t(cutime),
 		jiffies_to_clock_t(cstime),
 		priority,
@@ -415,6 +427,16 @@ int proc_pid_stat(struct task_struct *ta
 	return res;
 }
 
+int proc_tid_stat(struct task_struct *task, char * buffer)
+{
+	return do_task_stat(task, buffer, 0);
+}
+
+int proc_tgid_stat(struct task_struct *task, char * buffer)
+{
+	return do_task_stat(task, buffer, 1);
+}
+
 int proc_pid_statm(struct task_struct *task, char *buffer)
 {
 	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
diff -puN fs/proc/base.c~distinct-tgid-tid-cpu-usage fs/proc/base.c
--- 25/fs/proc/base.c~distinct-tgid-tid-cpu-usage	2004-09-11 17:24:39.246911032 -0700
+++ 25-akpm/fs/proc/base.c	2004-09-11 17:24:39.252910120 -0700
@@ -189,7 +189,8 @@ static inline int proc_type(struct inode
 	return PROC_I(inode)->type;
 }
 
-int proc_pid_stat(struct task_struct*,char*);
+int proc_tid_stat(struct task_struct*,char*);
+int proc_tgid_stat(struct task_struct*,char*);
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
 
@@ -1315,9 +1316,12 @@ static struct dentry *proc_pident_lookup
 			ei->op.proc_read = proc_pid_status;
 			break;
 		case PROC_TID_STAT:
+			inode->i_fop = &proc_info_file_operations;
+			ei->op.proc_read = proc_tid_stat;
+			break;
 		case PROC_TGID_STAT:
 			inode->i_fop = &proc_info_file_operations;
-			ei->op.proc_read = proc_pid_stat;
+			ei->op.proc_read = proc_tgid_stat;
 			break;
 		case PROC_TID_CMDLINE:
 		case PROC_TGID_CMDLINE:
_