exit: Always reap resource stats in __exit_signal()
authorRik van Riel <riel@redhat.com>
Fri, 15 Aug 2014 20:05:36 +0000 (16:05 -0400)
committerIngo Molnar <mingo@kernel.org>
Mon, 8 Sep 2014 06:17:00 +0000 (08:17 +0200)
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>
kernel/exit.c

index 32c58f7433a3672c636687cf81c108eb0f20761e..b93d46dab6fc016e8a684bc8acb69962278507d4 100644 (file)
@@ -115,30 +115,29 @@ static void __exit_signal(struct task_struct *tsk)
 
                if (tsk == sig->curr_target)
                        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--;
        __unhash_process(tsk, group_dead);