History

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.

Jiri Olsa committed 11 years ago

Commit 4e93ad61 parent 169b9321 file · +31 −11Browse files

Unified · Split

kernel/events/core.c+31−11
@@ -5682,6 +5682,17 @@ perf_event_aux_ctx(struct perf_event_context *ctx, · 5681 unmodified lines
56825682 }
56835683 }
56845684
5685+static void
5686+perf_event_aux_task_ctx(perf_event_aux_output_cb output, void *data,
5687+ struct perf_event_context *task_ctx)
5688+{
5689+ rcu_read_lock();
5690+ preempt_disable();
5691+ perf_event_aux_ctx(task_ctx, output, data);
5692+ preempt_enable();
5693+ rcu_read_unlock();
5694+}
5695+
56855696 static void
56865697 perf_event_aux(perf_event_aux_output_cb output, void *data,
56875698 struct perf_event_context *task_ctx)
@@ -5691,14 +5702,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, · 3 unmodified lines
56915702 struct pmu *pmu;
56925703 int ctxn;
56935704
5705+ /*
5706+ * If we have task_ctx != NULL we only notify
5707+ * the task context itself. The task_ctx is set
5708+ * only for EXIT events before releasing task
5709+ * context.
5710+ */
5711+ if (task_ctx) {
5712+ perf_event_aux_task_ctx(output, data, task_ctx);
5713+ return;
5714+ }
5715+
56945716 rcu_read_lock();
56955717 list_for_each_entry_rcu(pmu, &pmus, entry) {
56965718 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
56975719 if (cpuctx->unique_pmu != pmu)
56985720 goto next;
56995721 perf_event_aux_ctx(&cpuctx->ctx, output, data);
5700− if (task_ctx)
5701− goto next;
57025722 ctxn = pmu->task_ctx_nr;
57035723 if (ctxn < 0)
57045724 goto next;
@@ -5708,12 +5728,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, · 3 unmodified lines
57085728 next:
57095729 put_cpu_ptr(pmu->pmu_cpu_context);
57105730 }
5711−
5712− if (task_ctx) {
5713− preempt_disable();
5714− perf_event_aux_ctx(task_ctx, output, data);
5715− preempt_enable();
5716− }
57175731 rcu_read_unlock();
57185732 }
57195733
@@ -8803,10 +8817,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) · 3083 unmodified lines
88038817 struct perf_event_context *child_ctx, *clone_ctx = NULL;
88048818 unsigned long flags;
88058819
8806− if (likely(!child->perf_event_ctxp[ctxn])) {
8807− perf_event_task(child, NULL, 0);
8820+ if (likely(!child->perf_event_ctxp[ctxn]))
88088821 return;
8809− }
88108822
88118823 local_irq_save(flags);
88128824 /*
@@ -8890,6 +8902,14 @@ void perf_event_exit_task(struct task_struct *child) · 77 unmodified lines
88908902
88918903 for_each_task_context_nr(ctxn)
88928904 perf_event_exit_task_context(child, ctxn);
8905+
8906+ /*
8907+ * The perf_event_exit_task_context calls perf_event_task
8908+ * with child's task_ctx, which generates EXIT events for
8909+ * child contexts and sets child->perf_event_ctxp[] to NULL.
8910+ * At this point we need to send EXIT events to cpu contexts.
8911+ */
8912+ perf_event_task(child, NULL, 0);
88938913 }
88948914
88958915 static void perf_free_event(struct perf_event *event,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t