|
@@ -1545,6 +1545,19 @@ 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;
|
|
|
+ r->ru_inblock += task_io_get_inblock(t);
|
|
|
+ r->ru_oublock += task_io_get_oublock(t);
|
|
|
+}
|
|
|
+
|
|
|
static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
|
|
|
{
|
|
|
struct task_struct *t;
|
|
@@ -1554,6 +1567,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();
|
|
@@ -1586,14 +1604,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
|
|
|
r->ru_oublock += p->signal->oublock;
|
|
|
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;
|
|
|
- r->ru_inblock += task_io_get_inblock(t);
|
|
|
- r->ru_oublock += task_io_get_oublock(t);
|
|
|
+ accumulate_thread_rusage(t, r, &utime, &stime);
|
|
|
t = next_thread(t);
|
|
|
} while (t != p);
|
|
|
break;
|
|
@@ -1605,6 +1616,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);
|
|
|
}
|
|
@@ -1618,7 +1630,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);
|
|
|
}
|