[PATCH 04/21] perf tools: Add perf_sample__copy|free functions

Jiri Olsa
2018-01-24T11:51:58Z

Later in the patchset we are going to queue some samples
for later processing. To be able to do that I'm adding
perf_sample__copy|free functions that duplicate|free
perf_sample data.

Link: http://lkml.kernel.org/n/tip-lcwyac9i125cq89m9msvgu9f@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/builtin-report.c | 75 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/event.h | 1 +
2 files changed, 76 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9bae7f11691c..a08e2c88070a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -193,6 +193,81 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
return err;
}

+static void perf_sample__free(struct perf_sample *sample)
+{
+ if (sample->copy) {
+ free(sample->callchain);
+ free(sample->raw_data);
+ free(sample->branch_stack);
+ free(sample->user_regs.regs);
+ free(sample->intr_regs.regs);
+ free(sample->user_stack.data);
+ }
+}
+
+static __maybe_unused int
+perf_sample__copy(struct perf_sample *dst, struct perf_sample *src)
+{
+ int ret = -1;
+ u64 size;
+
+ *dst = *src;
+
+ dst->callchain = NULL;
+ dst->raw_data = NULL;
+ dst->branch_stack = NULL;
+ dst->user_regs.regs = NULL;
+ dst->intr_regs.regs = NULL;
+ dst->user_stack.data = NULL;
+
+#define DUP(__field, __size) \
+ do { \
+ dst->__field = memdup(src->__field, __size); \
+ if (!dst->__field) \
+ goto error; \
+ } while (0)
+
+ if (src->callchain) {
+ size = (src->callchain->nr + 1) * sizeof(u64);
+ DUP(callchain, size);
+ }
+
+ if (src->raw_data)
+ DUP(raw_data, src->raw_size);
+
+ if (src->branch_stack) {
+ size = sizeof(u64);
+ size += src->branch_stack->nr * sizeof(struct branch_entry);
+ DUP(branch_stack, size);
+ }
+
+ if (src->user_regs.regs) {
+ u64 mask = src->user_regs.mask;
+
+ size = hweight_long(mask) * sizeof(u64);
+ DUP(user_regs.regs, size);
+ }
+
+ if (src->intr_regs.regs) {
+ u64 mask = src->intr_regs.mask;
+
+ size = hweight_long(mask) * sizeof(u64);
+ DUP(intr_regs.regs, size);
+ }
+
+ if (src->user_stack.data)
+ DUP(user_stack.data, src->user_stack.size);
+
+#undef DUP
+ dst->copy = true;
+ ret = 0;
+
+error:
+ if (ret)
+ perf_sample__free(dst);
+ return ret;
+}
+
static int
perf_sample__process(struct perf_sample *sample, struct addr_location *al,
struct perf_evsel *evsel, struct report *rep)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 0f794744919c..546539da1592 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -189,6 +189,7 @@ enum {
#define MAX_INSN 16

struct perf_sample {
+ bool copy;
u64 ip;
u32 pid, tid;
u64 time;
--
2.13.6