From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752439AbbDAQ0z (ORCPT ); Wed, 1 Apr 2015 12:26:55 -0400 Received: from bombadil.infradead.org ([198.137.202.9]:45356 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751315AbbDAQ0x (ORCPT ); Wed, 1 Apr 2015 12:26:53 -0400 Date: Wed, 1 Apr 2015 18:26:38 +0200 From: Peter Zijlstra To: David Ahern Cc: Stephane Eranian , Arnaldo Carvalho de Melo , Thomas Gleixner , Jiri Olsa , Linus Torvalds , LKML , John Stultz , "H. Peter Anvin" , Andrew Morton , Ingo Molnar Subject: Re: [RFC][PATCH] perf tools: unify perf_event_attr printing Message-ID: <20150401162638.GN24151@twins.programming.kicks-ass.net> References: <551594DD.7050705@gmail.com> <20150327201534.GD6291@redhat.com> <20150327215942.GL23123@twins.programming.kicks-ass.net> <20150328075549.GG27490@worktop.programming.kicks-ass.net> <551986BC.3000409@gmail.com> <20150330193318.GF23123@twins.programming.kicks-ass.net> <5519A6D8.9060806@gmail.com> <20150331081955.GQ27490@worktop.programming.kicks-ass.net> <20150331104648.GD32047@worktop.ger.corp.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150331104648.GD32047@worktop.ger.corp.intel.com> User-Agent: Mutt/1.5.21 (2012-12-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org With some feedback from Jolsa, who showed me how to trigger the actual outputs. --- Subject: perf, tools: Merge all perf_event_attr print functions From: Peter Zijlstra Date: Tue Mar 31 13:01:54 CEST 2015 Currently there's 3 (that I found) different and incomplete implementations of printing perf_event_attr. This is quite silly. Merge the lot. While this patch does not retain the exact form all printing that I found is debug output and thus it should not be critical. Also, I cannot find a single print_event_desc() caller. Pre: $ perf record -vv -e cycles -- sleep 1 ------------------------------------------------------------ perf_event_attr: type 0 size 104 config 0 sample_period 4000 sample_freq 4000 sample_type 0x107 read_format 0 disabled 1 inherit 1 pinned 0 exclusive 0 exclude_user 0 exclude_kernel 0 exclude_hv 0 exclude_idle 0 mmap 1 comm 1 mmap2 1 comm_exec 1 freq 1 inherit_stat 0 enable_on_exec 1 task 1 watermark 0 precise_ip 0 mmap_data 0 sample_id_all 1 exclude_host 0 exclude_guest 1 excl.callchain_kern 0 excl.callchain_user 0 wakeup_events 0 wakeup_watermark 0 bp_type 0 bp_addr 0 config1 0 bp_len 0 config2 0 branch_sample_type 0 sample_regs_user 0 sample_stack_user 0 sample_regs_intr 0 ------------------------------------------------------------ $ perf evlist -vv cycles: sample_freq=4000, size: 104, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, mmap2: 1, comm: 1, comm_exec: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1 Post: $ ./perf record -vv -e cycles -- sleep 1 ------------------------------------------------------------ perf_event_attr: size 112 { sample_period, sample_freq } 4000 sample_type IP|TID|TIME|PERIOD disabled 1 inherit 1 mmap 1 comm 1 freq 1 enable_on_exec 1 task 1 sample_id_all 1 exclude_guest 1 mmap2 1 comm_exec 1 ------------------------------------------------------------ $ ./perf evlist -vv cycles: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1 Cc: acme@redhat.com Cc: jolsa@redhat.com Signed-off-by: Peter Zijlstra (Intel) --- tools/perf/util/Build | 1 tools/perf/util/evsel.c | 181 ++++++----------------------------------- tools/perf/util/header.c | 34 ++----- tools/perf/util/print_attr.h | 69 +++++++++++++++ tools/perf/util/print_helper.c | 52 +++++++++++ tools/perf/util/print_helper.h | 7 + 6 files changed, 170 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,18 @@ 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 { \ + if (attr->_f) { \ + ret += fprintf(fp, " %-32s ", _n); \ + ret += _p(fp, attr->_f); \ + ret += fprintf(fp, "\n"); \ + } \ +} while (0) + +#include "util/print_attr.h" + +#undef PRINT_ATTR ret += fprintf(fp, "%.60s\n", graph_dotted_line); @@ -1996,64 +1958,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 +1984,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 +#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