perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
A bit of trivia info is now automatically shown in the container
builds, the gcc version used to build the tools, that gets changed as the distros update gcc and as I update the container build images :-)
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit 0d3d73aac2ff05c78387aa9dcc2c8aa3804405e7:
perf/core: Rewrite event timekeeping (2017-10-27 10:31:59 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.15-20171103
for you to fetch changes up to 7285cf3325b4a1dfb336d31eebc27dfbc30fb9aa:
perf srcline: Show correct function name for srcline of callchains (2017-11-01 11:44:38 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
- Beautify the 'kcmp' and 'prctl' syscall arguments in 'perf trace' (Arnaldo Carvalho de Melo)
- Implement a way to print formatted output to per-event files in 'perf script' to facilitate generate flamegraphs, elliminating the need to write scripts to do that separation (yuzhoujian, Arnaldo Carvalho de Melo)
Make 'perf stat --per-thread' update shadow stats to show metrics (Jiri Olsa)
- Fix double mapping al->addr in callchain processing for children without self period (Namhyung Kim)
- Fix memory leak in addr2inlines() when libbfd is not used (Namhyung Kim)
- Show correct function name for srcline of callchains when libbfd is not used (Namhyung Kim)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (11):
perf script: Add a few missing conversions to fprintf style perf script: Use pr_debug where appropriate
perf script: Use event_format__fprintf()
perf evsel: Restore evsel->priv as a tool private area
perf script: Allow creating per-event dump files
tools include uapi: Grab a copy of linux/prctl.h
perf trace beauty prctl: Generate 'option' string table from kernel headers perf script: Print information about per-event-dump files tools include uapi: Grab a copy of linux/kcmp.h
perf trace beauty: Implement pid_fd beautifier
perf trace beauty kcmp: Beautify arguments
Jiri Olsa (5):
perf tools: Rename struct perf_data_file to perf_data
perf tools: Add struct perf_data_file
perf tools: Add perf_data_file__write function
perf stat: Move the shadow stats scale computation in perf_stat__update_shadow_stats perf stat: Make --per-thread update shadow stats to show metrics
Namhyung Kim (3):
perf callchain: Fix double mapping al->addr for children without self period perf srcline: Fix memory leak in addr2inlines()
perf srcline: Show correct function name for srcline of callchains
tools/include/uapi/linux/kcmp.h | 27 +++++ tools/include/uapi/linux/prctl.h | 200 +++++++++++++++++++++++++++++++ tools/perf/Documentation/perf-script.txt | 4 + tools/perf/Makefile.perf | 22 +++- tools/perf/builtin-annotate.c | 10 +- tools/perf/builtin-buildid-cache.c | 8 +- tools/perf/builtin-buildid-list.c | 16 +-- tools/perf/builtin-c2c.c | 10 +- tools/perf/builtin-diff.c | 18 +-- tools/perf/builtin-evlist.c | 12 +- tools/perf/builtin-inject.c | 36 +++--- tools/perf/builtin-kmem.c | 8 +- tools/perf/builtin-kvm.c | 14 ++- tools/perf/builtin-lock.c | 12 +- tools/perf/builtin-mem.c | 12 +- tools/perf/builtin-record.c | 50 ++++---- tools/perf/builtin-report.c | 14 +-- tools/perf/builtin-sched.c | 24 ++-- tools/perf/builtin-script.c | 169 ++++++++++++++++++++++---- tools/perf/builtin-stat.c | 39 +++--- tools/perf/builtin-timechart.c | 14 ++- tools/perf/builtin-trace.c | 40 ++++++- tools/perf/check-headers.sh | 2 + tools/perf/tests/topology.c | 22 ++-- tools/perf/trace/beauty/Build | 2 + tools/perf/trace/beauty/beauty.h | 18 +++ tools/perf/trace/beauty/kcmp.c | 44 +++++++ tools/perf/trace/beauty/kcmp_type.sh | 10 ++ tools/perf/trace/beauty/prctl.c | 82 +++++++++++++ tools/perf/trace/beauty/prctl_option.sh | 17 +++ tools/perf/util/auxtrace.c | 4 +- tools/perf/util/callchain.c | 5 +- tools/perf/util/data-convert-bt.c | 12 +- tools/perf/util/data.c | 94 ++++++++------- tools/perf/util/data.h | 38 +++--- tools/perf/util/evsel.h | 3 + tools/perf/util/header.c | 20 ++-- tools/perf/util/intel-bts.c | 6 +- tools/perf/util/intel-pt.c | 6 +- tools/perf/util/jit.h | 2 +- tools/perf/util/jitdump.c | 10 +- tools/perf/util/session.c | 44 +++---- tools/perf/util/session.h | 4 +- tools/perf/util/srcline.c | 102 +++++++++------- tools/perf/util/stat-shadow.c | 48 ++++---- tools/perf/util/stat.c | 24 ++-- tools/perf/util/stat.h | 2 +- 47 files changed, 999 insertions(+), 381 deletions(-) create mode 100644 tools/include/uapi/linux/kcmp.h create mode 100644 tools/include/uapi/linux/prctl.h create mode 100644 tools/perf/trace/beauty/kcmp.c create mode 100755 tools/perf/trace/beauty/kcmp_type.sh create mode 100644 tools/perf/trace/beauty/prctl.c create mode 100755 tools/perf/trace/beauty/prctl_option.sh
Test results:
The first ones are container (docker) based builds of tools/perf with and without libelf support. Where clang is available, it is also used to build perf with/without libelf.
The objtool and samples/bpf/ builds are disabled now that I'm switching from using the sources in a local volume to fetching them from a http server to build it inside the container, to make it easier to build in a container cluster. Those will come back later.
Several are cross builds, the ones with -x-ARCH and the android one, and those may not have all the features built, due to lack of multi-arch devel packages, available and being used so far on just a few, like debian:experimental-x-{arm64,mipsel}.
The 'perf test' one will perform a variety of tests exercising tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands with a variety of command line event specifications to then intercept the sys_perf_event syscall to check that the perf_event_attr fields are set up as expected, among a variety of other unit tests.
Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/ with a variety of feature sets, exercising the build with an incomplete set of features as well as with a complete one. It is planned to have it run on each of the containers mentioned above, using some container orchestration infrastructure. Get in contact if interested in helping having this in place.
# dm 1 alpine:3.4: Ok gcc (Alpine 5.3.0) 5.3.0 2 alpine:3.5: Ok gcc (Alpine 6.2.1) 6.2.1 20160822 3 alpine:3.6: Ok gcc (Alpine 6.3.0) 6.3.0 4 alpine:edge: Ok gcc (Alpine 6.4.0) 6.4.0 5 android-ndk:r12b-arm: Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 6 android-ndk:r15c-arm: Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 7 centos:5: Ok gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55) 8 centos:6: Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) 9 centos:7: Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) 10 debian:7: Ok gcc (Debian 4.7.2-5) 4.7.2 11 debian:8: Ok gcc (Debian 4.9.2-10) 4.9.2 12 debian:9: Ok gcc (Debian 6.3.0-18) 6.3.0 20170516 13 debian:experimental: Ok gcc (Debian 7.2.0-11) 7.2.0 14 debian:experimental-x-arm64: Ok aarch64-linux-gnu-gcc (Debian 7.2.0-6) 7.2.0 15 debian:experimental-x-mips: Ok mips-linux-gnu-gcc (Debian 7.2.0-6) 7.2.0 16 debian:experimental-x-mips64: Ok mips64-linux-gnuabi64-gcc (Debian 7.2.0-6) 7.2.0 17 debian:experimental-x-mipsel: Ok mipsel-linux-gnu-gcc (Debian 7.2.0-6) 7.2.0 18 fedora:20: Ok gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) 19 fedora:21: Ok gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) 20 fedora:22: Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 21 fedora:23: Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 22 fedora:24: Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) 23 fedora:24-x-ARC-uClibc: Ok arc-linux-gcc (ARCompact ISA Linux uClibc toolchain 2017.09-rc2) 7.1.1 20170710 24 fedora:25: Ok gcc (GCC) 6.4.1 20170727 (Red Hat 6.4.1-1) 25 fedora:26: Ok gcc (GCC) 7.2.1 20170915 (Red Hat 7.2.1-2) 26 fedora:rawhide: Ok gcc (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1) 27 mageia:5: Ok gcc (GCC) 4.9.2 28 mageia:6: Ok gcc (Mageia 5.4.0-5.mga6) 5.4.0 29 opensuse:42.1: Ok gcc (SUSE Linux) 4.8.5 30 opensuse:42.2: Ok gcc (SUSE Linux) 4.8.5 31 opensuse:42.3: Ok gcc (SUSE Linux) 4.8.5 32 opensuse:tumbleweed: Ok gcc (SUSE Linux) 7.2.1 20170901 [gcc-7-branch revision 251580] 33 oraclelinux:6: Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) 34 oraclelinux:7: Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) 35 ubuntu:12.04.5: Ok gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 36 ubuntu:14.04.4: Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 37 ubuntu:14.04.4-x-linaro-arm64: Ok aarch64-linux-gnu-gcc (Linaro GCC 5.4-2017.05) 5.4.1 20170404 38 ubuntu:15.04: Ok gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 39 ubuntu:15.10: Ok gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 40 ubuntu:16.04: Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609 41 ubuntu:16.04-x-arm: Ok arm-linux-gnueabihf-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 42 ubuntu:16.04-x-arm64: Ok aarch64-linux-gnu-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 43 ubuntu:16.04-x-powerpc: Ok powerpc-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 44 ubuntu:16.04-x-powerpc64: Ok powerpc64-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609 45 ubuntu:16.04-x-powerpc64el: Ok powerpc64le-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 46 ubuntu:16.04-x-s390: Ok s390x-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 47 ubuntu:16.10: Ok gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005 48 ubuntu:17.04: Ok gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406 49 ubuntu:17.10: Ok gcc (Ubuntu 7.2.0-8ubuntu3) 7.2.0 #
# uname -a Linux jouet 4.14.0-rc6+ #1 SMP Tue Oct 31 14:43:51 -03 2017 x86_64 x86_64 x86_64 GNU/Linux # perf test 1: vmlinux symtab matches kallsyms : Ok 2: Detect openat syscall event : Ok 3: Detect openat syscall event on all cpus : Ok 4: Read samples using the mmap interface : Ok 5: Test data source output : Ok 6: Parse event definition strings : Ok 7: Simple expression parser : Ok 8: PERF_RECORD_* events & perf_sample fields : Ok 9: Parse perf pmu format : Ok 10: DSO data read : Ok 11: DSO data cache : Ok 12: DSO data reopen : Ok 13: Roundtrip evsel->name : Ok 14: Parse sched tracepoints fields : Ok 15: syscalls:sys_enter_openat event fields : Ok 16: Setup struct perf_event_attr : Ok 17: Match and link multiple hists : Ok 18: 'import perf' in python : Ok 19: Breakpoint overflow signal handler : Ok 20: Breakpoint overflow sampling : Ok 21: Number of exit events of a simple workload : Ok 22: Software clock events period values : Ok 23: Object code reading : Ok 24: Sample parsing : Ok 25: Use a dummy software event to keep tracking : Ok 26: Parse with no sample_id_all bit set : Ok 27: Filter hist entries : Ok 28: Lookup mmap thread : Ok 29: Share thread mg : Ok 30: Sort output of hist entries : Ok 31: Cumulate child hist entries : Ok 32: Track with sched_switch : Ok 33: Filter fds with revents mask in a fdarray : Ok 34: Add fd to a fdarray, making it autogrow : Ok 35: kmod_path__parse : Ok 36: Thread map : Ok 37: LLVM search and compile : 37.1: Basic BPF llvm compile : Ok 37.2: kbuild searching : Ok 37.3: Compile source for BPF prologue generation : Ok 37.4: Compile source for BPF relocation : Ok 38: Session topology : Ok 39: BPF filter : 39.1: Basic BPF filtering : Ok 39.2: BPF pinning : Ok 39.3: BPF prologue generation : Ok 39.4: BPF relocation checker : Ok 40: Synthesize thread map : Ok 41: Remove thread map : Ok 42: Synthesize cpu map : Ok 43: Synthesize stat config : Ok 44: Synthesize stat : Ok 45: Synthesize stat round : Ok 46: Synthesize attr update : Ok 47: Event times : Ok 48: Read backward ring buffer : Ok 49: Print cpu map : Ok 50: Probe SDT events : Ok 51: is_printable_array : Ok 52: Print bitmap : Ok 53: perf hooks : Ok 54: builtin clang support : Skip (not compiled in) 55: unit_number__scnprintf : Ok 56: x86 rdpmc : Ok 57: Convert perf time to TSC : Ok 58: DWARF unwind : Ok 59: x86 instruction decoder - new instructions : Ok 60: Use vfs_getname probe to get syscall args filenames : Ok 61: probe libc's inet_pton & backtrace it with ping : Ok 62: Check open filename arg using perf trace + vfs_getname: Ok 63: Add vfs_getname probe to get syscall args filenames : Ok #
$ make -C tools/perf build-test
make: Entering directory '/home/acme/git/linux/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_clean_all_O: make clean all
make_no_libnuma_O: make NO_LIBNUMA=1
make_no_demangle_O: make NO_DEMANGLE=1
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_gtk2_O: make NO_GTK2=1
make_static_O: make LDFLAGS=-static
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_pure_O: make
make_no_libaudit_O: make NO_LIBAUDIT=1
make_debug_O: make DEBUG=1
make_no_newt_O: make NO_NEWT=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_no_slang_O: make NO_SLANG=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_install_prefix_O: make install prefix=/tmp/krava
make_no_libbionic_O: make NO_LIBBIONIC=1
make_doc_O: make doc
make_tags_O: make tags
make_with_babeltrace_O: make LIBBABELTRACE=1
make_no_libelf_O: make NO_LIBELF=1
make_no_libpython_O: make NO_LIBPYTHON=1
make_help_O: make help
make_no_libbpf_O: make NO_LIBBPF=1
make_perf_o_O: make perf.o
make_no_libunwind_O: make NO_LIBUNWIND=1
make_install_O: make install
make_util_map_o_O: make util/map.o
make_install_bin_O: make install-bin
make_no_backtrace_O: make NO_BACKTRACE=1
make_no_libperl_O: make NO_LIBPERL=1
make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
OK
make: Leaving directory '/home/acme/git/linux/tools/perf'
$Arnaldo Carvalho de Melo
maintainerPATCH 1/19 perf script: Add a few missing conversions to fprintf style
From: Arnaldo Carvalho de Melo <[email protected]>
In a1a587073ccd ("perf script: Use fprintf like printing uniformly") there were a few cases that were missed, fix it.
--- tools/perf/builtin-script.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
tools/perf/builtin-script.c +4 -5
@@ -1447,7 +1447,7 @@ static void process_event(struct perf_script *script,perf_sample__fprintf_start (sample, thread, evsel, fp);if (PRINT_FIELD (PERIOD )) -printf ("%10" PRIu64" " , sample->period); +fprintf (fp,"%10" PRIu64" " , sample->period);if (PRINT_FIELD (EVNAME )) {const char *evname =perf_evsel__name (evsel);
@@ -1455,8 +1455,7 @@ static void process_event(struct perf_script *script,if (!script->name_width) script->name_width =perf_evlist__max_name_len (script->session->evlist); -printf ("%*s: " , script->name_width, - evname ? evname :"[unknown]" ); +fprintf (fp,"%*s: " , script->name_width, evname ?:"[unknown]" ); }if (print_flags)
@@ -1513,8 +1512,8 @@ static void process_event(struct perf_script *script,perf_sample__fprintf_insn (sample, attr, thread, machine, fp);if (PRINT_FIELD (PHYS_ADDR )) -printf ("%16" PRIx64, sample->phys_addr); -printf ("\n" ); +fprintf (fp,"%16" PRIx64, sample->phys_addr); +fprintf (fp,"\n" ); }static struct scripting_ops *scripting_ops;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 2/19 perf script: Use pr_debug where appropriate
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We have facilities for reporting unexpected, unlikely errors, use them.
--- tools/perf/builtin-script.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
tools/perf/builtin-script.c +6 -7
@@ -769,27 +769,26 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,* but the exit is not. Let the caller patch it up. */ if (kernel !=machine__kernel_ip (machine, end)) { -printf ("\tblock %" PRIx64"-%" PRIx64" transfers between kernel and user\n" , - start, end); +pr_debug ("\tblock %" PRIx64"-%" PRIx64" transfers between kernel and user\n" , start, end);return -ENXIO ; }memset (&al,0 ,sizeof (al));if (end - start >MAXBB -MAXINSN ) {if (last) -printf ("\tbrstack does not reach to final jump (%" PRIx64"-%" PRIx64")\n" , start, end); +pr_debug ("\tbrstack does not reach to final jump (%" PRIx64"-%" PRIx64")\n" , start, end);else -printf ("\tblock %" PRIx64"-%" PRIx64" (%" PRIu64") too long to dump\n" , start, end, end - start); +pr_debug ("\tblock %" PRIx64"-%" PRIx64" (%" PRIu64") too long to dump\n" , start, end, end - start);return 0 ; }thread__find_addr_map (thread, *cpumode,MAP__FUNCTION , start, &al);if (!al.map || !al.map->dso) { -printf ("\tcannot resolve %" PRIx64"-%" PRIx64"\n" , start, end); +pr_debug ("\tcannot resolve %" PRIx64"-%" PRIx64"\n" , start, end);return 0 ; }if (al.map->dso->data.status ==DSO_DATA_STATUS_ERROR ) { -printf ("\tcannot resolve %" PRIx64"-%" PRIx64"\n" , start, end); +pr_debug ("\tcannot resolve %" PRIx64"-%" PRIx64"\n" , start, end);return 0 ; }
@@ -802,7 +801,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, *is64bit = al.map->dso->is_64_bit;if (len <=0 ) -printf ("\tcannot fetch code for block at %" PRIx64"-%" PRIx64"\n" , +pr_debug ("\tcannot fetch code for block at %" PRIx64"-%" PRIx64"\n" , start, end);return len; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 3/19 perf script: Use event_format__fprintf()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Another case where we a1a587073ccd ("perf script: Use fprintf like printing uniformly") forgot to redirect output to the FILE descriptor, fix this too.
--- tools/perf/builtin-script.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
tools/perf/builtin-script.c +4 -3
@@ -1465,9 +1465,10 @@ static void process_event(struct perf_script *script,return ; } -if (PRINT_FIELD (TRACE )) -event_format__print (evsel->tp_format, sample->cpu, - sample->raw_data, sample->raw_size); +if (PRINT_FIELD (TRACE )) { +event_format__fprintf (evsel->tp_format, sample->cpu, + sample->raw_data, sample->raw_size, fp); + }if (attr->type ==PERF_TYPE_SYNTH &&PRINT_FIELD (SYNTH ))perf_sample__fprintf_synth (sample, evsel, fp);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 4/19 perf evsel: Restore evsel->priv as a tool private area
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
When we started using it for stats and did it not just in builtin-stat.c, but also for builtin-script.c, then it stopped being a tool private area, so introduce a new pointer for these stats and leave ->priv to its original purpose.
--- tools/perf/builtin-stat.c | 4 ++-- tools/perf/util/evsel.h | 3 +++ tools/perf/util/stat.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-)
tools/perf/builtin-stat.c +2 -2
@@ -845,7 +845,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)if (run_count ==1 )return ; - ps = evsel->priv; + ps = evsel->stats;print_noise_pct (stddev_stats (&ps->res_stats[0 ]), avg); }
@@ -1432,7 +1432,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data, bool first __maybe_unused) {struct caggr_data *cd = data; -struct perf_stat_evsel *ps = counter->priv; +struct perf_stat_evsel *ps = counter->stats; cd->avg +=avg_stats (&ps->res_stats[0 ]); cd->avg_enabled +=avg_stats (&ps->res_stats[1 ]);
tools/perf/util/evsel.h +3 -0
@@ -68,6 +68,8 @@ struct perf_evsel_config_term { } val; }; +struct perf_stat_evsel ; +/** struct perf_evsel - event selector * * @evlist - evlist this evsel is in, if it is in one.
@@ -101,6 +103,7 @@ struct perf_evsel {const char *unit;struct event_format *tp_format;off_t id_offset; +struct perf_stat_evsel *stats;void *priv;u64 db_id;struct cgroup_sel *cgrp;
tools/perf/util/stat.c +8 -8
@@ -69,7 +69,7 @@ double rel_stddev_stats(double stddev, double avg)bool __perf_evsel_stat__is (struct perf_evsel *evsel,enum perf_stat_evsel_id id) { -struct perf_stat_evsel *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->stats;return ps->id == id; }
@@ -93,7 +93,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {void perf_stat_evsel_id_init (struct perf_evsel *evsel) { -struct perf_stat_evsel *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->stats;int i;/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -109,7 +109,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)static void perf_evsel__reset_stat_priv (struct perf_evsel *evsel) {int i; -struct perf_stat_evsel *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->stats;for (i =0 ; i <3 ; i++)init_stats (&ps->res_stats[i]);
@@ -119,8 +119,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)static int perf_evsel__alloc_stat_priv (struct perf_evsel *evsel) { - evsel->priv =zalloc (sizeof (struct perf_stat_evsel )); -if (evsel->priv ==NULL ) + evsel->stats =zalloc (sizeof (struct perf_stat_evsel )); +if (evsel->stats ==NULL )return -ENOMEM ;perf_evsel__reset_stat_priv (evsel);return 0 ;
@@ -128,11 +128,11 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)static void perf_evsel__free_stat_priv (struct perf_evsel *evsel) { -struct perf_stat_evsel *ps = evsel->priv; +struct perf_stat_evsel *ps = evsel->stats;if (ps)free (ps->group_data); -zfree (&evsel->priv); +zfree (&evsel->stats); } static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
@@ -318,7 +318,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, struct perf_evsel *counter) {struct perf_counts_values *aggr = &counter->counts->aggr; -struct perf_stat_evsel *ps = counter->priv; +struct perf_stat_evsel *ps = counter->stats;u64 *count = counter->counts->aggr.values;u64 val;int i, ret;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 5/19 perf script: Allow creating per-event dump files
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Introduce a new option to dump trace output to files named by the monitored events and update perf-script documentation accordingly.
Shown below is output of perf script command with the newly introduced option.
$ perf record -e cycles -e cs -ag -- sleep 1
$ perf script --per-event-dump
$ ls
perf.data.cycles.dump perf.data.cs.dumpWithout per-event-dump support, drawing flamegraphs for different events would require post processing to separate events. You can monitor only one event at a time if you want to get flamegraphs for different events. Using this option, you can get the trace output files named by the monitored events, and could draw flamegraphs according to the event's name.
--- tools/perf/Documentation/perf-script.txt | 4 +++ tools/perf/builtin-script.c | 59 +++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-script.txt +4 -0
@@ -325,6 +325,10 @@ include::itrace.txt[] Set the maximum number of program blocks to print with brstackasm for each sample. +--per-event-dump:: + Create per event files with a "perf.data.EVENT.dump" name instead of + printing to stdout, useful, for instance, for generating flamegraphs. + --inline:: If a callgraph address belongs to an inlined function, the inline stack will be printed. Each entry has function name and file/line. Enabled by
tools/perf/builtin-script.c +58 -1
91 lines not on this page · raw message
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 6/19 tools include uapi: Grab a copy of linux/prctl.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We will use it to generate tables for beautifying prctl's 'option' arg and some of the others eventually.
--- tools/include/uapi/linux/prctl.h | 200 +++++++++++++++++++++++++++++++++++++++ tools/perf/check-headers.sh | 1 + 2 files changed, 201 insertions(+) create mode 100644 tools/include/uapi/linux/prctl.h
tools/include/uapi/linux/prctl.h new file +200 -0
@@ -0,0 +1,200 @@ +#ifndef _LINUX_PRCTL_H +#define _LINUX_PRCTL_H + +#include <linux/types.h> + +/* Values to pass as first argument to prctl() */ + +#define PR_SET_PDEATHSIG 1/* Second arg is a signal */ +#define PR_GET_PDEATHSIG 2/* Second arg is a ptr to return the signal */ + +/* Get/set current->mm->dumpable */ +#define PR_GET_DUMPABLE 3 +#define PR_SET_DUMPABLE 4 + +/* Get/set unaligned access control bits (if meaningful) */ +#define PR_GET_UNALIGN 5 +#define PR_SET_UNALIGN 6 +# define PR_UNALIGN_NOPRINT 1/* silently fix up unaligned user accesses */ +# define PR_UNALIGN_SIGBUS 2/* generate SIGBUS on unaligned user access */ + +/* Get/set whether or not to drop capabilities on setuid() away from +* uid 0 (as per security/commoncap.c) */ +#define PR_GET_KEEPCAPS 7 +#define PR_SET_KEEPCAPS 8 + +/* Get/set floating-point emulation control bits (if meaningful) */ +#define PR_GET_FPEMU 9 +#define PR_SET_FPEMU 10 +# define PR_FPEMU_NOPRINT 1/* silently emulate fp operations accesses */ +# define PR_FPEMU_SIGFPE 2/* don't emulate fp operations, send SIGFPE instead */ + +/* Get/set floating-point exception mode (if meaningful) */ +#define PR_GET_FPEXC 11 +#define PR_SET_FPEXC 12 +# define PR_FP_EXC_SW_ENABLE 0x80/* Use FPEXC for FP exception enables */ +# define PR_FP_EXC_DIV 0x010000/* floating point divide by zero */ +# define PR_FP_EXC_OVF 0x020000/* floating point overflow */ +# define PR_FP_EXC_UND 0x040000/* floating point underflow */ +# define PR_FP_EXC_RES 0x080000/* floating point inexact result */ +# define PR_FP_EXC_INV 0x100000/* floating point invalid operation */ +# define PR_FP_EXC_DISABLED 0/* FP exceptions disabled */ +# define PR_FP_EXC_NONRECOV 1/* async non-recoverable exc. mode */ +# define PR_FP_EXC_ASYNC 2/* async recoverable exception mode */ +# define PR_FP_EXC_PRECISE 3/* precise exception mode */ + +/* Get/set whether we use statistical process timing or accurate timestamp +* based process timing */ +#define PR_GET_TIMING 13 +#define PR_SET_TIMING 14 +# define PR_TIMING_STATISTICAL 0/* Normal, traditional, +statistical process timing */ +# define PR_TIMING_TIMESTAMP 1/* Accurate timestamp based +process timing */ + +#define PR_SET_NAME 15/* Set process name */ +#define PR_GET_NAME 16/* Get process name */ + +/* Get/set process endian */ +#define PR_GET_ENDIAN 19 +#define PR_SET_ENDIAN 20 +# define PR_ENDIAN_BIG 0 +# define PR_ENDIAN_LITTLE 1/* True little endian mode */ +# define PR_ENDIAN_PPC_LITTLE 2/* "PowerPC" pseudo little endian */ + +/* Get/set process seccomp mode */ +#define PR_GET_SECCOMP 21 +#define PR_SET_SECCOMP 22 + +/* Get/set the capability bounding set (as per security/commoncap.c) */ +#define PR_CAPBSET_READ 23 +#define PR_CAPBSET_DROP 24 + +/* Get/set the process' ability to use the timestamp counter instruction */ +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +# define PR_TSC_ENABLE 1/* allow the use of the timestamp counter */ +# define PR_TSC_SIGSEGV 2/* throw a SIGSEGV instead of reading the TSC */ + +/* Get/set securebits (as per security/commoncap.c) */ +#define PR_GET_SECUREBITS 27 +#define PR_SET_SECUREBITS 28 + +/* +* Get/set the timerslack as used by poll/select/nanosleep +* A value of 0 means "use default" +*/ +#define PR_SET_TIMERSLACK 29 +#define PR_GET_TIMERSLACK 30 + +#define PR_TASK_PERF_EVENTS_DISABLE 31 +#define PR_TASK_PERF_EVENTS_ENABLE 32 + +/* +* Set early/late kill mode for hwpoison memory corruption. +* This influences when the process gets killed on a memory corruption. +*/ +#define PR_MCE_KILL 33 +# define PR_MCE_KILL_CLEAR 0 +# define PR_MCE_KILL_SET 1 + +# define PR_MCE_KILL_LATE 0 +# define PR_MCE_KILL_EARLY 1 +# define PR_MCE_KILL_DEFAULT 2 + +#define PR_MCE_KILL_GET 34 + +/* +* Tune up process memory map specifics. +*/ +#define PR_SET_MM 35 +# define PR_SET_MM_START_CODE 1 +# define PR_SET_MM_END_CODE 2 +# define PR_SET_MM_START_DATA 3 +# define PR_SET_MM_END_DATA 4 +# define PR_SET_MM_START_STACK 5 +# define PR_SET_MM_START_BRK 6 +# define PR_SET_MM_BRK 7 +# define PR_SET_MM_ARG_START 8 +# define PR_SET_MM_ARG_END 9 +# define PR_SET_MM_ENV_START 10 +# define PR_SET_MM_ENV_END 11 +# define PR_SET_MM_AUXV 12 +# define PR_SET_MM_EXE_FILE 13 +# define PR_SET_MM_MAP 14 +# define PR_SET_MM_MAP_SIZE 15 + +/* +* This structure provides new memory descriptor +* map which mostly modifies /proc/pid/stat[m] +* output for a task. This mostly done in a +* sake of checkpoint/restore functionality. +*/ +struct prctl_mm_map { +__u64 start_code;/* code section bounds */ +__u64 end_code; +__u64 start_data;/* data section bounds */ +__u64 end_data; +__u64 start_brk;/* heap for brk() syscall */ +__u64 brk; +__u64 start_stack;/* stack starts at */ +__u64 arg_start;/* command line arguments bounds */ +__u64 arg_end; +__u64 env_start;/* environment variables bounds */ +__u64 env_end; +__u64 *auxv;/* auxiliary vector */ +__u32 auxv_size;/* vector size */ +__u32 exe_fd;/* /proc/$pid/exe link file */ +}; + +/* +* Set specific pid that is allowed to ptrace the current task. +* A value of 0 mean "no process". +*/ +#define PR_SET_PTRACER 0x59616d61 +# define PR_SET_PTRACER_ANY ((unsigned long)-1) + +#define PR_SET_CHILD_SUBREAPER 36 +#define PR_GET_CHILD_SUBREAPER 37 + +/* +* If no_new_privs is set, then operations that grant new privileges (i.e. +* execve) will either fail or not grant them. This affects suid/sgid, +* file capabilities, and LSMs. +* +* Operations that merely manipulate or drop existing privileges (setresuid, +* capset, etc.) will still work. Drop those privileges if you want them gone. +* +* Changing LSM security domain is considered a new privilege. So, for example, +* asking selinux for a specific new context (e.g. with runcon) will result +* in execve returning -EPERM. +* +* See Documentation/prctl/no_new_privs.txt for more details. +*/ +#define PR_SET_NO_NEW_PRIVS 38 +#define PR_GET_NO_NEW_PRIVS 39 + +#define PR_GET_TID_ADDRESS 40 + +#define PR_SET_THP_DISABLE 41 +#define PR_GET_THP_DISABLE 42 + +/* +* Tell the kernel to start/stop helping userspace manage bounds tables. +*/ +#define PR_MPX_ENABLE_MANAGEMENT 43 +#define PR_MPX_DISABLE_MANAGEMENT 44 + +#define PR_SET_FP_MODE 45 +#define PR_GET_FP_MODE 46 +# define PR_FP_MODE_FR (1 << 0)/* 64b FP registers */ +# define PR_FP_MODE_FRE (1 << 1)/* 32b compatibility */ + +/* Control the ambient capability set */ +#define PR_CAP_AMBIENT 47 +# define PR_CAP_AMBIENT_IS_SET 1 +# define PR_CAP_AMBIENT_RAISE 2 +# define PR_CAP_AMBIENT_LOWER 3 +# define PR_CAP_AMBIENT_CLEAR_ALL 4 + +#endif /* _LINUX_PRCTL_H */
tools/perf/check-headers.sh +1 -0
@@ -6,6 +6,7 @@ include/uapi/drm/i915_drm.h include/uapi/linux/fcntl.h include/uapi/linux/kvm.h include/uapi/linux/perf_event.h +include/uapi/linux/prctl.h include/uapi/linux/sched.h include/uapi/linux/stat.h include/uapi/linux/vhost.h
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 7/19 perf trace beauty prctl: Generate 'option' string table from kernel headers
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is one more case where the way that syscall parameter values are defined in kernel headers are easy to parse using a shell script that will then generate the string table that gets used by the prctl 'option' argument beautifier.
This way as soon as the header syncronization mechanism in perf's build system detects a change in a copy of a kernel ABI header and that file is syncronized, we get 'perf trace' updated automagically.
Further work needed for the PR_SET_ values, as well for using eBPF to copy the non-integer arguments to/from the kernel.
E.g.: System wide prctl tracing:
# perf trace -e prctl 1668.028 ( 0.025 ms): TaskSchedulerR/10649 prctl(option: SET_NAME, arg2: 0x2b61d5db15d0) = 0 3365.663 ( 0.018 ms): chrome/10650 prctl(option: SET_SECCOMP, arg2: 2, arg4: 8 ) = -1 EFAULT Bad address 3366.585 ( 0.010 ms): chrome/10650 prctl(option: SET_NO_NEW_PRIVS, arg2: 1 ) = 0 3367.173 ( 0.009 ms): TaskSchedulerR/10652 prctl(option: SET_NAME, arg2: 0x2b61d2aaa300) = 0 3367.222 ( 0.003 ms): TaskSchedulerR/10653 prctl(option: SET_NAME, arg2: 0x2b61d2aaa1e0) = 0 3367.244 ( 0.002 ms): TaskSchedulerR/10654 prctl(option: SET_NAME, arg2: 0x2b61d2aaa0c0) = 0 3367.265 ( 0.002 ms): TaskSchedulerR/10655 prctl(option: SET_NAME, arg2: 0x2b61d2ac7f90) = 0 3367.281 ( 0.002 ms): Chrome_ChildIO/10656 prctl(option: SET_NAME, arg2: 0x7efbe406bb11) = 0 3367.220 ( 0.004 ms): TaskSchedulerS/10651 prctl(option: SET_NAME, arg2: 0x2b61d2ac1be0) = 0 3370.906 ( 0.010 ms): GpuMemoryThrea/10657 prctl(option: SET_NAME, arg2: 0x7efbe386ab11) = 0 3370.983 ( 0.003 ms): File/10658 prctl(option: SET_NAME, arg2: 0x7efbe3069b11 ) = 0 3384.272 ( 0.020 ms): Compositor/10659 prctl(option: SET_NAME, arg2: 0x7efbe2868b11 ) = 0 3612.091 ( 0.012 ms): DOM Worker/11489 prctl(option: SET_NAME, arg2: 0x7f49ab97ebf2 ) = 0 <SNIP> 4512.437 ( 0.004 ms): (sa1)/11490 prctl(option: SET_NAME, arg2: 0x7ffca15af844 ) = 0 4512.468 ( 0.002 ms): (sa1)/11490 prctl(option: SET_MM, arg2: ARG_START, arg3: 0x7f5cb7c81000) = 0 4512.472 ( 0.001 ms): (sa1)/11490 prctl(option: SET_MM, arg2: ARG_END, arg3: 0x7f5cb7c81006) = 0 4514.667 ( 0.002 ms): (sa1)/11490 prctl(option: GET_SECUREBITS ) = 0
--- tools/perf/Makefile.perf | 13 +++++- tools/perf/builtin-trace.c | 5 +- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 9 ++++ tools/perf/trace/beauty/prctl.c | 82 +++++++++++++++++++++++++++++++++ tools/perf/trace/beauty/prctl_option.sh | 17 +++++++ 6 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 tools/perf/trace/beauty/prctl.c create mode 100755 tools/perf/trace/beauty/prctl_option.sh
tools/perf/Makefile.perf +11 -2
@@ -448,6 +448,13 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh $(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ +prctl_option_array := $(beauty_outdir)/prctl_option_array.c +prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/ +prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh + +$(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl) + $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@ + all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -549,7 +556,8 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc $(kvm_ioctl_array) \ $(vhost_virtio_ioctl_array) \ $(madvise_behavior_array) \ - $(perf_ioctl_array) + $(perf_ioctl_array) \ + $(prctl_option_array) $(OUTPUT)%.o: %.c prepare FORCE $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -829,7 +837,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea $(OUTPUT)$(sndrv_pcm_ioctl_array) \ $(OUTPUT)$(kvm_ioctl_array) \ $(OUTPUT)$(vhost_virtio_ioctl_array) \ - $(OUTPUT)$(perf_ioctl_array) + $(OUTPUT)$(perf_ioctl_array) \ + $(OUTPUT)$(prctl_option_array) $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean #
tools/perf/builtin-trace.c +4 -1
@@ -578,7 +578,6 @@ static struct syscall_fmt { } syscall_fmts[] = { { .name = "access", .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, - { .name = "arch_prctl", .alias = "prctl", }, { .name = "bpf", .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, { .name = "brk", .hexret = true,
@@ -703,6 +702,10 @@ static struct syscall_fmt { [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, }, { .name = "poll", .timeout = true, }, { .name = "ppoll", .timeout = true, }, + { .name = "prctl", .alias = "arch_prctl", + .arg = { [0] = { .scnprintf = SCA_PRCTL_OPTION, /* option */ }, + [1] = { .scnprintf = SCA_PRCTL_ARG2, /* arg2 */ }, + [2] = { .scnprintf = SCA_PRCTL_ARG3, /* arg3 */ }, }, }, { .name = "pread", .alias = "pread64", }, { .name = "preadv", .alias = "pread", }, { .name = "prlimit64",
tools/perf/trace/beauty/Build +1 -0
@@ -4,4 +4,5 @@ ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) libperf-y += ioctl.o endif libperf-y += pkey_alloc.o +libperf-y += prctl.o libperf-y += statx.o
tools/perf/trace/beauty/beauty.h +9 -0
@@ -84,6 +84,15 @@ size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, stsize_t syscall_arg__scnprintf_open_flags (char *bf,size_t size,struct syscall_arg *arg);#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags +size_t syscall_arg__scnprintf_prctl_option (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_PRCTL_OPTION syscall_arg__scnprintf_prctl_option + +size_t syscall_arg__scnprintf_prctl_arg2 (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_PRCTL_ARG2 syscall_arg__scnprintf_prctl_arg2 + +size_t syscall_arg__scnprintf_prctl_arg3 (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 +size_t syscall_arg__scnprintf_statx_flags (char *bf,size_t size,struct syscall_arg *arg);#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
tools/perf/trace/beauty/prctl.c new file +82 -0
82 lines not on this page · raw message
tools/perf/trace/beauty/prctl_option.sh new file +17 -0
@@ -0,0 +1,17 @@ +#!/bin/sh + +header_dir=$1 + +printf "static const char *prctl_options[] = {\n" +regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*' +egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \ + sed -r "s/$regex/\2 \1/g" | \ + sort -n | xargs printf "\t[%s] = \"%s\",\n" +printf "};\n" + +printf "static const char *prctl_set_mm_options[] = {\n" +regex='^#[[:space:]]+define[[:space:]]+PR_SET_MM_(\w+)[[:space:]]*([[:digit:]]+).*' +egrep $regex ${header_dir}/prctl.h | \ + sed -r "s/$regex/\2 \1/g" | \ + sort -n | xargs printf "\t[%s] = \"%s\",\n" +printf "};\n"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 8/19 perf script: Print information about per-event-dump files
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
For a file generated by "perf sched record sleep 50":
# perf script --per-event-dump [ perf script: Wrote 23.121 MB perf.data.sched:sched_switch.dump (206015 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_wait.dump (0 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_sleep.dump (0 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_iowait.dump (0 samples) ] [ perf script: Wrote 17.680 MB perf.data.sched:sched_stat_runtime.dump (129342 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_process_fork.dump (24 samples) ] [ perf script: Wrote 11.328 MB perf.data.sched:sched_wakeup.dump (106770 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_wakeup_new.dump (24 samples) ] [ perf script: Wrote 2.477 MB perf.data.sched:sched_migrate_task.dump (20434 samples) ] #
Similar to what is generated by 'perf record'.
--- tools/perf/builtin-script.c | 77 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 8 deletions(-)
tools/perf/builtin-script.c +69 -8
@@ -210,6 +210,51 @@ static struct { }, }; +struct perf_evsel_script { +char *filename; +FILE *fp; +u64 samples; +}; + +static struct perf_evsel_script *perf_evsel_script__new (struct perf_evsel *evsel, +struct perf_data_file *file) +{ +struct perf_evsel_script *es =malloc (sizeof (*es)); + +if (es !=NULL ) { +if (asprintf (&es->filename,"%s.%s.dump" , file->path,perf_evsel__name (evsel)) <0 ) + goto out_free; + es->fp =fopen (es->filename,"w" ); +if (es->fp ==NULL ) + goto out_free_filename; + es->samples =0 ; + } + +return es; +out_free_filename: +zfree (&es->filename); +out_free: +free (es); +return NULL ; +} + +static void perf_evsel_script__delete (struct perf_evsel_script *es) +{ +zfree (&es->filename); +fclose (es->fp); + es->fp =NULL ; +free (es); +} + +static int perf_evsel_script__fprintf (struct perf_evsel_script *es,FILE *fp) +{ +struct stat st; + +fstat (fileno (es->fp), &st); +return fprintf (fp,"[ perf script: Wrote %.3f MB %s (%" PRIu64" samples) ]\n" , + st.st_size /1024.0 /1024.0 , es->filename, es->samples); +} +static inline int output_type (unsigned int type) {switch (type) {
@@ -1439,11 +1484,14 @@ static void process_event(struct perf_script *script,struct thread *thread = al->thread;struct perf_event_attr *attr = &evsel->attr;unsigned int type =output_type (attr->type); -FILE *fp = evsel->priv; +struct perf_evsel_script *es = evsel->priv; +FILE *fp = es->fp;if (output[type].fields ==0 )return ; + ++es->samples; +perf_sample__fprintf_start (sample, thread, evsel, fp);if (PRINT_FIELD (PERIOD ))
@@ -1896,7 +1944,7 @@ static void perf_script__fclose_per_event_dump(struct perf_script *script)evlist__for_each_entry (evlist, evsel) {if (!evsel->priv)break ; -fclose (evsel->priv); +perf_evsel_script__delete (evsel->priv); evsel->priv =NULL ; } }
@@ -1906,10 +1954,7 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script)struct perf_evsel *evsel;evlist__for_each_entry (script->session->evlist, evsel) { -char filename[PATH_MAX ]; -snprintf (filename,sizeof (filename),"%s.%s.dump" , - script->session->file->path,perf_evsel__name (evsel)); - evsel->priv =fopen (filename,"w" ); + evsel->priv =perf_evsel_script__new (evsel, script->session->file);if (evsel->priv ==NULL ) goto out_err_fclose; }
@@ -1924,16 +1969,32 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script)static int perf_script__setup_per_event_dump (struct perf_script *script) {struct perf_evsel *evsel; +static struct perf_evsel_script es_stdout;if (script->per_event_dump)return perf_script__fopen_per_event_dump (script); + es_stdout.fp = stdout; +evlist__for_each_entry (script->session->evlist, evsel) - evsel->priv = stdout; + evsel->priv = &es_stdout;return 0 ; } +static void perf_script__exit_per_event_dump_stats (struct perf_script *script) +{ +struct perf_evsel *evsel; + +evlist__for_each_entry (script->session->evlist, evsel) { +struct perf_evsel_script *es = evsel->priv; + +perf_evsel_script__fprintf (es, stdout); +perf_evsel_script__delete (es); + evsel->priv =NULL ; + } +} +static int __cmd_script (struct perf_script *script) {int ret;
@@ -1963,7 +2024,7 @@ static int __cmd_script(struct perf_script *script) ret =perf_session__process_events (script->session);if (script->per_event_dump) -perf_script__fclose_per_event_dump (script); +perf_script__exit_per_event_dump_stats (script);if (debug_mode)pr_err ("Misordered timestamps: %" PRIu64"\n" , nr_unordered);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 9/19 perf tools: Rename struct perf_data_file to perf_data
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Rename struct perf_data_file to perf_data, because we will add the possibility to have multiple files under perf.data, so the 'perf_data' name fits better.
--- tools/perf/builtin-annotate.c | 10 ++--- tools/perf/builtin-buildid-cache.c | 8 ++-- tools/perf/builtin-buildid-list.c | 8 ++-- tools/perf/builtin-c2c.c | 10 ++--- tools/perf/builtin-diff.c | 18 ++++---- tools/perf/builtin-evlist.c | 4 +- tools/perf/builtin-inject.c | 26 +++++------ tools/perf/builtin-kmem.c | 8 ++-- tools/perf/builtin-kvm.c | 6 +-- tools/perf/builtin-lock.c | 4 +- tools/perf/builtin-mem.c | 4 +- tools/perf/builtin-record.c | 50 ++++++++++----------- tools/perf/builtin-report.c | 14 +++--- tools/perf/builtin-sched.c | 8 ++-- tools/perf/builtin-script.c | 20 ++++----- tools/perf/builtin-stat.c | 32 ++++++------- tools/perf/builtin-timechart.c | 6 +-- tools/perf/builtin-trace.c | 4 +- tools/perf/tests/topology.c | 10 ++--- tools/perf/util/auxtrace.c | 4 +- tools/perf/util/data-convert-bt.c | 6 +-- tools/perf/util/data.c | 92 +++++++++++++++++++------------------- tools/perf/util/data.h | 32 ++++++------- tools/perf/util/header.c | 20 ++++----- tools/perf/util/intel-bts.c | 6 +-- tools/perf/util/intel-pt.c | 6 +-- tools/perf/util/jit.h | 2 +- tools/perf/util/jitdump.c | 10 ++--- tools/perf/util/session.c | 44 +++++++++--------- tools/perf/util/session.h | 4 +- 30 files changed, 238 insertions(+), 238 deletions(-)
tools/perf/builtin-annotate.c +5 -5
@@ -356,7 +356,7 @@ static int __cmd_annotate(struct perf_annotate *ann) }if (total_nr_samples ==0 ) { -ui__error ("The %s file has no samples!\n" , session->file->path); +ui__error ("The %s file has no samples!\n" , session->data->path); goto out; }
@@ -400,7 +400,7 @@ int cmd_annotate(int argc, const char **argv) .ordering_requires_timestamps = true, }, }; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , }; struct option options[] = {
@@ -410,7 +410,7 @@ int cmd_annotate(int argc, const char **argv) "only consider symbols in these dsos"),OPT_STRING ('s' ,"symbol" , &annotate.sym_hist_filter,"symbol" ,"symbol to annotate" ), -OPT_BOOLEAN ('f' ,"force" , &file.force,"don't complain, do it" ), +OPT_BOOLEAN ('f' ,"force" , &data.force,"don't complain, do it" ),OPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show symbol address, etc)" ), OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"),
@@ -482,9 +482,9 @@ int cmd_annotate(int argc, const char **argv)if (quiet)perf_quiet_option (); - file.path = input_name; + data.path = input_name; - annotate.session =perf_session__new (&file, false, &annotate.tool); + annotate.session =perf_session__new (&data, false, &annotate.tool);if (annotate.session ==NULL )return -1 ;
tools/perf/builtin-buildid-cache.c +4 -4
@@ -311,7 +311,7 @@ int cmd_buildid_cache(int argc, const char **argv) *kcore_filename =NULL ;char sbuf[STRERR_BUFSIZE ]; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , };struct perf_session *session =NULL ;
@@ -352,10 +352,10 @@ int cmd_buildid_cache(int argc, const char **argv) nsi =nsinfo__new (ns_id);if (missing_filename) { - file.path = missing_filename; - file.force = force; + data.path = missing_filename; + data.force = force; - session =perf_session__new (&file, false,NULL ); + session =perf_session__new (&data, false,NULL );if (session ==NULL )return -1 ; }
tools/perf/builtin-buildid-list.c +4 -4
@@ -50,7 +50,7 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)static int perf_session__list_build_ids (bool force,bool with_hits) {struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = force,
@@ -63,7 +63,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)if (filename__fprintf_build_id (input_name, stdout) >0 ) goto out; - session =perf_session__new (&file, false, &build_id__mark_dso_hit_ops); + session =perf_session__new (&data, false, &build_id__mark_dso_hit_ops);if (session ==NULL )return -1 ;
@@ -71,7 +71,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)* We take all buildids when the file contains AUX area tracing data * because we do not decode the trace because it would take too long. */ -if (!perf_data_file__is_pipe (&file) && +if (!perf_data__is_pipe (&data) &&perf_header__has_feat (&session->header,HEADER_AUXTRACE )) with_hits = false;
@@ -79,7 +79,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)* in pipe-mode, the only way to get the buildids is to parse * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID */ -if (with_hits ||perf_data_file__is_pipe (&file)) +if (with_hits ||perf_data__is_pipe (&data))perf_session__process_events (session);perf_session__fprintf_dsos_buildid (session, stdout, dso__skip_buildid, with_hits);
tools/perf/builtin-c2c.c +5 -5
@@ -2523,7 +2523,7 @@ static int perf_c2c__report(int argc, const char **argv) {struct perf_session *session;struct ui_progress prog; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , };char callchain_default_opt[] =CALLCHAIN_DEFAULT_OPT ;
@@ -2572,8 +2572,8 @@ static int perf_c2c__report(int argc, const char **argv)if (!input_name || !strlen (input_name)) input_name ="perf.data" ; - file.path = input_name; - file.force = symbol_conf.force; + data.path = input_name; + data.force = symbol_conf.force; err =setup_display (display);if (err)
@@ -2591,7 +2591,7 @@ static int perf_c2c__report(int argc, const char **argv) goto out; } - session =perf_session__new (&file,0 , &c2c.tool); + session =perf_session__new (&data,0 , &c2c.tool);if (session ==NULL ) {pr_debug ("No memory for session\n" ); goto out;
@@ -2611,7 +2611,7 @@ static int perf_c2c__report(int argc, const char **argv) goto out_session;/* No pipe support at the moment. */ -if (perf_data_file__is_pipe (session->file)) { +if (perf_data__is_pipe (session->data)) {pr_debug ("No pipe support at the moment.\n" ); goto out_session; }
tools/perf/builtin-diff.c +9 -9
@@ -47,7 +47,7 @@ struct diff_hpp_fmt {struct data__file {struct perf_session *session; -struct perf_data_file file; +struct perf_data data;int idx;struct hists *hists;struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX ];
@@ -707,7 +707,7 @@ static void data__fprintf(void)data__for_each_file (i, d)fprintf (stdout,"# [%d] %s %s\n" , - d->idx, d->file.path, + d->idx, d->data.path, !d->idx ?"(Baseline)" :"" );fprintf (stdout,"#\n" );
@@ -776,16 +776,16 @@ static int __cmd_diff(void)int ret = -EINVAL , i;data__for_each_file (i, d) { - d->session =perf_session__new (&d->file, false, &tool); + d->session =perf_session__new (&d->data, false, &tool);if (!d->session) { -pr_err ("Failed to open %s\n" , d->file.path); +pr_err ("Failed to open %s\n" , d->data.path); ret =-1 ; goto out_delete; } ret =perf_session__process_events (d->session);if (ret) { -pr_err ("Failed to process %s\n" , d->file.path); +pr_err ("Failed to process %s\n" , d->data.path); goto out_delete; }
@@ -1286,11 +1286,11 @@ static int data_init(int argc, const char **argv)return -ENOMEM ;data__for_each_file (i, d) { -struct perf_data_file *file = &d->file; +struct perf_data *data = &d->data; - file->path = use_default ? defaults[i] : argv[i]; - file->mode =PERF_DATA_MODE_READ , - file->force = force, + data->path = use_default ? defaults[i] : argv[i]; + data->mode =PERF_DATA_MODE_READ , + data->force = force, d->idx = i; }
tools/perf/builtin-evlist.c +2 -2
@@ -21,14 +21,14 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details {struct perf_session *session;struct perf_evsel *pos; -struct perf_data_file file = { +struct perf_data data = { .path = file_name, .mode =PERF_DATA_MODE_READ , .force = details->force, };bool has_tracepoint = false; - session =perf_session__new (&file,0 ,NULL ); + session =perf_session__new (&data,0 ,NULL );if (session ==NULL )return -1 ;
tools/perf/builtin-inject.c +13 -13
@@ -35,7 +35,7 @@ struct perf_inject {bool strip;bool jit_mode;const char *input_name; -struct perf_data_file output; +struct perf_data output;u64 bytes_written;u64 aux_id;struct list_head samples;
@@ -52,7 +52,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz) {ssize_t size; - size =perf_data_file__write (&inject->output, buf, sz); + size =perf_data__write (&inject->output, buf, sz);if (size <0 )return -errno;
@@ -154,11 +154,11 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,return ret; } -if (perf_data_file__is_pipe (session->file) || !session->one_mmap) { +if (perf_data__is_pipe (session->data) || !session->one_mmap) { ret =output_bytes (inject, event, event->header.size);if (ret <0 )return ret; - ret =copy_bytes (inject,perf_data_file__fd (session->file), + ret =copy_bytes (inject,perf_data__fd (session->data), event->auxtrace.size); }else { ret = output_bytes(inject, event,
@@ -637,8 +637,8 @@ static int __cmd_inject(struct perf_inject *inject) {int ret = -EINVAL ;struct perf_session *session = inject->session; -struct perf_data_file *file_out = &inject->output; -int fd =perf_data_file__fd (file_out); +struct perf_data *data_out = &inject->output; +int fd =perf_data__fd (data_out);u64 output_data_offset;signal (SIGINT , sig_handler);
@@ -693,14 +693,14 @@ static int __cmd_inject(struct perf_inject *inject)if (!inject->itrace_synth_opts.set)auxtrace_index__free (&session->auxtrace_index); -if (!file_out->is_pipe) +if (!data_out->is_pipe)lseek (fd, output_data_offset,SEEK_SET ); ret =perf_session__process_events (session);if (ret)return ret; -if (!file_out->is_pipe) { +if (!data_out->is_pipe) {if (inject->build_ids)perf_header__set_feat (&session->header,HEADER_BUILD_ID );
@@ -779,7 +779,7 @@ int cmd_inject(int argc, const char **argv) .mode = PERF_DATA_MODE_WRITE, }, }; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , };int ret;
@@ -801,7 +801,7 @@ int cmd_inject(int argc, const char **argv) "be more verbose (show build ids, etc)"),OPT_STRING (0 ,"kallsyms" , &symbol_conf.kallsyms_name,"file" ,"kallsyms pathname" ), -OPT_BOOLEAN ('f' ,"force" , &file.force,"don't complain, do it" ), +OPT_BOOLEAN ('f' ,"force" , &data.force,"don't complain, do it" ),OPT_CALLBACK_OPTARG (0 ,"itrace" , &inject.itrace_synth_opts,NULL ,"opts" ,"Instruction Tracing options" , itrace_parse_synth_opts),
@@ -829,15 +829,15 @@ int cmd_inject(int argc, const char **argv)return -1 ; } -if (perf_data_file__open (&inject.output)) { +if (perf_data__open (&inject.output)) {perror ("failed to create output file" );return -1 ; } inject.tool.ordered_events = inject.sched_stat; - file.path = inject.input_name; - inject.session =perf_session__new (&file, true, &inject.tool); + data.path = inject.input_name; + inject.session =perf_session__new (&data, true, &inject.tool);if (inject.session ==NULL )return -1 ;
tools/perf/builtin-kmem.c +4 -4
@@ -1893,7 +1893,7 @@ int cmd_kmem(int argc, const char **argv) {const char *const default_slab_sort ="frag,hit,bytes" ;const char *const default_page_sort ="bytes,hit" ; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , };const struct option kmem_options[] = {
@@ -1909,7 +1909,7 @@ int cmd_kmem(int argc, const char **argv) "page, order, migtype, gfp", parse_sort_opt),OPT_CALLBACK ('l' ,"line" ,NULL ,"num" ,"show n lines" , parse_line_opt),OPT_BOOLEAN (0 ,"raw-ip" , &raw_ip,"show raw ip instead of symbol" ), -OPT_BOOLEAN ('f' ,"force" , &file.force,"don't complain, do it" ), +OPT_BOOLEAN ('f' ,"force" , &data.force,"don't complain, do it" ),OPT_CALLBACK_NOOPT (0 ,"slab" ,NULL ,NULL ,"Analyze slab allocator" , parse_slab_opt), OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
@@ -1949,9 +1949,9 @@ int cmd_kmem(int argc, const char **argv)return __cmd_record (argc, argv); } - file.path = input_name; + data.path = input_name; - kmem_session = session =perf_session__new (&file, false, &perf_kmem); + kmem_session = session =perf_session__new (&data, false, &perf_kmem);if (session ==NULL )return -1 ;
tools/perf/builtin-kvm.c +3 -3
@@ -1067,7 +1067,7 @@ static int read_events(struct perf_kvm_stat *kvm) .namespaces = perf_event__process_namespaces, .ordered_events = true, }; -struct perf_data_file file = { +struct perf_data file = { .path = kvm->file_name, .mode =PERF_DATA_MODE_READ , .force = kvm->force,
@@ -1358,7 +1358,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,"perf kvm stat live [<options>]" , NULL }; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_WRITE , };
@@ -1432,7 +1432,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,/* * perf session */ - kvm->session =perf_session__new (&file, false, &kvm->tool); + kvm->session =perf_session__new (&data, false, &kvm->tool);if (kvm->session ==NULL ) { err =-1 ; goto out;
tools/perf/builtin-lock.c +2 -2
@@ -864,13 +864,13 @@ static int __cmd_report(bool display_info) .namespaces = perf_event__process_namespaces, .ordered_events = true, }; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = force, }; - session =perf_session__new (&file, false, &eops); + session =perf_session__new (&data, false, &eops);if (!session) {pr_err ("Initializing perf session failed\n" );return -1 ;
tools/perf/builtin-mem.c +2 -2
@@ -236,13 +236,13 @@ static int process_sample_event(struct perf_tool *tool,static int report_raw_events (struct perf_mem *mem) { -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = mem->force, };int ret; -struct perf_session *session =perf_session__new (&file, false, +struct perf_session *session =perf_session__new (&data, false, &mem->tool);if (session ==NULL )
tools/perf/builtin-record.c +25 -25
162 lines not on this page · raw message
tools/perf/builtin-report.c +7 -7
@@ -257,7 +257,7 @@ static int report__setup_sample_type(struct report *rep) {struct perf_session *session = rep->session;u64 sample_type =perf_evlist__combined_sample_type (session->evlist); -bool is_pipe =perf_data_file__is_pipe (session->file); +bool is_pipe =perf_data__is_pipe (session->data); if (session->itrace_synth_opts->callchain || (!is_pipe &&
@@ -568,7 +568,7 @@ static int __cmd_report(struct report *rep)int ret;struct perf_session *session = rep->session;struct perf_evsel *pos; -struct perf_data_file *file = session->file; +struct perf_data *data = session->data;signal (SIGINT , sig_handler);
@@ -637,7 +637,7 @@ static int __cmd_report(struct report *rep) rep->nr_entries +=evsel__hists (pos)->nr_entries;if (rep->nr_entries ==0 ) { -ui__error ("The %s file has no samples!\n" , file->path); +ui__error ("The %s file has no samples!\n" , data->path);return 0 ; }
@@ -879,7 +879,7 @@ int cmd_report(int argc, const char **argv) "Show inline function"), OPT_END() }; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , };int ret =hists__init ();
@@ -940,11 +940,11 @@ int cmd_report(int argc, const char **argv) input_name ="perf.data" ; } - file.path = input_name; - file.force = symbol_conf.force; + data.path = input_name; + data.force = symbol_conf.force; repeat: - session =perf_session__new (&file, false, &report.tool); + session =perf_session__new (&data, false, &report.tool);if (session ==NULL )return -1 ;
tools/perf/builtin-sched.c +4 -4
@@ -1700,14 +1700,14 @@ static int perf_sched__read_events(struct perf_sched *sched) { "sched:sched_migrate_task", process_sched_migrate_task_event, }, };struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = sched->force, };int rc =-1 ; - session =perf_session__new (&file, false, &sched->tool); + session =perf_session__new (&data, false, &sched->tool);if (session ==NULL ) {pr_debug ("No Memory for session\n" );return -1 ;
@@ -2902,7 +2902,7 @@ static int perf_sched__timehist(struct perf_sched *sched)const struct perf_evsel_str_handler migrate_handlers[] = { {"sched:sched_migrate_task" , timehist_migrate_task_event, }, }; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = sched->force,
@@ -2930,7 +2930,7 @@ static int perf_sched__timehist(struct perf_sched *sched) symbol_conf.use_callchain = sched->show_callchain; - session =perf_session__new (&file, false, &sched->tool); + session =perf_session__new (&data, false, &sched->tool);if (session ==NULL )return -ENOMEM ;
tools/perf/builtin-script.c +10 -10
@@ -217,12 +217,12 @@ struct perf_evsel_script { };static struct perf_evsel_script *perf_evsel_script__new (struct perf_evsel *evsel, -struct perf_data_file *file) +struct perf_data *data) {struct perf_evsel_script *es =malloc (sizeof (*es));if (es !=NULL ) { -if (asprintf (&es->filename,"%s.%s.dump" , file->path,perf_evsel__name (evsel)) <0 ) +if (asprintf (&es->filename,"%s.%s.dump" , data->path,perf_evsel__name (evsel)) <0 ) goto out_free; es->fp =fopen (es->filename,"w" );if (es->fp ==NULL )
@@ -1954,7 +1954,7 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script)struct perf_evsel *evsel;evlist__for_each_entry (script->session->evlist, evsel) { - evsel->priv =perf_evsel_script__new (evsel, script->session->file); + evsel->priv =perf_evsel_script__new (evsel, script->session->data);if (evsel->priv ==NULL ) goto out_err_fclose; }
@@ -2590,14 +2590,14 @@ int find_scripts(char **scripts_array, char **scripts_path_array)char scripts_path[MAXPATHLEN ], lang_path[MAXPATHLEN ];DIR *scripts_dir, *lang_dir;struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , };char *temp;int i =0 ; - session =perf_session__new (&file, false,NULL ); + session =perf_session__new (&data, false,NULL );if (!session)return -1 ;
@@ -2875,7 +2875,7 @@ int cmd_script(int argc, const char **argv) .ordering_requires_timestamps = true, }, }; -struct perf_data_file file = { +struct perf_data data = { .mode =PERF_DATA_MODE_READ , }; const struct option options[] = {
@@ -2982,8 +2982,8 @@ int cmd_script(int argc, const char **argv) argc =parse_options_subcommand (argc, argv, options, script_subcommands, script_usage,PARSE_OPT_STOP_AT_NON_OPTION ); - file.path = input_name; - file.force = symbol_conf.force; + data.path = input_name; + data.force = symbol_conf.force;if (argc >1 && !strncmp (argv[0 ],"rec" ,strlen ("rec" ))) { rec_script_path =get_script_path (argv[1 ],RECORD_SUFFIX );
@@ -3150,7 +3150,7 @@ int cmd_script(int argc, const char **argv)if (!script_name)setup_pager (); - session =perf_session__new (&file, false, &script.tool); + session =perf_session__new (&data, false, &script.tool);if (session ==NULL )return -1 ;
@@ -3206,7 +3206,7 @@ int cmd_script(int argc, const char **argv) goto out_delete; } - input =open (file.path,O_RDONLY );/* input_name */ + input =open (data.path,O_RDONLY );/* input_name */ if (input <0 ) { err = -errno;perror ("failed to open file" );
tools/perf/builtin-stat.c +16 -16
@@ -175,7 +175,7 @@ static int print_free_counters_hint;struct perf_stat {bool record; -struct perf_data_file file; +struct perf_data data;struct perf_session *session;u64 bytes_written;struct perf_tool tool;
@@ -253,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)* by attr->sample_type != 0, and we can't run it on * stat sessions. */ -if (!(STAT_RECORD && perf_stat.file.is_pipe)) +if (!(STAT_RECORD && perf_stat.data.is_pipe)) attr->sample_type =PERF_SAMPLE_IDENTIFIER ;/*
@@ -295,7 +295,7 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { - if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) { + if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) { pr_err("failed to write perf data, error: %m\n");return -1 ; }
@@ -628,7 +628,7 @@ static int __run_perf_stat(int argc, const char **argv)size_t l;int status =0 ;const bool forks = (argc >0 ); -bool is_pipe =STAT_RECORD ? perf_stat.file.is_pipe : false; +bool is_pipe =STAT_RECORD ? perf_stat.data.is_pipe : false;struct perf_evsel_config_term *err_term;if (interval) {
@@ -719,10 +719,10 @@ static int __run_perf_stat(int argc, const char **argv) }if (STAT_RECORD ) { -int err, fd =perf_data_file__fd (&perf_stat.file); +int err, fd =perf_data__fd (&perf_stat.data);if (is_pipe) { - err =perf_header__write_pipe (perf_data_file__fd (&perf_stat.file)); + err =perf_header__write_pipe (perf_data__fd (&perf_stat.data)); }else { err =perf_session__write_header (perf_stat.session, evsel_list, fd, false);
@@ -1696,7 +1696,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)char buf[64 ], *prefix =NULL ;/* Do not print anything if we record to the pipe. */ -if (STAT_RECORD && perf_stat.file.is_pipe) +if (STAT_RECORD && perf_stat.data.is_pipe)return ;if (interval)
@@ -2406,20 +2406,20 @@ static void init_features(struct perf_session *session)static int __cmd_record (int argc,const char **argv) {struct perf_session *session; -struct perf_data_file *file = &perf_stat.file; +struct perf_data *data = &perf_stat.data; argc =parse_options (argc, argv, stat_options, stat_record_usage,PARSE_OPT_STOP_AT_NON_OPTION );if (output_name) - file->path = output_name; + data->path = output_name;if (run_count !=1 || forever) {pr_err ("Cannot use -r option with perf stat record.\n" );return -1 ; } - session =perf_session__new (file, false,NULL ); + session =perf_session__new (data, false,NULL );if (session ==NULL ) {pr_err ("Perf session creation failed.\n" );return -1 ;
@@ -2477,7 +2477,7 @@ int process_stat_config_event(struct perf_tool *tool,if (st->aggr_mode !=AGGR_UNSET ) stat_config.aggr_mode = st->aggr_mode; -if (perf_stat.file.is_pipe) +if (perf_stat.data.is_pipe)perf_stat_init_aggr_mode ();else perf_stat_init_aggr_mode_file (st);
@@ -2585,10 +2585,10 @@ static int __cmd_report(int argc, const char **argv) input_name ="perf.data" ; } - perf_stat.file.path = input_name; - perf_stat.file.mode =PERF_DATA_MODE_READ ; + perf_stat.data.path = input_name; + perf_stat.data.mode =PERF_DATA_MODE_READ ; - session =perf_session__new (&perf_stat.file, false, &perf_stat.tool); + session =perf_session__new (&perf_stat.data, false, &perf_stat.tool);if (session ==NULL )return -1 ;
@@ -2859,7 +2859,7 @@ int cmd_stat(int argc, const char **argv)* records, but the need to suppress the kptr_restrict messages in older * tools remain -acme */ -int fd =perf_data_file__fd (&perf_stat.file); +int fd =perf_data__fd (&perf_stat.data);int err =perf_event__synthesize_kernel_mmap ((void *)&perf_stat, process_synthesized_event, &perf_stat.session->machines.host);
@@ -2873,7 +2873,7 @@ int cmd_stat(int argc, const char **argv)pr_err ("failed to write stat round event\n" ); } -if (!perf_stat.file.is_pipe) { +if (!perf_stat.data.is_pipe) { perf_stat.session->header.data_size += perf_stat.bytes_written;perf_session__write_header (perf_stat.session, evsel_list, fd, true); }
tools/perf/builtin-timechart.c +3 -3
@@ -1601,13 +1601,13 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) { "syscalls:sys_exit_pselect6", process_exit_poll }, { "syscalls:sys_exit_select", process_exit_poll }, }; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = tchart->force, }; -struct perf_session *session =perf_session__new (&file, false, +struct perf_session *session =perf_session__new (&data, false, &tchart->tool);int ret = -EINVAL ;
@@ -1617,7 +1617,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)symbol__init (&session->header.env); (void )perf_header__process_sections (&session->header, -perf_data_file__fd (session->file), +perf_data__fd (session->data), tchart, process_header);
tools/perf/builtin-trace.c +2 -2
@@ -2532,7 +2532,7 @@ static int trace__replay(struct trace *trace)const struct perf_evsel_str_handler handlers[] = { {"probe:vfs_getname" , trace__vfs_getname, }, }; -struct perf_data_file file = { +struct perf_data data = { .path = input_name, .mode =PERF_DATA_MODE_READ , .force = trace->force,
@@ -2558,7 +2558,7 @@ static int trace__replay(struct trace *trace)/* add tid to output */ trace->multiple_threads = true; - session =perf_session__new (&file, false, &trace->tool); + session =perf_session__new (&data, false, &trace->tool);if (session ==NULL )return -1 ;
tools/perf/tests/topology.c +5 -5
@@ -29,12 +29,12 @@ static int get_temp(char *path)static int session_write_header (char *path) {struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = path, .mode =PERF_DATA_MODE_WRITE , }; - session =perf_session__new (&file, false,NULL ); + session =perf_session__new (&data, false,NULL );TEST_ASSERT_VAL ("can't get session" , session); session->evlist =perf_evlist__new_default ();
@@ -46,7 +46,7 @@ static int session_write_header(char *path) session->header.data_size +=DATA_SIZE ;TEST_ASSERT_VAL ("failed to write header" , - !perf_session__write_header (session, session->evlist, file.fd, true)); + !perf_session__write_header (session, session->evlist, data.fd, true));perf_session__delete (session);
@@ -56,13 +56,13 @@ static int session_write_header(char *path)static int check_cpu_topology (char *path,struct cpu_map *map) {struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = path, .mode =PERF_DATA_MODE_READ , };int i; - session =perf_session__new (&file, false,NULL ); + session =perf_session__new (&data, false,NULL );TEST_ASSERT_VAL ("can't get session" , session);for (i =0 ; i < session->header.env.nr_cpus_avail; i++) {
tools/perf/util/auxtrace.c +2 -2
@@ -208,7 +208,7 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,static void *auxtrace_copy_data (u64 size,struct perf_session *session) { -int fd =perf_data_file__fd (session->file); +int fd =perf_data__fd (session->data);void *p;ssize_t ret;
@@ -305,7 +305,7 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,if (session->one_mmap) { buffer->data = buffer->data_offset - session->one_mmap_offset + session->one_mmap_addr; - }else if (perf_data_file__is_pipe (session->file)) { + }else if (perf_data__is_pipe (session->data)) { buffer->data =auxtrace_copy_data (buffer->size, session);if (!buffer->data)return -ENOMEM ;
tools/perf/util/data-convert-bt.c +3 -3
@@ -1577,7 +1577,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, struct perf_data_convert_opts *opts) {struct perf_session *session; -struct perf_data_file file = { +struct perf_data data = { .path = input, .mode =PERF_DATA_MODE_READ , .force = opts->force,
@@ -1619,7 +1619,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, err =-1 ;/* perf.data session */ - session =perf_session__new (&file,0 , &c.tool); + session =perf_session__new (&data,0 , &c.tool);if (!session) goto free_writer;
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,fprintf (stderr,"[ perf data convert: Converted '%s' into CTF data '%s' ]\n" , - file.path, path); + data.path, path); fprintf(stderr, "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
tools/perf/util/data.c +46 -46
214 lines not on this page · raw message
tools/perf/util/data.h +16 -16
@@ -8,7 +8,7 @@ enum perf_data_mode { PERF_DATA_MODE_READ, }; -struct perf_data_file { +struct perf_data {const char *path;int fd;bool is_pipe;
@@ -17,43 +17,43 @@ struct perf_data_file {enum perf_data_mode mode; }; -static inline bool perf_data_file__is_read (struct perf_data_file *file) +static inline bool perf_data__is_read (struct perf_data *data) { -return file->mode ==PERF_DATA_MODE_READ ; +return data->mode ==PERF_DATA_MODE_READ ; } -static inline bool perf_data_file__is_write (struct perf_data_file *file) +static inline bool perf_data__is_write (struct perf_data *data) { -return file->mode ==PERF_DATA_MODE_WRITE ; +return data->mode ==PERF_DATA_MODE_WRITE ; } -static inline int perf_data_file__is_pipe (struct perf_data_file *file) +static inline int perf_data__is_pipe (struct perf_data *data) { -return file->is_pipe; +return data->is_pipe; } -static inline int perf_data_file__fd (struct perf_data_file *file) +static inline int perf_data__fd (struct perf_data *data) { -return file->fd; +return data->fd; } -static inline unsigned long perf_data_file__size (struct perf_data_file *file) +static inline unsigned long perf_data__size (struct perf_data *data) { -return file->size; +return data->size; } -int perf_data_file__open (struct perf_data_file *file); -void perf_data_file__close (struct perf_data_file *file); -ssize_t perf_data_file__write (struct perf_data_file *file, +int perf_data__open (struct perf_data *data); +void perf_data__close (struct perf_data *data); +ssize_t perf_data__write (struct perf_data *data,void *buf,size_t size);/* * If at_exit is set, only rename current perf.data to -* perf.data.<postfix>, continue write on original file. +* perf.data.<postfix>, continue write on original data. * Set at_exit when flushing the last output. * * Return value is fd of new output. */ -int perf_data_file__switch (struct perf_data_file *file, +int perf_data__switch (struct perf_data *data,const char *postfix,size_t pos,bool at_exit);#endif /* __PERF_DATA_H */
tools/perf/util/header.c +10 -10
@@ -1762,7 +1762,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused) session = container_of(ff->ph, struct perf_session, header); -if (session->file->is_pipe) { +if (session->data->is_pipe) {/* Save events for reading later by print_event_desc, * since they can't be read again in pipe mode. */ ff->events = events;
@@ -1771,7 +1771,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)for (evsel = events; evsel->attr.size; evsel++)perf_evlist__set_event_name (session->evlist, evsel); -if (!session->file->is_pipe) +if (!session->data->is_pipe)free_event_desc (events);return 0 ;
@@ -2248,7 +2248,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) {struct header_print_data hd;struct perf_header *header = &session->header; -int fd =perf_data_file__fd (session->file); +int fd =perf_data__fd (session->data);struct stat st;int ret, bit;
@@ -2264,7 +2264,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)perf_header__process_sections (header, fd, &hd, perf_file_section__fprintf_info); -if (session->file->is_pipe) +if (session->data->is_pipe)return 0 ;fprintf (fp,"# missing features: " );
@@ -2757,7 +2757,7 @@ static int perf_header__read_pipe(struct perf_session *session)struct perf_pipe_file_header f_header;if (perf_file_header__read_pipe (&f_header, header, -perf_data_file__fd (session->file), +perf_data__fd (session->data), session->repipe) <0 ) {pr_debug ("incompatible file format\n" );return -EINVAL ;
@@ -2860,13 +2860,13 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,int perf_session__read_header (struct perf_session *session) { -struct perf_data_file *file = session->file; +struct perf_data *data = session->data;struct perf_header *header = &session->header;struct perf_file_header f_header;struct perf_file_attr f_attr;u64 f_id;int nr_attrs, nr_ids, i, j; -int fd =perf_data_file__fd (file); +int fd =perf_data__fd (data); session->evlist =perf_evlist__new ();if (session->evlist ==NULL )
@@ -2874,7 +2874,7 @@ int perf_session__read_header(struct perf_session *session) session->evlist->env = &header->env; session->machines.host.env = &header->env; -if (perf_data_file__is_pipe (file)) +if (perf_data__is_pipe (data))return perf_header__read_pipe (session);if (perf_file_header__read (&f_header, header, fd) <0 )
@@ -2889,7 +2889,7 @@ int perf_session__read_header(struct perf_session *session)if (f_header.data.size ==0 ) {pr_warning ("WARNING: The %s file's data size field is 0 which is unexpected.\n" "Was the 'perf record' command properly terminated?\n" , - file->path); + data->path); } nr_attrs = f_header.attrs.size / f_header.attr_size;
@@ -3397,7 +3397,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, struct perf_session *session) {ssize_t size_read, padding, size = event->tracing_data.size; -int fd =perf_data_file__fd (session->file); +int fd =perf_data__fd (session->data);off_t offset =lseek (fd,0 ,SEEK_CUR );char buf[BUFSIZ ];
tools/perf/util/intel-bts.c +3 -3
@@ -500,7 +500,7 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp) }if (!buffer->data) { -int fd =perf_data_file__fd (btsq->bts->session->file); +int fd =perf_data__fd (btsq->bts->session->data); buffer->data =auxtrace_buffer__get_data (buffer, fd);if (!buffer->data) {
@@ -664,10 +664,10 @@ static int intel_bts_process_auxtrace_event(struct perf_session *session,if (!bts->data_queued) {struct auxtrace_buffer *buffer;off_t data_offset; -int fd =perf_data_file__fd (session->file); +int fd =perf_data__fd (session->data);int err; -if (perf_data_file__is_pipe (session->file)) { +if (perf_data__is_pipe (session->data)) { data_offset =0 ; }else { data_offset =lseek (fd,0 ,SEEK_CUR );
tools/perf/util/intel-pt.c +3 -3
@@ -271,7 +271,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) ptq->buffer = buffer;if (!buffer->data) { -int fd =perf_data_file__fd (ptq->pt->session->file); +int fd =perf_data__fd (ptq->pt->session->data); buffer->data =auxtrace_buffer__get_data (buffer, fd);if (!buffer->data)
@@ -2084,10 +2084,10 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,if (!pt->data_queued) {struct auxtrace_buffer *buffer;off_t data_offset; -int fd =perf_data_file__fd (session->file); +int fd =perf_data__fd (session->data);int err; -if (perf_data_file__is_pipe (session->file)) { +if (perf_data__is_pipe (session->data)) { data_offset =0 ; }else { data_offset =lseek (fd,0 ,SEEK_CUR );
tools/perf/util/jit.h +1 -1
@@ -3,7 +3,7 @@#include <data.h> -int jit_process (struct perf_session *session,struct perf_data_file *output, +int jit_process (struct perf_session *session,struct perf_data *output,struct machine *machine,char *filename,pid_t pid,u64 *nbytes);int jit_inject_record (const char *filename);
tools/perf/util/jitdump.c +5 -5
@@ -29,7 +29,7 @@#include "sane_ctype.h" struct jit_buf_desc { -struct perf_data_file *output; +struct perf_data *output;struct perf_session *session;struct machine *machine;union jr_entry *entry;
@@ -60,8 +60,8 @@ struct debug_line_info {struct jit_tool {struct perf_tool tool; -struct perf_data_file output; -struct perf_data_file input; +struct perf_data output; +struct perf_data input;u64 bytes_written; };
@@ -356,7 +356,7 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) {ssize_t size; - size =perf_data_file__write (jd->output, event, event->header.size); + size =perf_data__write (jd->output, event, event->header.size);if (size <0 )return -1 ;
@@ -751,7 +751,7 @@ jit_detect(char *mmap_name, pid_t pid) int jit_process(struct perf_session *session, - struct perf_data_file *output, + struct perf_data *output, struct machine *machine, char *filename, pid_t pid,
tools/perf/util/session.c +22 -22
144 lines not on this page · raw message
tools/perf/util/session.h +2 -2
@@ -32,13 +32,13 @@ struct perf_session {void *one_mmap_addr;u64 one_mmap_offset;struct ordered_events ordered_events; -struct perf_data_file *file; +struct perf_data *data;struct perf_tool *tool; };struct perf_tool ; -struct perf_session *perf_session__new (struct perf_data_file *file, +struct perf_session *perf_session__new (struct perf_data *data,bool repipe,struct perf_tool *tool);void perf_session__delete (struct perf_session *session);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 10/19 perf tools: Add struct perf_data_file
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add struct perf_data_file to represent a single file within a perf_data struct.
--- tools/perf/builtin-annotate.c | 4 ++-- tools/perf/builtin-buildid-cache.c | 4 ++-- tools/perf/builtin-buildid-list.c | 8 ++++--- tools/perf/builtin-c2c.c | 4 ++-- tools/perf/builtin-diff.c | 12 +++++----- tools/perf/builtin-evlist.c | 8 ++++--- tools/perf/builtin-inject.c | 12 ++++++---- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-kvm.c | 8 ++++--- tools/perf/builtin-lock.c | 8 ++++--- tools/perf/builtin-mem.c | 8 ++++--- tools/perf/builtin-record.c | 6 ++--- tools/perf/builtin-report.c | 6 ++--- tools/perf/builtin-sched.c | 16 ++++++++----- tools/perf/builtin-script.c | 14 ++++++----- tools/perf/builtin-stat.c | 6 ++--- tools/perf/builtin-timechart.c | 8 ++++--- tools/perf/builtin-trace.c | 8 ++++--- tools/perf/tests/topology.c | 14 +++++++---- tools/perf/util/data-convert-bt.c | 8 +++---- tools/perf/util/data.c | 48 +++++++++++++++++++------------------- tools/perf/util/data.h | 10 +++++--- tools/perf/util/header.c | 2 +- 23 files changed, 127 insertions(+), 97 deletions(-)
tools/perf/builtin-annotate.c +2 -2
@@ -356,7 +356,7 @@ static int __cmd_annotate(struct perf_annotate *ann) }if (total_nr_samples ==0 ) { -ui__error ("The %s file has no samples!\n" , session->data->path); +ui__error ("The %s file has no samples!\n" , session->data->file.path); goto out; }
@@ -482,7 +482,7 @@ int cmd_annotate(int argc, const char **argv)if (quiet)perf_quiet_option (); - data.path = input_name; + data.file.path = input_name; annotate.session =perf_session__new (&data, false, &annotate.tool);if (annotate.session ==NULL )
tools/perf/builtin-buildid-cache.c +2 -2
@@ -352,8 +352,8 @@ int cmd_buildid_cache(int argc, const char **argv) nsi =nsinfo__new (ns_id);if (missing_filename) { - data.path = missing_filename; - data.force = force; + data.file.path = missing_filename; + data.force = force; session =perf_session__new (&data, false,NULL );if (session ==NULL )
tools/perf/builtin-buildid-list.c +5 -3
@@ -51,9 +51,11 @@ static int perf_session__list_build_ids(bool force, bool with_hits) {struct perf_session *session;struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = force, };symbol__elf_init ();
tools/perf/builtin-c2c.c +2 -2
@@ -2572,8 +2572,8 @@ static int perf_c2c__report(int argc, const char **argv)if (!input_name || !strlen (input_name)) input_name ="perf.data" ; - data.path = input_name; - data.force = symbol_conf.force; + data.file.path = input_name; + data.force = symbol_conf.force; err =setup_display (display);if (err)
tools/perf/builtin-diff.c +6 -6
@@ -707,7 +707,7 @@ static void data__fprintf(void)data__for_each_file (i, d)fprintf (stdout,"# [%d] %s %s\n" , - d->idx, d->data.path, + d->idx, d->data.file.path, !d->idx ?"(Baseline)" :"" );fprintf (stdout,"#\n" );
@@ -778,14 +778,14 @@ static int __cmd_diff(void)data__for_each_file (i, d) { d->session =perf_session__new (&d->data, false, &tool);if (!d->session) { -pr_err ("Failed to open %s\n" , d->data.path); +pr_err ("Failed to open %s\n" , d->data.file.path); ret =-1 ; goto out_delete; } ret =perf_session__process_events (d->session);if (ret) { -pr_err ("Failed to process %s\n" , d->data.path); +pr_err ("Failed to process %s\n" , d->data.file.path); goto out_delete; }
@@ -1288,9 +1288,9 @@ static int data_init(int argc, const char **argv)data__for_each_file (i, d) {struct perf_data *data = &d->data; - data->path = use_default ? defaults[i] : argv[i]; - data->mode =PERF_DATA_MODE_READ , - data->force = force, + data->file.path = use_default ? defaults[i] : argv[i]; + data->mode =PERF_DATA_MODE_READ , + data->force = force, d->idx = i; }
tools/perf/builtin-evlist.c +5 -3
@@ -22,9 +22,11 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *detailsstruct perf_session *session;struct perf_evsel *pos;struct perf_data data = { - .path = file_name, - .mode =PERF_DATA_MODE_READ , - .force = details->force, + .file = { + .path = file_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = details->force, };bool has_tracepoint = false;
tools/perf/builtin-inject.c +7 -5
@@ -145,7 +145,7 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,if (!inject->output.is_pipe) {off_t offset; - offset =lseek (inject->output.fd,0 ,SEEK_CUR ); + offset =lseek (inject->output.file.fd,0 ,SEEK_CUR );if (offset ==-1 )return -errno; ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
@@ -775,8 +775,10 @@ int cmd_inject(int argc, const char **argv) .input_name = "-", .samples = LIST_HEAD_INIT(inject.samples), .output = { - .path = "-", - .mode = PERF_DATA_MODE_WRITE, + .file = { + .path = "-", + }, + .mode = PERF_DATA_MODE_WRITE, }, };struct perf_data data = {
@@ -789,7 +791,7 @@ int cmd_inject(int argc, const char **argv) "Inject build-ids into the output stream"),OPT_STRING ('i' ,"input" , &inject.input_name,"file" ,"input file name" ), -OPT_STRING ('o' ,"output" , &inject.output.path,"file" , +OPT_STRING ('o' ,"output" , &inject.output.file.path,"file" ,"output file name" ),OPT_BOOLEAN ('s' ,"sched-stat" , &inject.sched_stat, "Merge sched-stat and sched-switch for getting events "
@@ -836,7 +838,7 @@ int cmd_inject(int argc, const char **argv) inject.tool.ordered_events = inject.sched_stat; - data.path = inject.input_name; + data.file.path = inject.input_name; inject.session =perf_session__new (&data, true, &inject.tool);if (inject.session ==NULL )return -1 ;
tools/perf/builtin-kmem.c +1 -1
@@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)return __cmd_record (argc, argv); } - data.path = input_name; + data.file.path = input_name; kmem_session = session =perf_session__new (&data, false, &perf_kmem);if (session ==NULL )
tools/perf/builtin-kvm.c +5 -3
@@ -1068,9 +1068,11 @@ static int read_events(struct perf_kvm_stat *kvm) .ordered_events = true, };struct perf_data file = { - .path = kvm->file_name, - .mode =PERF_DATA_MODE_READ , - .force = kvm->force, + .file = { + .path = kvm->file_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = kvm->force, }; kvm->tool = eops;
tools/perf/builtin-lock.c +5 -3
@@ -865,9 +865,11 @@ static int __cmd_report(bool display_info) .ordered_events = true, };struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = force, }; session =perf_session__new (&data, false, &eops);
tools/perf/builtin-mem.c +5 -3
@@ -237,9 +237,11 @@ static int process_sample_event(struct perf_tool *tool,static int report_raw_events (struct perf_mem *mem) {struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = mem->force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = mem->force, };int ret; struct perf_session *session = perf_session__new(&data, false,
tools/perf/builtin-record.c +3 -3
@@ -618,7 +618,7 @@ record__switch_output(struct record *rec, bool at_exit)if (!quiet)fprintf (stderr,"[ perf record: Dump %s.%s ]\n" , - data->path, timestamp); + data->file.path, timestamp);/* Output tracking events */ if (!at_exit) {
@@ -1118,7 +1118,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)fprintf (stderr,"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n" ,perf_data__size (data) /1024.0 /1024.0 , - data->path, postfix, samples); + data->file.path, postfix, samples); } out_delete_session:
@@ -1482,7 +1482,7 @@ static struct option __record_options[] = {OPT_STRING ('C' ,"cpu" , &record.opts.target.cpu_list,"cpu" ,"list of cpus to monitor" ),OPT_U64 ('c' ,"count" , &record.opts.user_interval,"event period to sample" ), -OPT_STRING ('o' ,"output" , &record.data.path,"file" , +OPT_STRING ('o' ,"output" , &record.data.file.path,"file" ,"output file name" ), OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, &record.opts.no_inherit_set,
tools/perf/builtin-report.c +3 -3
@@ -637,7 +637,7 @@ static int __cmd_report(struct report *rep) rep->nr_entries +=evsel__hists (pos)->nr_entries;if (rep->nr_entries ==0 ) { -ui__error ("The %s file has no samples!\n" , data->path); +ui__error ("The %s file has no samples!\n" , data->file.path);return 0 ; }
@@ -940,8 +940,8 @@ int cmd_report(int argc, const char **argv) input_name ="perf.data" ; } - data.path = input_name; - data.force = symbol_conf.force; + data.file.path = input_name; + data.force = symbol_conf.force; repeat: session =perf_session__new (&data, false, &report.tool);
tools/perf/builtin-sched.c +10 -6
@@ -1701,9 +1701,11 @@ static int perf_sched__read_events(struct perf_sched *sched) };struct perf_session *session;struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = sched->force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = sched->force, };int rc =-1 ;
@@ -2903,9 +2905,11 @@ static int perf_sched__timehist(struct perf_sched *sched) { "sched:sched_migrate_task", timehist_migrate_task_event, }, };struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = sched->force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = sched->force, };struct perf_session *session;
tools/perf/builtin-script.c +8 -6
@@ -222,7 +222,7 @@ static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evselstruct perf_evsel_script *es =malloc (sizeof (*es));if (es !=NULL ) { -if (asprintf (&es->filename,"%s.%s.dump" , data->path,perf_evsel__name (evsel)) <0 ) +if (asprintf (&es->filename,"%s.%s.dump" , data->file.path,perf_evsel__name (evsel)) <0 ) goto out_free; es->fp =fopen (es->filename,"w" );if (es->fp ==NULL )
@@ -2591,8 +2591,10 @@ int find_scripts(char **scripts_array, char **scripts_path_array)DIR *scripts_dir, *lang_dir;struct perf_session *session;struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , };char *temp;int i =0 ;
@@ -2982,8 +2984,8 @@ int cmd_script(int argc, const char **argv) argc =parse_options_subcommand (argc, argv, options, script_subcommands, script_usage,PARSE_OPT_STOP_AT_NON_OPTION ); - data.path = input_name; - data.force = symbol_conf.force; + data.file.path = input_name; + data.force = symbol_conf.force;if (argc >1 && !strncmp (argv[0 ],"rec" ,strlen ("rec" ))) { rec_script_path =get_script_path (argv[1 ],RECORD_SUFFIX );
@@ -3206,7 +3208,7 @@ int cmd_script(int argc, const char **argv) goto out_delete; } - input =open (data.path,O_RDONLY );/* input_name */ + input =open (data.file.path,O_RDONLY );/* input_name */ if (input <0 ) { err = -errno;perror ("failed to open file" );
tools/perf/builtin-stat.c +3 -3
@@ -2412,7 +2412,7 @@ static int __cmd_record(int argc, const char **argv) PARSE_OPT_STOP_AT_NON_OPTION);if (output_name) - data->path = output_name; + data->file.path = output_name;if (run_count !=1 || forever) {pr_err ("Cannot use -r option with perf stat record.\n" );
@@ -2585,8 +2585,8 @@ static int __cmd_report(int argc, const char **argv) input_name ="perf.data" ; } - perf_stat.data.path = input_name; - perf_stat.data.mode =PERF_DATA_MODE_READ ; + perf_stat.data.file.path = input_name; + perf_stat.data.mode =PERF_DATA_MODE_READ ; session =perf_session__new (&perf_stat.data, false, &perf_stat.tool);if (session ==NULL )
tools/perf/builtin-timechart.c +5 -3
@@ -1602,9 +1602,11 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) { "syscalls:sys_exit_select", process_exit_poll }, };struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = tchart->force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = tchart->force, }; struct perf_session *session = perf_session__new(&data, false,
tools/perf/builtin-trace.c +5 -3
@@ -2533,9 +2533,11 @@ static int trace__replay(struct trace *trace) { "probe:vfs_getname", trace__vfs_getname, }, };struct perf_data data = { - .path = input_name, - .mode =PERF_DATA_MODE_READ , - .force = trace->force, + .file = { + .path = input_name, + }, + .mode =PERF_DATA_MODE_READ , + .force = trace->force, };struct perf_session *session;struct perf_evsel *evsel;
tools/perf/tests/topology.c +9 -5
@@ -30,8 +30,10 @@ static int session_write_header(char *path) {struct perf_session *session;struct perf_data data = { - .path = path, - .mode =PERF_DATA_MODE_WRITE , + .file = { + .path = path, + }, + .mode =PERF_DATA_MODE_WRITE , }; session =perf_session__new (&data, false,NULL );
@@ -46,7 +48,7 @@ static int session_write_header(char *path) session->header.data_size +=DATA_SIZE ;TEST_ASSERT_VAL ("failed to write header" , - !perf_session__write_header (session, session->evlist, data.fd, true)); + !perf_session__write_header (session, session->evlist, data.file.fd, true));perf_session__delete (session);
@@ -57,8 +59,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map) {struct perf_session *session;struct perf_data data = { - .path = path, - .mode =PERF_DATA_MODE_READ , + .file = { + .path = path, + }, + .mode =PERF_DATA_MODE_READ , };int i;
tools/perf/util/data-convert-bt.c +4 -4
@@ -1578,9 +1578,9 @@ int bt_convert__perf2ctf(const char *input, const char *path, {struct perf_session *session;struct perf_data data = { - .path = input, - .mode =PERF_DATA_MODE_READ , - .force = opts->force, + .file.path = input, + .mode =PERF_DATA_MODE_READ , + .force = opts->force, };struct convert c = { .tool = {
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,fprintf (stderr,"[ perf data convert: Converted '%s' into CTF data '%s' ]\n" , - data.path, path); + data.file.path, path); fprintf(stderr, "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
tools/perf/util/data.c +24 -24
148 lines not on this page · raw message
tools/perf/util/data.h +7 -3
@@ -8,9 +8,13 @@ enum perf_data_mode { PERF_DATA_MODE_READ, }; +struct perf_data_file { +const char *path; +int fd; +}; +struct perf_data { -const char *path; -int fd; +struct perf_data_file file;bool is_pipe;bool force;unsigned long size;
@@ -34,7 +38,7 @@ static inline int perf_data__is_pipe(struct perf_data *data)static inline int perf_data__fd (struct perf_data *data) { -return data->fd; +return data->file.fd; }static inline unsigned long perf_data__size (struct perf_data *data)
tools/perf/util/header.c +1 -1
@@ -2889,7 +2889,7 @@ int perf_session__read_header(struct perf_session *session)if (f_header.data.size ==0 ) {pr_warning ("WARNING: The %s file's data size field is 0 which is unexpected.\n" "Was the 'perf record' command properly terminated?\n" , - data->path); + data->file.path); } nr_attrs = f_header.attrs.size / f_header.attr_size;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 11/19 perf tools: Add perf_data_file__write function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding perf_data_file__write function to provide single file write operation.
--- tools/perf/util/data.c | 8 +++++++- tools/perf/util/data.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-)
tools/perf/util/data.c +7 -1
@@ -144,10 +144,16 @@ void perf_data__close(struct perf_data *data)close (data->file.fd); } +ssize_t perf_data_file__write (struct perf_data_file *file, +void *buf,size_t size) +{ +return writen (file->fd, buf, size); +} +ssize_t perf_data__write (struct perf_data *data,void *buf,size_t size) { -return writen (data->file.fd, buf, size); +return perf_data_file__write (&data->file, buf, size); } int perf_data__switch(struct perf_data *data,
tools/perf/util/data.h +2 -0
@@ -50,6 +50,8 @@ int perf_data__open(struct perf_data *data);void perf_data__close (struct perf_data *data);ssize_t perf_data__write (struct perf_data *data,void *buf,size_t size); +ssize_t perf_data_file__write (struct perf_data_file *file, +void *buf,size_t size);/* * If at_exit is set, only rename current perf.data to * perf.data.<postfix>, continue write on original data.
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 12/19 perf stat: Move the shadow stats scale computation in perf_stat__update_shadow_stats
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move the shadow stats scale computation to the perf_stat__update_shadow_stats() function, so it's centralized and we don't forget to do it. It also saves few lines of code.
--- tools/perf/builtin-stat.c | 3 +-- tools/perf/util/stat-shadow.c | 48 ++++++++++++++++++++++--------------------- tools/perf/util/stat.c | 6 ++---- tools/perf/util/stat.h | 2 +- 4 files changed, 29 insertions(+), 30 deletions(-)
tools/perf/builtin-stat.c +1 -2
@@ -1267,8 +1267,7 @@ static void aggr_update_shadow(void)continue ; val +=perf_counts (counter->counts, cpu,0 )->val; } - val = val * counter->scale; -perf_stat__update_shadow_stats (counter, &val, +perf_stat__update_shadow_stats (counter, val,first_shadow_cpu (counter, id)); } }
tools/perf/util/stat-shadow.c +25 -23
83 lines not on this page · raw message
tools/perf/util/stat.c +2 -4
@@ -277,7 +277,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evselperf_evsel__compute_deltas (evsel, cpu, thread, count);perf_counts_values__scale (count, config->scale,NULL );if (config->aggr_mode ==AGGR_NONE ) -perf_stat__update_shadow_stats (evsel, count->values, cpu); +perf_stat__update_shadow_stats (evsel, count->val, cpu);break ;case AGGR_GLOBAL : aggr->val += count->val;
@@ -320,7 +320,6 @@ int perf_stat_process_counter(struct perf_stat_config *config,struct perf_counts_values *aggr = &counter->counts->aggr;struct perf_stat_evsel *ps = counter->stats;u64 *count = counter->counts->aggr.values; -u64 val;int i, ret; aggr->val = aggr->ena = aggr->run =0 ;
@@ -360,8 +359,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,/* * Save the full runtime - to allow normalization during printout: */ - val = counter->scale * *count; -perf_stat__update_shadow_stats (counter, &val,0 ); +perf_stat__update_shadow_stats (counter, *count,0 );return 0 ; }
tools/perf/util/stat.h +1 -1
@@ -82,7 +82,7 @@ typedef void (*new_line_t )(void *ctx);void perf_stat__init_shadow_stats (void );void perf_stat__reset_shadow_stats (void ); -void perf_stat__update_shadow_stats (struct perf_evsel *counter,u64 *count, +void perf_stat__update_shadow_stats (struct perf_evsel *counter,u64 count,int cpu);struct perf_stat_output_ctx {void *ctx;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 13/19 perf stat: Make --per-thread update shadow stats to show metrics
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We should support this because it would allow easily to collect metrics for different threads in applications.
Original patch from posted by Jin Yao in here [1].
1. Current output, for example:
root@skl:/tmp# perf stat --per-thread -p 21623 ^C Performance counter stats for process id '21623':
vmstat-21623 0.517479 task-clock (msec) # 0.000 CPUs utilized
vmstat-21623 1 context-switches
vmstat-21623 0 cpu-migrations
vmstat-21623 0 page-faults
vmstat-21623 461,306 cycles
vmstat-21623 630,724 instructions
vmstat-21623 136,265 branches
vmstat-21623 2,520 branch-misses1.444020756 seconds time elapsed
root@skl:/tmp# perf stat --per-thread --metrics ipc -p 21623 ^C Performance counter stats for process id '21623':
vmstat-21623 631,185 inst_retired.any
vmstat-21623 605,893 cpu_clk_unhalted.thread1.415679293 seconds time elapsed
2. With this patch, the result would be:
root@skl:/tmp# perf stat --per-thread -p 21623 ^C Performance counter stats for process id '21623':
vmstat-21623 0.533759 task-clock (msec) # 0.000 CPUs utilized
vmstat-21623 1 context-switches # 0.002 M/sec
vmstat-21623 0 cpu-migrations # 0.000 K/sec
vmstat-21623 0 page-faults # 0.000 K/sec
vmstat-21623 473,896 cycles # 0.888 GHz
vmstat-21623 631,072 instructions # 1.33 insn per cycle
vmstat-21623 136,307 branches # 255.372 M/sec
vmstat-21623 2,524 branch-misses # 1.85% of all branches1.544862861 seconds time elapsed
root@skl:/tmp# perf stat --per-thread --metrics ipc -p 21623 ^C Performance counter stats for process id '21623':
vmstat-21623 1,259,104 inst_retired.any # 1.2 IPC
vmstat-21623 1,056,756 cpu_clk_unhalted.thread2.040954502 seconds time elapsed
[1] https://marc.info/?l=linux-kernel&m=150777054620511&w=2
Originally-from: Jin Yao <[email protected]>
--- tools/perf/util/stat.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/stat.c +2 -0
@@ -278,6 +278,8 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evselperf_counts_values__scale (count, config->scale,NULL );if (config->aggr_mode ==AGGR_NONE )perf_stat__update_shadow_stats (evsel, count->val, cpu); +if (config->aggr_mode ==AGGR_THREAD ) +perf_stat__update_shadow_stats (evsel, count->val,0 );break ;case AGGR_GLOBAL : aggr->val += count->val;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 14/19 perf callchain: Fix double mapping al->addr for children without self period
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Milian Wolff found a problem he described in [1] and that for him would get fixed:
"Note how most of the large offset values are now gone. Most notably, we get proper srcline resolution for the random.h and complex headers."
Then Namhyung found the root cause:
"I looked into it and found a bug handling cumulative (children) entries. For children entries that have no self period, the al->addr (so he->ip) ends up having an doubly-mapped address.
It seems to be there from the beginning but only affects entries that have no srclines - finding srcline itself is done using a different address but it will show the invalid address if no srcline was found. I think we should fix the commit c7405d85d7a3 ("perf tools: Update cpumode for each cumulative entry")."
[1] https://lkml.kernel.org/r/[email protected]
--- tools/perf/util/callchain.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
tools/perf/util/callchain.c +1 -4
@@ -1091,10 +1091,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * al->map = node->map; al->sym = node->sym; al->srcline = node->srcline; -if (node->map) - al->addr = node->map->map_ip (node->map, node->ip); -else - al->addr = node->ip; + al->addr = node->ip;if (al->sym ==NULL ) {if (hide_unresolved)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 15/19 tools include uapi: Grab a copy of linux/kcmp.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We will use it to generate tables for beautifying kcmp's 'type' arg.
--- tools/include/uapi/linux/kcmp.h | 27 +++++++++++++++++++++++++++ tools/perf/check-headers.sh | 1 + 2 files changed, 28 insertions(+) create mode 100644 tools/include/uapi/linux/kcmp.h
tools/include/uapi/linux/kcmp.h new file +27 -0
@@ -0,0 +1,27 @@ +#ifndef _UAPI_LINUX_KCMP_H +#define _UAPI_LINUX_KCMP_H + +#include <linux/types.h> + +/* Comparison type */ +enum kcmp_type { +KCMP_FILE , +KCMP_VM , +KCMP_FILES , +KCMP_FS , +KCMP_SIGHAND , +KCMP_IO , +KCMP_SYSVSEM , +KCMP_EPOLL_TFD , + +KCMP_TYPES , +}; + +/* Slot for KCMP_EPOLL_TFD */ +struct kcmp_epoll_slot { +__u32 efd;/* epoll file descriptor */ +__u32 tfd;/* target file number */ +__u32 toff;/* target offset within same numbered sequence */ +}; + +#endif /* _UAPI_LINUX_KCMP_H */
tools/perf/check-headers.sh +1 -0
@@ -4,6 +4,7 @@ HEADERS=' include/uapi/drm/drm.h include/uapi/drm/i915_drm.h include/uapi/linux/fcntl.h +include/uapi/linux/kcmp.h include/uapi/linux/kvm.h include/uapi/linux/perf_event.h include/uapi/linux/prctl.h
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 16/19 perf trace beauty: Implement pid_fd beautifier
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
One that given a pid and a fd, will try to get the path for that fd. Will be used in the upcoming kcmp's KCMP_FILE beautifier.
--- tools/perf/builtin-trace.c | 17 +++++++++++++++++ tools/perf/trace/beauty/beauty.h | 3 +++ 2 files changed, 20 insertions(+)
tools/perf/builtin-trace.c +17 -0
@@ -988,6 +988,23 @@ size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)return printed; } +size_t pid__scnprintf_fd (struct trace *trace,pid_t pid,int fd,char *bf,size_t size) +{ +size_t printed =scnprintf (bf, size,"%d" , fd); +struct thread *thread =machine__find_thread (trace->host, pid, pid); + +if (thread) { +const char *path =thread__fd_path (thread, fd, trace); + +if (path) + printed +=scnprintf (bf + printed, size - printed,"<%s>" , path); + +thread__put (thread); + } + +return printed; +} +static size_t syscall_arg__scnprintf_close_fd (char *bf,size_t size,struct syscall_arg *arg) {
tools/perf/trace/beauty/beauty.h +3 -0
@@ -3,6 +3,7 @@#include <linux/kernel.h> #include <linux/types.h> +#include <sys/types.h> struct strarray {int offset;
@@ -26,6 +27,8 @@ size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const chastruct trace ;struct thread ; +size_t pid__scnprintf_fd (struct trace *trace,pid_t pid,int fd,char *bf,size_t size); +/** * @val: value of syscall argument being formatted * @args: All the args, use syscall_args__val(arg, nth) to access one
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 17/19 perf trace beauty kcmp: Beautify arguments
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
For some unknown reason there is no entry in tracefs's syscalls for kcmp, i.e. no tracefs/events/syscalls/sys_{enter,exit}_kcmp, so we need to provide a data dictionary for the fields.
To beautify the 'type' argument we automatically generate a strarray from tools/include/uapi/kcmp.h, the idx1 and idx2 args, nowadays used only if type == KCMP_FILE, are masked for all the other types and a lookup is made for the thread and fd to show the path, if possible, getting it from the probe:vfs_getname if in place or from procfs, races allowing.
A system wide strace like tracing session, with callchains shows just one user so far in this fedora 25 machine:
# perf trace --max-stack 5 -e kcmp
<SNIP>
1502914.400 ( 0.001 ms): systemd/1 kcmp(pid1: 1 (systemd), pid2: 1 (systemd), type: FILE, idx1: 271<socket:[4723475]>, idx2: 25<socket:[4788686]>) = -1 ENOSYS Function not implemented
syscall (/usr/lib64/libc-2.25.so)
same_fd (/usr/lib/systemd/libsystemd-shared-233.so)
service_add_fd_store (/usr/lib/systemd/systemd)
service_notify_message.lto_priv.127 (/usr/lib/systemd/systemd)
1502914.407 ( 0.001 ms): systemd/1 kcmp(pid1: 1 (systemd), pid2: 1 (systemd), type: FILE, idx1: 270<socket:[4726396]>, idx2: 25<socket:[4788686]>) = -1 ENOSYS Function not implemented
syscall (/usr/lib64/libc-2.25.so)
same_fd (/usr/lib/systemd/libsystemd-shared-233.so)
service_add_fd_store (/usr/lib/systemd/systemd)
service_notify_message.lto_priv.127 (/usr/lib/systemd/systemd)
<SNIP>The backtraces seem to agree this is really kcmp(), but this system doesn't have the sys_kcmp(), bummer:
# uname -a Linux jouet 4.14.0-rc3+ #1 SMP Fri Oct 13 12:21:12 -03 2017 x86_64 x86_64 x86_64 GNU/Linux # grep kcmp /proc/kallsyms ffffffffb60b8890 W sys_kcmp $ grep CONFIG_CHECKPOINT_RESTORE ../build/v4.14.0-rc3+/.config # CONFIG_CHECKPOINT_RESTORE is not set $
So systemd uses it, good fedora kernel config has it:
$ grep CONFIG_CHECKPOINT_RESTORE /boot/config-4.13.4-200.fc26.x86_64 CONFIG_CHECKPOINT_RESTORE=y [acme@jouet linux]$
/me goes to rebuild a kernel...
--- tools/perf/Makefile.perf | 9 ++++++++ tools/perf/builtin-trace.c | 6 +++++ tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 6 +++++ tools/perf/trace/beauty/kcmp.c | 44 ++++++++++++++++++++++++++++++++++++ tools/perf/trace/beauty/kcmp_type.sh | 10 ++++++++ 6 files changed, 76 insertions(+) create mode 100644 tools/perf/trace/beauty/kcmp.c create mode 100755 tools/perf/trace/beauty/kcmp_type.sh
tools/perf/Makefile.perf +9 -0
@@ -420,6 +420,13 @@ sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh $(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl) $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@ +kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c +kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/ +kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh + +$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl) + $(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@ + kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c kvm_hdr_dir := $(srctree)/tools/include/uapi/linux kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -553,6 +560,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc $(pkey_alloc_access_rights_array) \ $(sndrv_pcm_ioctl_array) \ $(sndrv_ctl_ioctl_array) \ + $(kcmp_type_array) \ $(kvm_ioctl_array) \ $(vhost_virtio_ioctl_array) \ $(madvise_behavior_array) \
@@ -836,6 +844,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea $(OUTPUT)$(sndrv_ctl_ioctl_array) \ $(OUTPUT)$(sndrv_pcm_ioctl_array) \ $(OUTPUT)$(kvm_ioctl_array) \ + $(OUTPUT)$(kcmp_type_array) \ $(OUTPUT)$(vhost_virtio_ioctl_array) \ $(OUTPUT)$(perf_ioctl_array) \ $(OUTPUT)$(prctl_option_array)
tools/perf/builtin-trace.c +6 -0
@@ -633,6 +633,12 @@ static struct syscall_fmt { #else [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, }, #endif + { .name = "kcmp", .nr_args = 5, + .arg = { [0] = { .name = "pid1", .scnprintf = SCA_PID, }, + [1] = { .name = "pid2", .scnprintf = SCA_PID, }, + [2] = { .name = "type", .scnprintf = SCA_KCMP_TYPE, }, + [3] = { .name = "idx1", .scnprintf = SCA_KCMP_IDX, }, + [4] = { .name = "idx2", .scnprintf = SCA_KCMP_IDX, }, }, }, { .name = "keyctl", .arg = { [0] = STRARRAY(option, keyctl_options), }, }, { .name = "kill",
tools/perf/trace/beauty/Build +1 -0
@@ -3,6 +3,7 @@ libperf-y += fcntl.o ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) libperf-y += ioctl.o endif +libperf-y += kcmp.o libperf-y += pkey_alloc.o libperf-y += prctl.o libperf-y += statx.o
tools/perf/trace/beauty/beauty.h +6 -0
@@ -81,6 +81,12 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arsize_t syscall_arg__scnprintf_ioctl_cmd (char *bf,size_t size,struct syscall_arg *arg);#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd +size_t syscall_arg__scnprintf_kcmp_type (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_KCMP_TYPE syscall_arg__scnprintf_kcmp_type + +size_t syscall_arg__scnprintf_kcmp_idx (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx +size_t syscall_arg__scnprintf_pkey_alloc_access_rights (char *bf,size_t size,struct syscall_arg *arg);#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
tools/perf/trace/beauty/kcmp.c new file +44 -0
44 lines not on this page · raw message
tools/perf/trace/beauty/kcmp_type.sh new file +10 -0
@@ -0,0 +1,10 @@ +#!/bin/sh + +header_dir=$1 + +printf "static const char *kcmp_types[] = {\n" +regex='^[[:space:]]+(KCMP_(\w+)),' +egrep $regex ${header_dir}/kcmp.h | grep -v KCMP_TYPES, | \ + sed -r "s/$regex/\1 \2/g" | \ + xargs printf "\t[%s]\t= \"%s\",\n" +printf "};\n"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 18/19 perf srcline: Fix memory leak in addr2inlines()
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When libbfd is not used, addr2inlines() executes addr2line -i and process output line by line. But it resets filename to NULL in the loop so getline() allocates additional memory everytime instead of realloc.
--- tools/perf/util/srcline.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
tools/perf/util/srcline.c +2 -5
@@ -456,20 +456,17 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,while (getline (&filename, &len, fp) !=-1 ) {char *srcline; -if (filename_split (filename, &line_nr) !=1 ) { -free (filename); +if (filename_split (filename, &line_nr) !=1 ) goto out; - } srcline =srcline_from_fileline (filename, line_nr);if (inline_list__append (sym, srcline, node) !=0 ) goto out; - - filename =NULL ; } out:pclose (fp); +free (filename);return node; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 19/19 perf srcline: Show correct function name for srcline of callchains
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When libbfd is not used, it doesn't show proper function name and reuse the original symbol of the sample. That's because it passes the original sym to inline_list__append(). As addr2line -f returns function names as well, use that to create an inline_sym and pass it to inline_list__append().
For example, following data shows that inlined entries of main have same name (main).
Before:
$ perf report -g srcline -q | head
45.22% inlining libm-2.26.so [.] __hypot_finite
|
---__hypot_finite ??:0
|
|--44.15%--hypot ??:0
| main complex:589
| main complex:597
| main complex:654
| main complex:664
| main inlining.cpp:14After:
$ perf report -g srcline -q | head
45.22% inlining libm-2.26.so [.] __hypot_finite
|
---__hypot_finite
|
|--44.15%--hypot
| std::__complex_abs complex:589 (inlined)
| std::abs<double> complex:597 (inlined)
| std::_Norm_helper<true>::_S_do_it<double> complex:654 (inlined)
| std::norm<double> complex:664 (inlined)
| main inlining.cpp:14--- tools/perf/util/srcline.c | 95 +++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 40 deletions(-)
tools/perf/util/srcline.c +55 -40
@@ -10,7 +10,7 @@#include "util/debug.h" #include "util/callchain.h" #include "srcline.h" - +#include "string2.h" #include "symbol.h" bool srcline_full_filename;
@@ -77,6 +77,41 @@ static char *srcline_from_fileline(const char *file, unsigned int line)return srcline; } +static struct symbol *new_inline_sym (struct dso *dso, +struct symbol *base_sym, +const char *funcname) +{ +struct symbol *inline_sym; +char *demangled =NULL ; + +if (dso) { + demangled =dso__demangle_sym (dso,0 , funcname); +if (demangled) + funcname = demangled; + } + +if (base_sym &&strcmp (funcname, base_sym->name) ==0 ) { +/* reuse the real, existing symbol */ + inline_sym = base_sym; +/* ensure that we don't alias an inlined symbol, which could +* lead to double frees in inline_node__delete +*/ +assert (!base_sym->inlined); + }else { +/* create a fake symbol for the inline frame */ + inline_sym =symbol__new (base_sym ? base_sym->start :0 , + base_sym ? base_sym->end :0 , + base_sym ? base_sym->binding :0 , + funcname); +if (inline_sym) + inline_sym->inlined =1 ; + } + +free (demangled); + +return inline_sym; +} +#ifdef HAVE_LIBBFD_SUPPORT /*
@@ -219,41 +254,6 @@ static void addr2line_cleanup(struct a2l_data *a2l)#define MAX_INLINE_NEST 1024 -static struct symbol *new_inline_sym (struct dso *dso, -struct symbol *base_sym, -const char *funcname) -{ -struct symbol *inline_sym; -char *demangled =NULL ; - -if (dso) { - demangled =dso__demangle_sym (dso,0 , funcname); -if (demangled) - funcname = demangled; - } - -if (base_sym &&strcmp (funcname, base_sym->name) ==0 ) { -/* reuse the real, existing symbol */ - inline_sym = base_sym; -/* ensure that we don't alias an inlined symbol, which could -* lead to double frees in inline_node__delete -*/ -assert (!base_sym->inlined); - }else { -/* create a fake symbol for the inline frame */ - inline_sym =symbol__new (base_sym ? base_sym->start :0 , - base_sym ? base_sym->end :0 , - base_sym ? base_sym->binding :0 , - funcname); -if (inline_sym) - inline_sym->inlined =1 ; - } - -free (demangled); - -return inline_sym; -} -static int inline_list__append_dso_a2l (struct dso *dso,struct inline_node *node,struct symbol *sym)
@@ -432,10 +432,11 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,char cmd[PATH_MAX ];struct inline_node *node;char *filename =NULL ; -size_t len; +char *funcname =NULL ; +size_t filelen, funclen;unsigned int line_nr =0 ; -scnprintf (cmd,sizeof (cmd),"addr2line -e %s -i %016" PRIx64, +scnprintf (cmd,sizeof (cmd),"addr2line -e %s -i -f %016" PRIx64, dso_name, addr); fp =popen (cmd,"r" );
@@ -453,20 +454,34 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,INIT_LIST_HEAD (&node->val); node->addr = addr; -while (getline (&filename, &len, fp) !=-1 ) { +/* addr2line -f generates two lines for each inlined functions */ +while (getline (&funcname, &funclen, fp) !=-1 ) {char *srcline; +struct symbol *inline_sym; + +rtrim (funcname); + +if (getline (&filename, &filelen, fp) ==-1 ) + goto out;if (filename_split (filename, &line_nr) !=1 ) goto out; srcline =srcline_from_fileline (filename, line_nr); -if (inline_list__append (sym, srcline, node) !=0 ) + inline_sym =new_inline_sym (dso, sym, funcname); + +if (inline_list__append (inline_sym, srcline, node) !=0 ) { +free (srcline); +if (inline_sym && inline_sym->inlined) +symbol__delete (inline_sym); goto out; + } } out:pclose (fp);free (filename); +free (funcname);return node; }
Signature · 1 line
2.13.6