aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/perf/perf_bundle.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/perf/perf_bundle.cpp b/src/perf/perf_bundle.cpp
index 38e1e91..e20a16c 100644
--- a/src/perf/perf_bundle.cpp
+++ b/src/perf/perf_bundle.cpp
@@ -284,6 +284,31 @@ static bool event_sort_function (void *i, void *j)
return (timestamp(I)<timestamp(J));
}
+/*
+ * sample's PERF_SAMPLE_CPU cpu nr is a raw_smp_processor_id() by the
+ * time of perf_event_output(), which may differ from struct perf_event
+ * cpu, thus we need to fix sample->trace.cpu.
+ */
+static void fixup_sample_trace_cpu(struct perf_sample *sample)
+{
+ struct event_format *event;
+ struct pevent_record rec;
+ unsigned long long cpu_nr;
+ int type;
+ int ret;
+
+ rec.data = &sample->data;
+ type = pevent_data_type(perf_event::pevent, &rec);
+ event = pevent_find_event(perf_event::pevent, type);
+ if (!event)
+ return;
+ /** don't touch trace if event does not contain cpu_id field*/
+ ret = pevent_get_field_val(NULL, event, "cpu_id", &rec, &cpu_nr, 0);
+ if (ret < 0)
+ return;
+ sample->trace.cpu = cpu_nr;
+}
+
void perf_bundle::process(void)
{
unsigned int i;
@@ -308,6 +333,7 @@ void perf_bundle::process(void)
if (sample->header.type != PERF_RECORD_SAMPLE)
continue;
+ fixup_sample_trace_cpu(sample);
handle_trace_point(&sample->data, sample->trace.cpu, sample->trace.time);
}
}