Re: [PATCH] taskstats: Add e/u/stime for TGID command

From: Andrew Morton
Date: Mon Mar 06 2017 - 18:46:40 EST


On Fri, 3 Mar 2017 10:33:44 +0800 Zhang Xiao <xiao.zhang@xxxxxxxxxxxxx> wrote:

> Add elapsed time, user CPU time and system CPU time to
> thread group status request.
>
> --- a/kernel/taskstats.c
> +++ b/kernel/taskstats.c
> @@ -210,6 +210,7 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
> struct task_struct *tsk, *first;
> unsigned long flags;
> int rc = -ESRCH;
> + u64 delta, utime, stime;
>
> /*
> * Add additional stats from live tasks except zombie thread group
> @@ -238,6 +239,16 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
> */
> delayacct_add_tsk(stats, tsk);
>
> + /* calculate task elapsed time in nsec */
> + delta = ktime_get_ns() - tsk->start_time;
> + /* Convert to micro seconds */
> + do_div(delta, NSEC_PER_USEC);
> + stats->ac_etime += delta;
> +
> + task_cputime(tsk, &utime, &stime);
> + stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
> + stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
> +
> stats->nvcsw += tsk->nvcsw;
> stats->nivcsw += tsk->nivcsw;
> } while_each_thread(first, tsk);

hm, OK, we were just leaving these at zero. Seems sane to me.

It would be more efficient and perhaps more deterministic to sample
ktime just once?

--- a/kernel/taskstats.c~taskstats-add-e-u-stime-for-tgid-command-fix
+++ a/kernel/taskstats.c
@@ -211,6 +211,7 @@ static int fill_stats_for_tgid(pid_t tgi
unsigned long flags;
int rc = -ESRCH;
u64 delta, utime, stime;
+ u64 start_time;

/*
* Add additional stats from live tasks except zombie thread group
@@ -228,6 +229,7 @@ static int fill_stats_for_tgid(pid_t tgi
memset(stats, 0, sizeof(*stats));

tsk = first;
+ start_time = ktime_get_ns();
do {
if (tsk->exit_state)
continue;
@@ -240,7 +242,7 @@ static int fill_stats_for_tgid(pid_t tgi
delayacct_add_tsk(stats, tsk);

/* calculate task elapsed time in nsec */
- delta = ktime_get_ns() - tsk->start_time;
+ delta = start_time - tsk->start_time;
/* Convert to micro seconds */
do_div(delta, NSEC_PER_USEC);
stats->ac_etime += delta;
_