[RFC][PATCH] perf tools: unify perf_event_attr printing

From: Peter Zijlstra
Date: Tue Mar 31 2015 - 06:46:54 EST


On Tue, Mar 31, 2015 at 10:19:55AM +0200, Peter Zijlstra wrote:
> Fwiw, having 3 incomplete ways to print perf_event_attr() is
> disgusting.

How about something like so? Its not identical, but at least its
complete and consistent.

---
tools/perf/util/print_attr.h | 69 +++++++++++++++
tools/perf/util/print_helper.c | 52 +++++++++++
tools/perf/util/print_helper.h | 7 +
tools/perf/util/Build | 1
tools/perf/util/evsel.c | 178 +++++----------------------------------
tools/perf/util/header.c | 34 ++-----
6 files changed, 167 insertions(+), 174 deletions(-)

--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -74,6 +74,7 @@ libperf-y += data.o
libperf-$(CONFIG_X86) += tsc.o
libperf-y += cloexec.o
libperf-y += thread-stack.o
+libperf-y += print_helper.o

libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-event.o
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -26,6 +26,7 @@
#include "perf_regs.h"
#include "debug.h"
#include "trace-event.h"
+#include "print_helper.h"

static struct {
bool sample_id_all;
@@ -1011,21 +1012,6 @@ static int get_group_fd(struct perf_evse
return fd;
}

-#define __PRINT_ATTR(fmt, cast, field) \
- fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field)
-
-#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field)
-#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field)
-#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field)
-#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field)
-
-#define PRINT_ATTR2N(name1, field1, name2, field2) \
- fprintf(fp, " %-19s %u %-19s %u\n", \
- name1, attr->field1, name2, attr->field2)
-
-#define PRINT_ATTR2(field1, field2) \
- PRINT_ATTR2N(#field1, field1, #field2, field2)
-
static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
{
size_t ret = 0;
@@ -1033,42 +1019,15 @@ static size_t perf_event_attr__fprintf(s
ret += fprintf(fp, "%.60s\n", graph_dotted_line);
ret += fprintf(fp, "perf_event_attr:\n");

- ret += PRINT_ATTR_U32(type);
- ret += PRINT_ATTR_U32(size);
- ret += PRINT_ATTR_X64(config);
- ret += PRINT_ATTR_U64(sample_period);
- ret += PRINT_ATTR_U64(sample_freq);
- ret += PRINT_ATTR_X64(sample_type);
- ret += PRINT_ATTR_X64(read_format);
-
- ret += PRINT_ATTR2(disabled, inherit);
- ret += PRINT_ATTR2(pinned, exclusive);
- ret += PRINT_ATTR2(exclude_user, exclude_kernel);
- ret += PRINT_ATTR2(exclude_hv, exclude_idle);
- ret += PRINT_ATTR2(mmap, comm);
- ret += PRINT_ATTR2(freq, inherit_stat);
- ret += PRINT_ATTR2(enable_on_exec, task);
- ret += PRINT_ATTR2(watermark, precise_ip);
- ret += PRINT_ATTR2(mmap_data, sample_id_all);
- ret += PRINT_ATTR2(exclude_host, exclude_guest);
- ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
- "excl.callchain_user", exclude_callchain_user);
- ret += PRINT_ATTR2(mmap2, comm_exec);
- ret += __PRINT_ATTR("%u",,use_clockid);
-
-
- ret += PRINT_ATTR_U32(wakeup_events);
- ret += PRINT_ATTR_U32(wakeup_watermark);
- ret += PRINT_ATTR_X32(bp_type);
- ret += PRINT_ATTR_X64(bp_addr);
- ret += PRINT_ATTR_X64(config1);
- ret += PRINT_ATTR_U64(bp_len);
- ret += PRINT_ATTR_X64(config2);
- ret += PRINT_ATTR_X64(branch_sample_type);
- ret += PRINT_ATTR_X64(sample_regs_user);
- ret += PRINT_ATTR_U32(sample_stack_user);
- ret += PRINT_ATTR_U32(clockid);
- ret += PRINT_ATTR_X64(sample_regs_intr);
+#define PRINT_ATTR(_n, _f, _p) \
+do { \
+ ret += fprintf(fp, " %-19s ", _n); \
+ ret += _p(fp, attr->_f); \
+} while (0)
+
+#include "util/print_attr.h"
+
+#undef PRINT_ATTR

ret += fprintf(fp, "%.60s\n", graph_dotted_line);

@@ -1996,64 +1955,6 @@ static int comma_fprintf(FILE *fp, bool
return ret;
}

-static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
-{
- if (value == 0)
- return 0;
-
- return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
-}
-
-#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
-
-struct bit_names {
- int bit;
- const char *name;
-};
-
-static int bits__fprintf(FILE *fp, const char *field, u64 value,
- struct bit_names *bits, bool *first)
-{
- int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
- bool first_bit = true;
-
- do {
- if (value & bits[i].bit) {
- printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
- first_bit = false;
- }
- } while (bits[++i].name != NULL);
-
- return printed;
-}
-
-static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
-{
-#define bit_name(n) { PERF_SAMPLE_##n, #n }
- struct bit_names bits[] = {
- bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
- bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
- bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
- bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
- bit_name(IDENTIFIER), bit_name(REGS_INTR),
- { .name = NULL, }
- };
-#undef bit_name
- return bits__fprintf(fp, "sample_type", value, bits, first);
-}
-
-static int read_format__fprintf(FILE *fp, bool *first, u64 value)
-{
-#define bit_name(n) { PERF_FORMAT_##n, #n }
- struct bit_names bits[] = {
- bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
- bit_name(ID), bit_name(GROUP),
- { .name = NULL, }
- };
-#undef bit_name
- return bits__fprintf(fp, "read_format", value, bits, first);
-}
-
int perf_evsel__fprintf(struct perf_evsel *evsel,
struct perf_attr_details *details, FILE *fp)
{
@@ -2080,51 +1981,24 @@ int perf_evsel__fprintf(struct perf_evse

printed += fprintf(fp, "%s", perf_evsel__name(evsel));

- if (details->verbose || details->freq) {
- printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
- (u64)evsel->attr.sample_freq);
- }

if (details->verbose) {
- if_print(type);
- if_print(config);
- if_print(config1);
- if_print(config2);
- if_print(size);
- printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
- if (evsel->attr.read_format)
- printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
- if_print(disabled);
- if_print(inherit);
- if_print(pinned);
- if_print(exclusive);
- if_print(exclude_user);
- if_print(exclude_kernel);
- if_print(exclude_hv);
- if_print(exclude_idle);
- if_print(mmap);
- if_print(comm);
- if_print(freq);
- if_print(inherit_stat);
- if_print(enable_on_exec);
- if_print(task);
- if_print(watermark);
- if_print(precise_ip);
- if_print(mmap_data);
- if_print(sample_id_all);
- if_print(exclude_host);
- if_print(exclude_guest);
- if_print(mmap2);
- if_print(comm_exec);
- if_print(use_clockid);
- if_print(__reserved_1);
- if_print(wakeup_events);
- if_print(bp_type);
- if_print(branch_sample_type);
- if_print(sample_regs_user);
- if_print(sample_stack_user);
- if_print(clockid);
- if_print(sample_regs_intr);
+
+#define PRINT_ATTR(_n, _f, _p) \
+do { \
+ if (evsel->attr._f) { \
+ printed += comma_fprintf(fp, &first, " %s: ", _n); \
+ printed += _p(fp, evsel->attr._f); \
+ } \
+} while (0)
+
+#include "util/print_attr.h"
+
+#undef PRINT_ATTR
+
+ } else if (details->freq) {
+ printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
+ (u64)evsel->attr.sample_freq);
}
out:
fputc('\n', fp);
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -23,6 +23,7 @@
#include "strbuf.h"
#include "build-id.h"
#include "data.h"
+#include "print_helper.h"

static u32 header_argc;
static const char **header_argv;
@@ -1069,26 +1070,6 @@ static void print_event_desc(struct perf
for (evsel = events; evsel->attr.size; evsel++) {
fprintf(fp, "# event : name = %s, ", evsel->name);

- fprintf(fp, "type = %d, config = 0x%"PRIx64
- ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
- evsel->attr.type,
- (u64)evsel->attr.config,
- (u64)evsel->attr.config1,
- (u64)evsel->attr.config2);
-
- fprintf(fp, ", excl_usr = %d, excl_kern = %d",
- evsel->attr.exclude_user,
- evsel->attr.exclude_kernel);
-
- fprintf(fp, ", excl_host = %d, excl_guest = %d",
- evsel->attr.exclude_host,
- evsel->attr.exclude_guest);
-
- fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
-
- fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
- fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
- fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
if (evsel->ids) {
fprintf(fp, ", id = {");
for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
@@ -1098,9 +1079,18 @@ static void print_event_desc(struct perf
}
fprintf(fp, " }");
}
- if (evsel->attr.use_clockid)
- fprintf(fp, ", clockid = %d", evsel->attr.clockid);

+#define PRINT_ATTR(_n, _f, _p) \
+do { \
+ if (evsel->attr._f) { \
+ fprintf(fp, ", %s =", _n); \
+ _p(fp, evsel->attr._f); \
+ } \
+} while (0)
+
+#include "util/print_attr.h"
+
+#undef PRINT_ATTR

fputc('\n', fp);
}
--- /dev/null
+++ b/tools/perf/util/print_attr.h
@@ -0,0 +1,69 @@
+
+#ifndef PRINT_ATTR
+/*
+ * #define PRINT_ATTR(name, field, print) \
+ * do { \
+ * fprintf(fp, " %s = ", name); \
+ * print(fp, attr->field); \
+ * } while (0)
+ */
+#error "General Error and Major Fault yell at you!"
+#endif
+
+#define p_hex(fp, val) fprintf(fp, "%"PRIx64, (uint64_t)(val))
+#define p_unsigned(fp, val) fprintf(fp, "%"PRIu64, (uint64_t)(val))
+#define p_signed(fp, val) fprintf(fp, "%"PRId64, (int64_t)(val))
+#define p_sample_type(fp, val) sample_type__fprintf(fp, val)
+#define p_read_format(fp, val) read_format__fprintf(fp, val)
+
+#define PRINT_ATTRf(field, print) PRINT_ATTR(#field, field, print)
+
+PRINT_ATTRf(type, p_unsigned);
+PRINT_ATTRf(size, p_unsigned);
+PRINT_ATTRf(config, p_hex);
+PRINT_ATTR("{ sample_period, sample_freq }", sample_period, p_unsigned);
+PRINT_ATTRf(sample_type, p_sample_type);
+PRINT_ATTRf(read_format, p_read_format);
+
+PRINT_ATTRf(disabled, p_unsigned);
+PRINT_ATTRf(inherit, p_unsigned);
+PRINT_ATTRf(pinned, p_unsigned);
+PRINT_ATTRf(exclusive, p_unsigned);
+PRINT_ATTRf(exclude_user, p_unsigned);
+PRINT_ATTRf(exclude_kernel, p_unsigned);
+PRINT_ATTRf(exclude_hv, p_unsigned);
+PRINT_ATTRf(exclude_idle, p_unsigned);
+PRINT_ATTRf(mmap, p_unsigned);
+PRINT_ATTRf(comm, p_unsigned);
+PRINT_ATTRf(freq, p_unsigned);
+PRINT_ATTRf(inherit_stat, p_unsigned);
+PRINT_ATTRf(enable_on_exec, p_unsigned);
+PRINT_ATTRf(task, p_unsigned);
+PRINT_ATTRf(watermark, p_unsigned);
+PRINT_ATTRf(precise_ip, p_unsigned);
+PRINT_ATTRf(mmap_data, p_unsigned);
+PRINT_ATTRf(sample_id_all, p_unsigned);
+PRINT_ATTRf(exclude_host, p_unsigned);
+PRINT_ATTRf(exclude_guest, p_unsigned);
+PRINT_ATTRf(exclude_callchain_kernel, p_unsigned);
+PRINT_ATTRf(exclude_callchain_user, p_unsigned);
+PRINT_ATTRf(mmap2, p_unsigned);
+PRINT_ATTRf(comm_exec, p_unsigned);
+PRINT_ATTRf(use_clockid, p_unsigned);
+
+PRINT_ATTR("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
+PRINT_ATTRf(bp_type, p_unsigned);
+PRINT_ATTR("{ bp_addr, config1 }", bp_addr, p_hex);
+PRINT_ATTR("{ bp_len, config2 }", bp_len, p_hex);
+PRINT_ATTRf(sample_regs_user, p_hex);
+PRINT_ATTRf(sample_stack_user, p_unsigned);
+PRINT_ATTRf(clockid, p_signed);
+PRINT_ATTRf(sample_regs_intr, p_hex);
+
+#undef PRINT_ATTRf
+
+#undef p_hex
+#undef p_unsigned
+#undef p_signed
+#undef p_sample_type
+#undef p_read_format
--- /dev/null
+++ b/tools/perf/util/print_helper.c
@@ -0,0 +1,52 @@
+
+#include <linux/perf_event.h>
+#include "util.h"
+#include "print_helper.h"
+
+struct bit_names {
+ int bit;
+ const char *name;
+};
+
+static int bits__fprintf(FILE *fp, u64 value, struct bit_names *bits)
+{
+ int i = 0, printed = 0;
+ bool first_bit = true;
+
+ do {
+ if (value & bits[i].bit) {
+ printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
+ first_bit = false;
+ }
+ } while (bits[++i].name != NULL);
+
+ return printed;
+}
+
+int sample_type__fprintf(FILE *fp, u64 value)
+{
+#define bit_name(n) { PERF_SAMPLE_##n, #n }
+ struct bit_names bits[] = {
+ bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
+ bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
+ bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
+ bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
+ bit_name(IDENTIFIER), bit_name(REGS_INTR),
+ { .name = NULL, }
+ };
+#undef bit_name
+ return bits__fprintf(fp, value, bits);
+}
+
+int read_format__fprintf(FILE *fp, u64 value)
+{
+#define bit_name(n) { PERF_FORMAT_##n, #n }
+ struct bit_names bits[] = {
+ bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
+ bit_name(ID), bit_name(GROUP),
+ { .name = NULL, }
+ };
+#undef bit_name
+ return bits__fprintf(fp, value, bits);
+}
+
--- /dev/null
+++ b/tools/perf/util/print_helper.h
@@ -0,0 +1,7 @@
+#ifndef PRINT_HELPER_H
+#define PRINT_HELPER_H
+
+extern int sample_type__fprintf(FILE *fp, u64 value);
+extern int read_format__fprintf(FILE *fp, u64 value);
+
+#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/