diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-19 04:20:42 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-23 06:45:16 -0500 |
commit | eef6cbf5844c620d9db9be99e4908cdf92492fb9 (patch) | |
tree | a4601e8d8ce64ca0f23f59b889360d578f663f5b /kernel/exit.c | |
parent | aa9c4c0f967fdb482ea95e8473ec3d201e6e0781 (diff) |
perfcounters: pull inherited counters
Change counter inheritance from a 'push' to a 'pull' model: instead of
child tasks pushing their final counts to the parent, reuse the wait4
infrastructure to pull counters as child tasks are exit-processed,
much like how cutime/cstime is collected.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 244edfd96865..101b7eeff44c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -153,6 +153,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp) | |||
153 | { | 153 | { |
154 | struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); | 154 | struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); |
155 | 155 | ||
156 | #ifdef CONFIG_PERF_COUNTERS | ||
157 | WARN_ON_ONCE(!list_empty(&tsk->perf_counter_ctx.counter_list)); | ||
158 | #endif | ||
156 | trace_sched_process_free(tsk); | 159 | trace_sched_process_free(tsk); |
157 | put_task_struct(tsk); | 160 | put_task_struct(tsk); |
158 | } | 161 | } |
@@ -922,12 +925,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
922 | forget_original_parent(tsk); | 925 | forget_original_parent(tsk); |
923 | exit_task_namespaces(tsk); | 926 | exit_task_namespaces(tsk); |
924 | 927 | ||
925 | /* | ||
926 | * Flush inherited counters to the parent - before the parent | ||
927 | * gets woken up by child-exit notifications. | ||
928 | */ | ||
929 | perf_counter_exit_task(tsk); | ||
930 | |||
931 | write_lock_irq(&tasklist_lock); | 928 | write_lock_irq(&tasklist_lock); |
932 | if (group_dead) | 929 | if (group_dead) |
933 | kill_orphaned_pgrp(tsk->group_leader, NULL); | 930 | kill_orphaned_pgrp(tsk->group_leader, NULL); |
@@ -1122,12 +1119,6 @@ NORET_TYPE void do_exit(long code) | |||
1122 | if (tsk->splice_pipe) | 1119 | if (tsk->splice_pipe) |
1123 | __free_pipe_info(tsk->splice_pipe); | 1120 | __free_pipe_info(tsk->splice_pipe); |
1124 | 1121 | ||
1125 | /* | ||
1126 | * These must happen late, after the PID is not | ||
1127 | * hashed anymore, but still at a point that may sleep: | ||
1128 | */ | ||
1129 | perf_counter_exit_task(tsk); | ||
1130 | |||
1131 | preempt_disable(); | 1122 | preempt_disable(); |
1132 | /* causes final put_task_struct in finish_task_switch(). */ | 1123 | /* causes final put_task_struct in finish_task_switch(). */ |
1133 | tsk->state = TASK_DEAD; | 1124 | tsk->state = TASK_DEAD; |
@@ -1371,6 +1362,12 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1371 | */ | 1362 | */ |
1372 | read_unlock(&tasklist_lock); | 1363 | read_unlock(&tasklist_lock); |
1373 | 1364 | ||
1365 | /* | ||
1366 | * Flush inherited counters to the parent - before the parent | ||
1367 | * gets woken up by child-exit notifications. | ||
1368 | */ | ||
1369 | perf_counter_exit_task(p); | ||
1370 | |||
1374 | retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; | 1371 | retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; |
1375 | status = (p->signal->flags & SIGNAL_GROUP_EXIT) | 1372 | status = (p->signal->flags & SIGNAL_GROUP_EXIT) |
1376 | ? p->signal->group_exit_code : p->exit_code; | 1373 | ? p->signal->group_exit_code : p->exit_code; |