perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit 7862edc4191123f9c7e7ec0a7b356d332a61c41e:
Merge remote-tracking branch 'torvalds/master' into perf/core (2017-11-13 09:39:12 -0300)
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-20171117
for you to fetch changes up to 05d3f1a1d5a3d37ca4b591d5524f5a5b159d0564:
perf tools: Move symbol__calc_percent() call to outside symbol__disassemble() (2017-11-17 12:16:26 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
- Optimize sample parsing for ordering events, where we don't need to parse all the PERF_SAMPLE_ bits, just the ones leading to the timestamp needed to reorder events (Jiri Olsa)
- Use a dummy event to ask for PERF_RECORD_{MMAP,COMM,EXEC} with 'perf record --delay', when the events asked by the user will only be enabled after the workload is started and the requested delay passes, so we need to add the dummy event and have it .enabled_on_exec. This then allows us to resolve symbols for the DSO executable MMAPs setup while we wait for the delay (Arnaldo Carvalho de Melo)
- Synchronize kcmp.h and prctl.h ABI headers wrt SPDX tags (Arnaldo Carvalho de Melo)
- Generalize the annotation code to support other source information besides objdump/DWARF obtained ones, starting with python scripts, that will is slated to be merged soon (Jiri Olsa)
- Advance the source code lines to right after the column with the address in asm lines (Jiri Olsa)
- Fix terminal dimensions resizing signal handling in 'perf top --stdio' (Jiri Olsa)
- Improve error messages for PMU events (Kim Phillips)
- Fix 'perf record' -c/-F options for cpu event aliases (Andi Kleen)
- Enable type checking for perf_evsel_config_term types (Andi Kleen)
- Call machine__exit() at 'perf trace' exit, so as to remove temporary files related to VDSO (Andrei Vagin)
- Add "reject" option to parse-events.l, fixing the build with newer flex releases. Noticed with flex 2.6.4 on Alpine Linux 3.6 and Edge (Jiri Olsa)
- Document some missing perf.data headers (Andi Kleen)
- Allow printing period for non freq mod groups (Andi Kleen)
- Do not warn the user about kernel.kptr_restrict when not sampling the kernel (Arnaldo Carvalho de Melo)
- Fix bug in 'perf help' introduced during conversion to strstart() (Namhyung Kim)
- Do not truncate ASM instruction mnemonics at 6 characters in the annotation output, PowerPC has long ones (Ravi Bangoria)
- Document some missing command line options (Sihyeon Jang)
- Update POWER9 vendor event tables (Sukadev Bhattiprolu)
- Fix 'perf test' shell entries on s390x, where the 'openat' syscall is used instead of 'open' in one of the tests and
- No need to use overwrite mmap mode in 'perf test', those tests do not generate massive amount of events to fill the ring buffer (Wang Nan)
- Add missing command line options (mostly --force/-f) to the man pages (Sihyeon Jang)
----------------------------------------------------------------
Andi Kleen (4):
perf record: Fix -c/-F options for cpu event aliases perf evsel: Enable type checking for perf_evsel_config_term types perf tools: Document some missing perf.data headers perf script: Allow printing period for non freq mode groups
Andrei Vagin (1):
perf trace: Fix an exit code of trace__symbols_init
Arnaldo Carvalho de Melo (10):
perf evlist: Set the correct idx when adding dummy events
perf record: Generate PERF_RECORD_{MMAP,COMM,EXEC} with --delay tools headers: Synchronize kernel ABI headers wrt SPDX tags perf evsel: Fix up leftover perf_evsel_stat usage via evsel->priv perf script: Fix --per-event-dump for auxtrace synth evsels perf machine: Guard against NULL in machine__exit()
perf evlist: Add helper to check if attr.exclude_kernel is set in all evsels perf report: Ignore kptr_restrict when not sampling the kernel perf record: Ignore kptr_restrict when not sampling the kernel perf top: Ignore kptr_restrict when not sampling the kernel
Jiri Olsa (46):
perf annotate: Add annotation_line struct
perf annotate: Move line/offset into annotation_line struct
perf annotate: Move ipc/cycles into annotation_line struct
perf annotate: Add symbol__annotate function
perf annotate: Add struct annotate_args
perf annotate: Add arch into struct annotate_args
perf annotate: Add map into struct annotate_args
perf annotate: Add offset/line/line_nr into struct annotate_args perf annotate: Add evsel into struct annotation_line_args
perf annotate: Add annotation_line__next function
perf annotate: Add annotation_line__add function
perf annotate: Move rb_node to struct annotation_line
perf annotate: Add annotation_line__(new|delete) functions
perf annotate: Add annotated_source__purge function
perf annotate: Add samples into struct annotation_line
perf annotate: Add symbol__calc_percent function
perf annotate: Add symbol__calc_lines function
perf annotate: Remove disasm__calc_percent() from disasm_line__print() perf annotate: Remove disasm__calc_percent() from annotate_browser__calc_percent() perf annotate: Remove disasm__calc_percent function
perf annotate: Remove struct source_line
perf annotate: Add annotation_line__print function
perf annotate: Factor annotation_line__print from disasm_line__print perf annotate browser: Use samples data from struct annotation_line perf annotate browser: Do not pass nr_events in disasm_rb_tree__insert perf annotate browser: Rename struct browser_disasm_line to browser_line perf annotate browser: Rename disasm_line__browser to browser_line perf annotate browser: Change selection to struct annotation_line perf annotate browser: Change offsets to struct annotation_line
perf annotate browser: Use struct annotation_line in browser_line perf annotate browser: Use struct annotation_line in find functions perf annotate browser: Use struct annotation_line in browser top perf annotate browser: Add disasm_line__write function
perf annotate: Align source and offset lines
perf tools: Use shell function for perl cflags retrieval
perf: Fix header.size for namespace events
perf callchain: Reset cursor arg instead of callchain_cursor
perf evsel: Centralize perf_sample initialization
perf evlist: Add perf_evlist__parse_sample_timestamp function
perf ordered_events: Pass timestamp arg in perf_session__queue_event perf tools: Optimize sample parsing for ordered events
perf top: Fix window dimensions change handling
perf top: Use signal interface for SIGWINCH handler
perf top: Fix crash when annotating symbol
perf tools: Change (symbol|annotation)__calc_percent return type to void perf tools: Move symbol__calc_percent() call to outside symbol__disassemble()
Kim Phillips (2):
perf c2c: Fix spelling mistakes in browser help text
perf evsel: Say which PMU Hardware event doesn't support sampling/overflow-interrupts
Namhyung Kim (1):
perf help: Fix a bug during strstart() conversion
Ravi Bangoria (1):
perf annotate: Do not truncate instruction names at 6 chars
Seonghyun Park (1):
perf tests: Add missing WRITE_ASS for new fields of perf_event_attr
Sihyeon Jang (9):
perf top: Document missing options
perf top: Remove a duplicate word
perf lock: Document missing options
perf inject: Document missing options
perf trace: Document missing option, colons perf timechart: Document missing --force option perf sched: Document missing --force option perf evlist: Document missing --force option perf buildid-cache: Document missing --force option
Sukadev Bhattiprolu (1):
perf vendor events powerpc: Update POWER9 events
Thomas Richter (2):
perf test shell: Fix check open filename arg using 'perf trace' on s390x
perf test shell: Fix test case probe libc's inet_pton on s390xThomas-Mich Richter (1):
perf buildid-cache: Update help text for purge command
Wang Nan (4):
perf tests: Set evlist of test__backward_ring_buffer() to !overwrite perf tests: Set evlist of test__sw_clock_freq() to !overwrite perf tests: Set evlist of test__basic_mmap() to !overwrite perf tests: Set evlist of test__task_exit() to !overwrite
kernel/events/core.c | 5 +- tools/include/uapi/linux/kcmp.h | 1 + tools/include/uapi/linux/prctl.h | 1 + tools/perf/Documentation/perf-buildid-cache.txt | 3 + tools/perf/Documentation/perf-evlist.txt | 4 + tools/perf/Documentation/perf-inject.txt | 4 + tools/perf/Documentation/perf-lock.txt | 4 + tools/perf/Documentation/perf-sched.txt | 4 + tools/perf/Documentation/perf-timechart.txt | 4 +- tools/perf/Documentation/perf-top.txt | 6 + tools/perf/Documentation/perf-trace.txt | 16 +- tools/perf/Documentation/perf.data-file-format.txt | 23 + tools/perf/Makefile.config | 2 +- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-c2c.c | 8 +- tools/perf/builtin-help.c | 4 +- tools/perf/builtin-kvm.c | 8 +- tools/perf/builtin-record.c | 42 +- tools/perf/builtin-report.c | 3 + tools/perf/builtin-script.c | 36 +- tools/perf/builtin-top.c | 44 +- tools/perf/builtin-trace.c | 6 +- .../perf/pmu-events/arch/powerpc/power9/cache.json | 5 - .../pmu-events/arch/powerpc/power9/frontend.json | 7 +- .../pmu-events/arch/powerpc/power9/marked.json | 27 +- .../perf/pmu-events/arch/powerpc/power9/other.json | 276 +++------ .../pmu-events/arch/powerpc/power9/pipeline.json | 14 +- tools/perf/pmu-events/arch/powerpc/power9/pmc.json | 2 +- .../arch/powerpc/power9/translation.json | 5 - tools/perf/tests/attr.c | 6 + tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- .../perf/tests/shell/trace+probe_libc_inet_pton.sh | 7 +- tools/perf/tests/shell/trace+probe_vfs_getname.sh | 6 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/ui/browsers/annotate.c | 401 +++++++------ tools/perf/ui/gtk/annotate.c | 25 +- tools/perf/util/annotate.c | 651 +++++++++++---------- tools/perf/util/annotate.h | 76 +-- tools/perf/util/evlist.c | 25 +- tools/perf/util/evlist.h | 6 + tools/perf/util/evsel.c | 92 ++- tools/perf/util/evsel.h | 10 +- tools/perf/util/machine.c | 5 +- tools/perf/util/ordered-events.c | 3 +- tools/perf/util/ordered-events.h | 2 +- tools/perf/util/parse-events.c | 2 + tools/perf/util/parse-events.h | 3 + tools/perf/util/pmu.c | 5 + tools/perf/util/session.c | 45 +- tools/perf/util/session.h | 2 +- 52 files changed, 1028 insertions(+), 920 deletions(-)
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-16) 7.2.0 14 debian:experimental-x-arm64: Ok aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 15 debian:experimental-x-mips: Ok mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 16 debian:experimental-x-mips64: Ok mips64-linux-gnuabi64-gcc (Debian 7.2.0-11) 7.2.0 17 fedora:20: Ok gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) 18 fedora:21: Ok gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) 19 fedora:22: Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 20 fedora:23: Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 21 fedora:24: Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) 22 fedora:24-x-ARC-uClibc: Ok arc-linux-gcc (ARCompact ISA Linux uClibc toolchain 2017.09-rc2) 7.1.1 20170710 23 fedora:25: Ok gcc (GCC) 6.4.1 20170727 (Red Hat 6.4.1-1) 24 fedora:26: Ok gcc (GCC) 7.2.1 20170915 (Red Hat 7.2.1-2) 25 fedora:27: FAIL gcc (GCC) 7.2.1 20170915 (Red Hat 7.2.1-2)
/usr/bin/ld: /tmp/build/perf/perf-in.o: relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /tmp/build/perf/libperf.a(libperf-in.o): relocation R_X86_64_32S against .text' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Jiri is working on a fix for this hardened build situation, where some CFLAGS used for perl/python are incompatible with what we use for the rest of the tools.
26 fedora:rawhide: Ok gcc (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1) 27 gentoo-stage3-amd64:latest: Ok gcc (Gentoo 5.4.0-r3 p1.7, pie-0.6.5) 5.4.0 28 mageia:5: Ok gcc (GCC) 4.9.2 29 mageia:6: Ok gcc (Mageia 5.4.0-5.mga6) 5.4.0 30 opensuse:42.1: Ok gcc (SUSE Linux) 4.8.5 31 opensuse:42.2: Ok gcc (SUSE Linux) 4.8.5 32 opensuse:42.3: Ok gcc (SUSE Linux) 4.8.5 33 opensuse:tumbleweed: Ok gcc (SUSE Linux) 7.2.1 20170901 [gcc-7-branch revision 251580] 34 oraclelinux:6: Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) 35 oraclelinux:7: Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) 36 ubuntu:12.04.5: Ok gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 37 ubuntu:14.04.4: Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 38 ubuntu:14.04.4-x-linaro-arm64: Ok aarch64-linux-gnu-gcc 39 ubuntu:15.04: Ok gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 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+ #2 SMP Thu Nov 16 12:09:19 -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_auxtrace_O: make NO_AUXTRACE=1
make_perf_o_O: make perf.o
make_install_prefix_O: make install prefix=/tmp/krava
make_no_libunwind_O: make NO_LIBUNWIND=1
make_util_map_o_O: make util/map.o
make_no_gtk2_O: make NO_GTK2=1
make_no_newt_O: make NO_NEWT=1
make_doc_O: make doc
make_pure_O: make
make_no_demangle_O: make NO_DEMANGLE=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_no_libnuma_O: make NO_LIBNUMA=1
make_install_bin_O: make install-bin
make_static_O: make LDFLAGS=-static
make_no_libbpf_O: make NO_LIBBPF=1
make_install_O: make install
make_no_libelf_O: make NO_LIBELF=1
make_help_O: make help
make_no_libbionic_O: make NO_LIBBIONIC=1
make_no_libaudit_O: make NO_LIBAUDIT=1
make_tags_O: make tags
make_no_slang_O: make NO_SLANG=1
make_debug_O: make DEBUG=1
make_no_libperl_O: make NO_LIBPERL=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_clean_all_O: make clean all
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
make_with_babeltrace_O: make LIBBABELTRACE=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_no_libpython_O: make NO_LIBPYTHON=1 make_with_clangllvm_O: make LIBCLANGLLVM=1
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_install_prefix_slash_O: make install prefix=/tmp/krava/
OK
make: Leaving directory '/home/acme/git/linux/tools/perf' $
Arnaldo Carvalho de Melo
maintainerPATCH 1/83 perf evlist: Set the correct idx when adding dummy events
From: Arnaldo Carvalho de Melo <[email protected]>
The evsel->idx field is used mainly to access the right bucket in per-event arrays such as the annotation ones, but also to set evsel->tracking, that in turn will decide what of the events will ask for PERF_RECORD_{MMAP,COMM,EXEC} to be generated, i.e. which perf_event_attr will have its mmap, etc fields set.
When we were adding the "dummy" event using perf_evlist__add_dummy() we were not setting it correctly, which could result in multiple tracking events.
Now that I'll try using a dummy event to be the tracking one when using 'perf record --delay', i.e. when we process the --delay setting we may already have the evlist set up, like with:
perf record -e cycles,instructions --delay 1000 ./workload
We will need to add a "dummy" event, then reset evsel->tracking for the first event, "cycles", and set it instead to the dummy one, and also setting its attr.enable_on_exec, so that we get the PERF_RECORD_MMAP, etc metadata events while waiting to enable the explicitely requested events, so lets get this straight and set the right evsel->idx.
--- tools/perf/util/evlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evlist.c +1 -1
@@ -257,7 +257,7 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist) .config = PERF_COUNT_SW_DUMMY, .size = sizeof(attr), /* to capture ABI version */ }; -struct perf_evsel *evsel =perf_evsel__new (&attr); +struct perf_evsel *evsel =perf_evsel__new_idx (&attr, evlist->nr_entries);if (evsel ==NULL )return -ENOMEM ;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 2/83 perf record: Generate PERF_RECORD_{MMAP,COMM,EXEC} with --delay
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
When we use an initial delay, e.g.: 'perf record --delay 1000', we do not enable the events until that delay has passed after we started the workload, including the tracking event, i.e. the one for which we have attr.mmap, etc, enabled to ask the kernel to generate the PERF_RECORD_{MMAP,COMM,EXEC} metadata events that will then allow us to resolve addresses in samples to the map, dso and symbol. There will be a shadow that even synthesizing samples won't cover, i.e. the workload that we start and other processes forking while we wait for the initial delay to expire.
So use a dummy event to be the tracking one and make it be enabled on exec.
Before:
# perf record --delay 1000 stress --cpu 1 --timeout 5
stress: info: [9029] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [9029] successful run completed in 5s
[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 0.624 MB perf.data (15908 samples) ]
# perf script | head
:9031 9031 32001.826888: 1 cycles:ppp: ffffffff831aa30d event_function (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826893: 1 cycles:ppp: ffffffff8300d1a0 intel_bts_enable_local (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826895: 7 cycles:ppp: ffffffff83023870 sched_clock (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826897: 103 cycles:ppp: ffffffff8300c331 intel_pmu_handle_irq (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826899: 1615 cycles:ppp: ffffffff830231f8 native_sched_clock (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826902: 26724 cycles:ppp: ffffffff8384c6a7 native_irq_return_iret (/lib/modules/4.14.0-rc6+/build/vmlinux)
:9031 9031 32001.826913: 329739 cycles:ppp: 7fb2a5410932 [unknown] ([unknown])
:9031 9031 32001.827033: 1225451 cycles:ppp: 7fb2a5410930 [unknown] ([unknown])
:9031 9031 32001.827474: 1391725 cycles:ppp: 7fb2a5410930 [unknown] ([unknown])
:9031 9031 32001.827978: 1233697 cycles:ppp: 7fb2a5410928 [unknown] ([unknown])
#After:
# perf record --delay 1000 stress --cpu 1 --timeout 5
stress: info: [9741] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [9741] successful run completed in 5s
[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 0.751 MB perf.data (15976 samples) ]
# perf script | head
stress 9742 32110.959106: 1 cycles:ppp: ffffffff831b26f6 __perf_event_task_sched_in (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959110: 1 cycles:ppp: ffffffff8300c2e9 intel_pmu_handle_irq (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959112: 7 cycles:ppp: ffffffff830231e0 native_sched_clock (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959115: 101 cycles:ppp: ffffffff83023870 sched_clock (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959117: 1533 cycles:ppp: ffffffff830231f8 native_sched_clock (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959119: 23992 cycles:ppp: ffffffff831b0900 ctx_sched_in (/lib/modules/4.14.0-rc6+/build/vmlinux)
stress 9742 32110.959129: 329406 cycles:ppp: 7f4b1b661930 __random_r (/usr/lib64/libc-2.25.so)
stress 9742 32110.959249: 1288322 cycles:ppp: 5566e1e7cbc9 hogcpu (/usr/bin/stress)
stress 9742 32110.959712: 1464046 cycles:ppp: 7f4b1b66179e __random (/usr/lib64/libc-2.25.so)
stress 9742 32110.960241: 1266918 cycles:ppp: 7f4b1b66195b __random_r (/usr/lib64/libc-2.25.so)
#--- tools/perf/builtin-record.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
tools/perf/builtin-record.c +16 -0
@@ -339,6 +339,22 @@ static int record__open(struct record *rec)struct perf_evsel_config_term *err_term;int rc =0 ; +/* +* For initial_delay we need to add a dummy event so that we can track +* PERF_RECORD_MMAP while we wait for the initial delay to enable the +* real events, the ones asked by the user. +*/ +if (opts->initial_delay) { +if (perf_evlist__add_dummy (evlist)) +return -ENOMEM ; + + pos =perf_evlist__first (evlist); + pos->tracking =0 ; + pos =perf_evlist__last (evlist); + pos->tracking =1 ; + pos->attr.enable_on_exec =1 ; + } +perf_evlist__config (evlist, opts, &callchain_param);evlist__for_each_entry (evlist, pos) {
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 3/83 perf annotate: Add annotation_line struct
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
In order to make the annotation support generic, addadding 'struct annotation_line', which will hold generic data common to annotation sources (such as the one for python scripts, coming on upcoming patches).
Having this, we can add different annotation line support other than objdump disasm.
--- tools/perf/ui/browsers/annotate.c | 34 +++++++++++++++++----------------- tools/perf/ui/gtk/annotate.c | 6 +++--- tools/perf/util/annotate.c | 20 ++++++++++---------- tools/perf/util/annotate.h | 20 ++++++++++++-------- 4 files changed, 42 insertions(+), 38 deletions(-)
tools/perf/ui/browsers/annotate.c +17 -17
@@ -84,7 +84,7 @@ static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, void *entry) {if (annotate_browser__opts.hide_src_code) { - struct disasm_line *dl = list_entry(entry, struct disasm_line, node); + struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node);return dl->offset ==-1 ; }
@@ -123,7 +123,7 @@ static int annotate_browser__cycles_width(struct annotate_browser *ab)static void annotate_browser__write (struct ui_browser *browser,void *entry,int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); - struct disasm_line *dl = list_entry(entry, struct disasm_line, node); + struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node);struct browser_disasm_line *bdl =disasm_line__browser (dl);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!annotate_browser__opts.hide_src_code &&
@@ -286,7 +286,7 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *systatic bool is_fused (struct annotate_browser *ab,struct disasm_line *cursor) { -struct disasm_line *pos =list_prev_entry (cursor, node); +struct disasm_line *pos =list_prev_entry (cursor, al.node);const char *name;if (!pos)
@@ -404,16 +404,16 @@ static void annotate_browser__set_top(struct annotate_browser *browser, browser->b.top_idx = browser->b.index = idx;while (browser->b.top_idx !=0 && back !=0 ) { - pos = list_entry(pos->node.prev, struct disasm_line, node); + pos = list_entry(pos->al.node.prev, struct disasm_line, al.node); -if (disasm_line__filter (&browser->b, &pos->node)) +if (disasm_line__filter (&browser->b, &pos->al.node))continue ; --browser->b.top_idx; --back; } - browser->b.top = pos; + browser->b.top = &pos->al; browser->b.navkeypressed = true; }
@@ -446,7 +446,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,pthread_mutex_lock (¬es->lock); -list_for_each_entry (pos, ¬es->src->source, node) { +list_for_each_entry (pos, ¬es->src->source, al.node) {struct browser_disasm_line *bpos =disasm_line__browser (pos);const char *path =NULL ;double max_percent =0.0 ;
@@ -492,7 +492,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek (&browser->b, offset,SEEK_CUR ); - dl = list_entry(browser->b.top, struct disasm_line, node); + dl = list_entry(browser->b.top, struct disasm_line, al.node); bdl =disasm_line__browser (dl);if (annotate_browser__opts.hide_src_code) {
@@ -589,10 +589,10 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browsstruct disasm_line *pos; *idx =0 ; -list_for_each_entry (pos, ¬es->src->source, node) { +list_for_each_entry (pos, ¬es->src->source, al.node) {if (pos->offset == offset)return pos; -if (!disasm_line__filter (&browser->b, &pos->node)) +if (!disasm_line__filter (&browser->b, &pos->al.node)) ++*idx; }
@@ -630,8 +630,8 @@ struct disasm_line *annotate_browser__find_string(struct annotate_browser *browsstruct disasm_line *pos = browser->selection; *idx = browser->b.index; -list_for_each_entry_continue (pos, ¬es->src->source, node) { -if (disasm_line__filter (&browser->b, &pos->node)) +list_for_each_entry_continue (pos, ¬es->src->source, al.node) { +if (disasm_line__filter (&browser->b, &pos->al.node))continue ; ++*idx;
@@ -669,8 +669,8 @@ struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browsestruct disasm_line *pos = browser->selection; *idx = browser->b.index; -list_for_each_entry_continue_reverse (pos, ¬es->src->source, node) { -if (disasm_line__filter (&browser->b, &pos->node)) +list_for_each_entry_continue_reverse (pos, ¬es->src->source, al.node) { +if (disasm_line__filter (&browser->b, &pos->al.node))continue ; --*idx;
@@ -1134,7 +1134,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, notes =symbol__annotation (sym); browser.start =map__rip_2objdump (map, sym->start); -list_for_each_entry (pos, ¬es->src->source, node) { +list_for_each_entry (pos, ¬es->src->source, al.node) {struct browser_disasm_line *bpos;size_t line_len =strlen (pos->line);
@@ -1174,8 +1174,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,annotate_browser__update_addr_width (&browser); ret =annotate_browser__run (&browser, evsel, hbt); -list_for_each_entry_safe (pos, n, ¬es->src->source, node) { -list_del (&pos->node); +list_for_each_entry_safe (pos, n, ¬es->src->source, al.node) { +list_del (&pos->al.node);disasm_line__free (pos); }
tools/perf/ui/gtk/annotate.c +3 -3
@@ -119,7 +119,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,gtk_tree_view_set_model (GTK_TREE_VIEW (view),GTK_TREE_MODEL (store));g_object_unref (GTK_TREE_MODEL (store)); -list_for_each_entry (pos, ¬es->src->source, node) { +list_for_each_entry (pos, ¬es->src->source, al.node) {GtkTreeIter iter;int ret =0 ;
@@ -148,8 +148,8 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,gtk_container_add (GTK_CONTAINER (window), view); -list_for_each_entry_safe (pos, n, ¬es->src->source, node) { -list_del (&pos->node); +list_for_each_entry_safe (pos, n, ¬es->src->source, al.node) { +list_del (&pos->al.node);disasm_line__free (pos); }
tools/perf/util/annotate.c +10 -10
@@ -931,12 +931,12 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool rstatic void disasm__add (struct list_head *head,struct disasm_line *line) { -list_add_tail (&line->node, head); +list_add_tail (&line->al.node, head); }struct disasm_line *disasm__get_next_ip_line (struct list_head *head,struct disasm_line *pos) { -list_for_each_entry_continue (pos, head, node) +list_for_each_entry_continue (pos, head, al.node)if (pos->offset >=0 )return pos;
@@ -1122,7 +1122,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 streturn 1 ;if (queue !=NULL ) { -list_for_each_entry_from (queue, ¬es->src->source, node) { +list_for_each_entry_from (queue, ¬es->src->source, al.node) {if (queue == dl)break ; disasm_line__print(queue, sym, start, evsel, len,
@@ -1305,7 +1305,7 @@ static void delete_last_nop(struct symbol *sym)struct disasm_line *dl;while (!list_empty (list)) { - dl = list_entry(list->prev, struct disasm_line, node); + dl = list_entry(list->prev, struct disasm_line, al.node);if (dl->ins.ops) {if (dl->ins.ops != &nop_ops)
@@ -1317,7 +1317,7 @@ static void delete_last_nop(struct symbol *sym)return ; } -list_del (&dl->node); +list_del (&dl->al.node);disasm_line__free (dl); } }
@@ -1844,7 +1844,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,if (verbose >0 )symbol__annotate_hits (sym, evsel); -list_for_each_entry (pos, ¬es->src->source, node) { +list_for_each_entry (pos, ¬es->src->source, al.node) {if (context && queue ==NULL ) { queue = pos; queue_len =0 ;
@@ -1874,7 +1874,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,if (!context)break ;if (queue_len == context) - queue =list_entry (queue->node.next,typeof (*queue), node); + queue =list_entry (queue->al.node.next,typeof (*queue), al.node);else ++queue_len;break ;
@@ -1911,8 +1911,8 @@ void disasm__purge(struct list_head *head) {struct disasm_line *pos, *n; -list_for_each_entry_safe (pos, n, head, node) { -list_del (&pos->node); +list_for_each_entry_safe (pos, n, head, al.node) { +list_del (&pos->al.node);disasm_line__free (pos); } }
@@ -1939,7 +1939,7 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)struct disasm_line *pos;size_t printed =0 ; -list_for_each_entry (pos, head, node) +list_for_each_entry (pos, head, al.node) printed +=disasm_line__fprintf (pos, fp);return printed;
tools/perf/util/annotate.h +12 -8
@@ -59,15 +59,19 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);struct annotation ; +struct annotation_line { +struct list_head node; +}; +struct disasm_line { -struct list_head node; -s64 offset; -char *line; -struct ins ins; -int line_nr; -float ipc; -u64 cycles; -struct ins_operands ops; +struct annotation_line al; +s64 offset; +char *line; +struct ins ins; +int line_nr; +float ipc; +u64 cycles; +struct ins_operands ops; };static inline bool disasm_line__has_offset (const struct disasm_line *dl)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 4/83 perf annotate: Move line/offset into annotation_line struct
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move the line/line_nr/offset menbers to the annotation_line struct to be used as generic members for any annotation source.
--- tools/perf/ui/browsers/annotate.c | 45 ++++++++++++++++++++------------------- tools/perf/ui/gtk/annotate.c | 14 ++++++------ tools/perf/util/annotate.c | 41 ++++++++++++++++++----------------- tools/perf/util/annotate.h | 6 +++--- 4 files changed, 54 insertions(+), 52 deletions(-)
tools/perf/ui/browsers/annotate.c +23 -22
@@ -84,8 +84,9 @@ static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, void *entry) {if (annotate_browser__opts.hide_src_code) { - struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); -return dl->offset ==-1 ; + struct annotation_line *al = list_entry(entry, struct annotation_line, node); + +return al->offset ==-1 ; }return false;
@@ -141,7 +142,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int percent_max = bdl->samples[i].percent; } -if ((row ==0 ) && (dl->offset ==-1 || percent_max ==0.0 )) { +if ((row ==0 ) && (dl->al.offset ==-1 || percent_max ==0.0 )) {if (ab->have_cycles) {if (dl->ipc ==0.0 && dl->cycles ==0 ) show_title = true;
@@ -149,7 +150,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int show_title = true; } -if (dl->offset !=-1 && percent_max !=0.0 ) { +if (dl->al.offset !=-1 && percent_max !=0.0 ) {for (i =0 ; i < ab->nr_events; i++) { ui_browser__set_percent_color(browser, bdl->samples[i].percent,
@@ -199,19 +200,19 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!browser->navkeypressed) width +=1 ; -if (!*dl->line) +if (!*dl->al.line)ui_browser__write_nstring (browser," " , width - pcnt_width - cycles_width); -else if (dl->offset ==-1 ) { -if (dl->line_nr && annotate_browser__opts.show_linenr) +else if (dl->al.offset ==-1 ) { +if (dl->al.line_nr && annotate_browser__opts.show_linenr) printed =scnprintf (bf,sizeof (bf),"%-*d " , - ab->addr_width +1 , dl->line_nr); + ab->addr_width +1 , dl->al.line_nr);else printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );ui_browser__write_nstring (browser, bf, printed); -ui_browser__write_nstring (browser, dl->line, width - printed - pcnt_width - cycles_width +1 ); +ui_browser__write_nstring (browser, dl->al.line, width - printed - pcnt_width - cycles_width +1 ); }else { -u64 addr = dl->offset; +u64 addr = dl->al.offset;int color =-1 ;if (!annotate_browser__opts.use_offset)
@@ -247,7 +248,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intui_browser__set_color (browser, color);if (dl->ins.ops && dl->ins.ops->scnprintf) {if (ins__is_jump (&dl->ins)) { -bool fwd = dl->ops.target.offset > dl->offset; +bool fwd = dl->ops.target.offset > dl->al.offset;ui_browser__write_graph (browser, fwd ?SLSMG_DARROW_CHAR :SLSMG_UARROW_CHAR );
@@ -452,7 +453,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,double max_percent =0.0 ;int i; -if (pos->offset ==-1 ) { +if (pos->al.offset ==-1 ) {RB_CLEAR_NODE (&bpos->rb_node);continue ; }
@@ -464,8 +465,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, bpos->samples[i].percent =disasm__calc_percent (notes, evsel->idx + i, - pos->offset, - next ? next->offset : len, + pos->al.offset, + next ? next->al.offset : len, &path, &sample); bpos->samples[i].he = sample;
@@ -590,7 +591,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows *idx =0 ;list_for_each_entry (pos, ¬es->src->source, al.node) { -if (pos->offset == offset) +if (pos->al.offset == offset)return pos;if (!disasm_line__filter (&browser->b, &pos->al.node)) ++*idx;
@@ -636,7 +637,7 @@ struct disasm_line *annotate_browser__find_string(struct annotate_browser *brows ++*idx; -if (pos->line &&strstr (pos->line, s) !=NULL ) +if (pos->al.line &&strstr (pos->al.line, s) !=NULL )return pos; }
@@ -675,7 +676,7 @@ struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browse --*idx; -if (pos->line &&strstr (pos->line, s) !=NULL ) +if (pos->al.line &&strstr (pos->al.line, s) !=NULL )return pos; }
@@ -901,7 +902,7 @@ static int annotate_browser__run(struct annotate_browser *browser,case K_RIGHT :if (browser->selection ==NULL )ui_helpline__puts ("Huh? No selection. Report to [email protected]" ); -else if (browser->selection->offset ==-1 ) +else if (browser->selection->al.offset ==-1 )ui_helpline__puts ("Actions are only available for assembly lines." );else if (!browser->selection->ins.ops) goto show_sup_ins;
@@ -1136,13 +1137,13 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,list_for_each_entry (pos, ¬es->src->source, al.node) {struct browser_disasm_line *bpos; -size_t line_len =strlen (pos->line); +size_t line_len =strlen (pos->al.line);if (browser.b.width < line_len) browser.b.width = line_len; bpos =disasm_line__browser (pos); bpos->idx = browser.nr_entries++; -if (pos->offset !=-1 ) { +if (pos->al.offset !=-1 ) { bpos->idx_asm = browser.nr_asm_entries++;/* * FIXME: short term bandaid to cope with assembly
@@ -1151,8 +1152,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,* * E.g. copy_user_generic_unrolled */ -if (pos->offset < (s64 )size) - browser.offsets[pos->offset] = pos; +if (pos->al.offset < (s64 )size) + browser.offsets[pos->al.offset] = pos; }else bpos->idx_asm =-1 ; }
tools/perf/ui/gtk/annotate.c +7 -7
@@ -31,14 +31,14 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,strcpy (buf,"" ); -if (dl->offset == (s64) -1 ) +if (dl->al.offset == (s64) -1 )return 0 ; symhist =annotation__histogram (symbol__annotation (sym), evidx); -if (!symbol_conf.event_group && !symhist->addr[dl->offset].nr_samples) +if (!symbol_conf.event_group && !symhist->addr[dl->al.offset].nr_samples)return 0 ; - percent =100.0 * symhist->addr[dl->offset].nr_samples / symhist->nr_samples; + percent =100.0 * symhist->addr[dl->al.offset].nr_samples / symhist->nr_samples; markup =perf_gtk__get_percent_color (percent);if (markup)
@@ -57,16 +57,16 @@ static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym,strcpy (buf,"" ); -if (dl->offset == (s64) -1 ) +if (dl->al.offset == (s64) -1 )return 0 ; -return scnprintf (buf, size,"%" PRIx64, start + dl->offset); +return scnprintf (buf, size,"%" PRIx64, start + dl->al.offset); }static int perf_gtk__get_line (char *buf,size_t size,struct disasm_line *dl) {int ret =0 ; -char *line =g_markup_escape_text (dl->line,-1 ); +char *line =g_markup_escape_text (dl->al.line,-1 );const char *markup ="<span fgcolor='gray'>" ;strcpy (buf,"" );
@@ -74,7 +74,7 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)if (!line)return 0 ; -if (dl->offset != (s64) -1 ) +if (dl->al.offset != (s64) -1 ) markup =NULL ;if (markup)
tools/perf/util/annotate.c +21 -20
113 lines not on this page · raw message
tools/perf/util/annotate.h +3 -3
@@ -61,14 +61,14 @@ struct annotation;struct annotation_line {struct list_head node; +s64 offset; +char *line; +int line_nr; };struct disasm_line {struct annotation_line al; -s64 offset; -char *line;struct ins ins; -int line_nr;float ipc;u64 cycles;struct ins_operands ops;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 5/83 perf annotate: Move ipc/cycles into annotation_line struct
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move ipc/cycles into annotation_line struct to be used as generic members for any annotation source.
--- tools/perf/ui/browsers/annotate.c | 16 ++++++++-------- tools/perf/util/annotate.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-)
tools/perf/ui/browsers/annotate.c +8 -8
@@ -144,7 +144,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif ((row ==0 ) && (dl->al.offset ==-1 || percent_max ==0.0 )) {if (ab->have_cycles) { -if (dl->ipc ==0.0 && dl->cycles ==0 ) +if (dl->al.ipc ==0.0 && dl->al.cycles ==0 ) show_title = true; }else show_title = true;
@@ -178,16 +178,16 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int } }if (ab->have_cycles) { -if (dl->ipc) -ui_browser__printf (browser,"%*.2f " ,IPC_WIDTH -1 , dl->ipc); +if (dl->al.ipc) +ui_browser__printf (browser,"%*.2f " ,IPC_WIDTH -1 , dl->al.ipc);else if (!show_title)ui_browser__write_nstring (browser," " ,IPC_WIDTH );else ui_browser__printf (browser,"%*s " ,IPC_WIDTH -1 ,"IPC" ); -if (dl->cycles) +if (dl->al.cycles)ui_browser__printf (browser,"%*" PRIu64" " , -CYCLES_WIDTH -1 , dl->cycles); +CYCLES_WIDTH -1 , dl->al.cycles);else if (!show_title)ui_browser__write_nstring (browser," " ,CYCLES_WIDTH );else
@@ -474,7 +474,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, max_percent = bpos->samples[i].percent; } -if (max_percent <0.01 && pos->ipc ==0 ) { +if (max_percent <0.01 && pos->al.ipc ==0 ) {RB_CLEAR_NODE (&bpos->rb_node);continue ; }
@@ -994,7 +994,7 @@ static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,struct disasm_line *dl = browser->offsets[offset];if (dl) - dl->ipc = ipc; + dl->al.ipc = ipc; } } }
@@ -1025,7 +1025,7 @@ static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,count_and_fill (browser, ch->start, offset, ch); dl = browser->offsets[offset];if (dl && ch->num_aggr) - dl->cycles = ch->cycles_aggr / ch->num_aggr; + dl->al.cycles = ch->cycles_aggr / ch->num_aggr; browser->have_cycles = true; } }
tools/perf/util/annotate.h +2 -2
@@ -64,13 +64,13 @@ struct annotation_line {s64 offset;char *line;int line_nr; +float ipc; +u64 cycles; };struct disasm_line {struct annotation_line al;struct ins ins; -float ipc; -u64 cycles;struct ins_operands ops; };
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 6/83 perf annotate: Add symbol__annotate function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add symbol__annotate function to have generic annotation function to be called for all annotation sources.
It calls the generic annotation init and then the specific annotation data retrieval function.
--- tools/perf/builtin-top.c | 2 +- tools/perf/ui/browsers/annotate.c | 6 ++-- tools/perf/ui/gtk/annotate.c | 4 +-- tools/perf/util/annotate.c | 58 ++++++++++++++++++++++----------------- tools/perf/util/annotate.h | 6 ++-- 5 files changed, 42 insertions(+), 34 deletions(-)
tools/perf/builtin-top.c +1 -1
@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)return err; } - err =symbol__disassemble (sym, map,NULL ,0 ,NULL ,NULL ); + err =symbol__annotate (sym, map,NULL ,0 ,NULL ,NULL );if (err ==0 ) { out_assign: top->sym_filter_entry = he;
tools/perf/ui/browsers/annotate.c +3 -3
@@ -1120,9 +1120,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, (nr_pcnt -1 ); } - err =symbol__disassemble (sym, map,perf_evsel__env_arch (evsel), - sizeof_bdl, &browser.arch, -perf_evsel__env_cpuid (evsel)); + err =symbol__annotate (sym, map,perf_evsel__env_arch (evsel), + sizeof_bdl, &browser.arch, +perf_evsel__env_cpuid (evsel));if (err) {char msg[BUFSIZ ];symbol__strerror_disassemble (sym, map, err, msg,sizeof (msg));
tools/perf/ui/gtk/annotate.c +2 -2
@@ -169,8 +169,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,if (map->dso->annotate_warned)return -1 ; - err =symbol__disassemble (sym, map,perf_evsel__env_arch (evsel), -0 ,NULL ,NULL ); + err =symbol__annotate (sym, map,perf_evsel__env_arch (evsel), +0 ,NULL ,NULL );if (err) {char msg[BUFSIZ ];symbol__strerror_disassemble (sym, map, err, msg,sizeof (msg));
tools/perf/util/annotate.c +33 -25
85 lines not on this page · raw message
tools/perf/util/annotate.h +3 -3
@@ -173,9 +173,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sampint symbol__alloc_hist (struct symbol *sym);void symbol__annotate_zero_histograms (struct symbol *sym); -int symbol__disassemble (struct symbol *sym,struct map *map, -const char *arch_name,size_t privsize, -struct arch **parch,char *cpuid); +int symbol__annotate (struct symbol *sym,struct map *map, +const char *arch_name,size_t privsize, +struct arch **parch,char *cpuid);enum symbol_disassemble_errno {SYMBOL_ANNOTATE_ERRNO__SUCCESS =0 ,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 7/83 perf annotate: Add struct annotate_args
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding struct annotate_args to reduce the number of arguments, that need to travel all the way to line allocation. This makes the code easier to read and ease up the changes for following patches.
--- tools/perf/util/annotate.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
tools/perf/util/annotate.c +18 -9
@@ -878,12 +878,17 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)return -1 ; } -static struct disasm_line *disasm_line__new (s64 offset,char *line, -size_t privsize,int line_nr, +struct annotate_args { +size_t privsize; +}; + +static struct disasm_line *disasm_line__new (struct annotate_args *args, +s64 offset,char *line, +int line_nr,struct arch *arch,struct map *map) { -struct disasm_line *dl =zalloc (sizeof (*dl) + privsize); +struct disasm_line *dl =zalloc (sizeof (*dl) + args->privsize);if (dl !=NULL ) { dl->al.offset = offset;
@@ -1217,8 +1222,8 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* The ops.raw part will be parsed further according to type of the instruction. */ static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -struct arch *arch, -FILE *file,size_t privsize, +struct arch *arch,FILE *file, +struct annotate_args *args,int *line_nr) {struct annotation *notes =symbol__annotation (sym);
@@ -1264,7 +1269,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (offset, parsed_line, privsize, *line_nr, arch, map); + dl =disasm_line__new (args, offset, parsed_line, *line_nr, arch, map);free (line); (*line_nr)++;
@@ -1426,7 +1431,8 @@ static const char *annotate__norm_arch(const char *arch_name) }static int symbol__disassemble (struct symbol *sym,struct map *map, -size_t privsize,struct arch *arch) +struct annotate_args *args, +struct arch *arch) {struct dso *dso = map->dso;char command[PATH_MAX *2 ];
@@ -1526,7 +1532,7 @@ static int symbol__disassemble(struct symbol *sym, struct map *map,* can associate it with the instructions till the next one. * See disasm_line__new() and struct disasm_line::line_nr. */ -if (symbol__parse_objdump_line (sym, map, arch, file, privsize, +if (symbol__parse_objdump_line (sym, map, arch, file, args, &lineno) <0 )break ; nline++;
@@ -1564,6 +1570,9 @@ int symbol__annotate(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize, struct arch **parch, char *cpuid) { + struct annotate_args args = { + .privsize = privsize, + };struct arch *arch;int err;
@@ -1586,7 +1595,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } -return symbol__disassemble (sym, map, privsize, arch); +return symbol__disassemble (sym, map, &args, arch); }static void insert_source_line (struct rb_root *root,struct source_line *src_line)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 8/83 perf annotate: Add arch into struct annotate_args
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add arch into struct annotate_args to reduce the number of arguments that need to travel all the way to line allocation.
--- tools/perf/util/annotate.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
tools/perf/util/annotate.c +8 -9
@@ -880,12 +880,12 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)struct annotate_args {size_t privsize; +struct arch *arch; };static struct disasm_line *disasm_line__new (struct annotate_args *args,s64 offset,char *line,int line_nr, -struct arch *arch,struct map *map) {struct disasm_line *dl =zalloc (sizeof (*dl) + args->privsize);
@@ -902,7 +902,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args,if (disasm_line__parse (dl->al.line, &dl->ins.name, &dl->ops.raw) <0 ) goto out_free_line; -disasm_line__init_ins (dl, arch, map); +disasm_line__init_ins (dl, args->arch, map); } }
@@ -1222,7 +1222,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* The ops.raw part will be parsed further according to type of the instruction. */ static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -struct arch *arch,FILE *file, +FILE *file,struct annotate_args *args,int *line_nr) {
@@ -1269,7 +1269,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (args, offset, parsed_line, *line_nr, arch, map); + dl =disasm_line__new (args, offset, parsed_line, *line_nr, map);free (line); (*line_nr)++;
@@ -1431,8 +1431,7 @@ static const char *annotate__norm_arch(const char *arch_name) }static int symbol__disassemble (struct symbol *sym,struct map *map, -struct annotate_args *args, -struct arch *arch) +struct annotate_args *args) {struct dso *dso = map->dso;char command[PATH_MAX *2 ];
@@ -1532,7 +1531,7 @@ static int symbol__disassemble(struct symbol *sym, struct map *map,* can associate it with the instructions till the next one. * See disasm_line__new() and struct disasm_line::line_nr. */ -if (symbol__parse_objdump_line (sym, map, arch, file, args, +if (symbol__parse_objdump_line (sym, map, file, args, &lineno) <0 )break ; nline++;
@@ -1580,7 +1579,7 @@ int symbol__annotate(struct symbol *sym, struct map *map,if (!arch_name)return -1 ; - arch =arch__find (arch_name); + args.arch = arch =arch__find (arch_name);if (arch ==NULL )return -ENOTSUP ;
@@ -1595,7 +1594,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } -return symbol__disassemble (sym, map, &args, arch); +return symbol__disassemble (sym, map, &args); }static void insert_source_line (struct rb_root *root,struct source_line *src_line)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 9/83 perf annotate: Add map into struct annotate_args
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add map into struct annotate_args to reduce the number of arguments that need to travel all the way to line allocation.
--- tools/perf/util/annotate.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
tools/perf/util/annotate.c +11 -11
@@ -881,12 +881,12 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)struct annotate_args {size_t privsize;struct arch *arch; +struct map *map; };static struct disasm_line *disasm_line__new (struct annotate_args *args,s64 offset,char *line, -int line_nr, -struct map *map) +int line_nr) {struct disasm_line *dl =zalloc (sizeof (*dl) + args->privsize);
@@ -902,7 +902,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args,if (disasm_line__parse (dl->al.line, &dl->ins.name, &dl->ops.raw) <0 ) goto out_free_line; -disasm_line__init_ins (dl, args->arch, map); +disasm_line__init_ins (dl, args->arch, args->map); } }
@@ -1221,11 +1221,11 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* means that it's not a disassembly line so should be treated differently. * The ops.raw part will be parsed further according to type of the instruction. */ -static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -FILE *file, +static int symbol__parse_objdump_line (struct symbol *sym,FILE *file,struct annotate_args *args,int *line_nr) { +struct map *map = args->map;struct annotation *notes =symbol__annotation (sym);struct disasm_line *dl;char *line =NULL , *parsed_line, *tmp, *tmp2;
@@ -1269,7 +1269,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (args, offset, parsed_line, *line_nr, map); + dl =disasm_line__new (args, offset, parsed_line, *line_nr);free (line); (*line_nr)++;
@@ -1430,9 +1430,9 @@ static const char *annotate__norm_arch(const char *arch_name)return normalize_arch ((char *)arch_name); } -static int symbol__disassemble (struct symbol *sym,struct map *map, -struct annotate_args *args) +static int symbol__disassemble (struct symbol *sym,struct annotate_args *args) { +struct map *map = args->map;struct dso *dso = map->dso;char command[PATH_MAX *2 ];FILE *file;
@@ -1531,8 +1531,7 @@ static int symbol__disassemble(struct symbol *sym, struct map *map,* can associate it with the instructions till the next one. * See disasm_line__new() and struct disasm_line::line_nr. */ -if (symbol__parse_objdump_line (sym, map, file, args, - &lineno) <0 ) +if (symbol__parse_objdump_line (sym, file, args, &lineno) <0 )break ; nline++; }
@@ -1571,6 +1570,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, {struct annotate_args args = { .privsize = privsize, + .map = map, };struct arch *arch;int err;
@@ -1594,7 +1594,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } -return symbol__disassemble (sym, map, &args); +return symbol__disassemble (sym, &args); }static void insert_source_line (struct rb_root *root,struct source_line *src_line)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 10/83 perf annotate: Add offset/line/line_nr into struct annotate_args
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add offset/line/line_nr into struct annotate_args to reduce the number of arguments that need to travel all the way to line allocation.
--- tools/perf/util/annotate.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
tools/perf/util/annotate.c +13 -8
@@ -882,23 +882,24 @@ struct annotate_args {size_t privsize;struct arch *arch;struct map *map; +s64 offset; +char *line; +int line_nr; }; -static struct disasm_line *disasm_line__new (struct annotate_args *args, -s64 offset,char *line, -int line_nr) +static struct disasm_line *disasm_line__new (struct annotate_args *args) {struct disasm_line *dl =zalloc (sizeof (*dl) + args->privsize);if (dl !=NULL ) { - dl->al.offset = offset; - dl->al.line =strdup (line); - dl->al.line_nr = line_nr; + dl->al.offset = args->offset; + dl->al.line =strdup (args->line); + dl->al.line_nr = args->line_nr;if (dl->al.line ==NULL ) goto out_delete; -if (offset !=-1 ) { +if (args->offset !=-1 ) {if (disasm_line__parse (dl->al.line, &dl->ins.name, &dl->ops.raw) <0 ) goto out_free_line;
@@ -1269,7 +1270,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (args, offset, parsed_line, *line_nr); + args->offset = offset; + args->line = parsed_line; + args->line_nr = *line_nr; + + dl =disasm_line__new (args);free (line); (*line_nr)++;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 11/83 perf annotate: Add evsel into struct annotation_line_args
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add evsel into struct annotate_args to reduce the number of arguments that need to travel all the way to line allocation.
This change also allow us to move the arch name initialization under symbol__annotate function.
--- tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/ui/gtk/annotate.c | 3 +-- tools/perf/util/annotate.c | 11 ++++++++--- tools/perf/util/annotate.h | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -1
@@ -1120,7 +1120,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, (nr_pcnt -1 ); } - err =symbol__annotate (sym, map,perf_evsel__env_arch (evsel), + err =symbol__annotate (sym, map, evsel, sizeof_bdl, &browser.arch,perf_evsel__env_cpuid (evsel));if (err) {
tools/perf/ui/gtk/annotate.c +1 -2
@@ -169,8 +169,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,if (map->dso->annotate_warned)return -1 ; - err =symbol__annotate (sym, map,perf_evsel__env_arch (evsel), -0 ,NULL ,NULL ); + err =symbol__annotate (sym, map, evsel,0 ,NULL ,NULL );if (err) {char msg[BUFSIZ ];symbol__strerror_disassemble (sym, map, err, msg,sizeof (msg));
tools/perf/util/annotate.c +8 -3
@@ -882,6 +882,7 @@ struct annotate_args {size_t privsize;struct arch *arch;struct map *map; +struct perf_evsel *evsel;s64 offset;char *line;int line_nr;
@@ -1570,16 +1571,21 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) }int symbol__annotate (struct symbol *sym,struct map *map, -const char *arch_name,size_t privsize, +struct perf_evsel *evsel,size_t privsize,struct arch **parch,char *cpuid) {struct annotate_args args = { .privsize = privsize, .map = map, + .evsel = evsel, }; +const char *arch_name =NULL ;struct arch *arch;int err; +if (evsel) + arch_name =perf_evsel__env_arch (evsel); + arch_name =annotate__norm_arch (arch_name);if (!arch_name)return -1 ;
@@ -1975,8 +1981,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,struct rb_root source_line =RB_ROOT ;u64 len; -if (symbol__annotate (sym, map,perf_evsel__env_arch (evsel), -0 ,NULL ,NULL ) <0 ) +if (symbol__annotate (sym, map, evsel,0 ,NULL ,NULL ) <0 )return -1 ; len =symbol__size (sym);
tools/perf/util/annotate.h +1 -1
@@ -174,7 +174,7 @@ int symbol__alloc_hist(struct symbol *sym);void symbol__annotate_zero_histograms (struct symbol *sym);int symbol__annotate (struct symbol *sym,struct map *map, -const char *arch_name,size_t privsize, +struct perf_evsel *evsel,size_t privsize,struct arch **parch,char *cpuid);enum symbol_disassemble_errno {
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 12/83 perf annotate: Add annotation_line__next function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Rename disasm__get_next_ip_line() to annotation_line__next() to make it work over a generic struct annotation_line.
--- tools/perf/ui/browsers/annotate.c | 7 ++++--- tools/perf/util/annotate.c | 13 +++++++------ tools/perf/util/annotate.h | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-)
tools/perf/ui/browsers/annotate.c +4 -3
@@ -440,7 +440,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos, *next; +struct annotation_line *next; +struct disasm_line *pos;s64 len =symbol__size (sym); browser->entries =RB_ROOT ;
@@ -458,7 +459,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,continue ; } - next =disasm__get_next_ip_line (¬es->src->source, pos); + next =annotation_line__next (&pos->al, ¬es->src->source);for (i =0 ; i < browser->nr_events; i++) {struct sym_hist_entry sample;
@@ -466,7 +467,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, bpos->samples[i].percent =disasm__calc_percent (notes, evsel->idx + i, pos->al.offset, - next ? next->al.offset : len, + next ? next->offset : len, &path, &sample); bpos->samples[i].he = sample;
tools/perf/util/annotate.c +7 -6
@@ -942,10 +942,11 @@ static void disasm__add(struct list_head *head, struct disasm_line *line)list_add_tail (&line->al.node, head); } -struct disasm_line *disasm__get_next_ip_line (struct list_head *head,struct disasm_line *pos) +struct annotation_line * +annotation_line__next (struct annotation_line *pos,struct list_head *head) { -list_for_each_entry_continue (pos, head, al.node) -if (pos->al.offset >=0 ) +list_for_each_entry_continue (pos, head, node) +if (pos->offset >=0 )return pos;return NULL ;
@@ -1096,10 +1097,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 ststruct annotation *notes =symbol__annotation (sym);s64 offset = dl->al.offset;const u64 addr = start + offset; -struct disasm_line *next; +struct annotation_line *next;struct block_range *br; - next =disasm__get_next_ip_line (¬es->src->source, dl); + next =annotation_line__next (&dl->al, ¬es->src->source);if (perf_evsel__is_group_event (evsel)) { nr_percent = evsel->nr_members;
@@ -1114,7 +1115,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st percent =disasm__calc_percent (notes, notes->src->lines ? i : evsel->idx + i, offset, - next ? next->al.offset : (s64 ) len, + next ? next->offset : (s64 ) len, &path, &sample); ppercents[i] = percent;
tools/perf/util/annotate.h +2 -1
@@ -85,7 +85,8 @@ struct sym_hist_entry { };void disasm_line__free (struct disasm_line *dl); -struct disasm_line *disasm__get_next_ip_line (struct list_head *head,struct disasm_line *pos); +struct annotation_line * +annotation_line__next (struct annotation_line *pos,struct list_head *head);int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp); double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 13/83 perf annotate: Add annotation_line__add function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Rename disasm__add() into annotation_line__add() to make it work over a generic struct annotation_line.
--- tools/perf/util/annotate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +3 -3
@@ -937,9 +937,9 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool rreturn ins__scnprintf (&dl->ins, bf, size, &dl->ops); } -static void disasm__add (struct list_head *head,struct disasm_line *line) +static void annotation_line__add (struct annotation_line *al,struct list_head *head) { -list_add_tail (&line->al.node, head); +list_add_tail (&al->node, head); } struct annotation_line *
@@ -1301,7 +1301,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file, dl->ops.target.name =strdup (target.sym->name); } -disasm__add (¬es->src->source, dl); +annotation_line__add (&dl->al, ¬es->src->source);return 0 ; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 14/83 perf annotate: Move rb_node to struct annotation_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move rb_node to struct annotation_line to make struct annotation_line the rb tree node for sorted lines used in both stdio and TUI code.
This way we can unite the sorted lines lines codes for both TUI and stdio in the following patches.
--- tools/perf/ui/browsers/annotate.c | 30 ++++++++++++++++-------------- tools/perf/util/annotate.h | 1 + 2 files changed, 17 insertions(+), 14 deletions(-)
tools/perf/ui/browsers/annotate.c +16 -14
@@ -26,7 +26,6 @@ struct disasm_line_samples {#define CYCLES_WIDTH 6struct browser_disasm_line { -struct rb_node rb_node;u32 idx;int idx_asm;int jump_sources;
@@ -362,9 +361,11 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)return ret; } -static int disasm__cmp (struct browser_disasm_line *a, -struct browser_disasm_line *b,int nr_pcnt) +static int disasm__cmp (struct disasm_line *da, +struct disasm_line *db,int nr_pcnt) { +struct browser_disasm_line *a =disasm_line__browser (da); +struct browser_disasm_line *b =disasm_line__browser (db);int i;for (i =0 ; i < nr_pcnt; i++) {
@@ -375,24 +376,24 @@ static int disasm__cmp(struct browser_disasm_line *a,return 0 ; } -static void disasm_rb_tree__insert (struct rb_root *root,struct browser_disasm_line *bdl, +static void disasm_rb_tree__insert (struct rb_root *root,struct disasm_line *dl,int nr_events) {struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ; -struct browser_disasm_line *l; +struct disasm_line *l;while (*p !=NULL ) { parent = *p; - l = rb_entry(parent, struct browser_disasm_line, rb_node); + l = rb_entry(parent, struct disasm_line, al.rb_node); -if (disasm__cmp (bdl, l, nr_events)) +if (disasm__cmp (dl, l, nr_events)) p = &(*p)->rb_left;else p = &(*p)->rb_right; } -rb_link_node (&bdl->rb_node, parent, p); -rb_insert_color (&bdl->rb_node, root); +rb_link_node (&dl->al.rb_node, parent, p); +rb_insert_color (&dl->al.rb_node, root); } static void annotate_browser__set_top(struct annotate_browser *browser,
@@ -425,8 +426,9 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,struct disasm_line *pos;u32 idx; - bpos = rb_entry(nd, struct browser_disasm_line, rb_node); - pos = ((struct disasm_line *)bpos) -1 ; + pos = rb_entry(nd, struct disasm_line, al.rb_node); + bpos =disasm_line__browser (pos); + idx = bpos->idx;if (annotate_browser__opts.hide_src_code) idx = bpos->idx_asm;
@@ -455,7 +457,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,int i;if (pos->al.offset ==-1 ) { -RB_CLEAR_NODE (&bpos->rb_node); +RB_CLEAR_NODE (&pos->al.rb_node);continue ; }
@@ -476,10 +478,10 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, }if (max_percent <0.01 && pos->al.ipc ==0 ) { -RB_CLEAR_NODE (&bpos->rb_node); +RB_CLEAR_NODE (&pos->al.rb_node);continue ; } -disasm_rb_tree__insert (&browser->entries, bpos, +disasm_rb_tree__insert (&browser->entries, pos, browser->nr_events); }pthread_mutex_unlock (¬es->lock);
tools/perf/util/annotate.h +1 -0
@@ -61,6 +61,7 @@ struct annotation;struct annotation_line {struct list_head node; +struct rb_node rb_node;s64 offset;char *line;int line_nr;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 15/83 perf annotate: Add annotation_line__(new|delete) functions
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Changing the way the annotation lines are allocated and adding annotation_line__(new|delete) functions to deal with this.
Before the allocation schema was as follows:
-----------------------------------------------------------
struct disasm_line | struct annotation_line | private space
-----------------------------------------------------------
Where the private space is used in TUI code to store computed annotation data for events. The stdio code computes the data on the fly.
The goal is to compute and store annotation line's data directly in the struct annotation_line itself, so this patch changes the line allocation schema as follows:
------------------------------------------------------------
privsize space | struct disasm_line | struct annotation_line
------------------------------------------------------------
Moving struct annotation_line to the end, because in following changes we will move here the non-fixed length event's data.
--- tools/perf/ui/browsers/annotate.c | 4 ++- tools/perf/util/annotate.c | 63 ++++++++++++++++++++++++++++++++++----- tools/perf/util/annotate.h | 10 ++++++- 3 files changed, 68 insertions(+), 9 deletions(-)
tools/perf/ui/browsers/annotate.c +3 -1
@@ -76,7 +76,9 @@ struct annotate_browser {static inline struct browser_disasm_line *disasm_line__browser (struct disasm_line *dl) { -return (struct browser_disasm_line *)(dl +1 ); +struct annotation_line *al = &dl->al; + +return (void *) al - al->privsize; } static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
tools/perf/util/annotate.c +56 -7
84 lines not on this page · raw message
tools/perf/util/annotate.h +9 -1
@@ -67,14 +67,22 @@ struct annotation_line {int line_nr;float ipc;u64 cycles; +size_t privsize; };struct disasm_line { -struct annotation_line al;struct ins ins;struct ins_operands ops; + +/* This needs to be at the end. */ +struct annotation_line al; }; +static inline struct disasm_line *disasm_line (struct annotation_line *al) +{ + return al ? container_of(al, struct disasm_line, al) : NULL; +} +static inline bool disasm_line__has_offset (const struct disasm_line *dl) {return dl->ops.target.offset_avail;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 16/83 perf annotate: Add annotated_source__purge function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Mov disasm__purge() to annotated_source__purge() to make it work over a generic struct annotation_line.
--- tools/perf/ui/browsers/annotate.c | 8 +++----- tools/perf/util/annotate.c | 12 ++++++------ tools/perf/util/annotate.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-)
tools/perf/ui/browsers/annotate.c +3 -5
@@ -1084,7 +1084,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,struct perf_evsel *evsel, struct hist_browser_timer *hbt) { - struct disasm_line *pos, *n; + struct disasm_line *pos;struct annotation *notes;size_t size; struct map_symbol ms = {
@@ -1180,10 +1180,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,annotate_browser__update_addr_width (&browser); ret =annotate_browser__run (&browser, evsel, hbt); -list_for_each_entry_safe (pos, n, ¬es->src->source, al.node) { -list_del (&pos->al.node); -disasm_line__free (pos); - } + +annotated_source__purge (notes->src); out_free_offsets:free (browser.offsets);
tools/perf/util/annotate.c +6 -6
@@ -1985,13 +1985,13 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) } } -void disasm__purge (struct list_head *head) +void annotated_source__purge (struct annotated_source *as) { -struct disasm_line *pos, *n; +struct annotation_line *al, *n; -list_for_each_entry_safe (pos, n, head, al.node) { -list_del (&pos->al.node); -disasm_line__free (pos); +list_for_each_entry_safe (al, n, &as->source, node) { +list_del (&al->node); +disasm_line__free (disasm_line (al)); } }
@@ -2047,7 +2047,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,if (print_lines)symbol__free_source_line (sym, len); -disasm__purge (&symbol__annotation (sym)->src->source); +annotated_source__purge (symbol__annotation (sym)->src);return 0 ; }
tools/perf/util/annotate.h +1 -1
@@ -212,7 +212,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int min_pcnt, int max_lines, int context);void symbol__annotate_zero_histogram (struct symbol *sym,int evidx);void symbol__annotate_decay_histogram (struct symbol *sym,int evidx); -void disasm__purge (struct list_head *head); +void annotated_source__purge (struct annotated_source *as);bool ui__has_annotation (void );
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 17/83 perf annotate: Add samples into struct annotation_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add samples array into struct annotation_line to hold the annotation data. The data is populated in the following patches.
--- tools/perf/util/annotate.c | 8 ++++++++ tools/perf/util/annotate.h | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-)
tools/perf/util/annotate.c +8 -0
@@ -911,7 +911,14 @@ static struct annotation_line * annotation_line__new(struct annotate_args *args, size_t privsize) {struct annotation_line *al; +struct perf_evsel *evsel = args->evsel;size_t size = privsize +sizeof (*al); +int nr =1 ; + +if (perf_evsel__is_group_event (evsel)) + nr = evsel->nr_members; + + size +=sizeof (al->samples[0 ]) * nr; al =zalloc (size);if (al) {
@@ -920,6 +927,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize) al->offset = args->offset; al->line =strdup (args->line); al->line_nr = args->line_nr; + al->samples_nr = nr; }return al;
tools/perf/util/annotate.h +12 -5
@@ -59,6 +59,16 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);struct annotation ; +struct sym_hist_entry { +u64 nr_samples; +u64 period; +}; + +struct annotation_data { +double percent; +struct sym_hist_entry he; +}; +struct annotation_line {struct list_head node;struct rb_node rb_node;
@@ -68,6 +78,8 @@ struct annotation_line {float ipc;u64 cycles;size_t privsize; +int samples_nr; +struct annotation_data samples[0 ]; };struct disasm_line {
@@ -88,11 +100,6 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)return dl->ops.target.offset_avail; } -struct sym_hist_entry { -u64 nr_samples; -u64 period; -}; -void disasm_line__free (struct disasm_line *dl);struct annotation_line *annotation_line__next (struct annotation_line *pos,struct list_head *head);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 18/83 perf annotate: Add symbol__calc_percent function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add symbol__calc_percent function, that calculates annotation data for symbol and put the data in the struct annotation_line::samples array.
Committer notes:
Made symbol__calc_percent non static to be used in the next two patches, which will get some fixups from jolsa, doing it this way to keep this bisectable.
--- tools/perf/util/annotate.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/annotate.h | 1 + 2 files changed, 62 insertions(+), 1 deletion(-)
tools/perf/util/annotate.c +61 -1
@@ -1628,6 +1628,62 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) goto out_remove_tmp; } +static void calc_percent (struct sym_hist *hist, +struct annotation_data *sample, +s64 offset,s64 end) +{ +unsigned int hits =0 ; +u64 period =0 ; + +while (offset < end) { + hits += hist->addr[offset].nr_samples; + period += hist->addr[offset].period; + ++offset; + } + +if (hist->nr_samples) { + sample->he.period = period; + sample->he.nr_samples = hits; + sample->percent =100.0 * hits / hist->nr_samples; + } +} + +static int annotation__calc_percent (struct annotation *notes, +struct perf_evsel *evsel,s64 len) +{ +struct annotation_line *al, *next; + +list_for_each_entry (al, ¬es->src->source, node) { +s64 end; +int i; + +if (al->offset ==-1 ) +continue ; + + next =annotation_line__next (al, ¬es->src->source); + end = next ? next->offset : len; + +for (i =0 ; i < al->samples_nr; i++) { +struct annotation_data *sample; +struct sym_hist *hist; + + hist =annotation__histogram (notes, evsel->idx + i); + sample = &al->samples[i]; + +calc_percent (hist, sample, al->offset, end); + } + } + +return 0 ; +} + +int symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel) +{ +struct annotation *notes =symbol__annotation (sym); + +return annotation__calc_percent (notes, evsel,symbol__size (sym)); +} +int symbol__annotate (struct symbol *sym,struct map *map,struct perf_evsel *evsel,size_t privsize,struct arch **parch,char *cpuid)
@@ -1663,7 +1719,11 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } -return symbol__disassemble (sym, &args); + err =symbol__disassemble (sym, &args); +if (err) +return err; + +return symbol__calc_percent (sym, evsel); }static void insert_source_line (struct rb_root *root,struct source_line *src_line)
tools/perf/util/annotate.h +1 -0
@@ -107,6 +107,7 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool rsize_t disasm__fprintf (struct list_head *head,FILE *fp);double disasm__calc_percent (struct annotation *notes,int evidx,s64 offset,s64 end,const char **path,struct sym_hist_entry *sample); +int symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel);struct sym_hist {u64 nr_samples;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 19/83 perf annotate: Add symbol__calc_lines function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Replace symbol__get_source_line() with symbol__calc_lines(), which calculates the source line tree over the struct annotation_line.
This will allow us to remove redundant struct source_line in following patches.
--- tools/perf/util/annotate.c | 186 ++++++++++++++++----------------------------- tools/perf/util/annotate.h | 2 + 2 files changed, 68 insertions(+), 120 deletions(-)
tools/perf/util/annotate.c +66 -120
@@ -892,6 +892,7 @@ static void annotation_line__delete(struct annotation_line *al) {void *ptr = (void *) al - al->privsize; +free_srcline (al->path);zfree (&al->line);free (ptr); }
@@ -1726,21 +1727,21 @@ int symbol__annotate(struct symbol *sym, struct map *map,return symbol__calc_percent (sym, evsel); } -static void insert_source_line (struct rb_root *root,struct source_line *src_line) +static void insert_source_line (struct rb_root *root,struct annotation_line *al) { -struct source_line *iter; +struct annotation_line *iter;struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ;int i, ret;while (*p !=NULL ) { parent = *p; - iter = rb_entry(parent, struct source_line, node); + iter = rb_entry(parent, struct annotation_line, rb_node); - ret =strcmp (iter->path, src_line->path); + ret =strcmp (iter->path, al->path);if (ret ==0 ) { -for (i =0 ; i < src_line->nr_pcnt; i++) - iter->samples[i].percent_sum += src_line->samples[i].percent; +for (i =0 ; i < al->samples_nr; i++) + iter->samples[i].percent_sum += al->samples[i].percent;return ; }
@@ -1750,18 +1751,18 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin p = &(*p)->rb_right; } -for (i =0 ; i < src_line->nr_pcnt; i++) - src_line->samples[i].percent_sum = src_line->samples[i].percent; +for (i =0 ; i < al->samples_nr; i++) + al->samples[i].percent_sum = al->samples[i].percent; -rb_link_node (&src_line->node, parent, p); -rb_insert_color (&src_line->node, root); +rb_link_node (&al->rb_node, parent, p); +rb_insert_color (&al->rb_node, root); } -static int cmp_source_line (struct source_line *a,struct source_line *b) +static int cmp_source_line (struct annotation_line *a,struct annotation_line *b) {int i; -for (i =0 ; i < a->nr_pcnt; i++) { +for (i =0 ; i < a->samples_nr; i++) {if (a->samples[i].percent_sum == b->samples[i].percent_sum)continue ;return a->samples[i].percent_sum > b->samples[i].percent_sum;
@@ -1770,135 +1771,47 @@ static int cmp_source_line(struct source_line *a, struct source_line *b)return 0 ; } -static void __resort_source_line (struct rb_root *root,struct source_line *src_line) +static void __resort_source_line (struct rb_root *root,struct annotation_line *al) { -struct source_line *iter; +struct annotation_line *iter;struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ;while (*p !=NULL ) { parent = *p; - iter = rb_entry(parent, struct source_line, node); + iter = rb_entry(parent, struct annotation_line, rb_node); -if (cmp_source_line (src_line, iter)) +if (cmp_source_line (al, iter)) p = &(*p)->rb_left;else p = &(*p)->rb_right; } -rb_link_node (&src_line->node, parent, p); -rb_insert_color (&src_line->node, root); +rb_link_node (&al->rb_node, parent, p); +rb_insert_color (&al->rb_node, root); }static void resort_source_line (struct rb_root *dest_root,struct rb_root *src_root) { -struct source_line *src_line; +struct annotation_line *al;struct rb_node *node; node =rb_first (src_root);while (node) {struct rb_node *next; - src_line = rb_entry(node, struct source_line, node); + al = rb_entry(node, struct annotation_line, rb_node); next =rb_next (node);rb_erase (node, src_root); -__resort_source_line (dest_root, src_line); +__resort_source_line (dest_root, al); node = next; } } -static void symbol__free_source_line (struct symbol *sym,int len) -{ -struct annotation *notes =symbol__annotation (sym); -struct source_line *src_line = notes->src->lines; -size_t sizeof_src_line; -int i; - - sizeof_src_line =sizeof (*src_line) + - (sizeof (src_line->samples) * (src_line->nr_pcnt -1 )); - -for (i =0 ; i < len; i++) { -free_srcline (src_line->path); - src_line = (void *)src_line + sizeof_src_line; - } - -zfree (¬es->src->lines); -} - -/* Get the filename:line for the colored entries */ -static int symbol__get_source_line (struct symbol *sym,struct map *map, -struct perf_evsel *evsel, -struct rb_root *root,int len) -{ -u64 start; -int i, k; -int evidx = evsel->idx; -struct source_line *src_line; -struct annotation *notes =symbol__annotation (sym); -struct sym_hist *h =annotation__histogram (notes, evidx); -struct rb_root tmp_root =RB_ROOT ; -int nr_pcnt =1 ; -u64 nr_samples = h->nr_samples; -size_t sizeof_src_line =sizeof (struct source_line ); - -if (perf_evsel__is_group_event (evsel)) { -for (i =1 ; i < evsel->nr_members; i++) { - h =annotation__histogram (notes, evidx + i); - nr_samples += h->nr_samples; - } - nr_pcnt = evsel->nr_members; - sizeof_src_line += (nr_pcnt -1 ) *sizeof (src_line->samples); - } - -if (!nr_samples) -return 0 ; - - src_line = notes->src->lines =calloc (len, sizeof_src_line); -if (!notes->src->lines) -return -1 ; - - start =map__rip_2objdump (map, sym->start); - -for (i =0 ; i < len; i++) { -u64 offset; -double percent_max =0.0 ; - - src_line->nr_pcnt = nr_pcnt; - -for (k =0 ; k < nr_pcnt; k++) { -double percent =0.0 ; - - h =annotation__histogram (notes, evidx + k); - nr_samples = h->addr[i].nr_samples; -if (h->nr_samples) - percent =100.0 * nr_samples / h->nr_samples; - -if (percent > percent_max) - percent_max = percent; - src_line->samples[k].percent = percent; - src_line->samples[k].nr = nr_samples; - } - -if (percent_max <=0.5 ) - goto next; - - offset = start + i; - src_line->path =get_srcline (map->dso, offset,NULL , - false, true); -insert_source_line (&tmp_root, src_line); - - next: - src_line = (void *)src_line + sizeof_src_line; - } - -resort_source_line (root, &tmp_root); -return 0 ; -} -static void print_summary (struct rb_root *root,const char *filename) { -struct source_line *src_line; +struct annotation_line *al;struct rb_node *node;printf ("\nSorted summary for file %s\n" , filename);
@@ -1916,9 +1829,9 @@ static void print_summary(struct rb_root *root, const char *filename)char *path;int i; - src_line = rb_entry(node, struct source_line, node); -for (i =0 ; i < src_line->nr_pcnt; i++) { - percent = src_line->samples[i].percent_sum; + al = rb_entry(node, struct annotation_line, rb_node); +for (i =0 ; i < al->samples_nr; i++) { + percent = al->samples[i].percent_sum; color =get_percent_color (percent);color_fprintf (stdout, color," %7.2f" , percent);
@@ -1926,7 +1839,7 @@ static void print_summary(struct rb_root *root, const char *filename) percent_max = percent; } - path = src_line->path; + path = al->path; color =get_percent_color (percent_max);color_fprintf (stdout, color," %s\n" , path);
@@ -2091,29 +2004,62 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)return printed; } +static void annotation__calc_lines (struct annotation *notes,struct map *map, +struct rb_root *root,u64 start) +{ +struct annotation_line *al; +struct rb_root tmp_root =RB_ROOT ; + +list_for_each_entry (al, ¬es->src->source, node) { +double percent_max =0.0 ; +int i; + +for (i =0 ; i < al->samples_nr; i++) { +struct annotation_data *sample; + + sample = &al->samples[i]; + +if (sample->percent > percent_max) + percent_max = sample->percent; + } + +if (percent_max <=0.5 ) +continue ; + + al->path =get_srcline (map->dso, start + al->offset,NULL , false, true); +insert_source_line (&tmp_root, al); + } + +resort_source_line (root, &tmp_root); +} + +static void symbol__calc_lines (struct symbol *sym,struct map *map, +struct rb_root *root) +{ +struct annotation *notes =symbol__annotation (sym); +u64 start =map__rip_2objdump (map, sym->start); + +annotation__calc_lines (notes, map, root, start); +} +int symbol__tty_annotate (struct symbol *sym,struct map *map,struct perf_evsel *evsel,bool print_lines,bool full_paths,int min_pcnt,int max_lines) {struct dso *dso = map->dso;struct rb_root source_line =RB_ROOT ; -u64 len;if (symbol__annotate (sym, map, evsel,0 ,NULL ,NULL ) <0 )return -1 ; - len =symbol__size (sym); -if (print_lines) { srcline_full_filename = full_paths; -symbol__get_source_line (sym, map, evsel, &source_line, len); +symbol__calc_lines (sym, map, &source_line);print_summary (&source_line, dso->long_name); }symbol__annotate_printf (sym, map, evsel, full_paths, min_pcnt, max_lines,0 ); -if (print_lines) -symbol__free_source_line (sym, len);annotated_source__purge (symbol__annotation (sym)->src);
tools/perf/util/annotate.h +2 -0
@@ -66,6 +66,7 @@ struct sym_hist_entry {struct annotation_data {double percent; +double percent_sum;struct sym_hist_entry he; };
@@ -78,6 +79,7 @@ struct annotation_line {float ipc;u64 cycles;size_t privsize; +char *path;int samples_nr;struct annotation_data samples[0 ]; };
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 20/83 perf annotate: Remove disasm__calc_percent() from disasm_line__print()
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Remove disasm__calc_percent() from disasm_line__print(), because we already have the data calculated in struct annotation_line.
--- tools/perf/builtin-top.c | 3 +++ tools/perf/util/annotate.c | 59 ++++++++++++---------------------------------- 2 files changed, 18 insertions(+), 44 deletions(-)
tools/perf/builtin-top.c +3 -0
@@ -226,6 +226,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,static void perf_top__show_details (struct perf_top *top) {struct hist_entry *he = top->sym_filter_entry; +struct perf_evsel *evsel =hists_to_evsel (he->hists);struct annotation *notes;struct symbol *symbol;int more;
@@ -238,6 +239,8 @@ static void perf_top__show_details(struct perf_top *top)pthread_mutex_lock (¬es->lock); +symbol__calc_percent (symbol, evsel); +if (notes->src ==NULL ) goto out_unlock;
tools/perf/util/annotate.c +15 -44
97 lines not on this page · raw message
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 21/83 perf annotate: Remove disasm__calc_percent() from annotate_browser__calc_percent()
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Remove disasm__calc_percent() from annotate_browser__calc_percent(), because we already have the data calculated in struct annotation_line.
--- tools/perf/ui/browsers/annotate.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
tools/perf/ui/browsers/annotate.c +6 -13
@@ -444,17 +444,16 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct annotation_line *next;struct disasm_line *pos; -s64 len =symbol__size (sym); browser->entries =RB_ROOT ;pthread_mutex_lock (¬es->lock); +symbol__calc_percent (sym, evsel); +list_for_each_entry (pos, ¬es->src->source, al.node) {struct browser_disasm_line *bpos =disasm_line__browser (pos); -const char *path =NULL ;double max_percent =0.0 ;int i;
@@ -463,17 +462,11 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,continue ; } - next =annotation_line__next (&pos->al, ¬es->src->source); -for (i =0 ; i < browser->nr_events; i++) { -struct sym_hist_entry sample; - - bpos->samples[i].percent =disasm__calc_percent (notes, - evsel->idx + i, - pos->al.offset, - next ? next->offset : len, - &path, &sample); - bpos->samples[i].he = sample; +struct annotation_data *sample = &pos->al.samples[i]; + + bpos->samples[i].percent = sample->percent; + bpos->samples[i].he = sample->he;if (max_percent < bpos->samples[i].percent) max_percent = bpos->samples[i].percent;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 22/83 perf annotate: Remove disasm__calc_percent function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Remove disasm__calc_percent() function, because it's no longer needed.
--- tools/perf/util/annotate.c | 44 -------------------------------------------- tools/perf/util/annotate.h | 2 -- 2 files changed, 46 deletions(-)
tools/perf/util/annotate.c +0 -44
@@ -1010,50 +1010,6 @@ annotation_line__next(struct annotation_line *pos, struct list_head *head)return NULL ; } -double disasm__calc_percent (struct annotation *notes,int evidx,s64 offset, -s64 end,const char **path,struct sym_hist_entry *sample) -{ -struct source_line *src_line = notes->src->lines; -double percent =0.0 ; - - sample->nr_samples = sample->period =0 ; - -if (src_line) { -size_t sizeof_src_line =sizeof (*src_line) + -sizeof (src_line->samples) * (src_line->nr_pcnt -1 ); - -while (offset < end) { - src_line = (void *)notes->src->lines + - (sizeof_src_line * offset); - -if (*path ==NULL ) - *path = src_line->path; - - percent += src_line->samples[evidx].percent; - sample->nr_samples += src_line->samples[evidx].nr; - offset++; - } - }else { -struct sym_hist *h =annotation__histogram (notes, evidx); -unsigned int hits =0 ; -u64 period =0 ; - -while (offset < end) { - hits += h->addr[offset].nr_samples; - period += h->addr[offset].period; - ++offset; - } - -if (h->nr_samples) { - sample->period = period; - sample->nr_samples = hits; - percent =100.0 * hits / h->nr_samples; - } - } - -return percent; -} -static const char *annotate__address_color (struct block_range *br) {double cov =block_range__coverage (br);
tools/perf/util/annotate.h +0 -2
@@ -107,8 +107,6 @@ struct annotation_line * annotation_line__next(struct annotation_line *pos, struct list_head *head);int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp); -double disasm__calc_percent (struct annotation *notes,int evidx,s64 offset, -s64 end,const char **path,struct sym_hist_entry *sample);int symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel);struct sym_hist {
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 23/83 perf annotate: Remove struct source_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Remove struct source_line*, no longer needed.
--- tools/perf/util/annotate.h | 14 -------------- 1 file changed, 14 deletions(-)
tools/perf/util/annotate.h +0 -14
@@ -126,19 +126,6 @@ struct cyc_hist {u16 reset; }; -struct source_line_samples { -double percent; -double percent_sum; -u64 nr; -}; - -struct source_line { -struct rb_node node; -char *path; -int nr_pcnt; -struct source_line_samples samples[1 ]; -}; -/** struct annotated_source - symbols with hits have this attached as in sannotation * * @histogram: Array of addr hit histograms per event being monitored
@@ -154,7 +141,6 @@ struct source_line {*/ struct annotated_source {struct list_head source; -struct source_line *lines;int nr_histograms;size_t sizeof_sym_hist;struct cyc_hist *cycles_hist;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 24/83 perf annotate: Add annotation_line__print function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Separating struct annotation_line display function, it will hold the generic line display code.
--- tools/perf/util/annotate.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)
tools/perf/util/annotate.c +22 -6
@@ -1189,6 +1189,18 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 streturn 0 ; } +static int +annotation_line__print (struct annotation_line *al,struct symbol *sym,u64 start, +struct perf_evsel *evsel,u64 len,int min_pcnt,int printed, +int max_lines,struct annotation_line *aq) +{ + struct disasm_line *dl = container_of(al, struct disasm_line, al); + struct disasm_line *queue = container_of(aq, struct disasm_line, al); + +return disasm_line__print (dl, sym, start, evsel, len, min_pcnt, printed, + max_lines, queue); +} +/* * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw) * which looks like following
@@ -1797,7 +1809,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,const char *evsel_name =perf_evsel__name (evsel);struct annotation *notes =symbol__annotation (sym);struct sym_hist *h =annotation__histogram (notes, evsel->idx); -struct disasm_line *pos, *queue =NULL ; +struct annotation_line *pos, *queue =NULL ;u64 start =map__rip_2objdump (map, sym->start);int printed =2 , queue_len =0 ;int more =0 ;
@@ -1830,15 +1842,19 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,if (verbose >0 )symbol__annotate_hits (sym, evsel); -list_for_each_entry (pos, ¬es->src->source, al.node) { +list_for_each_entry (pos, ¬es->src->source, node) { +int err; +if (context && queue ==NULL ) { queue = pos; queue_len =0 ; } -switch (disasm_line__print (pos, sym, start, evsel, len, - min_pcnt, printed, max_lines, - queue)) { + err =annotation_line__print (pos, sym, start, evsel, len, + min_pcnt, printed, max_lines, + queue); + +switch (err) {case 0 : ++printed;if (context) {
@@ -1860,7 +1876,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,if (!context)break ;if (queue_len == context) - queue =list_entry (queue->al.node.next,typeof (*queue), al.node); + queue =list_entry (queue->node.next,typeof (*queue), node);else ++queue_len;break ;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 25/83 perf annotate: Factor annotation_line__print from disasm_line__print
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move generic annotation line display code into annotation_line__print function.
--- tools/perf/util/annotate.c | 69 ++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 36 deletions(-)
tools/perf/util/annotate.c +33 -36
@@ -1093,24 +1093,36 @@ static void annotate__branch_printf(struct block_range *br, u64 addr) } -static int disasm_line__print (struct disasm_line *dl,struct symbol *sym,u64 start, -struct perf_evsel *evsel,u64 len,int min_pcnt,int printed, -int max_lines,struct disasm_line *queue) +static int disasm_line__print (struct disasm_line *dl,u64 start) { +s64 offset = dl->al.offset; +const u64 addr = start + offset; +struct block_range *br; + + br =block_range__find (addr); +color_fprintf (stdout,annotate__address_color (br)," %" PRIx64":" , addr); +color_fprintf (stdout,annotate__asm_color (br),"%s" , dl->al.line); +annotate__branch_printf (br, addr); +return 0 ; +} + +static int +annotation_line__print (struct annotation_line *al,struct symbol *sym,u64 start, +struct perf_evsel *evsel,u64 len,int min_pcnt,int printed, +int max_lines,struct annotation_line *queue) +{ + struct disasm_line *dl = container_of(al, struct disasm_line, al);static const char *prev_line;static const char *prev_color; -if (dl->al.offset !=-1 ) { +if (al->offset !=-1 ) {double max_percent =0.0 ;int i, nr_percent =1 ;const char *color;struct annotation *notes =symbol__annotation (sym); -s64 offset = dl->al.offset; -const u64 addr = start + offset; -struct block_range *br; -for (i =0 ; i < dl->al.samples_nr; i++) { -struct annotation_data *sample = &dl->al.samples[i]; +for (i =0 ; i < al->samples_nr; i++) { +struct annotation_data *sample = &al->samples[i];if (sample->percent > max_percent) max_percent = sample->percent;
@@ -1123,11 +1135,11 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 streturn 1 ;if (queue !=NULL ) { -list_for_each_entry_from (queue, ¬es->src->source, al.node) { -if (queue == dl) +list_for_each_entry_from (queue, ¬es->src->source, node) { +if (queue == al)break ; -disasm_line__print (queue, sym, start, evsel, len, -0 ,0 ,1 ,NULL ); +annotation_line__print (queue, sym, start, evsel, len, +0 ,0 ,1 ,NULL ); } }
@@ -1138,17 +1150,17 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* the same color than the percentage. Don't print it * twice for close colored addr with the same filename:line */ -if (dl->al.path) { -if (!prev_line ||strcmp (prev_line, dl->al.path) +if (al->path) { +if (!prev_line ||strcmp (prev_line, al->path) || color != prev_color) { -color_fprintf (stdout, color," %s" , dl->al.path); - prev_line = dl->al.path; +color_fprintf (stdout, color," %s" , al->path); + prev_line = al->path; prev_color = color; } }for (i =0 ; i < nr_percent; i++) { -struct annotation_data *sample = &dl->al.samples[i]; +struct annotation_data *sample = &al->samples[i]; color =get_percent_color (sample->percent);
@@ -1164,10 +1176,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stprintf (" : " ); - br =block_range__find (addr); -color_fprintf (stdout,annotate__address_color (br)," %" PRIx64":" , addr); -color_fprintf (stdout,annotate__asm_color (br),"%s" , dl->al.line); -annotate__branch_printf (br, addr); +disasm_line__print (dl, start);printf ("\n" ); }else if (max_lines && printed >= max_lines)return 1 ;
@@ -1180,27 +1189,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 stif (perf_evsel__is_group_event (evsel)) width *= evsel->nr_members; -if (!*dl->al.line) +if (!*al->line)printf (" %*s:\n" , width," " );else -printf (" %*s: %s\n" , width," " , dl->al.line); +printf (" %*s: %s\n" , width," " , al->line); }return 0 ; } -static int -annotation_line__print (struct annotation_line *al,struct symbol *sym,u64 start, -struct perf_evsel *evsel,u64 len,int min_pcnt,int printed, -int max_lines,struct annotation_line *aq) -{ - struct disasm_line *dl = container_of(al, struct disasm_line, al); - struct disasm_line *queue = container_of(aq, struct disasm_line, al); - -return disasm_line__print (dl, sym, start, evsel, len, min_pcnt, printed, - max_lines, queue); -} -/* * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw) * which looks like following
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 26/83 perf annotate browser: Use samples data from struct annotation_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We now carry the data in 'struct annotation_line', so using it instead of samples from 'struct browser_disasm_line' and removing it and its setup.
--- tools/perf/ui/browsers/annotate.c | 57 ++++++++++++++------------------------- 1 file changed, 20 insertions(+), 37 deletions(-)
tools/perf/ui/browsers/annotate.c +20 -37
@@ -29,11 +29,6 @@ struct browser_disasm_line {u32 idx;int idx_asm;int jump_sources; -/* -* actual length of this array is saved on the nr_events field -* of the struct annotate_browser -*/ -struct disasm_line_samples samples[1 ]; }; static struct annotate_browser_opt {
@@ -76,9 +71,7 @@ struct annotate_browser {static inline struct browser_disasm_line *disasm_line__browser (struct disasm_line *dl) { -struct annotation_line *al = &dl->al; - -return (void *) al - al->privsize; +return (void *) dl -sizeof (struct browser_disasm_line ); } static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
@@ -139,8 +132,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intbool show_title = false;for (i =0 ; i < ab->nr_events; i++) { -if (bdl->samples[i].percent > percent_max) - percent_max = bdl->samples[i].percent; +if (dl->al.samples[i].percent > percent_max) + percent_max = dl->al.samples[i].percent; }if ((row ==0 ) && (dl->al.offset ==-1 || percent_max ==0.0 )) {
@@ -154,17 +147,17 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (dl->al.offset !=-1 && percent_max !=0.0 ) {for (i =0 ; i < ab->nr_events; i++) {ui_browser__set_percent_color (browser, - bdl->samples[i].percent, + dl->al.samples[i].percent, current_entry);if (annotate_browser__opts.show_total_period) {ui_browser__printf (browser,"%11" PRIu64" " , - bdl->samples[i].he.period); + dl->al.samples[i].he.period); }else if (annotate_browser__opts.show_nr_samples) {ui_browser__printf (browser,"%6" PRIu64" " , - bdl->samples[i].he.nr_samples); + dl->al.samples[i].he.nr_samples); }else {ui_browser__printf (browser,"%6.2f " , - bdl->samples[i].percent); + dl->al.samples[i].percent); } } }else {
@@ -363,11 +356,9 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)return ret; } -static int disasm__cmp (struct disasm_line *da, -struct disasm_line *db,int nr_pcnt) +static int disasm__cmp (struct annotation_line *a, +struct annotation_line *b,int nr_pcnt) { -struct browser_disasm_line *a =disasm_line__browser (da); -struct browser_disasm_line *b =disasm_line__browser (db);int i;for (i =0 ; i < nr_pcnt; i++) {
@@ -378,24 +369,24 @@ static int disasm__cmp(struct disasm_line *da,return 0 ; } -static void disasm_rb_tree__insert (struct rb_root *root,struct disasm_line *dl, +static void disasm_rb_tree__insert (struct rb_root *root,struct annotation_line *al,int nr_events) {struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ; -struct disasm_line *l; +struct annotation_line *l;while (*p !=NULL ) { parent = *p; - l = rb_entry(parent, struct disasm_line, al.rb_node); + l = rb_entry(parent, struct annotation_line, rb_node); -if (disasm__cmp (dl, l, nr_events)) +if (disasm__cmp (al, l, nr_events)) p = &(*p)->rb_left;else p = &(*p)->rb_right; } -rb_link_node (&dl->al.rb_node, parent, p); -rb_insert_color (&dl->al.rb_node, root); +rb_link_node (&al->rb_node, parent, p); +rb_insert_color (&al->rb_node, root); } static void annotate_browser__set_top(struct annotate_browser *browser,
@@ -453,7 +444,6 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,symbol__calc_percent (sym, evsel);list_for_each_entry (pos, ¬es->src->source, al.node) { -struct browser_disasm_line *bpos =disasm_line__browser (pos);double max_percent =0.0 ;int i;
@@ -465,18 +455,15 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,for (i =0 ; i < browser->nr_events; i++) {struct annotation_data *sample = &pos->al.samples[i]; - bpos->samples[i].percent = sample->percent; - bpos->samples[i].he = sample->he; - -if (max_percent < bpos->samples[i].percent) - max_percent = bpos->samples[i].percent; +if (max_percent < sample->percent) + max_percent = sample->percent; }if (max_percent <0.01 && pos->al.ipc ==0 ) {RB_CLEAR_NODE (&pos->al.rb_node);continue ; } -disasm_rb_tree__insert (&browser->entries, pos, +disasm_rb_tree__insert (&browser->entries, &pos->al, browser->nr_events); }pthread_mutex_unlock (¬es->lock);
@@ -1096,7 +1083,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, };int ret =-1 , err;int nr_pcnt =1 ; -size_t sizeof_bdl =sizeof (struct browser_disasm_line );if (sym ==NULL )return -1 ;
@@ -1112,14 +1098,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,return -1 ; } -if (perf_evsel__is_group_event (evsel)) { +if (perf_evsel__is_group_event (evsel)) nr_pcnt = evsel->nr_members; - sizeof_bdl +=sizeof (struct disasm_line_samples ) * - (nr_pcnt -1 ); - } err =symbol__annotate (sym, map, evsel, - sizeof_bdl, &browser.arch, +sizeof (struct browser_disasm_line ), &browser.arch,perf_evsel__env_cpuid (evsel));if (err) {char msg[BUFSIZ ];
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 27/83 perf annotate browser: Do not pass nr_events in disasm_rb_tree__insert
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We now keep samples_nr in struct annotation_line, so there's no need to pass nr_events to disasm_rb_tree__insert function.
--- tools/perf/ui/browsers/annotate.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
tools/perf/ui/browsers/annotate.c +6 -9
@@ -356,12 +356,11 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)return ret; } -static int disasm__cmp (struct annotation_line *a, -struct annotation_line *b,int nr_pcnt) +static int disasm__cmp (struct annotation_line *a,struct annotation_line *b) {int i; -for (i =0 ; i < nr_pcnt; i++) { +for (i =0 ; i < a->samples_nr; i++) {if (a->samples[i].percent == b->samples[i].percent)continue ;return a->samples[i].percent < b->samples[i].percent;
@@ -369,8 +368,7 @@ static int disasm__cmp(struct annotation_line *a,return 0 ; } -static void disasm_rb_tree__insert (struct rb_root *root,struct annotation_line *al, -int nr_events) +static void disasm_rb_tree__insert (struct rb_root *root,struct annotation_line *al) {struct rb_node **p = &root->rb_node;struct rb_node *parent =NULL ;
@@ -380,7 +378,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line parent = *p; l = rb_entry(parent, struct annotation_line, rb_node); -if (disasm__cmp (al, l, nr_events)) +if (disasm__cmp (al, l)) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -452,7 +450,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,continue ; } -for (i =0 ; i < browser->nr_events; i++) { +for (i =0 ; i < pos->al.samples_nr; i++) {struct annotation_data *sample = &pos->al.samples[i];if (max_percent < sample->percent)
@@ -463,8 +461,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,RB_CLEAR_NODE (&pos->al.rb_node);continue ; } -disasm_rb_tree__insert (&browser->entries, &pos->al, - browser->nr_events); +disasm_rb_tree__insert (&browser->entries, &pos->al); }pthread_mutex_unlock (¬es->lock);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 28/83 perf annotate browser: Rename struct browser_disasm_line to browser_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Rename struct browser_disasm_line to browser_line, because the browser operates now on generic lines and no longer on disasm lines.
--- tools/perf/ui/browsers/annotate.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
tools/perf/ui/browsers/annotate.c +13 -13
@@ -25,10 +25,10 @@ struct disasm_line_samples {#define IPC_WIDTH 6#define CYCLES_WIDTH 6 -struct browser_disasm_line { -u32 idx; -int idx_asm; -int jump_sources; +struct browser_line { +u32 idx; +int idx_asm; +int jump_sources; }; static struct annotate_browser_opt {
@@ -69,9 +69,9 @@ struct annotate_browser {char search_bf[128 ]; }; -static inline struct browser_disasm_line *disasm_line__browser (struct disasm_line *dl) +static inline struct browser_line *disasm_line__browser (struct disasm_line *dl) { -return (void *) dl -sizeof (struct browser_disasm_line ); +return (void *) dl -sizeof (struct browser_line ); } static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
@@ -119,7 +119,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); -struct browser_disasm_line *bdl =disasm_line__browser (dl); +struct browser_line *bdl =disasm_line__browser (dl);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!annotate_browser__opts.hide_src_code && (!current_entry || (browser->use_navkeypressed &&
@@ -302,7 +302,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct disasm_line *cursor = ab->selection, *target; -struct browser_disasm_line *btarget, *bcursor; +struct browser_line *btarget, *bcursor;unsigned int from, to;struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym;
@@ -413,7 +413,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,static void annotate_browser__set_rb_top (struct annotate_browser *browser,struct rb_node *nd) { -struct browser_disasm_line *bpos; +struct browser_line *bpos;struct disasm_line *pos;u32 idx;
@@ -471,7 +471,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,static bool annotate_browser__toggle_source (struct annotate_browser *browser) {struct disasm_line *dl; -struct browser_disasm_line *bdl; +struct browser_line *bdl;off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek (&browser->b, offset,SEEK_CUR );
@@ -1027,7 +1027,7 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserfor (offset =0 ; offset < size; ++offset) {struct disasm_line *dl = browser->offsets[offset], *dlt; -struct browser_disasm_line *bdlt; +struct browser_line *bdlt;if (!disasm_line__is_valid_jump (dl, sym))continue ;
@@ -1099,7 +1099,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, nr_pcnt = evsel->nr_members; err =symbol__annotate (sym, map, evsel, -sizeof (struct browser_disasm_line ), &browser.arch, +sizeof (struct browser_line ), &browser.arch,perf_evsel__env_cpuid (evsel));if (err) {char msg[BUFSIZ ];
@@ -1114,7 +1114,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.start =map__rip_2objdump (map, sym->start);list_for_each_entry (pos, ¬es->src->source, al.node) { -struct browser_disasm_line *bpos; +struct browser_line *bpos;size_t line_len =strlen (pos->al.line);if (browser.b.width < line_len)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 29/83 perf annotate browser: Rename disasm_line__browser to browser_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Rename disasm_line__browser function to browser_line, because the browser got generic and is no longer disasm specific.
--- tools/perf/ui/browsers/annotate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
tools/perf/ui/browsers/annotate.c +8 -8
@@ -69,7 +69,7 @@ struct annotate_browser {char search_bf[128 ]; }; -static inline struct browser_line *disasm_line__browser (struct disasm_line *dl) +static inline struct browser_line *browser_line (struct disasm_line *dl) {return (void *) dl -sizeof (struct browser_line ); }
@@ -119,7 +119,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); -struct browser_line *bdl =disasm_line__browser (dl); +struct browser_line *bdl =browser_line (dl);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!annotate_browser__opts.hide_src_code && (!current_entry || (browser->use_navkeypressed &&
@@ -319,8 +319,8 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)if (!target)return ; - bcursor =disasm_line__browser (cursor); - btarget =disasm_line__browser (target); + bcursor =browser_line (cursor); + btarget =browser_line (target);if (annotate_browser__opts.hide_src_code) { from = bcursor->idx_asm;
@@ -418,7 +418,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,u32 idx; pos = rb_entry(nd, struct disasm_line, al.rb_node); - bpos =disasm_line__browser (pos); + bpos =browser_line (pos); idx = bpos->idx;if (annotate_browser__opts.hide_src_code)
@@ -476,7 +476,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) browser->b.seek (&browser->b, offset,SEEK_CUR ); dl = list_entry(browser->b.top, struct disasm_line, al.node); - bdl =disasm_line__browser (dl); + bdl =browser_line (dl);if (annotate_browser__opts.hide_src_code) {if (bdl->idx_asm < offset)
@@ -1040,7 +1040,7 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserif (dlt ==NULL )continue ; - bdlt =disasm_line__browser (dlt); + bdlt =browser_line (dlt);if (++bdlt->jump_sources > browser->max_jump_sources) browser->max_jump_sources = bdlt->jump_sources;
@@ -1119,7 +1119,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (browser.b.width < line_len) browser.b.width = line_len; - bpos =disasm_line__browser (pos); + bpos =browser_line (pos); bpos->idx = browser.nr_entries++;if (pos->al.offset !=-1 ) { bpos->idx_asm = browser.nr_asm_entries++;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 30/83 perf annotate browser: Change selection to struct annotation_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Use struct annotation_line as a browser::selection.
We want to be able to use the annotate_browser for all sorts of source data, so it needs to be able to work over the generic struct annotation_line.
--- tools/perf/ui/browsers/annotate.c | 63 +++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 29 deletions(-)
tools/perf/ui/browsers/annotate.c +34 -29
@@ -47,26 +47,26 @@ static struct annotate_browser_opt {struct arch ;struct annotate_browser { -struct ui_browser b; -struct rb_root entries; -struct rb_node *curr_hot; -struct disasm_line *selection; -struct disasm_line **offsets; -struct arch *arch; -int nr_events; -u64 start; -int nr_asm_entries; -int nr_entries; -int max_jump_sources; -int nr_jumps; -bool searching_backwards; -bool have_cycles; -u8 addr_width; -u8 jumps_width; -u8 target_width; -u8 min_addr_width; -u8 max_addr_width; -char search_bf[128 ]; +struct ui_browser b; +struct rb_root entries; +struct rb_node *curr_hot; +struct annotation_line *selection; +struct disasm_line **offsets; +struct arch *arch; +int nr_events; +u64 start; +int nr_asm_entries; +int nr_entries; +int max_jump_sources; +int nr_jumps; +bool searching_backwards; +bool have_cycles; +u8 addr_width; +u8 jumps_width; +u8 target_width; +u8 min_addr_width; +u8 max_addr_width; +char search_bf[128 ]; };static inline struct browser_line *browser_line (struct disasm_line *dl)
@@ -265,7 +265,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int }if (current_entry) - ab->selection = dl; + ab->selection = &dl->al; }static bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym)
@@ -301,7 +301,8 @@ static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)static void annotate_browser__draw_current_jump (struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); -struct disasm_line *cursor = ab->selection, *target; +struct disasm_line *cursor =disasm_line (ab->selection); +struct disasm_line *target;struct browser_line *btarget, *bcursor;unsigned int from, to;struct map_symbol *ms = ab->b.priv;
@@ -526,7 +527,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, struct hist_browser_timer *hbt) {struct map_symbol *ms = browser->b.priv; -struct disasm_line *dl = browser->selection; +struct disasm_line *dl =disasm_line (browser->selection);struct annotation *notes;struct addr_map_symbol target = { .map = ms->map,
@@ -584,7 +585,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browsstatic bool annotate_browser__jump (struct annotate_browser *browser) { -struct disasm_line *dl = browser->selection; +struct disasm_line *dl =disasm_line (browser->selection);u64 offset;s64 idx;
@@ -610,7 +611,7 @@ struct disasm_line *annotate_browser__find_string(struct annotate_browser *browsstruct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos = browser->selection; +struct disasm_line *pos =disasm_line (browser->selection); *idx = browser->b.index;list_for_each_entry_continue (pos, ¬es->src->source, al.node) {
@@ -649,7 +650,7 @@ struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browsestruct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos = browser->selection; +struct disasm_line *pos =disasm_line (browser->selection); *idx = browser->b.index;list_for_each_entry_continue_reverse (pos, ¬es->src->source, al.node) {
@@ -882,13 +883,16 @@ static int annotate_browser__run(struct annotate_browser *browser,continue ;case K_ENTER :case K_RIGHT : + { +struct disasm_line *dl =disasm_line (browser->selection); +if (browser->selection ==NULL )ui_helpline__puts ("Huh? No selection. Report to [email protected]" ); -else if (browser->selection->al.offset ==-1 ) +else if (browser->selection->offset ==-1 )ui_helpline__puts ("Actions are only available for assembly lines." ); -else if (!browser->selection->ins.ops) +else if (!dl->ins.ops) goto show_sup_ins; -else if (ins__is_ret (&browser->selection->ins)) +else if (ins__is_ret (&dl->ins)) goto out;else if (!(annotate_browser__jump (browser) ||annotate_browser__callq (browser, evsel, hbt))) {
@@ -896,6 +900,7 @@ static int annotate_browser__run(struct annotate_browser *browser,ui_helpline__puts ("Actions are only available for function call/return & jump/branch instructions." ); }continue ; + }case 't' :if (annotate_browser__opts.show_total_period) { annotate_browser__opts.show_total_period = false;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 31/83 perf annotate browser: Change offsets to struct annotation_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Use struct annotation_line as a browser::offsets array entry.
--- tools/perf/ui/browsers/annotate.c | 49 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-)
tools/perf/ui/browsers/annotate.c +29 -20
@@ -51,7 +51,7 @@ struct annotate_browser {struct rb_root entries;struct rb_node *curr_hot;struct annotation_line *selection; -struct disasm_line **offsets; +struct annotation_line **offsets;struct arch *arch;int nr_events;u64 start;
@@ -303,6 +303,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct disasm_line *cursor =disasm_line (ab->selection);struct disasm_line *target; +struct annotation_line *al;struct browser_line *btarget, *bcursor;unsigned int from, to;struct map_symbol *ms = ab->b.priv;
@@ -316,10 +317,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)if (!disasm_line__is_valid_jump (cursor, sym))return ; - target = ab->offsets[cursor->ops.target.offset]; -if (!target) + al = ab->offsets[cursor->ops.target.offset]; +if (!al)return ; + target =disasm_line (al); + bcursor =browser_line (cursor); btarget =browser_line (target);
@@ -978,10 +981,10 @@ static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,return ;for (offset = start; offset <= end; offset++) { -struct disasm_line *dl = browser->offsets[offset]; +struct annotation_line *al = browser->offsets[offset]; -if (dl) - dl->al.ipc = ipc; +if (al) + al->ipc = ipc; } } }
@@ -1006,13 +1009,13 @@ static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, ch = ¬es->src->cycles_hist[offset];if (ch && ch->cycles) { -struct disasm_line *dl; +struct annotation_line *al;if (ch->have_start)count_and_fill (browser, ch->start, offset, ch); - dl = browser->offsets[offset]; -if (dl && ch->num_aggr) - dl->al.cycles = ch->cycles_aggr / ch->num_aggr; + al = browser->offsets[offset]; +if (al && ch->num_aggr) + al->cycles = ch->cycles_aggr / ch->num_aggr; browser->have_cycles = true; } }
@@ -1031,13 +1034,18 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserreturn ;for (offset =0 ; offset < size; ++offset) { -struct disasm_line *dl = browser->offsets[offset], *dlt; +struct annotation_line *al = browser->offsets[offset]; +struct disasm_line *dl, *dlt;struct browser_line *bdlt; + dl =disasm_line (al); +if (!disasm_line__is_valid_jump (dl, sym))continue ; - dlt = browser->offsets[dl->ops.target.offset]; + al = browser->offsets[dl->ops.target.offset]; + dlt =disasm_line (al); +/* * FIXME: Oops, no jump target? Buggy disassembler? Or do we * have to adjust to the previous offset?
@@ -1066,7 +1074,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,struct perf_evsel *evsel, struct hist_browser_timer *hbt) { - struct disasm_line *pos; + struct annotation_line *al;struct annotation *notes;size_t size; struct map_symbol ms = {
@@ -1094,7 +1102,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (map->dso->annotate_warned)return -1 ; - browser.offsets =zalloc (size *sizeof (struct disasm_line *)); + browser.offsets =zalloc (size *sizeof (struct annotation_line *));if (browser.offsets ==NULL ) {ui__error ("Not enough memory!" );return -1 ;
@@ -1118,15 +1126,16 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, notes =symbol__annotation (sym); browser.start =map__rip_2objdump (map, sym->start); -list_for_each_entry (pos, ¬es->src->source, al.node) { +list_for_each_entry (al, ¬es->src->source, node) { +struct disasm_line *dl =disasm_line (al);struct browser_line *bpos; -size_t line_len =strlen (pos->al.line); +size_t line_len =strlen (al->line);if (browser.b.width < line_len) browser.b.width = line_len; - bpos =browser_line (pos); + bpos =browser_line (dl); bpos->idx = browser.nr_entries++; -if (pos->al.offset !=-1 ) { +if (al->offset !=-1 ) { bpos->idx_asm = browser.nr_asm_entries++;/* * FIXME: short term bandaid to cope with assembly
@@ -1135,8 +1144,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,* * E.g. copy_user_generic_unrolled */ -if (pos->al.offset < (s64 )size) - browser.offsets[pos->al.offset] = pos; +if (al->offset < (s64 )size) + browser.offsets[al->offset] = al; }else bpos->idx_asm =-1 ; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 32/83 perf annotate browser: Use struct annotation_line in browser_line
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Using struct annotation_line arg in browser_line function to make it generic.
--- tools/perf/ui/browsers/annotate.c | 60 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 32 deletions(-)
tools/perf/ui/browsers/annotate.c +28 -32
@@ -69,9 +69,12 @@ struct annotate_browser {char search_bf[128 ]; }; -static inline struct browser_line *browser_line (struct disasm_line *dl) +static inline struct browser_line *browser_line (struct annotation_line *al) { -return (void *) dl -sizeof (struct browser_line ); +void *ptr = al; + + ptr = container_of(al, struct disasm_line, al); +return ptr -sizeof (struct browser_line ); } static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
@@ -119,7 +122,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); -struct browser_line *bdl =browser_line (dl); +struct browser_line *bdl =browser_line (&dl->al);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!annotate_browser__opts.hide_src_code && (!current_entry || (browser->use_navkeypressed &&
@@ -302,8 +305,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct disasm_line *cursor =disasm_line (ab->selection); -struct disasm_line *target; -struct annotation_line *al; +struct annotation_line *target;struct browser_line *btarget, *bcursor;unsigned int from, to;struct map_symbol *ms = ab->b.priv;
@@ -317,13 +319,9 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)if (!disasm_line__is_valid_jump (cursor, sym))return ; - al = ab->offsets[cursor->ops.target.offset]; -if (!al) -return ; - - target =disasm_line (al); + target = ab->offsets[cursor->ops.target.offset]; - bcursor =browser_line (cursor); + bcursor =browser_line (&cursor->al); btarget =browser_line (target);if (annotate_browser__opts.hide_src_code) {
@@ -422,7 +420,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,u32 idx; pos = rb_entry(nd, struct disasm_line, al.rb_node); - bpos =browser_line (pos); + bpos =browser_line (&pos->al); idx = bpos->idx;if (annotate_browser__opts.hide_src_code)
@@ -475,37 +473,37 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,static bool annotate_browser__toggle_source (struct annotate_browser *browser) {struct disasm_line *dl; -struct browser_line *bdl; +struct browser_line *bl;off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek (&browser->b, offset,SEEK_CUR ); dl = list_entry(browser->b.top, struct disasm_line, al.node); - bdl =browser_line (dl); + bl =browser_line (&dl->al);if (annotate_browser__opts.hide_src_code) { -if (bdl->idx_asm < offset) - offset = bdl->idx; +if (bl->idx_asm < offset) + offset = bl->idx; browser->b.nr_entries = browser->nr_entries; annotate_browser__opts.hide_src_code = false; browser->b.seek (&browser->b, -offset,SEEK_CUR ); - browser->b.top_idx = bdl->idx - offset; - browser->b.index = bdl->idx; + browser->b.top_idx = bl->idx - offset; + browser->b.index = bl->idx; }else { -if (bdl->idx_asm <0 ) { +if (bl->idx_asm <0 ) {ui_helpline__puts ("Only available for assembly lines." ); browser->b.seek (&browser->b, -offset,SEEK_CUR );return false; } -if (bdl->idx_asm < offset) - offset = bdl->idx_asm; +if (bl->idx_asm < offset) + offset = bl->idx_asm; browser->b.nr_entries = browser->nr_asm_entries; annotate_browser__opts.hide_src_code = true; browser->b.seek (&browser->b, -offset,SEEK_CUR ); - browser->b.top_idx = bdl->idx_asm - offset; - browser->b.index = bdl->idx_asm; + browser->b.top_idx = bl->idx_asm - offset; + browser->b.index = bl->idx_asm; }return true;
@@ -1035,8 +1033,8 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserfor (offset =0 ; offset < size; ++offset) {struct annotation_line *al = browser->offsets[offset]; -struct disasm_line *dl, *dlt; -struct browser_line *bdlt; +struct disasm_line *dl; +struct browser_line *blt; dl =disasm_line (al);
@@ -1044,18 +1042,17 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browsercontinue ; al = browser->offsets[dl->ops.target.offset]; - dlt =disasm_line (al);/* * FIXME: Oops, no jump target? Buggy disassembler? Or do we * have to adjust to the previous offset? */ -if (dlt ==NULL ) +if (al ==NULL )continue ; - bdlt =browser_line (dlt); -if (++bdlt->jump_sources > browser->max_jump_sources) - browser->max_jump_sources = bdlt->jump_sources; + blt =browser_line (al); +if (++blt->jump_sources > browser->max_jump_sources) + browser->max_jump_sources = blt->jump_sources; ++browser->nr_jumps; }
@@ -1127,13 +1124,12 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.start =map__rip_2objdump (map, sym->start);list_for_each_entry (al, ¬es->src->source, node) { -struct disasm_line *dl =disasm_line (al);struct browser_line *bpos;size_t line_len =strlen (al->line);if (browser.b.width < line_len) browser.b.width = line_len; - bpos =browser_line (dl); + bpos =browser_line (al); bpos->idx = browser.nr_entries++;if (al->offset !=-1 ) { bpos->idx_asm = browser.nr_asm_entries++;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 33/83 perf annotate browser: Use struct annotation_line in find functions
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Use struct annotation_line in find functions:
annotate_browser__find_string annotate_browser__find_string_reverse
--- tools/perf/ui/browsers/annotate.c | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-)
tools/perf/ui/browsers/annotate.c +20 -20
@@ -606,23 +606,23 @@ static bool annotate_browser__jump(struct annotate_browser *browser) }static -struct disasm_line *annotate_browser__find_string (struct annotate_browser *browser, +struct annotation_line *annotate_browser__find_string (struct annotate_browser *browser,char *s,s64 *idx) {struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos =disasm_line (browser->selection); +struct annotation_line *al = browser->selection; *idx = browser->b.index; -list_for_each_entry_continue (pos, ¬es->src->source, al.node) { -if (disasm_line__filter (&browser->b, &pos->al.node)) +list_for_each_entry_continue (al, ¬es->src->source, node) { +if (disasm_line__filter (&browser->b, &al->node))continue ; ++*idx; -if (pos->al.line &&strstr (pos->al.line, s) !=NULL ) -return pos; +if (al->line &&strstr (al->line, s) !=NULL ) +return al; }return NULL ;
@@ -630,38 +630,38 @@ struct disasm_line *annotate_browser__find_string(struct annotate_browser *browsstatic bool __annotate_browser__search (struct annotate_browser *browser) { -struct disasm_line *dl; +struct annotation_line *al;s64 idx; - dl =annotate_browser__find_string (browser, browser->search_bf, &idx); -if (dl ==NULL ) { + al =annotate_browser__find_string (browser, browser->search_bf, &idx); +if (al ==NULL ) {ui_helpline__puts ("String not found!" );return false; } -annotate_browser__set_top (browser, dl, idx); +annotate_browser__set_top (browser,disasm_line (al), idx); browser->searching_backwards = false;return true; }static -struct disasm_line *annotate_browser__find_string_reverse (struct annotate_browser *browser, +struct annotation_line *annotate_browser__find_string_reverse (struct annotate_browser *browser,char *s,s64 *idx) {struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -struct disasm_line *pos =disasm_line (browser->selection); +struct annotation_line *al = browser->selection; *idx = browser->b.index; -list_for_each_entry_continue_reverse (pos, ¬es->src->source, al.node) { -if (disasm_line__filter (&browser->b, &pos->al.node)) +list_for_each_entry_continue_reverse (al, ¬es->src->source, node) { +if (disasm_line__filter (&browser->b, &al->node))continue ; --*idx; -if (pos->al.line &&strstr (pos->al.line, s) !=NULL ) -return pos; +if (al->line &&strstr (al->line, s) !=NULL ) +return al; }return NULL ;
@@ -669,16 +669,16 @@ struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browsestatic bool __annotate_browser__search_reverse (struct annotate_browser *browser) { -struct disasm_line *dl; +struct annotation_line *al;s64 idx; - dl =annotate_browser__find_string_reverse (browser, browser->search_bf, &idx); -if (dl ==NULL ) { + al =annotate_browser__find_string_reverse (browser, browser->search_bf, &idx); +if (al ==NULL ) {ui_helpline__puts ("String not found!" );return false; } -annotate_browser__set_top (browser, dl, idx); +annotate_browser__set_top (browser,disasm_line (al), idx); browser->searching_backwards = true;return true; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 34/83 perf annotate browser: Use struct annotation_line in browser top
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Use struct annotation_line in browser::b::top.
--- tools/perf/ui/browsers/annotate.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
tools/perf/ui/browsers/annotate.c +13 -13
@@ -390,7 +390,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line }static void annotate_browser__set_top (struct annotate_browser *browser, -struct disasm_line *pos,u32 idx) +struct annotation_line *pos,u32 idx) {unsigned back;
@@ -399,16 +399,16 @@ static void annotate_browser__set_top(struct annotate_browser *browser, browser->b.top_idx = browser->b.index = idx;while (browser->b.top_idx !=0 && back !=0 ) { - pos = list_entry(pos->al.node.prev, struct disasm_line, al.node); + pos = list_entry(pos->node.prev, struct annotation_line, node); -if (disasm_line__filter (&browser->b, &pos->al.node)) +if (disasm_line__filter (&browser->b, &pos->node))continue ; --browser->b.top_idx; --back; } - browser->b.top = &pos->al; + browser->b.top = pos; browser->b.navkeypressed = true; }
@@ -416,11 +416,11 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, struct rb_node *nd) {struct browser_line *bpos; -struct disasm_line *pos; +struct annotation_line *pos;u32 idx; - pos = rb_entry(nd, struct disasm_line, al.rb_node); - bpos =browser_line (&pos->al); + pos = rb_entry(nd, struct annotation_line, rb_node); + bpos =browser_line (pos); idx = bpos->idx;if (annotate_browser__opts.hide_src_code)
@@ -472,13 +472,13 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,static bool annotate_browser__toggle_source (struct annotate_browser *browser) { -struct disasm_line *dl; +struct annotation_line *al;struct browser_line *bl;off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek (&browser->b, offset,SEEK_CUR ); - dl = list_entry(browser->b.top, struct disasm_line, al.node); - bl =browser_line (&dl->al); + al = list_entry(browser->b.top, struct annotation_line, node); + bl =browser_line (al);if (annotate_browser__opts.hide_src_code) {if (bl->idx_asm < offset)
@@ -600,7 +600,7 @@ static bool annotate_browser__jump(struct annotate_browser *browser)return true; } -annotate_browser__set_top (browser, dl, idx); +annotate_browser__set_top (browser, &dl->al, idx);return true; }
@@ -639,7 +639,7 @@ static bool __annotate_browser__search(struct annotate_browser *browser)return false; } -annotate_browser__set_top (browser,disasm_line (al), idx); +annotate_browser__set_top (browser, al, idx); browser->searching_backwards = false;return true; }
@@ -678,7 +678,7 @@ static bool __annotate_browser__search_reverse(struct annotate_browser *browser)return false; } -annotate_browser__set_top (browser,disasm_line (al), idx); +annotate_browser__set_top (browser, al, idx); browser->searching_backwards = true;return true; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 35/83 perf annotate browser: Add disasm_line__write function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Factor disasm_line__write function from annotate_browser__write, which now keeps only generic display code.
--- tools/perf/ui/browsers/annotate.c | 98 +++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 45 deletions(-)
tools/perf/ui/browsers/annotate.c +53 -45
@@ -118,11 +118,37 @@ static int annotate_browser__cycles_width(struct annotate_browser *ab)return ab->have_cycles ?IPC_WIDTH +CYCLES_WIDTH :0 ; } +static void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser, +char *bf,size_t size) +{ +if (dl->ins.ops && dl->ins.ops->scnprintf) { +if (ins__is_jump (&dl->ins)) { +bool fwd = dl->ops.target.offset > dl->al.offset; + +ui_browser__write_graph (browser, fwd ?SLSMG_DARROW_CHAR : +SLSMG_UARROW_CHAR ); +SLsmg_write_char (' ' ); + }else if (ins__is_call (&dl->ins)) { +ui_browser__write_graph (browser,SLSMG_RARROW_CHAR ); +SLsmg_write_char (' ' ); + }else if (ins__is_ret (&dl->ins)) { +ui_browser__write_graph (browser,SLSMG_LARROW_CHAR ); +SLsmg_write_char (' ' ); + }else { +ui_browser__write_nstring (browser," " ,2 ); + } + }else { +ui_browser__write_nstring (browser," " ,2 ); + } + +disasm_line__scnprintf (dl, bf, size, !annotate_browser__opts.use_offset); +} +static void annotate_browser__write (struct ui_browser *browser,void *entry,int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); - struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); -struct browser_line *bdl =browser_line (&dl->al); + struct annotation_line *al = list_entry(entry, struct annotation_line, node); +struct browser_line *bl =browser_line (al);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!annotate_browser__opts.hide_src_code && (!current_entry || (browser->use_navkeypressed &&
@@ -135,32 +161,32 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intbool show_title = false;for (i =0 ; i < ab->nr_events; i++) { -if (dl->al.samples[i].percent > percent_max) - percent_max = dl->al.samples[i].percent; +if (al->samples[i].percent > percent_max) + percent_max = al->samples[i].percent; } -if ((row ==0 ) && (dl->al.offset ==-1 || percent_max ==0.0 )) { +if ((row ==0 ) && (al->offset ==-1 || percent_max ==0.0 )) {if (ab->have_cycles) { -if (dl->al.ipc ==0.0 && dl->al.cycles ==0 ) +if (al->ipc ==0.0 && al->cycles ==0 ) show_title = true; }else show_title = true; } -if (dl->al.offset !=-1 && percent_max !=0.0 ) { +if (al->offset !=-1 && percent_max !=0.0 ) {for (i =0 ; i < ab->nr_events; i++) {ui_browser__set_percent_color (browser, - dl->al.samples[i].percent, + al->samples[i].percent, current_entry);if (annotate_browser__opts.show_total_period) {ui_browser__printf (browser,"%11" PRIu64" " , - dl->al.samples[i].he.period); + al->samples[i].he.period); }else if (annotate_browser__opts.show_nr_samples) {ui_browser__printf (browser,"%6" PRIu64" " , - dl->al.samples[i].he.nr_samples); + al->samples[i].he.nr_samples); }else {ui_browser__printf (browser,"%6.2f " , - dl->al.samples[i].percent); + al->samples[i].percent); } } }else {
@@ -175,16 +201,16 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int } }if (ab->have_cycles) { -if (dl->al.ipc) -ui_browser__printf (browser,"%*.2f " ,IPC_WIDTH -1 , dl->al.ipc); +if (al->ipc) +ui_browser__printf (browser,"%*.2f " ,IPC_WIDTH -1 , al->ipc);else if (!show_title)ui_browser__write_nstring (browser," " ,IPC_WIDTH );else ui_browser__printf (browser,"%*s " ,IPC_WIDTH -1 ,"IPC" ); -if (dl->al.cycles) +if (al->cycles)ui_browser__printf (browser,"%*" PRIu64" " , -CYCLES_WIDTH -1 , dl->al.cycles); +CYCLES_WIDTH -1 , al->cycles);else if (!show_title)ui_browser__write_nstring (browser," " ,CYCLES_WIDTH );else
@@ -197,19 +223,19 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!browser->navkeypressed) width +=1 ; -if (!*dl->al.line) +if (!*al->line)ui_browser__write_nstring (browser," " , width - pcnt_width - cycles_width); -else if (dl->al.offset ==-1 ) { -if (dl->al.line_nr && annotate_browser__opts.show_linenr) +else if (al->offset ==-1 ) { +if (al->line_nr && annotate_browser__opts.show_linenr) printed =scnprintf (bf,sizeof (bf),"%-*d " , - ab->addr_width +1 , dl->al.line_nr); + ab->addr_width +1 , al->line_nr);else printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );ui_browser__write_nstring (browser, bf, printed); -ui_browser__write_nstring (browser, dl->al.line, width - printed - pcnt_width - cycles_width +1 ); +ui_browser__write_nstring (browser, al->line, width - printed - pcnt_width - cycles_width +1 ); }else { -u64 addr = dl->al.offset; +u64 addr = al->offset;int color =-1 ;if (!annotate_browser__opts.use_offset)
@@ -218,13 +244,13 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!annotate_browser__opts.use_offset) { printed =scnprintf (bf,sizeof (bf),"%" PRIx64": " , addr); }else { -if (bdl->jump_sources) { +if (bl->jump_sources) {if (annotate_browser__opts.show_nr_jumps) {int prev; printed =scnprintf (bf,sizeof (bf),"%*d " , ab->jumps_width, - bdl->jump_sources); - prev =annotate_browser__set_jumps_percent_color (ab, bdl->jump_sources, + bl->jump_sources); + prev =annotate_browser__set_jumps_percent_color (ab, bl->jump_sources, current_entry);ui_browser__write_nstring (browser, bf, printed);ui_browser__set_color (browser, prev);
@@ -243,32 +269,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intui_browser__write_nstring (browser, bf, printed);if (change_color)ui_browser__set_color (browser, color); -if (dl->ins.ops && dl->ins.ops->scnprintf) { -if (ins__is_jump (&dl->ins)) { -bool fwd = dl->ops.target.offset > dl->al.offset; - -ui_browser__write_graph (browser, fwd ?SLSMG_DARROW_CHAR : -SLSMG_UARROW_CHAR ); -SLsmg_write_char (' ' ); - }else if (ins__is_call (&dl->ins)) { -ui_browser__write_graph (browser,SLSMG_RARROW_CHAR ); -SLsmg_write_char (' ' ); - }else if (ins__is_ret (&dl->ins)) { -ui_browser__write_graph (browser,SLSMG_LARROW_CHAR ); -SLsmg_write_char (' ' ); - }else { -ui_browser__write_nstring (browser," " ,2 ); - } - }else { -ui_browser__write_nstring (browser," " ,2 ); - } -disasm_line__scnprintf (dl, bf,sizeof (bf), !annotate_browser__opts.use_offset); +disasm_line__write (disasm_line (al), browser, bf,sizeof (bf)); +ui_browser__write_nstring (browser, bf, width - pcnt_width - cycles_width -3 - printed); }if (current_entry) - ab->selection = &dl->al; + ab->selection = al; }static bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 36/83 perf annotate: Align source and offset lines
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Align source with offset lines, which are more advanced, because of the address column.
Before:
: static void *worker_thread(void *__tdata)
: {
0.00 : 48a971: push %rbp
0.00 : 48a972: mov %rsp,%rbp
0.00 : 48a975: sub $0x30,%rsp
0.00 : 48a979: mov %rdi,-0x28(%rbp)
0.00 : 48a97d: mov %fs:0x28,%rax
0.00 : 48a986: mov %rax,-0x8(%rbp)
0.00 : 48a98a: xor %eax,%eax
: struct thread_data *td = __tdata;
0.00 : 48a98c: mov -0x28(%rbp),%rax
0.00 : 48a990: mov %rax,-0x10(%rbp)
: int m = 0, i;
0.00 : 48a994: movl $0x0,-0x1c(%rbp)
: int ret;
:
: for (i = 0; i < loops; i++) {
0.00 : 48a99b: movl $0x0,-0x18(%rbp)
After:
: static void *worker_thread(void *__tdata)
: {
0.00 : 48a971: push %rbp
0.00 : 48a972: mov %rsp,%rbp
0.00 : 48a975: sub $0x30,%rsp
0.00 : 48a979: mov %rdi,-0x28(%rbp)
0.00 : 48a97d: mov %fs:0x28,%rax
0.00 : 48a986: mov %rax,-0x8(%rbp)
0.00 : 48a98a: xor %eax,%eax
: struct thread_data *td = __tdata;
0.00 : 48a98c: mov -0x28(%rbp),%rax
0.00 : 48a990: mov %rax,-0x10(%rbp)
: int m = 0, i;
0.00 : 48a994: movl $0x0,-0x1c(%rbp)
: int ret;
:
: for (i = 0; i < loops; i++) {
0.00 : 48a99b: movl $0x0,-0x18(%rbp)It makes bigger different when displaying script sources, where the comment lines looks oddly shifted from the lines which actually hold code. I'll send script support separately.
Committer note:
Do not use a fixed column width for the addresses, as kernel ones se more than 10 columns, look at the last offset and get the right width.
--- tools/perf/util/annotate.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-)
tools/perf/util/annotate.c +24 -10
@@ -1092,15 +1092,14 @@ static void annotate__branch_printf(struct block_range *br, u64 addr) } } - -static int disasm_line__print (struct disasm_line *dl,u64 start) +static int disasm_line__print (struct disasm_line *dl,u64 start,int addr_fmt_width) {s64 offset = dl->al.offset;const u64 addr = start + offset;struct block_range *br; br =block_range__find (addr); -color_fprintf (stdout,annotate__address_color (br)," %" PRIx64":" , addr); +color_fprintf (stdout,annotate__address_color (br)," %*" PRIx64":" , addr_fmt_width, addr);color_fprintf (stdout,annotate__asm_color (br),"%s" , dl->al.line);annotate__branch_printf (br, addr);return 0 ;
@@ -1109,7 +1108,7 @@ static int disasm_line__print(struct disasm_line *dl, u64 start)static int annotation_line__print (struct annotation_line *al,struct symbol *sym,u64 start,struct perf_evsel *evsel,u64 len,int min_pcnt,int printed, -int max_lines,struct annotation_line *queue) +int max_lines,struct annotation_line *queue,int addr_fmt_width) { struct disasm_line *dl = container_of(al, struct disasm_line, al);static const char *prev_line;
@@ -1139,7 +1138,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 startif (queue == al)break ;annotation_line__print (queue, sym, start, evsel, len, -0 ,0 ,1 ,NULL ); +0 ,0 ,1 ,NULL , addr_fmt_width); } }
@@ -1174,9 +1173,9 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 startcolor_fprintf (stdout, color," %7.2f" , sample->percent); } -printf (" : " ); +printf (" : " ); -disasm_line__print (dl, start); +disasm_line__print (dl, start, addr_fmt_width);printf ("\n" ); }else if (max_lines && printed >= max_lines)return 1 ;
@@ -1192,7 +1191,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 startif (!*al->line)printf (" %*s:\n" , width," " );else -printf (" %*s: %s\n" , width," " , al->line); +printf (" %*s: %*s %s\n" , width," " , addr_fmt_width," " , al->line); }return 0 ;
@@ -1796,6 +1795,19 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)printf ("%*s: %" PRIu64"\n" ,BITS_PER_LONG /2 ,"h->nr_samples" , h->nr_samples); } +static int annotated_source__addr_fmt_width (struct list_head *lines,u64 start) +{ +char bf[32 ]; +struct annotation_line *line; + +list_for_each_entry_reverse (line, lines, node) { +if (line->offset !=-1 ) +return scnprintf (bf,sizeof (bf),"%" PRIx64, start + line->offset); + } + +return 0 ; +} +int symbol__annotate_printf (struct symbol *sym,struct map *map,struct perf_evsel *evsel,bool full_paths,int min_pcnt,int max_lines,int context)
@@ -1808,7 +1820,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,struct sym_hist *h =annotation__histogram (notes, evsel->idx);struct annotation_line *pos, *queue =NULL ;u64 start =map__rip_2objdump (map, sym->start); -int printed =2 , queue_len =0 ; +int printed =2 , queue_len =0 , addr_fmt_width;int more =0 ;u64 len;int width = symbol_conf.show_total_period ?12 :8 ;
@@ -1839,6 +1851,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,if (verbose >0 )symbol__annotate_hits (sym, evsel); + addr_fmt_width =annotated_source__addr_fmt_width (¬es->src->source, start); +list_for_each_entry (pos, ¬es->src->source, node) {int err;
@@ -1849,7 +1863,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, err =annotation_line__print (pos, sym, start, evsel, len, min_pcnt, printed, max_lines, - queue); + queue, addr_fmt_width);switch (err) {case 0 :
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 37/83 tools headers: Synchronize kernel ABI headers wrt SPDX tags
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Two more, that were just in perf/core and thus weren't covered by Ingo's latest headers synch, kcmp.h and prctl.h, silencing this:
Warning: Kernel ABI header at 'tools/include/uapi/linux/kcmp.h' differs from latest version at 'include/uapi/linux/kcmp.h'
Warning: Kernel ABI header at 'tools/include/uapi/linux/prctl.h' differs from latest version at 'include/uapi/linux/prctl.h'
--- tools/include/uapi/linux/kcmp.h | 1 + tools/include/uapi/linux/prctl.h | 1 + 2 files changed, 2 insertions(+)
tools/include/uapi/linux/kcmp.h +1 -0
@@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _UAPI_LINUX_KCMP_H#define _UAPI_LINUX_KCMP_H
tools/include/uapi/linux/prctl.h +1 -0
@@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _LINUX_PRCTL_H#define _LINUX_PRCTL_H
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 38/83 perf record: Fix -c/-F options for cpu event aliases
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
The Intel PMU event aliases have a implicit period= specifier to set the default period.
Unfortunately this breaks overriding these periods with -c or -F, because the alias terms look like they are user specified to the internal parser, and user specified event qualifiers override the command line options.
Track that they are coming from aliases by adding a "weak" state to the term. Any weak terms don't override command line options.
I only did it for -c/-F for now, I think that's the only case that's broken currently.
Before:
$ perf record -c 1000 -vv -e uops_issued.any
...
{ sample_period, sample_freq } 2000003After:
$ perf record -c 1000 -vv -e uops_issued.any
...
{ sample_period, sample_freq } 1000--- tools/perf/util/evsel.c | 12 ++++++++---- tools/perf/util/evsel.h | 1 + tools/perf/util/parse-events.c | 2 ++ tools/perf/util/parse-events.h | 3 +++ tools/perf/util/pmu.c | 5 +++++ 5 files changed, 19 insertions(+), 4 deletions(-)
tools/perf/util/evsel.c +8 -4
@@ -733,12 +733,16 @@ static void apply_config_terms(struct perf_evsel *evsel,list_for_each_entry (term, config_terms, list) {switch (term->type) {case PERF_EVSEL__CONFIG_TERM_PERIOD : - attr->sample_period = term->val.period; - attr->freq =0 ; +if (!(term->weak && opts->user_interval !=ULLONG_MAX )) { + attr->sample_period = term->val.period; + attr->freq =0 ; + }break ;case PERF_EVSEL__CONFIG_TERM_FREQ : - attr->sample_freq = term->val.freq; - attr->freq =1 ; +if (!(term->weak && opts->user_freq !=UINT_MAX )) { + attr->sample_freq = term->val.freq; + attr->freq =1 ; + }break ;case PERF_EVSEL__CONFIG_TERM_TIME :if (term->val.time)
tools/perf/util/evsel.h +1 -0
@@ -67,6 +67,7 @@ struct perf_evsel_config_term {bool overwrite;char *branch; } val; +bool weak; };struct perf_stat_evsel ;
tools/perf/util/parse-events.c +2 -0
@@ -1116,6 +1116,7 @@ do { \INIT_LIST_HEAD (&__t->list); \ __t->type = PERF_EVSEL__CONFIG_TERM_ ## __type; \ __t->val.__name = __val; \ + __t->weak = term->weak; \list_add_tail (&__t->list, head_terms); \ }while (0 )
@@ -2410,6 +2411,7 @@ static int new_term(struct parse_events_term **_term, *term = *temp;INIT_LIST_HEAD (&term->list); + term->weak = false;switch (term->type_val) {case PARSE_EVENTS__TERM_TYPE_NUM :
tools/perf/util/parse-events.h +3 -0
@@ -101,6 +101,9 @@ struct parse_events_term {/* error string indexes for within parsed string */ int err_term;int err_val; + +/* Coming from implicit alias */ +bool weak; };struct parse_events_error {
tools/perf/util/pmu.c +5 -0
@@ -405,6 +405,11 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,parse_events_terms__purge (&list);return ret; } +/* +* Weak terms don't override command line options, +* which we don't want for implicit terms in aliases. +*/ + cloned->weak = true;list_add_tail (&cloned->list, &list); }list_splice (&list, terms);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 39/83 perf evsel: Enable type checking for perf_evsel_config_term types
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Use a typed enum for the perf_evsel_config_term type enum. This allows gcc to do much stronger type checks, and also check for missing case statements.
I removed the unused _MAX member from the number.
It found one missing case. I'm not sure it's a real problem, so I just turned it into a BUG_ON for now.
--- tools/perf/util/evsel.c | 2 ++ tools/perf/util/evsel.h | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-)
tools/perf/util/evsel.c +2 -0
@@ -779,6 +779,8 @@ static void apply_config_terms(struct perf_evsel *evsel,case PERF_EVSEL__CONFIG_TERM_OVERWRITE : attr->write_backward = term->val.overwrite ?1 :0 ;break ; +case PERF_EVSEL__CONFIG_TERM_DRV_CFG : +BUG_ON (1 );default :break ; }
tools/perf/util/evsel.h +2 -3
@@ -38,7 +38,7 @@ struct cgroup_sel;* It is allocated within event parsing and attached to * perf_evsel::config_terms list head. */ -enum { +enum term_type {PERF_EVSEL__CONFIG_TERM_PERIOD ,PERF_EVSEL__CONFIG_TERM_FREQ ,PERF_EVSEL__CONFIG_TERM_TIME ,
@@ -49,12 +49,11 @@ enum { PERF_EVSEL__CONFIG_TERM_OVERWRITE,PERF_EVSEL__CONFIG_TERM_DRV_CFG , PERF_EVSEL__CONFIG_TERM_BRANCH, - PERF_EVSEL__CONFIG_TERM_MAX, };struct perf_evsel_config_term {struct list_head list; -int type; +enum term_type type;union {u64 period;u64 freq;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 40/83 perf trace: Fix an exit code of trace__symbols_init
In reply to Arnaldo Carvalho de MeloFrom: Andrei Vagin <[email protected]>
Currently if trace_event__register_resolver() fails, we return -errno, but we can't be sure that errno isn't zero in this case.
--- tools/perf/builtin-trace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/builtin-trace.c +4 -2
@@ -1152,12 +1152,14 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)if (trace->host ==NULL )return -ENOMEM ; -if (trace_event__register_resolver (trace->host, trace__machine__resolve_kernel_addr) <0 ) -return -errno; + err =trace_event__register_resolver (trace->host, trace__machine__resolve_kernel_addr); +if (err <0 ) + goto out; err =__machine__synthesize_threads (trace->host, &trace->tool, &trace->opts.target, evlist->threads, trace__tool_process, false, trace->opts.proc_map_timeout,1 ); +out:if (err)symbol__exit ();
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 41/83 perf tools: Use shell function for perl cflags retrieval
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Using the shell function for perl CFLAGS retrieval instead of back quotes (``). Both execute shell with the command, but the latter is more explicit and seems to be the preferred way.
Also we don't have any other use of the back quotes in perf Makefiles.
--- tools/perf/Makefile.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/Makefile.config +1 -1
@@ -579,7 +579,7 @@ else PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) - PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` + PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null) FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) ifneq ($(feature-libperl), 1)
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 42/83 perf evsel: Fix up leftover perf_evsel_stat usage via evsel->priv
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
I forgot one conversion, which got noticed by Thomas when running:
$ perf stat -e '{cpu-clock,instructions}' kill
kill: not enough arguments
Segmentation fault (core dumped)
$Fix it, those stats are in evsel->stats, not anymore in evsel->priv.
--- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evsel.c +1 -1
@@ -1377,7 +1377,7 @@ perf_evsel__process_group_data(struct perf_evsel *leader,static int perf_evsel__read_group (struct perf_evsel *leader,int cpu,int thread) { -struct perf_stat_evsel *ps = leader->priv; +struct perf_stat_evsel *ps = leader->stats;u64 read_format = leader->attr.read_format;int size =perf_evsel__read_size (leader);u64 *data = ps->group_data;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 43/83 perf tests: Add missing WRITE_ASS for new fields of perf_event_attr
In reply to Arnaldo Carvalho de MeloFrom: Seonghyun Park <[email protected]>
Include newly added fields 'mmap2', 'comm_exec', 'use_clockid', 'namespaces', 'write_backward' and 'context_switch' from perf_event_attr to store_event().
--- tools/perf/tests/attr.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/tests/attr.c +6 -0
@@ -124,6 +124,12 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,WRITE_ASS (exclude_guest,"d" );WRITE_ASS (exclude_callchain_kernel,"d" );WRITE_ASS (exclude_callchain_user,"d" ); +WRITE_ASS (mmap2,"d" ); +WRITE_ASS (comm_exec,"d" ); +WRITE_ASS (context_switch,"d" ); +WRITE_ASS (write_backward,"d" ); +WRITE_ASS (namespaces,"d" ); +WRITE_ASS (use_clockid,"d" );WRITE_ASS (wakeup_events, PRIu32);WRITE_ASS (bp_type, PRIu32);WRITE_ASS (config1,"llu" );
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 44/83 perf script: Fix --per-event-dump for auxtrace synth evsels
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
When processing PERF_RECORD_AUXTRACE_INFO several perf_evsel entries will be synthesized and inserted into session->evlist, eventually ending in perf_script.tool.sample(), which ends up calling builtin-script.c's process_event(), that expects evsel->priv to be a perf_evsel_script object with a valid FILE pointer in fp.
So we need to intercept the processing of PERF_RECORD_AUXTRACE_INFO and then setup evsel->priv for these newly created perf_evsel instances, do it to fix the segfault in process_event() trying to use a NULL for that FILE pointer.
--- tools/perf/builtin-script.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
tools/perf/builtin-script.c +30 -1
@@ -1955,6 +1955,16 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script)struct perf_evsel *evsel;evlist__for_each_entry (script->session->evlist, evsel) { +/* +* Already setup? I.e. we may be called twice in cases like +* Intel PT, one for the intel_pt// and dummy events, then +* for the evsels syntheized from the auxtrace info. +* +* Ses perf_script__process_auxtrace_info. +*/ +if (evsel->priv !=NULL ) +continue ; + evsel->priv =perf_evsel_script__new (evsel, script->session->data);if (evsel->priv ==NULL ) goto out_err_fclose;
@@ -2838,6 +2848,25 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,return set_maps (script); } +#ifdef HAVE_AUXTRACE_SUPPORT +static int perf_script__process_auxtrace_info (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session) +{ +int ret =perf_event__process_auxtrace_info (tool, event, session); + +if (ret ==0 ) { + struct perf_script *script = container_of(tool, struct perf_script, tool); + + ret =perf_script__setup_per_event_dump (script); + } + +return ret; +} +#else +#define perf_script__process_auxtrace_info 0 +#endif +int cmd_script (int argc,const char **argv) {bool show_full_info = false;
@@ -2866,7 +2895,7 @@ int cmd_script(int argc, const char **argv) .feature = perf_event__process_feature, .build_id = perf_event__process_build_id, .id_index = perf_event__process_id_index, - .auxtrace_info = perf_event__process_auxtrace_info, + .auxtrace_info = perf_script__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, .auxtrace_error = perf_event__process_auxtrace_error, .stat = perf_event__process_stat_event,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 45/83 perf vendor events powerpc: Update POWER9 events
In reply to Arnaldo Carvalho de MeloFrom: Sukadev Bhattiprolu <[email protected]>
The POWER9 hardware has dropped support for several events, added a few new events and changed the category for a couple of events.
Update the POWER9 events in Linux to reflect these changes.
--- .../perf/pmu-events/arch/powerpc/power9/cache.json | 5 - .../pmu-events/arch/powerpc/power9/frontend.json | 7 +- .../pmu-events/arch/powerpc/power9/marked.json | 27 +- .../perf/pmu-events/arch/powerpc/power9/other.json | 276 ++++++--------------- .../pmu-events/arch/powerpc/power9/pipeline.json | 14 +- tools/perf/pmu-events/arch/powerpc/power9/pmc.json | 2 +- .../arch/powerpc/power9/translation.json | 5 - 7 files changed, 88 insertions(+), 248 deletions(-)
tools/perf/pmu-events/arch/powerpc/power9/cache.json +0 -5
@@ -125,11 +125,6 @@ "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied" }, {, - "EventCode": "0x3006C", - "EventName": "PM_RUN_CYC_SMT2_MODE", - "BriefDescription": "Cycles in which this thread's run latch is set and the core is in SMT2 mode" - }, - {, "EventCode": "0x1C058", "EventName": "PM_DTLB_MISS_16G", "BriefDescription": "Data TLB Miss page size 16G"
tools/perf/pmu-events/arch/powerpc/power9/frontend.json +1 -6
@@ -1,10 +1,5 @@ [ {, - "EventCode": "0x3E15C", - "EventName": "PM_MRK_L2_TM_ST_ABORT_SISTER", - "BriefDescription": "TM marked store abort for this thread" - }, - {, "EventCode": "0x25044", "EventName": "PM_IPTEG_FROM_L31_MOD", "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a instruction side request"
@@ -369,4 +364,4 @@ "EventName": "PM_IPTEG_FROM_L31_ECO_MOD", "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request" } -] +]
tools/perf/pmu-events/arch/powerpc/power9/marked.json +6 -21
@@ -1,10 +1,5 @@ [ {, - "EventCode": "0x3C052", - "EventName": "PM_DATA_SYS_PUMP_MPRED", - "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load" - }, - {, "EventCode": "0x3013E", "EventName": "PM_MRK_STALL_CMPLU_CYC", "BriefDescription": "Number of cycles the marked instruction is experiencing a stall while it is next to complete (NTC)"
@@ -255,6 +250,11 @@ "BriefDescription": "A Page Directory Entry was reloaded to a level 1 page walk cache from the core's L3 data cache" }, {, + "EventCode": "0x3C052", + "EventName": "PM_DATA_SYS_PUMP_MPRED", + "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load" + }, + {, "EventCode": "0x4D142", "EventName": "PM_MRK_DATA_FROM_L3", "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a marked load"
@@ -435,21 +435,6 @@ "BriefDescription": "ITLB Reloaded. Counts 1 per ITLB miss for HPT but multiple for radix depending on number of levels traveresed" }, {, - "EventCode": "0x2D024", - "EventName": "PM_RADIX_PWC_L2_HIT", - "BriefDescription": "A radix translation attempt missed in the TLB but hit on both the first and second levels of page walk cache." - }, - {, - "EventCode": "0x3F056", - "EventName": "PM_RADIX_PWC_L3_HIT", - "BriefDescription": "A radix translation attempt missed in the TLB but hit on the first, second, and third levels of page walk cache." - }, - {, - "EventCode": "0x4E014", - "EventName": "PM_TM_TX_PASS_RUN_INST", - "BriefDescription": "Run instructions spent in successful transactions" - }, - {, "EventCode": "0x1E044", "EventName": "PM_DPTEG_FROM_L3_NO_CONFLICT", "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -644,4 +629,4 @@ "EventName": "PM_MRK_BR_MPRED_CMPL", "BriefDescription": "Marked Branch Mispredicted" } -] +]
tools/perf/pmu-events/arch/powerpc/power9/other.json +73 -203
604 lines not on this page · raw message
tools/perf/pmu-events/arch/powerpc/power9/pipeline.json +7 -7
@@ -125,6 +125,11 @@ "BriefDescription": "Overflow from counter 5" }, {, + "EventCode": "0x4505E", + "EventName": "PM_FLOP_CMPL", + "BriefDescription": "Floating Point Operation Finished" + }, + {, "EventCode": "0x2C018", "EventName": "PM_CMPLU_STALL_DMISS_L21_L31", "BriefDescription": "Completion stall by Dcache miss which resolved on chip ( excluding local L2/L3)"
@@ -390,11 +395,6 @@ "BriefDescription": "Ict empty for this thread due to branch mispred" }, {, - "EventCode": "0x3405E", - "EventName": "PM_IFETCH_THROTTLE", - "BriefDescription": "Cycles in which Instruction fetch throttle was active." - }, - {, "EventCode": "0x1F148", "EventName": "PM_MRK_DPTEG_FROM_ON_CHIP_CACHE", "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -422,7 +422,7 @@ {, "EventCode": "0xD0A8", "EventName": "PM_DSLB_MISS", - "BriefDescription": "Data SLB Miss - Total of all segment sizes" + "BriefDescription": "gate_and(sd_pc_c0_comp_valid AND sd_pc_c0_comp_thread(0:1)=tid,sd_pc_c0_comp_ppc_count(0:3)) + gate_and(sd_pc_c1_comp_valid AND sd_pc_c1_comp_thread(0:1)=tid,sd_pc_c1_comp_ppc_count(0:3))" }, {, "EventCode": "0x4C058",
@@ -549,4 +549,4 @@ "EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC", "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load" } -] +]
tools/perf/pmu-events/arch/powerpc/power9/pmc.json +1 -1
@@ -119,4 +119,4 @@ "EventName": "PM_1FLOP_CMPL", "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed" } -] +]
tools/perf/pmu-events/arch/powerpc/power9/translation.json +0 -5
@@ -90,11 +90,6 @@ "BriefDescription": "stcx failed" }, {, - "EventCode": "0x20112", - "EventName": "PM_MRK_NTF_FIN", - "BriefDescription": "Marked next to finish instruction finished" - }, - {, "EventCode": "0x300F0", "EventName": "PM_ST_MISS_L1", "BriefDescription": "Store Missed L1"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 46/83 perf buildid-cache: Update help text for purge command
In reply to Arnaldo Carvalho de MeloFrom: Thomas-Mich Richter <[email protected]>
Clarify the perf buildid-cache help text for the purge operation. The purge subcommand takes a list of files (binaries) as option parameter. Make the wording the same as for the add and remove operation.
LPU-Reference: [email protected]
--- tools/perf/builtin-buildid-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-buildid-cache.c +2 -2
@@ -325,8 +325,8 @@ int cmd_buildid_cache(int argc, const char **argv) "file", "kcore file to add"),OPT_STRING ('r' ,"remove" , &remove_name_list_str,"file list" ,"file(s) to remove" ), -OPT_STRING ('p' ,"purge" , &purge_name_list_str,"path list" , -"path(s) to remove (remove old caches too)" ), +OPT_STRING ('p' ,"purge" , &purge_name_list_str,"file list" , +"file(s) to remove (remove old caches too)" ),OPT_STRING ('M' ,"missing" , &missing_filename,"file" ,"to find missing build ids in the cache" ), OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 47/83 perf tools: Document some missing perf.data headers
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Document STAT and CACHE header entries.
--- tools/perf/Documentation/perf.data-file-format.txt | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+)
tools/perf/Documentation/perf.data-file-format.txt +23 -0
@@ -238,6 +238,29 @@ struct auxtrace_index { struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT]; }; + HEADER_STAT = 19, + +This is merely a flag signifying that the data section contains data +recorded from perf stat record. + + HEADER_CACHE = 20, + +Description of the cache hierarchy. Based on the Linux sysfs format +in /sys/devices/system/cpu/cpu*/cache/ + + u32 version Currently always 1 + u32 number_of_cache_levels + +struct { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + struct perf_header_string type; + struct perf_header_string size; + struct perf_header_string map; +}[number_of_cache_levels]; + other bits are reserved and should ignored for now HEADER_FEAT_BITS = 256,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 48/83 perf script: Allow printing period for non freq mode groups
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
When using leader sampling the values of the not sampled but counted events are shown by perf script in "period".
Currently printing period is only allowed when the main event has a period, that is it is in frequency mode.
This implies that we cannot dump the values of counted events when the leader event is not in frequency mode.
Just remove the check that the period must be set on all events. It will just be printed as 0 instead if it's not available.
This fixes the following:
$ perf record -c 100000 -e '{cycles,branches}:S'
$ perf script -F event,periodFurther commentary by Jiri Olsa:
The period will be the value of configured period, not 0:
int perf_evsel__parse_sample(struct ...
...
data->period = evsel->attr.sample_period;
$ perf record -c 100000
$ perf script -F event,period | head -3
Failed to open /tmp/perf-2048.map, continuing without symbols
100000 cycles:ppp:
100000 cycles:ppp:other than that I think we can remove that check, because we will have always sane number in period
--- tools/perf/builtin-script.c | 5 ----- 1 file changed, 5 deletions(-)
tools/perf/builtin-script.c +0 -5
@@ -423,11 +423,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, PERF_OUTPUT_CPU, allow_user_set))return -EINVAL ; -if (PRINT_FIELD (PERIOD ) && -perf_evsel__check_stype (evsel,PERF_SAMPLE_PERIOD ,"PERIOD" , -PERF_OUTPUT_PERIOD )) -return -EINVAL ; -if (PRINT_FIELD (IREGS ) &&perf_evsel__check_stype (evsel,PERF_SAMPLE_REGS_INTR ,"IREGS" ,PERF_OUTPUT_IREGS ))
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 49/83 perf top: Document missing options
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
--- tools/perf/Documentation/perf-top.txt | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/Documentation/perf-top.txt +6 -0
@@ -268,6 +268,12 @@ INTERACTIVE PROMPTING KEYS [S]:: Stop annotation, return to full profile display. +[K]:: + Hide kernel symbols. + +[U]:: + Hide user symbols. + [z]:: Toggle event count zeroing across display updates.
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 50/83 perf top: Remove a duplicate word
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
--- tools/perf/builtin-top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/builtin-top.c +1 -1
@@ -412,7 +412,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)fprintf (stdout,"\t[S] stop annotation.\n" );fprintf (stdout, -"\t[K] hide kernel_symbols symbols. \t(%s)\n" , +"\t[K] hide kernel symbols. \t(%s)\n" , top->hide_kernel_symbols ?"yes" :"no" ); fprintf(stdout, "\t[U] hide user symbols. \t(%s)\n",
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 51/83 perf tests: Set evlist of test__backward_ring_buffer() to !overwrite
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Setting overwrite in perf_evlist__mmap() is meaningless because the event in this evlist is already have 'overwrite' postfix and goes to backward ring buffer automatically. Pass 'false' to perf_evlist__mmap() to make it similar to others.
--- tools/perf/tests/backward-ring-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/backward-ring-buffer.c +1 -1
@@ -59,7 +59,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,int err;char sbuf[STRERR_BUFSIZE ]; - err =perf_evlist__mmap (evlist, mmap_pages, true); + err =perf_evlist__mmap (evlist, mmap_pages, false);if (err <0 ) {pr_debug ("perf_evlist__mmap: %s\n" ,str_error_r (errno, sbuf,sizeof (sbuf)));
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 52/83 perf tests: Set evlist of test__sw_clock_freq() to !overwrite
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Unsetting overwrite when calling perf_evlist__mmap is harmless. This commit passes false to it, makes following commits eliminate the overwrite argument easier.
--- tools/perf/tests/sw-clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/sw-clock.c +1 -1
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) goto out_delete_evlist; } - err =perf_evlist__mmap (evlist,128 , true); + err =perf_evlist__mmap (evlist,128 , false);if (err <0 ) {pr_debug ("failed to mmap event: %d (%s)\n" , errno,str_error_r (errno, sbuf,sizeof (sbuf)));
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 53/83 perf tests: Set evlist of test__basic_mmap() to !overwrite
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
In this test, a large ring buffer is required so all events can feed into, so overwrite or not is meaningless.
Change to !overwrite so following commits can remove this argument.
--- tools/perf/tests/mmap-basic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/mmap-basic.c +1 -1
@@ -94,7 +94,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse expected_nr_events[i] =1 +rand () %127 ; } -if (perf_evlist__mmap (evlist,128 , true) <0 ) { +if (perf_evlist__mmap (evlist,128 , false) <0 ) {pr_debug ("failed to mmap events: %d (%s)\n" , errno,str_error_r (errno, sbuf,sizeof (sbuf))); goto out_delete_evlist;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 54/83 perf tests: Set evlist of test__task_exit() to !overwrite
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Changing ringbuffer to !overwrite in this task is harmless because this test uses a very low frequency (1) and using a very simple program (true). There should have only 3 events in the whole test. Overwriting is impossible to happen.
--- tools/perf/tests/task-exit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/task-exit.c +1 -1
@@ -97,7 +97,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused goto out_delete_evlist; } -if (perf_evlist__mmap (evlist,128 , true) <0 ) { +if (perf_evlist__mmap (evlist,128 , false) <0 ) {pr_debug ("failed to mmap events: %d (%s)\n" , errno,str_error_r (errno, sbuf,sizeof (sbuf))); goto out_delete_evlist;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 55/83 perf machine: Guard against NULL in machine__exit()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
A recent fix for 'perf trace' introduced a bug where machine__exit(trace->host) could be called while trace->host was still NULL, so make this more robust by guarding against NULL, just like free() does.
The problem happens, for instance, when !root users try to run 'perf trace':
[acme@jouet linux]$ trace
Error: No permissions to read /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
perf: Segmentation fault
Obtained 7 stack frames.
[0x4f1b2e]
/lib64/libc.so.6(+0x3671f) [0x7f43a1dd971f] [0x4f3fec]
[0x47468b]
[0x42a2db] /lib64/libc.so.6(__libc_start_main+0xe9) [0x7f43a1dc3509] [0x42a6c9]
Segmentation fault (core dumped)
[acme@jouet linux]$
--- tools/perf/util/machine.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/machine.c +3 -0
@@ -172,6 +172,9 @@ void machine__exit(struct machine *machine) {int i; +if (machine ==NULL ) +return ; +machine__destroy_kernel_maps (machine);map_groups__exit (&machine->kmaps);dsos__exit (&machine->dsos);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 56/83 perf help: Fix a bug during strstart() conversion
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The commit 8e99b6d4533c changed prefixcmp() to strstart() but missed to change the return value in some place. It makes perf help print annoying output even for sane config items like below:
$ perf help '.root': unsupported man viewer sub key. ...
--- tools/perf/builtin-help.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-help.c +2 -2
@@ -284,7 +284,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)add_man_viewer (value);return 0 ; } -if (!strstarts (var,"man." )) +if (strstarts (var,"man." ))return add_man_viewer_info (var, value);return 0 ;
@@ -314,7 +314,7 @@ static const char *cmd_to_page(const char *perf_cmd)if (!perf_cmd)return "perf" ; -else if (!strstarts (perf_cmd,"perf" )) +else if (strstarts (perf_cmd,"perf" ))return perf_cmd;return asprintf (&s,"perf-%s" , perf_cmd) <0 ?NULL : s;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 57/83 perf annotate: Do not truncate instruction names at 6 chars
In reply to Arnaldo Carvalho de MeloFrom: Ravi Bangoria <[email protected]>
There are many instructions, esp on PowerPC, whose mnemonics are longer than 6 characters. Using precision limit causes truncation of such mnemonics.
Fix this by removing precision limit. Note that, 'width' is still 6, so alignment won't get affected for length <= 6.
Before:
li r11,-1
xscvdp vs1,vs1
add. r10,r10,r11
After:
li r11,-1
xscvdpsxds vs1,vs1
add. r10,r10,r11
--- tools/perf/util/annotate.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
tools/perf/util/annotate.c +9 -9
@@ -165,7 +165,7 @@ static void ins__delete(struct ins_operands *ops)static int ins__raw_scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops) { -return scnprintf (bf, size,"%-6.6s %s" , ins->name, ops->raw); +return scnprintf (bf, size,"%-6s %s" , ins->name, ops->raw); } int ins__scnprintf(struct ins *ins, char *bf, size_t size,
@@ -230,12 +230,12 @@ static int call__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) {if (ops->target.name) -return scnprintf (bf, size,"%-6.6s %s" , ins->name, ops->target.name); +return scnprintf (bf, size,"%-6s %s" , ins->name, ops->target.name);if (ops->target.addr ==0 )return ins__raw_scnprintf (ins, bf, size, ops); -return scnprintf (bf, size,"%-6.6s *%" PRIx64, ins->name, ops->target.addr); +return scnprintf (bf, size,"%-6s *%" PRIx64, ins->name, ops->target.addr); }static struct ins_ops call_ops = {
@@ -299,7 +299,7 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, c++; } -return scnprintf (bf, size,"%-6.6s %.*s%" PRIx64, +return scnprintf (bf, size,"%-6s %.*s%" PRIx64, ins->name, c ? c - ops->raw :0 , ops->raw, ops->target.offset); }
@@ -372,7 +372,7 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,if (ops->locked.ins.ops ==NULL )return ins__raw_scnprintf (ins, bf, size, ops); - printed =scnprintf (bf, size,"%-6.6s " , ins->name); + printed =scnprintf (bf, size,"%-6s " , ins->name);return printed +ins__scnprintf (&ops->locked.ins, bf + printed, size - printed, ops->locked.ops); }
@@ -448,7 +448,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *mstatic int mov__scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops) { -return scnprintf (bf, size,"%-6.6s %s,%s" , ins->name, +return scnprintf (bf, size,"%-6s %s,%s" , ins->name, ops->source.name ?: ops->source.raw, ops->target.name ?: ops->target.raw); }
@@ -488,7 +488,7 @@ static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *opsstatic int dec__scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops) { -return scnprintf (bf, size,"%-6.6s %s" , ins->name, +return scnprintf (bf, size,"%-6s %s" , ins->name, ops->target.name ?: ops->target.raw); }
@@ -500,7 +500,7 @@ static struct ins_ops dec_ops = {static int nop__scnprintf (struct ins *ins__maybe_unused ,char *bf,size_t size,struct ins_operands *ops__maybe_unused ) { -return scnprintf (bf, size,"%-6.6s" ,"nop" ); +return scnprintf (bf, size,"%-6s" ,"nop" ); }static struct ins_ops nop_ops = {
@@ -990,7 +990,7 @@ void disasm_line__free(struct disasm_line *dl)int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw) {if (raw || !dl->ins.ops) -return scnprintf (bf, size,"%-6.6s %s" , dl->ins.name, dl->ops.raw); +return scnprintf (bf, size,"%-6s %s" , dl->ins.name, dl->ops.raw);return ins__scnprintf (&dl->ins, bf, size, &dl->ops); }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 58/83 perf test shell: Fix check open filename arg using 'perf trace' on s390x
In reply to Arnaldo Carvalho de MeloFrom: Thomas Richter <[email protected]>
This 'perf test' case fails on s390x. The 'touch' command on s390x uses the 'openat' system call to open the file named on the command line:
[root@s35lp76 perf]# perf probe -l
probe:vfs_getname (on getname_flags:72@fs/namei.c with pathname)
[root@s35lp76 perf]# perf trace -e open touch /tmp/abc
0.400 ( 0.015 ms): touch/27542 open(filename:
/usr/lib/locale/locale-archive, flags: CLOEXEC) = 3
[root@s35lp76 perf]#
There is no 'open' system call for file '/tmp/abc'. Instead the 'openat' system call is used:
[root@s35lp76 perf]# strace touch /tmp/abc
execve("/usr/bin/touch", ["touch", "/tmp/abc"], 0x3ffd547ec98
/* 30 vars */) = 0
[...]
openat(AT_FDCWD, "/tmp/abc", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
[...]On s390x the 'egrep' command does not find a matching pattern and returns an error.
Fix this for s390x create a platform dependent command line to enable the 'perf probe' call to listen to the 'openat' system call and get the expected output.
LPU-Reference: [email protected]
--- tools/perf/tests/shell/trace+probe_vfs_getname.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/tests/shell/trace+probe_vfs_getname.sh +4 -2
@@ -17,8 +17,10 @@ skip_if_no_perf_probe || exit 2 file=$(mktemp /tmp/temporary_file.XXXXX) trace_open_vfs_getname() { - perf trace -e open touch $file 2>&1 | \ - egrep " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch\/[0-9]+ open\(filename: +${file}, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$" + test "$(uname -m)" = s390x && { svc="openat"; txt="dfd: +CWD, +"; } + + perf trace -e ${svc:-open} touch $file 2>&1 | \ + egrep " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch\/[0-9]+ ${svc:-open}\(${txt}filename: +${file}, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$" }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 59/83 perf test shell: Fix test case probe libc's inet_pton on s390x
In reply to Arnaldo Carvalho de MeloFrom: Thomas Richter <[email protected]>
The 'perf test' case "probe libc's inet_pton & backtrace it with ping" fails on s390x. The reason is the 'realpath /lib64/ld*.so.* | uniq' line which returns 2 libraries:
root@s35lp76 shell]# realpath /lib64/ld*.so.* | uniq
/usr/lib64/ld-2.26.so
/usr/lib64/ld_pre_smc.so.1.0.1
[root@s35lp76 shell]This output makes the "perf probe" command lines invalid.
Use ldd tool to find out the libraries required by "bash" and check if symbol "inet_pton" is part of the "libc" library. Some distros do not have a /lib64 directory.
I have also added a check for the existence of an IPv6 network interface before it is being used.
Committer changes:
We can't really use ldd for libc, as in some systems, such as x86_64, it has hardlinks and then ldd sees one and the kernel the other, so grep for libc in /proc/self/maps to get the one we'll receive from PERF_RECORD_MMAP.
Thomas checked this change and acked it.
--- tools/perf/tests/shell/trace+probe_libc_inet_pton.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
tools/perf/tests/shell/trace+probe_libc_inet_pton.sh +5 -2
@@ -10,8 +10,8 @@ . $(dirname $0)/lib/probe.sh -ld=$(realpath /lib64/ld*.so.* | uniq) -libc=$(echo $ld | sed 's/ld/libc/g') +libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g') +nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254 trace_libc_inet_pton_backtrace() { idx=0
@@ -37,6 +37,9 @@ trace_libc_inet_pton_backtrace() { done } +# Check for IPv6 interface existence +ip a sh lo | fgrep -q inet6 || exit 2 + skip_if_no_perf_probe && \ perf probe -q $libc inet_pton && \ trace_libc_inet_pton_backtrace
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 60/83 perf evlist: Add helper to check if attr.exclude_kernel is set in all evsels
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
The warning about kptr_restrict needs to be emitted only when it is set and we ask for kernel space samples, so add a helper to help with that.
--- tools/perf/util/evlist.c | 12 ++++++++++++ tools/perf/util/evlist.h | 2 ++ 2 files changed, 14 insertions(+)
tools/perf/util/evlist.c +12 -0
@@ -1786,3 +1786,15 @@ void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, state_err:return ; } + +bool perf_evlist__exclude_kernel (struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; + +evlist__for_each_entry (evlist, evsel) { +if (!evsel->attr.exclude_kernel) +return false; + } + +return true; +}
tools/perf/util/evlist.h +2 -0
@@ -312,4 +312,6 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);struct perf_evsel *perf_evlist__event2evsel (struct perf_evlist *evlist,union perf_event *event); + +bool perf_evlist__exclude_kernel (struct perf_evlist *evlist);#endif /* __PERF_EVLIST_H */
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 61/83 perf report: Ignore kptr_restrict when not sampling the kernel
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
If none of the evsels has attr.exclude_kernel set to zero, no kernel samples, so no point in warning the user about problems in processing kernel samples, as there will be none.
--- tools/perf/builtin-report.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/builtin-report.c +3 -0
@@ -441,6 +441,9 @@ static void report__warn_kptr_restrict(const struct report *rep)struct map *kernel_map =machine__kernel_map (&rep->session->machines.host);struct kmap *kernel_kmap = kernel_map ?map__kmap (kernel_map) :NULL ; +if (perf_evlist__exclude_kernel (rep->session->evlist)) +return ; + if (kernel_map == NULL || (kernel_map->dso->hit && (kernel_kmap->ref_reloc_sym == NULL ||
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 62/83 perf record: Ignore kptr_restrict when not sampling the kernel
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
If we're not sampling the kernel, we shouldn't care about kptr_restrict neither synthesize anything for assisting in resolving kernel samples, like the reference relocation symbol or kernel modules information.
Before:
$ cat /proc/sys/kernel/kptr_restrict /proc/sys/kernel/perf_event_paranoid
2
2
$ perf record sleep 1
WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,
check /proc/sys/kernel/kptr_restrict.Samples in kernel functions may not be resolved if a suitable vmlinux file is not found in the buildid cache or in the vmlinux path.
Samples in kernel modules won't be resolved at all.
If some relocation was applied (e.g. kexec) symbols may be misresolved even with a suitable vmlinux or kallsyms file.
Couldn't record kernel reference relocation symbol
Symbol resolution may be skewed if relocation was used (e.g. kexec). Check /proc/kallsyms permission or run as root.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.001 MB perf.data (8 samples) ]
$ perf evlist -v
cycles:uppp: size: 112, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, exclude_kernel: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, precise_ip: 3, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
$After:
$ perf record sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.001 MB perf.data (10 samples) ] $
--- tools/perf/builtin-record.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
tools/perf/builtin-record.c +14 -12
@@ -765,17 +765,19 @@ static int record__synthesize(struct record *rec, bool tail) goto out; } - err =perf_event__synthesize_kernel_mmap (tool, process_synthesized_event, - machine); -WARN_ONCE (err <0 ,"Couldn't record kernel reference relocation symbol\n" -"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" -"Check /proc/kallsyms permission or run as root.\n" ); - - err =perf_event__synthesize_modules (tool, process_synthesized_event, - machine); -WARN_ONCE (err <0 ,"Couldn't record kernel module information.\n" -"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" -"Check /proc/modules permission or run as root.\n" ); +if (!perf_evlist__exclude_kernel (rec->evlist)) { + err =perf_event__synthesize_kernel_mmap (tool, process_synthesized_event, + machine); +WARN_ONCE (err <0 ,"Couldn't record kernel reference relocation symbol\n" +"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" +"Check /proc/kallsyms permission or run as root.\n" ); + + err =perf_event__synthesize_modules (tool, process_synthesized_event, + machine); +WARN_ONCE (err <0 ,"Couldn't record kernel module information.\n" +"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" +"Check /proc/modules permission or run as root.\n" ); + }if (perf_guest) { machines__process_guests(&session->machines,
@@ -1709,7 +1711,7 @@ int cmd_record(int argc, const char **argv) err = -ENOMEM ; -if (symbol_conf.kptr_restrict) +if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel (rec->evlist))pr_warning ("WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" "check /proc/sys/kernel/kptr_restrict.\n\n"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 63/83 perf top: Ignore kptr_restrict when not sampling the kernel
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
If all events have attr.exclude_kernel set, no need to look at kptr_restrict.
--- tools/perf/builtin-top.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/perf/builtin-top.c +5 -3
@@ -735,14 +735,16 @@ static void perf_event__process_sample(struct perf_tool *tool,if (!machine->kptr_restrict_warned && symbol_conf.kptr_restrict && al.cpumode ==PERF_RECORD_MISC_KERNEL ) { -ui__warning ( +if (!perf_evlist__exclude_kernel (top->session->evlist)) { +ui__warning ("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n" "Check /proc/sys/kernel/kptr_restrict.\n\n" "Kernel%s samples will not be resolved.\n" , al.map && !RB_EMPTY_ROOT (&al.map->dso->symbols[MAP__FUNCTION ]) ?" modules" :"" ); -if (use_browser <=0 ) -sleep (5 ); +if (use_browser <=0 ) +sleep (5 ); + } machine->kptr_restrict_warned = true; }
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 64/83 perf c2c: Fix spelling mistakes in browser help text
In reply to Arnaldo Carvalho de MeloFrom: Kim Phillips <[email protected]>
Togle -> Toggle, lenght -> length.
--- tools/perf/builtin-c2c.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/builtin-c2c.c +4 -4
@@ -2224,9 +2224,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)struct hist_browser *browser;int key =-1 ;const char help[] = -" ENTER Togle callchains (if present) \n" -" n Togle Node details info \n" -" s Togle full lenght of symbol and source line columns \n" +" ENTER Toggle callchains (if present) \n" +" n Toggle Node details info \n" +" s Toggle full length of symbol and source line columns \n" " q Return back to cacheline list \n" ;/* Display compact version first. */
@@ -2303,7 +2303,7 @@ static int perf_c2c__hists_browse(struct hists *hists)int key =-1 ;const char help[] =" d Display cacheline details \n" -" ENTER Togle callchains (if present) \n" +" ENTER Toggle callchains (if present) \n" " q Quit \n" ; browser =perf_c2c_browser__new (hists);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 65/83 perf evsel: Say which PMU Hardware event doesn't support sampling/overflow-interrupts
In reply to Arnaldo Carvalho de MeloFrom: Kim Phillips <[email protected]>
Help identify to the user the event with the unsupported sampling error. Also suggest a corrective action.
BEFORE:
$ sudo ./oldperf record -e armv8_pmuv3/mem_access/,ccn/cycles/,armv8_pmuv3/l2d_cache/ true Error: PMU Hardware doesn't support sampling/overflow-interrupts.
AFTER:
$ sudo ./newperf record -e armv8_pmuv3/mem_access/,ccn/cycles/,armv8_pmuv3/l2d_cache/ true Error: ccn/cycles/: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'
--- tools/perf/util/evsel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/evsel.c +3 -2
@@ -2745,8 +2745,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,break ;case EOPNOTSUPP :if (evsel->attr.sample_period !=0 ) -return scnprintf (msg, size,"%s" , -"PMU Hardware doesn't support sampling/overflow-interrupts." ); +return scnprintf (msg, size, +"%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'" , +perf_evsel__name (evsel));if (evsel->attr.precise_ip)return scnprintf (msg, size,"%s" ,"\'precise\' request may not be supported. Try removing 'p' modifier." );
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 66/83 perf lock: Document missing options
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add man page entry for --force.
--- tools/perf/Documentation/perf-lock.txt | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/Documentation/perf-lock.txt +4 -0
@@ -42,6 +42,10 @@ COMMON OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. +-f:: +--force:: + Don't complan, do it. + REPORT OPTIONS --------------
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 67/83 perf: Fix header.size for namespace events
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Reset header size for namespace events, otherwise it only gets bigger in ctx iterations.
--- kernel/events/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/events/core.c +4 -1
@@ -6640,6 +6640,7 @@ static void perf_event_namespaces_output(struct perf_event *event,struct perf_namespaces_event *namespaces_event = data;struct perf_output_handle handle;struct perf_sample_data sample; +u16 header_size = namespaces_event->event_id.header.size;int ret;if (!perf_event_namespaces_match (event))
@@ -6650,7 +6651,7 @@ static void perf_event_namespaces_output(struct perf_event *event, ret =perf_output_begin (&handle, event, namespaces_event->event_id.header.size);if (ret) -return ; + goto out; namespaces_event->event_id.pid =perf_event_pid (event, namespaces_event->task);
@@ -6662,6 +6663,8 @@ static void perf_event_namespaces_output(struct perf_event *event,perf_event__output_id_sample (event, &handle, &sample);perf_output_end (&handle); +out: + namespaces_event->event_id.header.size = header_size; } static void perf_fill_ns_link_info(struct perf_ns_link_info *ns_link_info,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 68/83 perf inject: Document missing options
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add the missing --force option to the man page.
--- tools/perf/Documentation/perf-inject.txt | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/Documentation/perf-inject.txt +4 -0
@@ -60,6 +60,10 @@ include::itrace.txt[] found in the jitdumps files captured in the input perf.data file. Use this option if you are monitoring environment using JIT runtimes, such as Java, DART or V8. +-f:: +--force:: + Don't complain, do it. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 69/83 perf trace: Document missing option, colons
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add missing --force option to the man page.
--- tools/perf/Documentation/perf-trace.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
tools/perf/Documentation/perf-trace.txt +10 -6
@@ -86,18 +86,18 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0- In per-thread mode with inheritance mode on (default), Events are captured only when the thread executes on the designated CPUs. Default is to monitor all CPUs. ---duration: +--duration:: Show only events that had a duration greater than N.M ms. ---sched: +--sched:: Accrue thread runtime and provide a summary at the end of the session. --i ---input +-i:: +--input:: Process events from a given perf data file. --T ---time +-T:: +--time:: Print full timestamp rather time relative to first sample. --comm::
@@ -117,6 +117,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. Show tool stats such as number of times fd->pathname was discovered thru hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc. +-f:: +--force:: + Don't complain, do it. + -F=[all|min|maj]:: --pf=[all|min|maj]:: Trace pagefaults. Optionally, you can specify whether you want minor,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 70/83 perf timechart: Document missing --force option
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add --force to the man page.
--- tools/perf/Documentation/perf-timechart.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-timechart.txt +3 -1
@@ -50,7 +50,9 @@ TIMECHART OPTIONS -p:: --process:: Select the processes to display, by name or PID - +-f:: +--force:: + Don't complain, do it. --symfs=<directory>:: Look for files with symbols relative to this directory. -n::
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 71/83 perf sched: Document missing --force option
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add --force to the man page.
--- tools/perf/Documentation/perf-sched.txt | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/Documentation/perf-sched.txt +4 -0
@@ -74,6 +74,10 @@ OPTIONS --dump-raw-trace=:: Display verbose dump of the sched data. +-f:: +--force:: + Don't complain, do it. + OPTIONS for 'perf sched map' ----------------------------
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 72/83 perf evlist: Document missing --force option
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add --force to the man page.
--- tools/perf/Documentation/perf-evlist.txt | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/Documentation/perf-evlist.txt +4 -0
@@ -20,6 +20,10 @@ OPTIONS --input=:: Input file name. (default: perf.data unless stdin is a fifo) +-f:: +--force:: + Don't complain, do it. + -F:: --freq=:: Show just the sample frequency used for each event.
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 73/83 perf buildid-cache: Document missing --force option
In reply to Arnaldo Carvalho de MeloFrom: Sihyeon Jang <[email protected]>
Add --force to the man page.
--- tools/perf/Documentation/perf-buildid-cache.txt | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/Documentation/perf-buildid-cache.txt +3 -0
@@ -24,6 +24,9 @@ OPTIONS -a:: --add=:: Add specified file to the cache. +-f:: +--force:: + Don't complain, do it. -k:: --kcore:: Add specified kcore file to the cache. For the current host that is
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 74/83 perf callchain: Reset cursor arg instead of callchain_cursor
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We already pass cursor into thread__resolve_callchain function, so there's no point in resetting the global instance.
--- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/machine.c +1 -1
@@ -2204,7 +2204,7 @@ int thread__resolve_callchain(struct thread *thread, {int ret =0 ; -callchain_cursor_reset (&callchain_cursor); +callchain_cursor_reset (cursor);if (callchain_param.order ==ORDER_CALLEE ) { ret = thread__resolve_callchain_sample(thread, cursor,
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 75/83 perf evsel: Centralize perf_sample initialization
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Move the initialization bits into common place at the beginning of the function.
Also removing some superfluous zero initialization for addr and transaction, because we zero all the data at the top.
--- tools/perf/util/evsel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/evsel.c +2 -4
@@ -1983,6 +1983,8 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, data->stream_id = data->id = data->time =-1ULL ; data->period = evsel->attr.sample_period; data->cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ; + data->id =-1ULL ; + data->data_src =PERF_MEM_DATA_SRC_NONE ;if (event->header.type !=PERF_RECORD_SAMPLE ) {if (!evsel->attr.sample_id_all)
@@ -2000,7 +2002,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,if (evsel->sample_size +sizeof (event->header) > event->header.size)return -EFAULT ; - data->id =-1ULL ;if (type &PERF_SAMPLE_IDENTIFIER ) { data->id = *array; array++;
@@ -2030,7 +2031,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array++; } - data->addr =0 ;if (type &PERF_SAMPLE_ADDR ) { data->addr = *array; array++;
@@ -2194,14 +2194,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array++; } - data->data_src =PERF_MEM_DATA_SRC_NONE ;if (type &PERF_SAMPLE_DATA_SRC ) {OVERFLOW_CHECK_u64 (array); data->data_src = *array; array++; } - data->transaction =0 ;if (type &PERF_SAMPLE_TRANSACTION ) {OVERFLOW_CHECK_u64 (array); data->transaction = *array;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 76/83 perf evlist: Add perf_evlist__parse_sample_timestamp function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Add perf_evlist__parse_sample_timestamp to retrieve the timestamp of the sample.
The idea is to use this function instead of the full sample parsing before we queue the sample. At that time only the timestamp is needed and we parse the sample once again later on delivery.
--- tools/perf/util/evlist.c | 11 ++++++++ tools/perf/util/evlist.h | 4 +++ tools/perf/util/evsel.c | 65 +++++++++++++++++++++++++++++++++++++++++++----- tools/perf/util/evsel.h | 4 +++ 4 files changed, 78 insertions(+), 6 deletions(-)
tools/perf/util/evlist.c +11 -0
@@ -1582,6 +1582,17 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *evenreturn perf_evsel__parse_sample (evsel, event, sample); } +int perf_evlist__parse_sample_timestamp (struct perf_evlist *evlist, +union perf_event *event, +u64 *timestamp) +{ +struct perf_evsel *evsel =perf_evlist__event2evsel (evlist, event); + +if (!evsel) +return -EFAULT ; +return perf_evsel__parse_sample_timestamp (evsel, event, timestamp); +} +size_t perf_evlist__fprintf (struct perf_evlist *evlist,FILE *fp) {struct perf_evsel *evsel;
tools/perf/util/evlist.h +4 -0
@@ -205,6 +205,10 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);int perf_evlist__parse_sample (struct perf_evlist *evlist,union perf_event *event,struct perf_sample *sample); +int perf_evlist__parse_sample_timestamp (struct perf_evlist *evlist, +union perf_event *event, +u64 *timestamp); +bool perf_evlist__valid_sample_type (struct perf_evlist *evlist);bool perf_evlist__valid_sample_id_all (struct perf_evlist *evlist);bool perf_evlist__valid_read_format (struct perf_evlist *evlist);
tools/perf/util/evsel.c +59 -6
83 lines not on this page · raw message
tools/perf/util/evsel.h +4 -0
@@ -338,6 +338,10 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,int perf_evsel__parse_sample (struct perf_evsel *evsel,union perf_event *event,struct perf_sample *sample); +int perf_evsel__parse_sample_timestamp (struct perf_evsel *evsel, +union perf_event *event, +u64 *timestamp); +static inline struct perf_evsel *perf_evsel__next (struct perf_evsel *evsel) { return list_entry(evsel->node.next, struct perf_evsel, node);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 77/83 perf ordered_events: Pass timestamp arg in perf_session__queue_event
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
There's no need to pass whole sample data, because it's only timestamp that is used.
--- tools/perf/builtin-kvm.c | 2 +- tools/perf/util/ordered-events.c | 3 +-- tools/perf/util/ordered-events.h | 2 +- tools/perf/util/session.c | 6 +++--- tools/perf/util/session.h | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-)
tools/perf/builtin-kvm.c +1 -1
@@ -754,7 +754,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,return -1 ; } - err =perf_session__queue_event (kvm->session, event, &sample,0 ); + err =perf_session__queue_event (kvm->session, event, sample.time,0 );/* * FIXME: Here we can't consume the event, as perf_session__queue_event will * point to it, and it'll get possibly overwritten by the kernel.
tools/perf/util/ordered-events.c +1 -2
@@ -157,9 +157,8 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve }int ordered_events__queue (struct ordered_events *oe,union perf_event *event, -struct perf_sample *sample,u64 file_offset) +u64 timestamp,u64 file_offset) { -u64 timestamp = sample->time;struct ordered_event *oevent;if (!timestamp || timestamp == ~0ULL )
tools/perf/util/ordered-events.h +1 -1
@@ -45,7 +45,7 @@ struct ordered_events { };int ordered_events__queue (struct ordered_events *oe,union perf_event *event, -struct perf_sample *sample,u64 file_offset); +u64 timestamp,u64 file_offset);void ordered_events__delete (struct ordered_events *oe,struct ordered_event *event);int ordered_events__flush (struct ordered_events *oe,enum oe_flush how);void ordered_events__init (struct ordered_events *oe,ordered_events__deliver_t deliver);
tools/perf/util/session.c +3 -3
@@ -873,9 +873,9 @@ static int process_finished_round(struct perf_tool *tool __maybe_unused, }int perf_session__queue_event (struct perf_session *s,union perf_event *event, -struct perf_sample *sample,u64 file_offset) +u64 timestamp,u64 file_offset) { -return ordered_events__queue (&s->ordered_events, event, sample, file_offset); +return ordered_events__queue (&s->ordered_events, event, timestamp, file_offset); }static void callchain__lbr_callstack_printf (struct perf_sample *sample)
@@ -1517,7 +1517,7 @@ static s64 perf_session__process_event(struct perf_session *session,return ret;if (tool->ordered_events) { - ret =perf_session__queue_event (session, event, &sample, file_offset); + ret =perf_session__queue_event (session, event, sample.time, file_offset);if (ret != -ETIME )return ret; }
tools/perf/util/session.h +1 -1
@@ -53,7 +53,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,int perf_session__process_events (struct perf_session *session);int perf_session__queue_event (struct perf_session *s,union perf_event *event, -struct perf_sample *sample,u64 file_offset); +u64 timestamp,u64 file_offset);void perf_tool__fill_defaults (struct perf_tool *tool);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 78/83 perf tools: Optimize sample parsing for ordered events
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Currently when using ordered events we parse the sample twice (the perf_evlist__parse_sample function). Once before we queue the sample for sorting:
perf_session__process_event
perf_evlist__parse_sample(sample)
perf_session__queue_event(sample.time)
And then when we deliver the sorted sample:
ordered_events__deliver_event
perf_evlist__parse_sample
perf_session__deliver_event
We can skip the initial full sample parsing by using perf_evlist__parse_sample_timestamp function, which got introduced earlier. The new path looks like:
perf_session__process_event
perf_evlist__parse_sample_timestamp
perf_session__queue_event
ordered_events__deliver_event
perf_session__deliver_event
perf_evlist__parse_sample
It saves some instructions and is slightly faster:
Before:
Performance counter stats for './perf.old report --stdio' (5 runs):
64,396,007,225 cycles:u ( +- 0.97% ) 105,882,112,735 instructions:u # 1.64 insn per cycle ( +- 0.00% )
21.618103465 seconds time elapsed ( +- 1.12% )
After:
Performance counter stats for './perf report --stdio' (5 runs):
60,567,807,182 cycles:u ( +- 0.40% ) 104,853,333,514 instructions:u # 1.73 insn per cycle ( +- 0.00% )
20.168895243 seconds time elapsed ( +- 0.32% )
--- tools/perf/builtin-kvm.c | 8 ++++---- tools/perf/util/session.c | 41 ++++++++++++++++++----------------------- 2 files changed, 22 insertions(+), 27 deletions(-)
tools/perf/builtin-kvm.c +4 -4
@@ -741,20 +741,20 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, u64 *mmap_time) {union perf_event *event; -struct perf_sample sample; +u64 timestamp;s64 n =0 ;int err; *mmap_time =ULLONG_MAX ;while ((event =perf_evlist__mmap_read (kvm->evlist, idx)) !=NULL ) { - err =perf_evlist__parse_sample (kvm->evlist, event, &sample); + err =perf_evlist__parse_sample_timestamp (kvm->evlist, event, ×tamp);if (err) {perf_evlist__mmap_consume (kvm->evlist, idx);pr_err ("Failed to parse sample\n" );return -1 ; } - err =perf_session__queue_event (kvm->session, event, sample.time,0 ); + err =perf_session__queue_event (kvm->session, event, timestamp,0 );/* * FIXME: Here we can't consume the event, as perf_session__queue_event will * point to it, and it'll get possibly overwritten by the kernel.
@@ -768,7 +768,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,/* save time stamp of our first sample for this mmap */ if (n ==0 ) - *mmap_time = sample.time; + *mmap_time = timestamp;/* limit events per mmap handled all at once */ n++;
tools/perf/util/session.c +18 -23
90 lines not on this page · raw message
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 79/83 perf top: Fix window dimensions change handling
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
The stdio perf top crashes when we change the terminal window size. The reason is that we assumed we get the perf_top pointer as a signal handler argument which is not the case.
Changing the SIGWINCH handler logic to change global resize variable, which is checked in the main thread loop.
--- tools/perf/builtin-top.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
tools/perf/builtin-top.c +12 -3
@@ -77,6 +77,7 @@#include "sane_ctype.h" static volatile int done; +static volatile int resize;#define HEADER_LINE_NR 5
@@ -86,10 +87,13 @@ static void perf_top__update_print_entries(struct perf_top *top) }static void perf_top__sig_winch (int sig__maybe_unused , -siginfo_t *info__maybe_unused ,void *arg) +siginfo_t *info__maybe_unused ,void *arg__maybe_unused ) { -struct perf_top *top = arg; + resize =1 ; +} +static void perf_top__resize (struct perf_top *top) +{get_term_dimensions (&top->winsize);perf_top__update_print_entries (top); }
@@ -480,7 +484,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) .sa_sigaction = perf_top__sig_winch, .sa_flags = SA_SIGINFO, }; -perf_top__sig_winch (SIGWINCH ,NULL , top); +perf_top__resize (top);sigaction (SIGWINCH , &act,NULL ); }else {signal (SIGWINCH ,SIG_DFL );
@@ -1035,6 +1039,11 @@ static int __cmd_top(struct perf_top *top)if (hits == top->samples) ret =perf_evlist__poll (top->evlist,100 ); + +if (resize) { +perf_top__resize (top); + resize =0 ; + } } ret =0 ;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 80/83 perf top: Use signal interface for SIGWINCH handler
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
There's no need for SA_SIGINFO data in SIGWINCH handler, switching it to register the handler via signal interface as we do for the rest of the signals in perf top.
--- tools/perf/builtin-top.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-)
tools/perf/builtin-top.c +3 -12
@@ -86,8 +86,7 @@ static void perf_top__update_print_entries(struct perf_top *top) top->print_entries = top->winsize.ws_row -HEADER_LINE_NR ; } -static void perf_top__sig_winch (int sig__maybe_unused , -siginfo_t *info__maybe_unused ,void *arg__maybe_unused ) +static void winch_sig (int sig__maybe_unused ) { resize =1 ; }
@@ -480,12 +479,8 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)case 'e' :prompt_integer (&top->print_entries,"Enter display entries (lines)" );if (top->print_entries ==0 ) { -struct sigaction act = { - .sa_sigaction = perf_top__sig_winch, - .sa_flags =SA_SIGINFO , - };perf_top__resize (top); -sigaction (SIGWINCH , &act,NULL ); +signal (SIGWINCH , winch_sig); }else {signal (SIGWINCH ,SIG_DFL ); }
@@ -1366,12 +1361,8 @@ int cmd_top(int argc, const char **argv)get_term_dimensions (&top.winsize);if (top.print_entries ==0 ) { -struct sigaction act = { - .sa_sigaction = perf_top__sig_winch, - .sa_flags =SA_SIGINFO , - };perf_top__update_print_entries (&top); -sigaction (SIGWINCH , &act,NULL ); +signal (SIGWINCH , winch_sig); } status =__cmd_top (&top);
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 81/83 perf top: Fix crash when annotating symbol
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Ravi reported crash in perf top --stdio when annotating a function [1]. The issue was, that we don't pass evsel pointer into symbol__annotate() function, which got over looked in the last annotation changes.
[1] https://marc.info/?l=linux-kernel&m=151060884412702&w=2
Committer note:
This fixes the crash, but makes it stumble into another bug, double locking the annotation data structures, that is in turn fixed by the next patch in this series.
--- tools/perf/builtin-top.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-top.c +2 -1
@@ -99,6 +99,7 @@ static void perf_top__resize(struct perf_top *top)static int perf_top__parse_source (struct perf_top *top,struct hist_entry *he) { +struct perf_evsel *evsel =hists_to_evsel (he->hists);struct symbol *sym;struct annotation *notes;struct map *map;
@@ -137,7 +138,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)return err; } - err =symbol__annotate (sym, map,NULL ,0 ,NULL ,NULL ); + err =symbol__annotate (sym, map, evsel,0 ,NULL ,NULL );if (err ==0 ) { out_assign: top->sym_filter_entry = he;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 82/83 perf tools: Change (symbol|annotation)__calc_percent return type to void
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
There's no need for symbol__calc_percent and annotation__calc_percent functions to return any value, since it's always zero. Changing both function to return void.
--- tools/perf/util/annotate.c | 17 ++++++++--------- tools/perf/util/annotate.h | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-)
tools/perf/util/annotate.c +8 -9
@@ -1584,8 +1584,8 @@ static void calc_percent(struct sym_hist *hist, } } -static int annotation__calc_percent (struct annotation *notes, -struct perf_evsel *evsel,s64 len) +static void annotation__calc_percent (struct annotation *notes, +struct perf_evsel *evsel,s64 len) {struct annotation_line *al, *next;
@@ -1609,15 +1609,13 @@ static int annotation__calc_percent(struct annotation *notes,calc_percent (hist, sample, al->offset, end); } } - -return 0 ; } -int symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel) +void symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel) {struct annotation *notes =symbol__annotation (sym); -return annotation__calc_percent (notes, evsel,symbol__size (sym)); +annotation__calc_percent (notes, evsel,symbol__size (sym)); } int symbol__annotate(struct symbol *sym, struct map *map,
@@ -1656,10 +1654,11 @@ int symbol__annotate(struct symbol *sym, struct map *map, } err =symbol__disassemble (sym, &args); -if (err) -return err; +if (!err) +symbol__calc_percent (sym, evsel); + +return err; -return symbol__calc_percent (sym, evsel); }static void insert_source_line (struct rb_root *root,struct annotation_line *al)
tools/perf/util/annotate.h +1 -1
@@ -107,7 +107,7 @@ struct annotation_line * annotation_line__next(struct annotation_line *pos, struct list_head *head);int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp); -int symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel); +void symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel);struct sym_hist {u64 nr_samples;
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 83/83 perf tools: Move symbol__calc_percent() call to outside symbol__disassemble()
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We need to call symbol__calc_percent() periodicaly for top, so it's no longer convenient to keep it in symbol__disassemble().
Let's separate the symbol__disassemble() to allocate and init the symbol annotation structs and symbol__calc_percent() to compute the lines percentages based on symbol hists data.
--- tools/perf/ui/browsers/annotate.c | 2 ++ tools/perf/ui/gtk/annotate.c | 2 ++ tools/perf/util/annotate.c | 9 +++------ 3 files changed, 7 insertions(+), 6 deletions(-)
tools/perf/ui/browsers/annotate.c +2 -0
@@ -1126,6 +1126,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, goto out_free_offsets; } +symbol__calc_percent (sym, evsel); +ui_helpline__push ("Press ESC to exit" ); notes =symbol__annotation (sym);
tools/perf/ui/gtk/annotate.c +2 -0
@@ -177,6 +177,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,return -1 ; } +symbol__calc_percent (sym, evsel); +if (perf_gtk__is_active_context (pgctx)) { window = pgctx->main_window; notebook = pgctx->notebook;
tools/perf/util/annotate.c +3 -6
@@ -1653,12 +1653,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } - err =symbol__disassemble (sym, &args); -if (!err) -symbol__calc_percent (sym, evsel); - -return err; - +return symbol__disassemble (sym, &args); }static void insert_source_line (struct rb_root *root,struct annotation_line *al)
@@ -2005,6 +2000,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,if (symbol__annotate (sym, map, evsel,0 ,NULL ,NULL ) <0 )return -1 ; +symbol__calc_percent (sym, evsel); +if (print_lines) { srcline_full_filename = full_paths;symbol__calc_lines (sym, map, &source_line);
Signature · 1 line
2.13.6
Quoted 238 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit
7862edc4191123f9c7e7ec0a7b356d332a61c41e:Merge remote-tracking branch 'torvalds/master' into perf/core (2017-11-13 09:39:12 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-4.15-20171117for you to fetch changes up to
05d3f1a1d5a3d37ca4b591d5524f5a5b159d0564:perf tools: Move
symbol__calc_percent()call to outsidesymbol__disassemble()(2017-11-17 12:16:26 -0300)----------------------------------------------------------------
perf/core improvements and fixes:- Optimize sample parsing for ordering events, where we don't need to parse all the
PERF_SAMPLE_bits, just the ones leading to the timestamp needed to reorder events (Jiri Olsa)- Use a dummy event to ask for PERF_RECORD_{MMAP,COMM,EXEC} with 'perf record --delay', when the events asked by the user will only be enabled after the workload is started and the requested delay passes, so we need to add the dummy event and have it .enabled_on_exec. This then allows us to resolve symbols for the DSO executable MMAPs setup while we wait for the delay (Arnaldo Carvalho de Melo)
- Synchronize
kcmp.handprctl.hABI headers wrt SPDX tags (Arnaldo Carvalho de Melo)- Generalize the annotation code to support other source information besides objdump/DWARF obtained ones, starting with python scripts, that will is slated to be merged soon (Jiri Olsa)
- Advance the source code lines to right after the column with the address in asm lines (Jiri Olsa)
- Fix terminal dimensions resizing signal handling in 'perf top --stdio' (Jiri Olsa)
- Improve error messages for PMU events (Kim Phillips)
- Fix 'perf record' -c/-F options for cpu event aliases (Andi Kleen)
- Enable type checking for
perf_evsel_config_termtypes (Andi Kleen)- Call
machine__exit()at 'perf trace' exit, so as to remove temporary files related to VDSO (Andrei Vagin)- Add "reject" option to parse-events.l, fixing the build with newer flex releases. Noticed with flex 2.6.4 on Alpine Linux 3.6 and Edge (Jiri Olsa)
- Document some missing perf.data headers (Andi Kleen)
- Allow printing period for non freq mod groups (Andi Kleen)
- Do not warn the user about kernel.kptr_restrict when not sampling the kernel (Arnaldo Carvalho de Melo)
- Fix bug in 'perf help' introduced during conversion to
strstart()(Namhyung Kim)- Do not truncate ASM instruction mnemonics at 6 characters in the annotation output, PowerPC has long ones (Ravi Bangoria)
- Document some missing command line options (Sihyeon Jang)
- Update POWER9 vendor event tables (Sukadev Bhattiprolu)
- Fix 'perf test' shell entries on s390x, where the 'openat' syscall is used instead of 'open' in one of the tests and
- No need to use overwrite mmap mode in 'perf test', those tests do not generate massive amount of events to fill the ring buffer (Wang Nan)
- Add missing command line options (mostly --force/-f) to the man pages (Sihyeon Jang)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Andi Kleen (4):
perf record: Fix -c/-F options for cpu event aliases perf evsel: Enable type checking forperf_evsel_config_termtypes perf tools: Document some missing perf.data headers perf script: Allow printing period for non freq mode groupsAndrei Vagin (1):
perf trace: Fix an exit code oftrace__symbols_initArnaldo Carvalho de Melo (10):
perf evlist: Set the correct idx when adding dummy events
perf record: Generate PERF_RECORD_{MMAP,COMM,EXEC} with --delay tools headers: Synchronize kernel ABI headers wrt SPDX tags perf evsel: Fix up leftoverperf_evsel_statusage viaevsel->privperf script: Fix --per-event-dump for auxtrace synth evsels perf machine: Guard against NULL inmachine__exit()
perf evlist: Add helper to check if attr.exclude_kernel is set in all evsels perf report: Ignorekptr_restrictwhen not sampling the kernel perf record: Ignorekptr_restrictwhen not sampling the kernel perf top: Ignorekptr_restrictwhen not sampling the kernelJiri Olsa (46):
perf annotate: Addannotation_linestruct
perf annotate: Move line/offset intoannotation_linestruct
perf annotate: Move ipc/cycles intoannotation_linestruct
perf annotate: Addsymbol__annotatefunction
perf annotate: Add structannotate_args
perf annotate: Add arch into structannotate_args
perf annotate: Add map into structannotate_args
perf annotate: Add offset/line/line_nr into structannotate_argsperf annotate: Add evsel into structannotation_line_args
perf annotate: Addannotation_line__nextfunction
perf annotate: Addannotation_line__addfunction
perf annotate: Moverb_nodeto structannotation_line
perf annotate: Addannotation_line__(new|delete)functions
perf annotate: Addannotated_source__purgefunction
perf annotate: Add samples into structannotation_line
perf annotate: Addsymbol__calc_percentfunction
perf annotate: Addsymbol__calc_linesfunction
perf annotate: Removedisasm__calc_percent()fromdisasm_line__print()perf annotate: Removedisasm__calc_percent()fromannotate_browser__calc_percent()perf annotate: Removedisasm__calc_percentfunction
perf annotate: Remove structsource_line
perf annotate: Addannotation_line__printfunction
perf annotate: Factorannotation_line__printfromdisasm_line__printperf annotate browser: Use samples data from structannotation_lineperf annotate browser: Do not passnr_eventsindisasm_rb_tree__insertperf annotate browser: Rename structbrowser_disasm_linetobrowser_lineperf annotate browser: Renamedisasm_line__browsertobrowser_lineperf annotate browser: Change selection to structannotation_lineperf annotate browser: Change offsets to structannotation_line
perf annotate browser: Use structannotation_lineinbrowser_lineperf annotate browser: Use structannotation_linein find functions perf annotate browser: Use structannotation_linein browser top perf annotate browser: Adddisasm_line__writefunction
perf annotate: Align source and offset lines
perf tools: Use shell function for perl cflags retrieval
perf: Fix header.size for namespace events
perf callchain: Reset cursor arg instead ofcallchain_cursor
perf evsel: Centralizeperf_sampleinitialization
perf evlist: Addperf_evlist__parse_sample_timestampfunction
perfordered_events: Pass timestamp arg inperf_session__queue_eventperf tools: Optimize sample parsing for ordered events
perf top: Fix window dimensions change handling
perf top: Use signal interface for SIGWINCH handler
perf top: Fix crash when annotating symbol
perf tools: Change (symbol|annotation)__calc_percent return type to void perf tools: Movesymbol__calc_percent()call to outsidesymbol__disassemble()Kim Phillips (2):
perf c2c: Fix spelling mistakes in browser help text
perf evsel: Say which PMU Hardware event doesn't support sampling/overflow-interruptsNamhyung Kim (1):
perf help: Fix a bug duringstrstart()conversionRavi Bangoria (1):
perf annotate: Do not truncate instruction names at 6 charsSeonghyun Park (1):
perf tests: Add missingWRITE_ASSfor new fields ofperf_event_attrSihyeon Jang (9):
perf top: Document missing options
perf top: Remove a duplicate word
perf lock: Document missing options
perf inject: Document missing options
perf trace: Document missing option, colons perf timechart: Document missing --force option perf sched: Document missing --force option perf evlist: Document missing --force option perf buildid-cache: Document missing --force optionSukadev Bhattiprolu (1):
perf vendor events powerpc: Update POWER9 eventsThomas Richter (2):
perf test shell: Fix check open filename arg using 'perf trace' on s390x perf test shell: Fix test case probe libc's inet_pton on s390xThomas-Mich Richter (1):
perf buildid-cache: Update help text for purge commandWang Nan (4):
perf tests: Set evlist oftest__backward_ring_buffer()to !overwrite perf tests: Set evlist oftest__sw_clock_freq()to !overwrite perf tests: Set evlist oftest__basic_mmap()to !overwrite perf tests: Set evlist oftest__task_exit()to !overwritekernel/events/core.c | 5 +- tools/include/uapi/linux/kcmp.h | 1 + tools/include/uapi/linux/prctl.h | 1 + tools/perf/Documentation/perf-buildid-cache.txt | 3 + tools/perf/Documentation/perf-evlist.txt | 4 + tools/perf/Documentation/perf-inject.txt | 4 + tools/perf/Documentation/perf-lock.txt | 4 + tools/perf/Documentation/perf-sched.txt | 4 + tools/perf/Documentation/perf-timechart.txt | 4 +- tools/perf/Documentation/perf-top.txt | 6 + tools/perf/Documentation/perf-trace.txt | 16 +- tools/perf/Documentation/perf.data-file-format.txt | 23 + tools/perf/Makefile.config | 2 +- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-c2c.c | 8 +- tools/perf/builtin-help.c | 4 +- tools/perf/builtin-kvm.c | 8 +- tools/perf/builtin-record.c | 42 +- tools/perf/builtin-report.c | 3 + tools/perf/builtin-script.c | 36 +- tools/perf/builtin-top.c | 44 +- tools/perf/builtin-trace.c | 6 +- .../perf/pmu-events/arch/powerpc/power9/cache.json | 5 - .../pmu-events/arch/powerpc/power9/frontend.json | 7 +- .../pmu-events/arch/powerpc/power9/marked.json | 27 +- .../perf/pmu-events/arch/powerpc/power9/other.json | 276 +++------ .../pmu-events/arch/powerpc/power9/pipeline.json | 14 +- tools/perf/pmu-events/arch/powerpc/power9/pmc.json | 2 +- .../arch/powerpc/power9/translation.json | 5 - tools/perf/tests/attr.c | 6 + tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- .../perf/tests/shell/trace+probe_libc_inet_pton.sh | 7 +- tools/perf/tests/shell/trace+probe_vfs_getname.sh | 6 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/ui/browsers/annotate.c | 401 +++++++------ tools/perf/ui/gtk/annotate.c | 25 +- tools/perf/util/annotate.c | 651 +++++++++++---------- tools/perf/util/annotate.h | 76 +-- tools/perf/util/evlist.c | 25 +- tools/perf/util/evlist.h | 6 + tools/perf/util/evsel.c | 92 ++- tools/perf/util/evsel.h | 10 +- tools/perf/util/machine.c | 5 +-
Quoted 8 lines
tools/perf/util/ordered-events.c | 3 +- tools/perf/util/ordered-events.h | 2 +- tools/perf/util/parse-events.c | 2 + tools/perf/util/parse-events.h | 3 + tools/perf/util/pmu.c | 5 + tools/perf/util/session.c | 45 +- tools/perf/util/session.h | 2 +- 52 files changed, 1028 insertions(+), 920 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo