[RFC][PATCH v2 6/7] taskstats: Fix accounting for non-leader thread exec

From: Michael Holzheu
Date: Thu Nov 11 2010 - 12:09:00 EST


From: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxx>

If a non-leader thread calls exec(), in the de_thread() function it
gets some of the identity of the old thread group leader e.g. the PID
and the start time. But it keeps the old CPU times. This may lead to
confusion in user space, because CPU time can go backwards for the
thread group leader. For example the top command shows the following
for that test case:

# top -H
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17278 root 20 0 84128 664 500 R >>9999.0<< 0.0 0:02.75 pthread_exec

To fix this problem, this patch exchanges the accounting data between the
exec() calling thread an the thread group leader in de_thread().
One problem with this patch could be that the scheduler might get confused
by the CPU time change.

Signed-off-by: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxx>
---
fs/exec.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)

--- a/fs/exec.c
+++ b/fs/exec.c
@@ -844,16 +844,32 @@ static int de_thread(struct task_struct

/*
* The only record we have of the real-time age of a
- * process, regardless of execs it's done, is start_time.
+ * process, regardless of execs it's done, is start_time
+ * and the accounting data.
* All the past CPU time is accumulated in signal_struct
* from sister threads now dead. But in this non-leader
* exec, nothing survives from the original leader thread,
* whose birth marks the true age of this process now.
* When we take on its identity by switching to its PID, we
- * also take its birthdate (always earlier than our own).
+ * also take its birthdate (always earlier than our own)
+ * and the accounting data.
*/
tsk->start_time = leader->start_time;
-
+ swap(tsk->nvcsw, leader->nvcsw);
+ swap(tsk->nivcsw, leader->nivcsw);
+ swap(tsk->min_flt, leader->min_flt);
+ swap(tsk->ioac, leader->ioac);
+ swap(tsk->utime, leader->utime);
+ swap(tsk->stime, leader->stime);
+ swap(tsk->gtime, leader->gtime);
+ swap(tsk->sttime, leader->sttime);
+ swap(tsk->acct_time, leader->acct_time);
+ swap(tsk->real_start_time, leader->real_start_time);
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+ swap(tsk->prev_utime, leader->prev_utime);
+ swap(tsk->prev_stime, leader->prev_stime);
+ swap(tsk->prev_sttime, leader->prev_sttime);
+#endif
BUG_ON(!same_thread_group(leader, tsk));
BUG_ON(has_group_leader_pid(tsk));
/*

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/