perf: Do not send exit event twice
Jiri Olsa
reviewerPATCH 1/1 perf: Do not send exit event twice
In case we monitor events system wide, we get EXIT event (when configured) twice for each task that exited.
Note doubled lines with same pid/tid in following example:
$ sudo ./perf record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.480 MB perf.data (2518 samples) ] $ sudo ./perf report -D | grep EXIT
0 60290687567581 0x59910 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687568354 0x59948 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687988744 0x59ad8 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687989198 0x59b10 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 1 60290692567895 0x62af0 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 1 60290692568322 0x62b28 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 2 60290692739276 0x69a18 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252) 2 60290692739910 0x69a50 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252)
The reason is that the cpu contexts are processes each time we call perf_event_task. I'm changing the perf_event_aux logic to serve task_ctx and cpu contexts separately, which ensure we don't get EXIT event generated twice on same cpu context.
This does not affect other auxiliary events, as they don't use task_ctx at all.
--- kernel/events/core.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-)
kernel/events/core.c +31 -11
@@ -5661,6 +5661,17 @@ perf_event_aux_ctx(struct perf_event_context *ctx, }static void +perf_event_aux_task_ctx (perf_event_aux_output_cb output,void *data, +struct perf_event_context *task_ctx) +{ +rcu_read_lock (); +preempt_disable (); +perf_event_aux_ctx (task_ctx, output, data); +preempt_enable (); +rcu_read_unlock (); +} + +static void perf_event_aux (perf_event_aux_output_cb output,void *data,struct perf_event_context *task_ctx) {
@@ -5669,14 +5680,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data,struct pmu *pmu;int ctxn; +/* +* If we have task_ctx != NULL we only notify +* the task context itself. The task_ctx is set +* only for EXIT events before releasing task +* context. +*/ +if (task_ctx) { +perf_event_aux_task_ctx (output, data, task_ctx); +return ; + } +rcu_read_lock ();list_for_each_entry_rcu (pmu, &pmus, entry) { cpuctx =get_cpu_ptr (pmu->pmu_cpu_context);if (cpuctx->unique_pmu != pmu) goto next;perf_event_aux_ctx (&cpuctx->ctx, output, data); -if (task_ctx) - goto next; ctxn = pmu->task_ctx_nr;if (ctxn <0 ) goto next;
@@ -5686,12 +5706,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, next:put_cpu_ptr (pmu->pmu_cpu_context); } - -if (task_ctx) { -preempt_disable (); -perf_event_aux_ctx (task_ctx, output, data); -preempt_enable (); - }rcu_read_unlock (); }
@@ -8777,10 +8791,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)struct perf_event_context *child_ctx, *clone_ctx =NULL ;unsigned long flags; -if (likely (!child->perf_event_ctxp[ctxn])) { -perf_event_task (child,NULL ,0 ); +if (likely (!child->perf_event_ctxp[ctxn]))return ; - }local_irq_save (flags);/*
@@ -8864,6 +8876,14 @@ void perf_event_exit_task(struct task_struct *child)for_each_task_context_nr (ctxn)perf_event_exit_task_context (child, ctxn); + +/* +* The perf_event_exit_task_context calls perf_event_task +* with child's task_ctx, which generates EXIT events for +* child contexts and sets child->perf_event_ctxp[] to NULL. +* At this point we need to send EXIT events to cpu contexts. +*/ +perf_event_task (child,NULL ,0 ); } static void perf_free_event(struct perf_event *event,
Signature · 1 line
2.4.3
Peter Zijlstra
maintainerQuoted 2 lines · Jiri Olsa
This does not affect other auxiliary events, as they don't use
task_ctxat all.
FORK does..
Quoted 1 line
Please fix your script to never emit /n/ links; those are no longer appreciated.
Quoted 5 lines · Peter Zijlstra
Quoted 2 lines · Jiri Olsa
This does not affect other auxiliary events, as they don't use
task_ctxat all.FORK does..
hum, I don't see that, it passes NULL as task_ctx:
void perf_event_fork(struct task_struct *task)
{
perf_event_task(task, NULL, 1);
}Quoted 5 lines
Quoted 2 lines
Please fix your script to never emit /n/ links; those are no longer appreciated.
will do
thanks.
jirka
Peter Zijlstra
maintainerQuoted 5 lines · Jiri Olsa
Quoted 4 lines · Peter Zijlstra
Quoted 2 lines · Jiri Olsa
This does not affect other auxiliary events, as they don't use
task_ctxat all.
Quoted 8 lines
Quoted 1 line
FORK does..
hum, I don't see that, it passes NULL as
task_ctx:void
perf_event_fork(struct task_struct *task){ perf_event_task(task, NULL, 1); }
Bah, I'll go sit in a corner, or rather, have a nap. Clearly I cannot even read anymore.
Quoted 10 lines · Peter Zijlstra
Quoted 9 lines · Jiri Olsa
Quoted 5 lines · Peter Zijlstra
Quoted 2 lines · Jiri Olsa
This does not affect other auxiliary events, as they don't use
task_ctxat all.FORK does..
hum, I don't see that, it passes NULL as
task_ctx:
Quoted 7 lines
Quoted 4 lines
void
perf_event_fork(struct task_struct *task){ perf_event_task(task, NULL, 1); }Bah, I'll go sit in a corner, or rather, have a nap. Clearly I cannot even read anymore.
heya,
can't see this one being in any queue so far.. could you please take it together with:
perf x86 intel: Fix INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA macro
thanks,
jirka
tip-bot for Jiri Olsa
merge botperf: Do not send exit event twice
Commit-ID: b85da9c1e52eb570fc16a42ae241ee5039c9151b Gitweb: http://git.kernel.org/tip/b85da9c1e52eb570fc16a42ae241ee5039c9151b Author: Jiri Olsa <[email protected]> AuthorDate: Wed, 4 Nov 2015 16:00:05 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 4 Dec 2015 10:08:07 +0100
perf: Do not send exit event twice
In case we monitor events system wide, we get EXIT event (when configured) twice for each task that exited.
Note doubled lines with same pid/tid in following example:
$ sudo ./perf record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.480 MB perf.data (2518 samples) ] $ sudo ./perf report -D | grep EXIT
0 60290687567581 0x59910 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687568354 0x59948 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687988744 0x59ad8 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687989198 0x59b10 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 1 60290692567895 0x62af0 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 1 60290692568322 0x62b28 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 2 60290692739276 0x69a18 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252) 2 60290692739910 0x69a50 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252)
The reason is that the cpu contexts are processes each time we call perf_event_task. I'm changing the perf_event_aux logic to serve task_ctx and cpu contexts separately, which ensure we don't get EXIT event generated twice on same cpu context.
This does not affect other auxiliary events, as they don't use task_ctx at all.
--- kernel/events/core.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-)
kernel/events/core.c +31 -11
@@ -5683,6 +5683,17 @@ perf_event_aux_ctx(struct perf_event_context *ctx, }static void +perf_event_aux_task_ctx (perf_event_aux_output_cb output,void *data, +struct perf_event_context *task_ctx) +{ +rcu_read_lock (); +preempt_disable (); +perf_event_aux_ctx (task_ctx, output, data); +preempt_enable (); +rcu_read_unlock (); +} + +static void perf_event_aux (perf_event_aux_output_cb output,void *data,struct perf_event_context *task_ctx) {
@@ -5691,14 +5702,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data,struct pmu *pmu;int ctxn; +/* +* If we have task_ctx != NULL we only notify +* the task context itself. The task_ctx is set +* only for EXIT events before releasing task +* context. +*/ +if (task_ctx) { +perf_event_aux_task_ctx (output, data, task_ctx); +return ; + } +rcu_read_lock ();list_for_each_entry_rcu (pmu, &pmus, entry) { cpuctx =get_cpu_ptr (pmu->pmu_cpu_context);if (cpuctx->unique_pmu != pmu) goto next;perf_event_aux_ctx (&cpuctx->ctx, output, data); -if (task_ctx) - goto next; ctxn = pmu->task_ctx_nr;if (ctxn <0 ) goto next;
@@ -5708,12 +5728,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, next:put_cpu_ptr (pmu->pmu_cpu_context); } - -if (task_ctx) { -preempt_disable (); -perf_event_aux_ctx (task_ctx, output, data); -preempt_enable (); - }rcu_read_unlock (); }
@@ -8803,10 +8817,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)struct perf_event_context *child_ctx, *clone_ctx =NULL ;unsigned long flags; -if (likely (!child->perf_event_ctxp[ctxn])) { -perf_event_task (child,NULL ,0 ); +if (likely (!child->perf_event_ctxp[ctxn]))return ; - }local_irq_save (flags);/*
@@ -8890,6 +8902,14 @@ void perf_event_exit_task(struct task_struct *child)for_each_task_context_nr (ctxn)perf_event_exit_task_context (child, ctxn); + +/* +* The perf_event_exit_task_context calls perf_event_task +* with child's task_ctx, which generates EXIT events for +* child contexts and sets child->perf_event_ctxp[] to NULL. +* At this point we need to send EXIT events to cpu contexts. +*/ +perf_event_task (child,NULL ,0 ); } static void perf_free_event(struct perf_event *event,
tip-bot for Jiri Olsa
merge botperf: Do not send exit event twice
Commit-ID: 4e93ad601a4308d4a67673c81556580817d56940 Gitweb: http://git.kernel.org/tip/4e93ad601a4308d4a67673c81556580817d56940 Author: Jiri Olsa <[email protected]> AuthorDate: Wed, 4 Nov 2015 16:00:05 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 6 Dec 2015 12:54:49 +0100
perf: Do not send exit event twice
In case we monitor events system wide, we get EXIT event (when configured) twice for each task that exited.
Note doubled lines with same pid/tid in following example:
$ sudo ./perf record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.480 MB perf.data (2518 samples) ] $ sudo ./perf report -D | grep EXIT
0 60290687567581 0x59910 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687568354 0x59948 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687988744 0x59ad8 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 0 60290687989198 0x59b10 [0x38]: PERF_RECORD_EXIT(1250:1250):(1250:1250) 1 60290692567895 0x62af0 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 1 60290692568322 0x62b28 [0x38]: PERF_RECORD_EXIT(1253:1253):(1253:1253) 2 60290692739276 0x69a18 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252) 2 60290692739910 0x69a50 [0x38]: PERF_RECORD_EXIT(1252:1252):(1252:1252)
The reason is that the cpu contexts are processes each time we call perf_event_task. I'm changing the perf_event_aux logic to serve task_ctx and cpu contexts separately, which ensure we don't get EXIT event generated twice on same cpu context.
This does not affect other auxiliary events, as they don't use task_ctx at all.
--- kernel/events/core.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-)
kernel/events/core.c +31 -11
@@ -5683,6 +5683,17 @@ perf_event_aux_ctx(struct perf_event_context *ctx, }static void +perf_event_aux_task_ctx (perf_event_aux_output_cb output,void *data, +struct perf_event_context *task_ctx) +{ +rcu_read_lock (); +preempt_disable (); +perf_event_aux_ctx (task_ctx, output, data); +preempt_enable (); +rcu_read_unlock (); +} + +static void perf_event_aux (perf_event_aux_output_cb output,void *data,struct perf_event_context *task_ctx) {
@@ -5691,14 +5702,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data,struct pmu *pmu;int ctxn; +/* +* If we have task_ctx != NULL we only notify +* the task context itself. The task_ctx is set +* only for EXIT events before releasing task +* context. +*/ +if (task_ctx) { +perf_event_aux_task_ctx (output, data, task_ctx); +return ; + } +rcu_read_lock ();list_for_each_entry_rcu (pmu, &pmus, entry) { cpuctx =get_cpu_ptr (pmu->pmu_cpu_context);if (cpuctx->unique_pmu != pmu) goto next;perf_event_aux_ctx (&cpuctx->ctx, output, data); -if (task_ctx) - goto next; ctxn = pmu->task_ctx_nr;if (ctxn <0 ) goto next;
@@ -5708,12 +5728,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, next:put_cpu_ptr (pmu->pmu_cpu_context); } - -if (task_ctx) { -preempt_disable (); -perf_event_aux_ctx (task_ctx, output, data); -preempt_enable (); - }rcu_read_unlock (); }
@@ -8803,10 +8817,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)struct perf_event_context *child_ctx, *clone_ctx =NULL ;unsigned long flags; -if (likely (!child->perf_event_ctxp[ctxn])) { -perf_event_task (child,NULL ,0 ); +if (likely (!child->perf_event_ctxp[ctxn]))return ; - }local_irq_save (flags);/*
@@ -8890,6 +8902,14 @@ void perf_event_exit_task(struct task_struct *child)for_each_task_context_nr (ctxn)perf_event_exit_task_context (child, ctxn); + +/* +* The perf_event_exit_task_context calls perf_event_task +* with child's task_ctx, which generates EXIT events for +* child contexts and sets child->perf_event_ctxp[] to NULL. +* At this point we need to send EXIT events to cpu contexts. +*/ +perf_event_task (child,NULL ,0 ); } static void perf_free_event(struct perf_event *event,