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
5682 }5682 }
5683}5683}
5684 5684
5685static void
5686perf_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
5685static void5696static void
5686perf_event_aux(perf_event_aux_output_cb output, void *data,5697perf_event_aux(perf_event_aux_output_cb output, void *data,
5687 struct perf_event_context *task_ctx)5698 struct perf_event_context *task_ctx)
@@ -5691,14 +5702,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, · 3 unmodified lines
5691 struct pmu *pmu;5702 struct pmu *pmu;
5692 int ctxn;5703 int ctxn;
5693 5704
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
5694 rcu_read_lock();5716 rcu_read_lock();
5695 list_for_each_entry_rcu(pmu, &pmus, entry) {5717 list_for_each_entry_rcu(pmu, &pmus, entry) {
5696 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);5718 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
5697 if (cpuctx->unique_pmu != pmu)5719 if (cpuctx->unique_pmu != pmu)
5698 goto next;5720 goto next;
5699 perf_event_aux_ctx(&cpuctx->ctx, output, data);5721 perf_event_aux_ctx(&cpuctx->ctx, output, data);
5700 if (task_ctx)
5701 goto next;
5702 ctxn = pmu->task_ctx_nr;5722 ctxn = pmu->task_ctx_nr;
5703 if (ctxn < 0)5723 if (ctxn < 0)
5704 goto next;5724 goto next;
@@ -5708,12 +5728,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, · 3 unmodified lines
5708next:5728next:
5709 put_cpu_ptr(pmu->pmu_cpu_context);5729 put_cpu_ptr(pmu->pmu_cpu_context);
5710 }5730 }
5711
5712 if (task_ctx) {
5713 preempt_disable();
5714 perf_event_aux_ctx(task_ctx, output, data);
5715 preempt_enable();
5716 }
5717 rcu_read_unlock();5731 rcu_read_unlock();
5718}5732}
5719 5733
@@ -8803,10 +8817,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) · 3083 unmodified lines
8803 struct perf_event_context *child_ctx, *clone_ctx = NULL;8817 struct perf_event_context *child_ctx, *clone_ctx = NULL;
8804 unsigned long flags;8818 unsigned long flags;
8805 8819
8806 if (likely(!child->perf_event_ctxp[ctxn])) {8820 if (likely(!child->perf_event_ctxp[ctxn]))
8807 perf_event_task(child, NULL, 0);
8808 return;8821 return;
8809 }
8810 8822
8811 local_irq_save(flags);8823 local_irq_save(flags);
8812 /*8824 /*
@@ -8890,6 +8902,14 @@ void perf_event_exit_task(struct task_struct *child) · 77 unmodified lines
8890 8902
8891 for_each_task_context_nr(ctxn)8903 for_each_task_context_nr(ctxn)
8892 perf_event_exit_task_context(child, ctxn);8904 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);
8893}8913}
8894 8914
8895static void perf_free_event(struct perf_event *event,8915static 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