exit: Always reap resource stats in __exit_signal()
Oleg pointed out that wait_task_zombie adds a task's usage statistics to the parent's signal struct, but the task's own signal struct should also propagate the statistics at exit time. This allows thread_group_cputime(reaped_zombie) to get the statistics after __unhash_process() has made the task invisible to for_each_thread, but before the thread has actually been rcu freed, making sure no non-monotonic results are returned inside that window. Suggested-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: David Rientjes <rientjes@google.com> Cc: Guillaume Morin <guillaume@morinfr.org> Cc: Ionut Alexa <ionut.m.alexa@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Li Zefan <lizefan@huawei.com> Cc: Michal Hocko <mhocko@suse.cz> Cc: Michal Schmidt <mschmidt@redhat.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: umgwanakikbuti@gmail.com Cc: fweisbec@gmail.com Cc: srao@redhat.com Cc: lwoodman@redhat.com Cc: atheurer@redhat.com Link: http://lkml.kernel.org/r/1408133138-22048-2-git-send-email-riel@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
e2627dce26
commit
90ed9cbe76
|
@ -115,30 +115,29 @@ static void __exit_signal(struct task_struct *tsk)
|
||||||
|
|
||||||
if (tsk == sig->curr_target)
|
if (tsk == sig->curr_target)
|
||||||
sig->curr_target = next_thread(tsk);
|
sig->curr_target = next_thread(tsk);
|
||||||
/*
|
|
||||||
* Accumulate here the counters for all threads but the
|
|
||||||
* group leader as they die, so they can be added into
|
|
||||||
* the process-wide totals when those are taken.
|
|
||||||
* The group leader stays around as a zombie as long
|
|
||||||
* as there are other threads. When it gets reaped,
|
|
||||||
* the exit.c code will add its counts into these totals.
|
|
||||||
* We won't ever get here for the group leader, since it
|
|
||||||
* will have been the last reference on the signal_struct.
|
|
||||||
*/
|
|
||||||
task_cputime(tsk, &utime, &stime);
|
|
||||||
sig->utime += utime;
|
|
||||||
sig->stime += stime;
|
|
||||||
sig->gtime += task_gtime(tsk);
|
|
||||||
sig->min_flt += tsk->min_flt;
|
|
||||||
sig->maj_flt += tsk->maj_flt;
|
|
||||||
sig->nvcsw += tsk->nvcsw;
|
|
||||||
sig->nivcsw += tsk->nivcsw;
|
|
||||||
sig->inblock += task_io_get_inblock(tsk);
|
|
||||||
sig->oublock += task_io_get_oublock(tsk);
|
|
||||||
task_io_accounting_add(&sig->ioac, &tsk->ioac);
|
|
||||||
sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accumulate here the counters for all threads but the group leader
|
||||||
|
* as they die, so they can be added into the process-wide totals
|
||||||
|
* when those are taken. The group leader stays around as a zombie as
|
||||||
|
* long as there are other threads. When it gets reaped, the exit.c
|
||||||
|
* code will add its counts into these totals. We won't ever get here
|
||||||
|
* for the group leader, since it will have been the last reference on
|
||||||
|
* the signal_struct.
|
||||||
|
*/
|
||||||
|
task_cputime(tsk, &utime, &stime);
|
||||||
|
sig->utime += utime;
|
||||||
|
sig->stime += stime;
|
||||||
|
sig->gtime += task_gtime(tsk);
|
||||||
|
sig->min_flt += tsk->min_flt;
|
||||||
|
sig->maj_flt += tsk->maj_flt;
|
||||||
|
sig->nvcsw += tsk->nvcsw;
|
||||||
|
sig->nivcsw += tsk->nivcsw;
|
||||||
|
sig->inblock += task_io_get_inblock(tsk);
|
||||||
|
sig->oublock += task_io_get_oublock(tsk);
|
||||||
|
task_io_accounting_add(&sig->ioac, &tsk->ioac);
|
||||||
|
sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
|
||||||
sig->nr_threads--;
|
sig->nr_threads--;
|
||||||
__unhash_process(tsk, group_dead);
|
__unhash_process(tsk, group_dead);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue