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); }