Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1853

kernel-2.6.18-238.el5.src.rpm

From: Jerome Marchand <jmarchan@redhat.com>
Date: Thu, 5 Feb 2009 16:21:33 +0100
Subject: [misc] backport RUSAGE_THREAD support
Message-id: 498B03FD.6010607@redhat.com
O-Subject: [RHEL5.4 Patch] BZ451063: backport RUSAGE_THREAD support
Bugzilla: 451063
RH-Acked-by: Vitaly Mayatskikh <vmayatsk@redhat.com>
RH-Acked-by: Anton Arapov <aarapov@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>

Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=451063

Description:
As it is now, getrusage syscall is not able to discriminate different
threads from the same process. RUSAGE_THREAD option allows to get the
resource usage for one thread independently from other threads of the
same process.

Upstream status:
commit 679c9cd4acc2cf2872171813752eab3320273339

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=1667317

Test status:
I tested that getrusage returns coherent metrics for thread, process
and children.

Regards,
Jérôme

diff --git a/include/linux/resource.h b/include/linux/resource.h
index 14757af..07a1e51 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -19,6 +19,7 @@ struct task_struct;
 #define	RUSAGE_SELF	0
 #define	RUSAGE_CHILDREN	(-1)
 #define RUSAGE_BOTH	(-2)		/* sys_wait4() uses this */
+#define	RUSAGE_THREAD	1		/* only the calling thread */
 
 struct	rusage {
 	struct timeval ru_utime;	/* user time used */
diff --git a/kernel/sys.c b/kernel/sys.c
index 18b3f74..4a46572 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1883,6 +1883,17 @@ out:
  *
  */
 
+static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r,
+				     cputime_t *utimep, cputime_t *stimep)
+{
+	*utimep = cputime_add(*utimep, t->utime);
+	*stimep = cputime_add(*stimep, t->stime);
+	r->ru_nvcsw += t->nvcsw;
+	r->ru_nivcsw += t->nivcsw;
+	r->ru_minflt += t->min_flt;
+	r->ru_majflt += t->maj_flt;
+}
+
 static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 {
 	struct task_struct *t;
@@ -1892,6 +1903,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 	memset((char *) r, 0, sizeof *r);
 	utime = stime = cputime_zero;
 
+	if (who == RUSAGE_THREAD) {
+		accumulate_thread_rusage(p, r, &utime, &stime);
+		goto out;
+	}
+
 	rcu_read_lock();
 	if (!lock_task_sighand(p, &flags)) {
 		rcu_read_unlock();
@@ -1920,12 +1936,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 			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;
-				r->ru_majflt += t->maj_flt;
+				accumulate_thread_rusage(t, r, &utime, &stime);
 				t = next_thread(t);
 			} while (t != p);
 			break;
@@ -1937,6 +1948,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 	unlock_task_sighand(p, &flags);
 	rcu_read_unlock();
 
+out:
 	cputime_to_timeval(utime, &r->ru_utime);
 	cputime_to_timeval(stime, &r->ru_stime);
 }
@@ -1950,7 +1962,8 @@ int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
 
 asmlinkage long sys_getrusage(int who, struct rusage __user *ru)
 {
-	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
+	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
+	    who != RUSAGE_THREAD)
 		return -EINVAL;
 	return getrusage(current, who, ru);
 }