perf/core improvements and fixes
Subsystems (5)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit ff2ebe46e15bd49d52b9c2f3fc77f3a9d94eac7b:
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core (2014-07-16 13:48:13 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to 0b437860818dc717f6a9e8a5089223a8414f5fff:
perf tools: Allow TSC conversion on any arch (2014-07-17 12:59:00 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
o Support S/390 in 'perf kvm stat' (Alexander Yarygin)
Developer Stuff:
o Various fixes and prep work related to supporting Intel PT (Adrian Hunter)
o Introduce multiple debug variables control (Jiri Olsa)
o Add callchain and additional sample information for python scripts (Joseph Schuchart)
----------------------------------------------------------------
Adrian Hunter (21):
perf machine: Fix the value used for unknown pids perf script: Display PERF_RECORD_MISC_COMM_EXEC flag perf record: Select comm_exec flag if supported
perf tools: Fix missing kernel map load
perf symbols: Fix missing GNU IFUNC symbols
perf inject: Fix build id injection
perf callchain: Fix appending a callchain from a previous sample perf buildid-cache: Apply force option to copying kcore perf symbols: Record whether a dso is 64-bit
perf symbols: Do not attempt to read data from kallsyms perf symbols: Add ability to iterate over a dso's symbols perf session: Flag if the event stream is entirely in memory perf evlist: Pass mmap parameters in a struct
perf tools: Add feature test for __sync_val_compare_and_swap perf tools: Add option macro OPT_CALLBACK_OPTARG
perf evsel: Add 'no_aux_samples' option
perf evsel: Add 'immediate' option
perf machine: Fix map groups of threads with unknown pids perf thread: Allow deletion of a thread with no map groups perf machine: Fix leak of 'struct thread' on error path perf tools: Allow TSC conversion on any arch
Alexander Yarygin (4):
perf kvm: Use defines of kvm events perf kvm: Move arch specific code into arch/ perf kvm: Add skip_event() for --duration option perf kvm: Add stat support on s390
Jiri Olsa (5):
perf tools: Remove verbose from functions prototypes perf tools: Move pr_* debug macros into debug object perf tools: Factor eprintf to allow different debug variables perf tools: Add --debug optionto set debug variable perf tools: Remove needless getopt.h includes
Joseph Schuchart (3):
perf script: Add missing calls to Py_DECREF for return values perf script: Add callchain to generic and tracepoint events perf script: Provide additional sample information on generic events
arch/s390/include/uapi/asm/Kbuild | 1 + arch/s390/include/uapi/asm/kvm_perf.h | 25 ++ arch/x86/include/uapi/asm/Kbuild | 1 + arch/x86/include/uapi/asm/kvm_perf.h | 16 + tools/perf/Documentation/perf-kvm.txt | 16 +- tools/perf/Documentation/perf.txt | 10 +- tools/perf/MANIFEST | 3 + tools/perf/Makefile.perf | 3 + tools/perf/arch/s390/Makefile | 2 + tools/perf/arch/s390/util/kvm-stat.c | 105 ++++++ tools/perf/arch/x86/Makefile | 1 + tools/perf/arch/x86/tests/dwarf-unwind.c | 1 + tools/perf/arch/x86/util/kvm-stat.c | 156 +++++++++ tools/perf/arch/x86/util/tsc.c | 22 +- tools/perf/arch/x86/util/tsc.h | 3 - tools/perf/arch/x86/util/unwind-libunwind.c | 1 + tools/perf/builtin-buildid-cache.c | 8 +- tools/perf/builtin-evlist.c | 1 + tools/perf/builtin-help.c | 1 + tools/perf/builtin-inject.c | 3 + tools/perf/builtin-kvm.c | 384 ++++++--------------- tools/perf/builtin-sched.c | 12 +- tools/perf/builtin-timechart.c | 1 + tools/perf/config/Makefile | 6 + tools/perf/config/feature-checks/Makefile | 4 + tools/perf/config/feature-checks/test-all.c | 5 + .../feature-checks/test-sync-compare-and-swap.c | 14 + tools/perf/perf.c | 13 +- .../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +- tools/perf/scripts/python/check-perf-trace.py | 4 +- .../perf/scripts/python/failed-syscalls-by-pid.py | 2 +- tools/perf/scripts/python/futex-contention.py | 4 +- tools/perf/scripts/python/net_dropmonitor.py | 2 +- tools/perf/scripts/python/netdev-times.py | 26 +- tools/perf/scripts/python/sched-migration.py | 41 ++- tools/perf/scripts/python/sctop.py | 2 +- tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +- tools/perf/scripts/python/syscall-counts.py | 2 +- tools/perf/tests/dso-data.c | 1 + tools/perf/tests/evsel-roundtrip-name.c | 1 + tools/perf/tests/evsel-tp-sched.c | 1 + tools/perf/tests/open-syscall-tp-fields.c | 1 + tools/perf/tests/parse-events.c | 1 + tools/perf/tests/parse-no-sample-id-all.c | 1 + tools/perf/tests/perf-time-to-tsc.c | 3 +- tools/perf/tests/sample-parsing.c | 1 + tools/perf/tests/thread-mg-share.c | 1 + tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/callchain.c | 2 +- tools/perf/util/data.c | 1 + tools/perf/util/debug.c | 56 ++- tools/perf/util/debug.h | 22 ++ tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 1 + tools/perf/util/event.c | 10 +- tools/perf/util/evlist.c | 46 +-- tools/perf/util/evsel.c | 14 +- tools/perf/util/evsel.h | 2 + tools/perf/util/include/linux/kernel.h | 21 -- tools/perf/util/kvm-stat.h | 140 ++++++++ tools/perf/util/machine.c | 63 +++- tools/perf/util/map.c | 38 +- tools/perf/util/map.h | 10 +- tools/perf/util/parse-options.h | 5 + tools/perf/util/probe-finder.c | 1 - tools/perf/util/pstack.c | 1 + tools/perf/util/python.c | 4 +- tools/perf/util/record.c | 18 +- .../perf/util/scripting-engines/trace-event-perl.c | 1 + .../util/scripting-engines/trace-event-python.c | 140 +++++++- tools/perf/util/session.c | 14 +- tools/perf/util/session.h | 3 + tools/perf/util/symbol-elf.c | 6 +- tools/perf/util/symbol-minimal.c | 22 ++ tools/perf/util/symbol.c | 20 +- tools/perf/util/symbol.h | 4 + tools/perf/util/thread.c | 12 +- tools/perf/util/trace-event-info.c | 1 + tools/perf/util/trace-event-read.c | 2 +- tools/perf/util/tsc.c | 25 ++ tools/perf/util/tsc.h | 11 + tools/perf/util/unwind-libdw.c | 1 + tools/perf/util/unwind-libunwind.c | 1 + tools/perf/util/util.c | 1 + tools/perf/util/vdso.c | 1 + 85 files changed, 1170 insertions(+), 470 deletions(-) create mode 100644 arch/s390/include/uapi/asm/kvm_perf.h create mode 100644 arch/x86/include/uapi/asm/kvm_perf.h create mode 100644 tools/perf/arch/s390/util/kvm-stat.c create mode 100644 tools/perf/arch/x86/util/kvm-stat.c create mode 100644 tools/perf/config/feature-checks/test-sync-compare-and-swap.c create mode 100644 tools/perf/util/kvm-stat.h create mode 100644 tools/perf/util/tsc.c create mode 100644 tools/perf/util/tsc.h
Arnaldo Carvalho de Melo
maintainerPATCH 1/33 perf kvm: Use defines of kvm events
From: Alexander Yarygin <[email protected]>
Currently perf-kvm uses string literals for kvm event names, but it works only for x86, because other architectures may have other names for those events.
To reduce dependence on architecture, we add <asm/kvm_perf.h> file with defines for:
- kvm_entry and kvm_exit events,
- exit reason field name in kvm_exit event,
- length of exit reasons strings,
- vcpu_id field name in kvm trace events,
and replace literals in perf-kvm.
Reviewed-by David Ahern <[email protected]>
--- arch/x86/include/uapi/asm/Kbuild | 1 + arch/x86/include/uapi/asm/kvm_perf.h | 16 ++++++++++++++++ tools/perf/MANIFEST | 1 + tools/perf/builtin-kvm.c | 34 ++++++++++++++++------------------ 4 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 arch/x86/include/uapi/asm/kvm_perf.h
arch/x86/include/uapi/asm/Kbuild +1 -0
@@ -22,6 +22,7 @@ header-y += ipcbuf.h header-y += ist.h header-y += kvm.h header-y += kvm_para.h +header-y += kvm_perf.h header-y += ldt.h header-y += mce.h header-y += mman.h
arch/x86/include/uapi/asm/kvm_perf.h new file +16 -0
@@ -0,0 +1,16 @@ +#ifndef _ASM_X86_KVM_PERF_H +#define _ASM_X86_KVM_PERF_H + +#include <asm/svm.h> +#include <asm/vmx.h> +#include <asm/kvm.h> + +#define DECODE_STR_LEN 20 + +#define VCPU_ID "vcpu_id" + +#define KVM_ENTRY_TRACE "kvm:kvm_entry" +#define KVM_EXIT_TRACE "kvm:kvm_exit" +#define KVM_EXIT_REASON "exit_reason" + +#endif /* _ASM_X86_KVM_PERF_H */
tools/perf/MANIFEST +1 -0
@@ -37,3 +37,4 @@ arch/x86/include/asm/kvm_host.h arch/x86/include/uapi/asm/svm.h arch/x86/include/uapi/asm/vmx.h arch/x86/include/uapi/asm/kvm.h +arch/x86/include/uapi/asm/kvm_perf.h
tools/perf/builtin-kvm.c +16 -18
@@ -30,9 +30,7 @@#include <math.h> #ifdef HAVE_KVM_STAT_SUPPORT -#include <asm/svm.h> -#include <asm/vmx.h> -#include <asm/kvm.h> +#include <asm/kvm_perf.h> struct event_key { #define INVALID_KEY (~0ULL)
@@ -75,7 +73,7 @@ struct kvm_events_ops {bool (*is_end_event)(struct perf_evsel *evsel,struct perf_sample *sample,struct event_key *key);void (*decode_key)(struct perf_kvm_stat *kvm,struct event_key *key, -char decode[20 ]); +char *decode);const char *name; };
@@ -126,12 +124,12 @@ static void exit_event_get_key(struct perf_evsel *evsel, struct event_key *key) { key->info =0 ; - key->key =perf_evsel__intval (evsel, sample,"exit_reason" ); + key->key =perf_evsel__intval (evsel, sample,KVM_EXIT_REASON ); }static bool kvm_exit_event (struct perf_evsel *evsel) { -return !strcmp (evsel->name,"kvm:kvm_exit" ); +return !strcmp (evsel->name,KVM_EXIT_TRACE ); } static bool exit_event_begin(struct perf_evsel *evsel,
@@ -147,7 +145,7 @@ static bool exit_event_begin(struct perf_evsel *evsel,static bool kvm_entry_event (struct perf_evsel *evsel) { -return !strcmp (evsel->name,"kvm:kvm_entry" ); +return !strcmp (evsel->name,KVM_ENTRY_TRACE ); } static bool exit_event_end(struct perf_evsel *evsel,
@@ -182,12 +180,12 @@ static const char *get_exit_reason(struct perf_kvm_stat *kvm,static void exit_event_decode_key (struct perf_kvm_stat *kvm,struct event_key *key, -char decode[20 ]) +char *decode) {const char *exit_reason =get_exit_reason (kvm, kvm->exit_reasons, key->key); -scnprintf (decode,20 ,"%s" , exit_reason); +scnprintf (decode,DECODE_STR_LEN ,"%s" , exit_reason); }static struct kvm_events_ops exit_events = {
@@ -249,9 +247,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,static void mmio_event_decode_key (struct perf_kvm_stat *kvm__maybe_unused ,struct event_key *key, -char decode[20 ]) +char *decode) { -scnprintf (decode,20 ,"%#lx:%s" , (unsigned long )key->key, +scnprintf (decode,DECODE_STR_LEN ,"%#lx:%s" , (unsigned long )key->key, key->info ==KVM_TRACE_MMIO_WRITE ?"W" :"R" ); }
@@ -292,9 +290,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,static void ioport_event_decode_key (struct perf_kvm_stat *kvm__maybe_unused ,struct event_key *key, -char decode[20 ]) +char *decode) { -scnprintf (decode,20 ,"%#llx:%s" , (unsigned long long )key->key, +scnprintf (decode,DECODE_STR_LEN ,"%#llx:%s" , (unsigned long long )key->key, key->info ?"POUT" :"PIN" ); }
@@ -524,7 +522,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, time_diff = sample->time - time_begin;if (kvm->duration && time_diff > kvm->duration) { -char decode[32 ]; +char decode[DECODE_STR_LEN ]; kvm->events_ops->decode_key (kvm, &event->key, decode);if (strcmp (decode,"HLT" )) {
@@ -552,7 +550,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,return NULL ; } - vcpu_record->vcpu_id =perf_evsel__intval (evsel, sample,"vcpu_id" ); + vcpu_record->vcpu_id =perf_evsel__intval (evsel, sample,VCPU_ID ); thread->priv = vcpu_record; }
@@ -739,7 +737,7 @@ static void show_timeofday(void)static void print_result (struct perf_kvm_stat *kvm) { -char decode[20 ]; +char decode[DECODE_STR_LEN ];struct kvm_event *event;int vcpu = kvm->trace_vcpu;
@@ -750,7 +748,7 @@ static void print_result(struct perf_kvm_stat *kvm)pr_info ("\n\n" );print_vcpu_info (kvm); -pr_info ("%20s " , kvm->events_ops->name); +pr_info ("%*s " ,DECODE_STR_LEN , kvm->events_ops->name);pr_info ("%10s " ,"Samples" );pr_info ("%9s " ,"Samples%" );
@@ -769,7 +767,7 @@ static void print_result(struct perf_kvm_stat *kvm) min =get_event_min (event, vcpu); kvm->events_ops->decode_key (kvm, &event->key, decode); -pr_info ("%20s " , decode); +pr_info ("%*s " ,DECODE_STR_LEN , decode);pr_info ("%10llu " , (unsigned long long )ecount);pr_info ("%8.2f%% " , (double )ecount / kvm->total_count *100 );pr_info ("%8.2f%% " , (double )etime / kvm->total_time *100 );
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/33 perf kvm: Move arch specific code into arch/
In reply to Arnaldo Carvalho de MeloFrom: Alexander Yarygin <[email protected]>
Parts of a 'perf kvm stat' code make sense only for x86.
Let's move this code into the arch/x86/kvm-stat.c file and add util/kvm-stat.h for generic structure definitions.
Add a global array 'kvm_reg_events_ops' for accessing the arch-specific 'kvm_events_ops' from generic code.
Since the several global arrays (i.e. 'kvm_events_tp') have been moved to arch/*, we can not know their sizes and use them directly in builtin-kvm.c. This patch fixes that problem by adding trimming NULL element to each array and changing the behavior of their handlers in generic code.
--- tools/perf/Makefile.perf | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/arch/x86/util/kvm-stat.c | 151 ++++++++++++++++++ tools/perf/builtin-kvm.c | 297 +++++------------------------------- tools/perf/util/kvm-stat.h | 130 ++++++++++++++++ 5 files changed, 317 insertions(+), 263 deletions(-) create mode 100644 tools/perf/arch/x86/util/kvm-stat.c create mode 100644 tools/perf/util/kvm-stat.h
tools/perf/Makefile.perf +1 -0
@@ -300,6 +300,7 @@ LIB_H += ui/progress.h LIB_H += ui/util.h LIB_H += ui/ui.h LIB_H += util/data.h +LIB_H += util/kvm-stat.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o
tools/perf/arch/x86/Makefile +1 -0
@@ -16,3 +16,4 @@ LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o LIB_H += arch/$(ARCH)/util/tsc.h HAVE_KVM_STAT_SUPPORT := 1 +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
tools/perf/arch/x86/util/kvm-stat.c new file +151 -0
151 lines not on this page · raw message
tools/perf/builtin-kvm.c +34 -263
403 lines not on this page · raw message
tools/perf/util/kvm-stat.h new file +130 -0
130 lines not on this page · raw message
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/33 perf kvm: Add skip_event() for --duration option
In reply to Arnaldo Carvalho de MeloFrom: Alexander Yarygin <[email protected]>
Current code skips output of the x86 specific HLT event in order to avoid flooding the output with enabled --duration option. The events to be skipped should be architecture dependent, though.
Let's add an architecture specific array of events to be skipped and introduce a skip_event() function checking against that array.
--- tools/perf/arch/x86/util/kvm-stat.c | 5 +++++ tools/perf/builtin-kvm.c | 13 ++++++++++++- tools/perf/util/kvm-stat.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-)
tools/perf/arch/x86/util/kvm-stat.c +5 -0
@@ -136,6 +136,11 @@ struct kvm_reg_events_ops kvm_reg_events_ops[] = { { NULL, NULL }, }; +const char *const kvm_skip_events[] = { +"HLT" , +NULL , +}; +int cpu_isa_init (struct perf_kvm_stat *kvm,const char *cpuid) {if (strstr (cpuid,"Intel" )) {
tools/perf/builtin-kvm.c +12 -1
@@ -261,6 +261,17 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,return true; } +static bool skip_event (const char *event) +{ +const char *const *skip_events; + +for (skip_events = kvm_skip_events; *skip_events; skip_events++) +if (!strcmp (event, *skip_events)) +return true; + +return false; +} + static bool handle_end_event(struct perf_kvm_stat *kvm, struct vcpu_event_record *vcpu_record, struct event_key *key,
@@ -312,7 +323,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,char decode[DECODE_STR_LEN ]; kvm->events_ops->decode_key (kvm, &event->key, decode); -if (strcmp (decode,"HLT" )) { +if (!skip_event (decode)) {pr_info ("%" PRIu64" VM %d, vcpu %d: %s event took %" PRIu64"usec\n" , sample->time, sample->pid, vcpu_record->vcpu_id, decode, time_diff/1000 );
tools/perf/util/kvm-stat.h +1 -0
@@ -126,5 +126,6 @@ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);extern const char *const kvm_events_tp[];extern struct kvm_reg_events_ops kvm_reg_events_ops[]; +extern const char *const kvm_skip_events[];#endif /* __PERF_KVM_STAT_H */
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/33 perf kvm: Add stat support on s390
In reply to Arnaldo Carvalho de MeloFrom: Alexander Yarygin <[email protected]>
On s390, the vmexit event has a tree-like structure: between exit_event_begin and exit_event_end several other events may happen and with each of them refining the previous ones.
This patch adds a decoder for such events to the generic code and also the files <asm/kvm_perf.h> and kvm-stat.c for s390.
Commands 'perf kvm stat record', 'report' and 'live' are supported.
--- arch/s390/include/uapi/asm/Kbuild | 1 + arch/s390/include/uapi/asm/kvm_perf.h | 25 ++++++++ tools/perf/Documentation/perf-kvm.txt | 16 +++--- tools/perf/MANIFEST | 2 + tools/perf/arch/s390/Makefile | 2 + tools/perf/arch/s390/util/kvm-stat.c | 105 ++++++++++++++++++++++++++++++++++ tools/perf/builtin-kvm.c | 52 +++++++++++++++-- tools/perf/util/kvm-stat.h | 9 +++ 8 files changed, 201 insertions(+), 11 deletions(-) create mode 100644 arch/s390/include/uapi/asm/kvm_perf.h create mode 100644 tools/perf/arch/s390/util/kvm-stat.c
arch/s390/include/uapi/asm/Kbuild +1 -0
@@ -16,6 +16,7 @@ header-y += ioctls.h header-y += ipcbuf.h header-y += kvm.h header-y += kvm_para.h +header-y += kvm_perf.h header-y += kvm_virtio.h header-y += mman.h header-y += monwriter.h
arch/s390/include/uapi/asm/kvm_perf.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* Definitions for perf-kvm on s390 +* +* Copyright 2014 IBM Corp. +* Author(s): Alexander Yarygin <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (version 2 only) +* as published by the Free Software Foundation. +*/ + +#ifndef __LINUX_KVM_PERF_S390_H +#define __LINUX_KVM_PERF_S390_H + +#include <asm/sie.h> + +#define DECODE_STR_LEN 40 + +#define VCPU_ID "id" + +#define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter" +#define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit" +#define KVM_EXIT_REASON "icptcode" + +#endif
tools/perf/Documentation/perf-kvm.txt +9 -7
@@ -51,9 +51,9 @@ There are a couple of variants of perf kvm: 'perf kvm stat <command>' to run a command and gather performance counter statistics. Especially, perf 'kvm stat record/report' generates a statistical analysis - of KVM events. Currently, vmexit, mmio and ioport events are supported. - 'perf kvm stat record <command>' records kvm events and the events between - start and end <command>. + of KVM events. Currently, vmexit, mmio (x86 only) and ioport (x86 only) + events are supported. 'perf kvm stat record <command>' records kvm events + and the events between start and end <command>. And this command produces a file which contains tracing results of kvm events.
@@ -103,8 +103,8 @@ STAT REPORT OPTIONS analyze events which occures on this vcpu. (default: all vcpus) --event=<value>:: - event to be analyzed. Possible values: vmexit, mmio, ioport. - (default: vmexit) + event to be analyzed. Possible values: vmexit, mmio (x86 only), + ioport (x86 only). (default: vmexit) -k:: --key=<value>:: Sorting key. Possible values: sample (default, sort by samples
@@ -138,7 +138,8 @@ STAT LIVE OPTIONS --event=<value>:: - event to be analyzed. Possible values: vmexit, mmio, ioport. + event to be analyzed. Possible values: vmexit, + mmio (x86 only), ioport (x86 only). (default: vmexit) -k::
@@ -147,7 +148,8 @@ STAT LIVE OPTIONS number), time (sort by average time). --duration=<value>:: - Show events other than HLT that take longer than duration usecs. + Show events other than HLT (x86 only) or Wait state (s390 only) + that take longer than duration usecs. SEE ALSO --------
tools/perf/MANIFEST +2 -0
@@ -38,3 +38,5 @@ arch/x86/include/uapi/asm/svm.h arch/x86/include/uapi/asm/vmx.h arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm_perf.h +arch/s390/include/uapi/asm/sie.h +arch/s390/include/uapi/asm/kvm_perf.h
tools/perf/arch/s390/Makefile +2 -0
@@ -3,3 +3,5 @@ PERF_HAVE_DWARF_REGS := 1 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o +HAVE_KVM_STAT_SUPPORT := 1 +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
tools/perf/arch/s390/util/kvm-stat.c new file +105 -0
105 lines not on this page · raw message
tools/perf/builtin-kvm.c +48 -4
88 lines not on this page · raw message
tools/perf/util/kvm-stat.h +9 -0
@@ -12,6 +12,7 @@ struct event_key {#define INVALID_KEY (~0ULL)u64 key;int info; +struct exit_reasons_table *exit_reasons; };struct kvm_event_stats {
@@ -41,12 +42,20 @@ struct kvm_event_key {struct perf_kvm_stat ; +struct child_event_ops { +void (*get_key)(struct perf_evsel *evsel, +struct perf_sample *sample, +struct event_key *key); +const char *name; +}; +struct kvm_events_ops {bool (*is_begin_event)(struct perf_evsel *evsel,struct perf_sample *sample,struct event_key *key);bool (*is_end_event)(struct perf_evsel *evsel,struct perf_sample *sample,struct event_key *key); +struct child_event_ops *child_ops;void (*decode_key)(struct perf_kvm_stat *kvm,struct event_key *key,char *decode);const char *name;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/33 perf script: Add missing calls to Py_DECREF for return values
In reply to Arnaldo Carvalho de MeloFrom: Joseph Schuchart <[email protected]>
--- tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +10 -2
@@ -50,10 +50,14 @@ static int zero_flag_atom;static PyObject *main_module, *main_dict; +static void handler_call_die(const char *handler_name) NORETURN;static void handler_call_die (const char *handler_name) {PyErr_Print ();Py_FatalError ("problem in Python trace event handler" ); +// Py_FatalError does not return +// but we have to make the compiler happy +abort (); }/*
@@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type, retval =PyObject_CallObject (handler, t);if (retval ==NULL )handler_call_die (handler_name); +Py_DECREF (retval); }Py_DECREF (t);
@@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type, retval =PyObject_CallObject (handler, t);if (retval ==NULL )handler_call_die (handler_name); +Py_DECREF (retval); }Py_DECREF (t);
@@ -361,6 +367,7 @@ static void python_process_tracepoint(struct perf_sample *sample, retval =PyObject_CallObject (handler, t);if (retval ==NULL )handler_call_die (handler_name); +Py_DECREF (retval); }else { handler =PyDict_GetItemString (main_dict,"trace_unhandled" );if (handler &&PyCallable_Check (handler)) {
@@ -368,6 +375,7 @@ static void python_process_tracepoint(struct perf_sample *sample, retval =PyObject_CallObject (handler, t);if (retval ==NULL )handler_call_die ("trace_unhandled" ); +Py_DECREF (retval); }Py_DECREF (dict); }
@@ -427,6 +435,7 @@ static void python_process_general_event(struct perf_sample *sample, retval =PyObject_CallObject (handler, t);if (retval ==NULL )handler_call_die (handler_name); +Py_DECREF (retval); exit:Py_DECREF (dict);Py_DECREF (t);
@@ -548,8 +557,7 @@ static int python_stop_script(void) retval =PyObject_CallObject (handler,NULL );if (retval ==NULL )handler_call_die ("trace_end" ); -else -Py_DECREF (retval); +Py_DECREF (retval); out:Py_XDECREF (main_dict);Py_XDECREF (main_module);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/33 perf script: Add callchain to generic and tracepoint events
In reply to Arnaldo Carvalho de MeloFrom: Joseph Schuchart <[email protected]>
This provides valuable information for tracing performance problems.
Since this change alters the interface for the python scripts, also adjust the script generation and the provided scripts.
--- .../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +- tools/perf/scripts/python/check-perf-trace.py | 4 +- .../perf/scripts/python/failed-syscalls-by-pid.py | 2 +- tools/perf/scripts/python/futex-contention.py | 4 +- tools/perf/scripts/python/net_dropmonitor.py | 2 +- tools/perf/scripts/python/netdev-times.py | 26 ++--- tools/perf/scripts/python/sched-migration.py | 41 ++++---- tools/perf/scripts/python/sctop.py | 2 +- tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +- tools/perf/scripts/python/syscall-counts.py | 2 +- .../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++- 11 files changed, 146 insertions(+), 48 deletions(-)
tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py +2 -1
@@ -107,12 +107,13 @@ def taskState(state): class EventHeaders: def __init__(self, common_cpu, common_secs, common_nsecs, - common_pid, common_comm): + common_pid, common_comm, common_callchain): self.cpu = common_cpu self.secs = common_secs self.nsecs = common_nsecs self.pid = common_pid self.comm = common_comm + self.callchain = common_callchain def ts(self): return (self.secs * (10 ** 9)) + self.nsecs
tools/perf/scripts/python/check-perf-trace.py +2 -2
@@ -27,7 +27,7 @@ def trace_end(): def irq__softirq_entry(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - vec): + common_callchain, vec): print_header(event_name, common_cpu, common_secs, common_nsecs, common_pid, common_comm)
@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu, def kmem__kmalloc(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - call_site, ptr, bytes_req, bytes_alloc, + common_callchain, call_site, ptr, bytes_req, bytes_alloc, gfp_flags): print_header(event_name, common_cpu, common_secs, common_nsecs, common_pid, common_comm)
tools/perf/scripts/python/failed-syscalls-by-pid.py +1 -1
@@ -39,7 +39,7 @@ def trace_end(): def raw_syscalls__sys_exit(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - id, ret): + common_callchain, id, ret): if (for_comm and common_comm != for_comm) or \ (for_pid and common_pid != for_pid ): return
tools/perf/scripts/python/futex-contention.py +2 -2
@@ -21,7 +21,7 @@ thread_blocktime = {} lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time process_names = {} # long-lived pid-to-execname mapping -def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, +def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, nr, uaddr, op, val, utime, uaddr2, val3): cmd = op & FUTEX_CMD_MASK if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, thread_thislock[tid] = uaddr thread_blocktime[tid] = nsecs(s, ns) -def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, +def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, nr, ret): if thread_blocktime.has_key(tid): elapsed = nsecs(s, ns) - thread_blocktime[tid]
tools/perf/scripts/python/net_dropmonitor.py +1 -1
@@ -66,7 +66,7 @@ def trace_end(): print_drop_table() # called from perf, when it finds a correspoinding event -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, location, protocol): slocation = str(location) try:
tools/perf/scripts/python/netdev-times.py +13 -13
@@ -224,75 +224,75 @@ def trace_end(): (len(rx_skb_list), of_count_rx_skb_list) # called from perf, when it finds a correspoinding event -def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec): +def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec): if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": return event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) all_event_list.append(event_info) -def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec): +def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec): if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": return event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) all_event_list.append(event_info) -def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec): +def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec): if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": return event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) all_event_list.append(event_info) def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm, - irq, irq_name): + callchain, irq, irq_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, irq_name) all_event_list.append(event_info) -def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret): +def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) all_event_list.append(event_info) -def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name): +def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, napi, dev_name) all_event_list.append(event_info) -def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr, +def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, skblen, dev_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, skblen, dev_name) all_event_list.append(event_info) -def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr, +def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, skblen, dev_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, skblen, dev_name) all_event_list.append(event_info) -def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, +def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, skblen, dev_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, skblen, dev_name) all_event_list.append(event_info) -def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, +def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, skblen, rc, dev_name): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, skblen, rc ,dev_name) all_event_list.append(event_info) -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, protocol, location): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, protocol, location) all_event_list.append(event_info) -def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr): +def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr) all_event_list.append(event_info) -def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, +def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, skblen): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, skbaddr, skblen)
tools/perf/scripts/python/sched-migration.py +20 -21
113 lines not on this page · raw message
tools/perf/scripts/python/sctop.py +1 -1
@@ -44,7 +44,7 @@ def trace_begin(): def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - id, args): + common_callchain, id, args): if for_comm is not None: if common_comm != for_comm: return
tools/perf/scripts/python/syscall-counts-by-pid.py +1 -1
@@ -38,7 +38,7 @@ def trace_end(): def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - id, args): + common_callchain, id, args): if (for_comm and common_comm != for_comm) or \ (for_pid and common_pid != for_pid ):
tools/perf/scripts/python/syscall-counts.py +1 -1
@@ -35,7 +35,7 @@ def trace_end(): def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, - id, args): + common_callchain, id, args): if for_comm is not None: if common_comm != for_comm: return
tools/perf/util/scripting-engines/trace-event-python.c +102 -4
177 lines not on this page · raw message
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/33 perf script: Provide additional sample information on generic events
In reply to Arnaldo Carvalho de MeloFrom: Joseph Schuchart <[email protected]>
To python scripts, including pid, tid, and cpu for which the event was recorded.
At the moment, the pointer to the sample struct is passed to scripts, which seems to be of little use.
The patch puts this information in dictionaries for easy access by Python scripts.
--- .../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +20 -3
@@ -473,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,struct thread *thread, struct addr_location *al) { - PyObject *handler, *retval, *t, *dict, *callchain; + PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;static char handler_name[64 ];unsigned n =0 ;
@@ -489,6 +489,10 @@ static void python_process_general_event(struct perf_sample *sample,if (!dict)Py_FatalError ("couldn't create Python dictionary" ); + dict_sample =PyDict_New (); +if (!dict_sample) +Py_FatalError ("couldn't create Python dictionary" ); +snprintf (handler_name,sizeof (handler_name),"%s" ,"process_event" ); handler =PyDict_GetItemString (main_dict, handler_name);
@@ -498,8 +502,21 @@ static void python_process_general_event(struct perf_sample *sample,pydict_set_item_string_decref (dict,"ev_name" ,PyString_FromString (perf_evsel__name (evsel)));pydict_set_item_string_decref (dict,"attr" ,PyString_FromStringAndSize ( (const char *)&evsel->attr,sizeof (evsel->attr))); -pydict_set_item_string_decref (dict,"sample" ,PyString_FromStringAndSize ( - (const char *)sample,sizeof (*sample))); + +pydict_set_item_string_decref (dict_sample,"pid" , +PyInt_FromLong (sample->pid)); +pydict_set_item_string_decref (dict_sample,"tid" , +PyInt_FromLong (sample->tid)); +pydict_set_item_string_decref (dict_sample,"cpu" , +PyInt_FromLong (sample->cpu)); +pydict_set_item_string_decref (dict_sample,"ip" , +PyLong_FromUnsignedLongLong (sample->ip)); +pydict_set_item_string_decref (dict_sample,"time" , +PyLong_FromUnsignedLongLong (sample->time)); +pydict_set_item_string_decref (dict_sample,"period" , +PyLong_FromUnsignedLongLong (sample->period)); +pydict_set_item_string_decref (dict,"sample" , dict_sample); +pydict_set_item_string_decref (dict,"raw_buf" ,PyString_FromStringAndSize ( (const char *)sample->raw_data, sample->raw_size)); pydict_set_item_string_decref(dict, "comm",
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/33 perf machine: Fix the value used for unknown pids
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
The value used for unknown pids cannot be zero because that is used by the "idle" task.
Use -1 instead. Also handle the unknown pid case when creating map groups.
Note that, threads with an unknown pid should not occur because fork (or synthesized) events precede the thread's existence.
--- tools/perf/builtin-sched.c | 12 ++++++------ tools/perf/util/machine.c | 6 +++--- tools/perf/util/session.c | 5 +++-- tools/perf/util/thread.c | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-)
tools/perf/builtin-sched.c +6 -6
@@ -935,8 +935,8 @@ static int latency_switch_event(struct perf_sched *sched,return -1 ; } - sched_out =machine__findnew_thread (machine,0 , prev_pid); - sched_in =machine__findnew_thread (machine,0 , next_pid); + sched_out =machine__findnew_thread (machine,-1 , prev_pid); + sched_in =machine__findnew_thread (machine,-1 , next_pid); out_events =thread_atoms_search (&sched->atom_root, sched_out, &sched->cmp_pid);if (!out_events) {
@@ -979,7 +979,7 @@ static int latency_runtime_event(struct perf_sched *sched, {const u32 pid =perf_evsel__intval (evsel, sample,"pid" );const u64 runtime =perf_evsel__intval (evsel, sample,"runtime" ); -struct thread *thread =machine__findnew_thread (machine,0 , pid); +struct thread *thread =machine__findnew_thread (machine,-1 , pid);struct work_atoms *atoms =thread_atoms_search (&sched->atom_root, thread, &sched->cmp_pid);u64 timestamp = sample->time;int cpu = sample->cpu;
@@ -1012,7 +1012,7 @@ static int latency_wakeup_event(struct perf_sched *sched,struct thread *wakee;u64 timestamp = sample->time; - wakee =machine__findnew_thread (machine,0 , pid); + wakee =machine__findnew_thread (machine,-1 , pid); atoms =thread_atoms_search (&sched->atom_root, wakee, &sched->cmp_pid);if (!atoms) {if (thread_atoms_insert (sched, wakee))
@@ -1072,7 +1072,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,if (sched->profile_cpu ==-1 )return 0 ; - migrant =machine__findnew_thread (machine,0 , pid); + migrant =machine__findnew_thread (machine,-1 , pid); atoms =thread_atoms_search (&sched->atom_root, migrant, &sched->cmp_pid);if (!atoms) {if (thread_atoms_insert (sched, migrant))
@@ -1290,7 +1290,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,return -1 ; } - sched_in =machine__findnew_thread (machine,0 , next_pid); + sched_in =machine__findnew_thread (machine,-1 , next_pid); sched->curr_thread[this_cpu] = sched_in;
tools/perf/util/machine.c +3 -3
@@ -34,7 +34,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)return -ENOMEM ;if (pid !=HOST_KERNEL_ID ) { -struct thread *thread =machine__findnew_thread (machine,0 , +struct thread *thread =machine__findnew_thread (machine,-1 , pid);char comm[64 ];
@@ -286,7 +286,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,* the full rbtree: */ if (machine->last_match && machine->last_match->tid == tid) { -if (pid && pid != machine->last_match->pid_) +if (pid !=-1 && pid != machine->last_match->pid_) machine->last_match->pid_ = pid;return machine->last_match; }
@@ -297,7 +297,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,if (th->tid == tid) { machine->last_match = th; -if (pid && pid != th->pid_) +if (pid !=-1 && pid != th->pid_) th->pid_ = pid;return th; }
tools/perf/util/session.c +3 -2
@@ -1083,13 +1083,14 @@ void perf_event_header__bswap(struct perf_event_header *hdr)struct thread *perf_session__findnew (struct perf_session *session,pid_t pid) { -return machine__findnew_thread (&session->machines.host,0 , pid); +return machine__findnew_thread (&session->machines.host,-1 , pid); }static struct thread *perf_session__register_idle_thread (struct perf_session *session) { -struct thread *thread =perf_session__findnew (session,0 ); +struct thread *thread; + thread =machine__findnew_thread (&session->machines.host,0 ,0 );if (thread ==NULL ||thread__set_comm (thread,"swapper" ,0 )) {pr_err ("problem inserting idle task.\n" ); thread =NULL ;
tools/perf/util/thread.c +1 -1
@@ -13,7 +13,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)struct thread *leader;pid_t pid = thread->pid_; -if (pid == thread->tid) { +if (pid == thread->tid || pid ==-1 ) { thread->mg =map_groups__new (); }else { leader =machine__findnew_thread (machine, pid, pid);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/33 perf script: Display PERF_RECORD_MISC_COMM_EXEC flag
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
--- tools/perf/util/event.c | 9 ++++++++- tools/perf/util/evsel.c | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-)
tools/perf/util/event.c +8 -1
@@ -603,7 +603,14 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,size_t perf_event__fprintf_comm (union perf_event *event,FILE *fp) { -return fprintf (fp,": %s:%d\n" , event->comm.comm, event->comm.tid); +const char *s; + +if (event->header.misc &PERF_RECORD_MISC_COMM_EXEC ) + s =" exec" ; +else + s ="" ; + +return fprintf (fp,"%s: %s:%d\n" , s, event->comm.comm, event->comm.tid); } int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
tools/perf/util/evsel.c +2 -1
@@ -960,6 +960,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) ret +=PRINT_ATTR2 (exclude_user, exclude_kernel); ret +=PRINT_ATTR2 (exclude_hv, exclude_idle); ret +=PRINT_ATTR2 (mmap, comm); + ret +=PRINT_ATTR2 (mmap2, comm_exec); ret +=PRINT_ATTR2 (freq, inherit_stat); ret +=PRINT_ATTR2 (enable_on_exec, task); ret +=PRINT_ATTR2 (watermark, precise_ip);
@@ -967,7 +968,6 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) ret +=PRINT_ATTR2 (exclude_host, exclude_guest); ret +=PRINT_ATTR2N ("excl.callchain_kern" , exclude_callchain_kernel,"excl.callchain_user" , exclude_callchain_user); - ret +=PRINT_ATTR_U32 (mmap2); ret +=PRINT_ATTR_U32 (wakeup_events); ret +=PRINT_ATTR_U32 (wakeup_watermark);
@@ -1940,6 +1940,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,if_print (mmap);if_print (mmap2);if_print (comm); +if_print (comm_exec);if_print (freq);if_print (inherit_stat);if_print (enable_on_exec);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/33 perf record: Select comm_exec flag if supported
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
The comm_exec flag on the attribute can later be found in the perf.data file allowing a tool to know in advance if the captured data has the flag.
--- tools/perf/util/record.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
tools/perf/util/record.c +17 -1
@@ -69,15 +69,26 @@ static void perf_probe_sample_identifier(struct perf_evsel *evsel) evsel->attr.sample_type |=PERF_SAMPLE_IDENTIFIER ; } +static void perf_probe_comm_exec (struct perf_evsel *evsel) +{ + evsel->attr.comm_exec =1 ; +} +bool perf_can_sample_identifier (void ) {return perf_probe_api (perf_probe_sample_identifier); } +static bool perf_can_comm_exec (void ) +{ +return perf_probe_api (perf_probe_comm_exec); +} +void perf_evlist__config (struct perf_evlist *evlist,struct record_opts *opts) {struct perf_evsel *evsel;bool use_sample_identifier = false; +bool use_comm_exec;/* * Set the evsel leader links before we configure attributes,
@@ -89,8 +100,13 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)if (evlist->cpus->map[0 ] <0 ) opts->no_inherit = true; -evlist__for_each (evlist, evsel) + use_comm_exec =perf_can_comm_exec (); + +evlist__for_each (evlist, evsel) {perf_evsel__config (evsel, opts); +if (!evsel->idx && use_comm_exec) + evsel->attr.comm_exec =1 ; + }if (evlist->nr_entries >1 ) {struct perf_evsel *first =perf_evlist__first (evlist);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 11/33 perf tools: Fix missing kernel map load
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
thread__find_addr_map() falls back to trying the kernel maps if the address is negative and is not found in userspace maps. As commented in the code, the kernel maps must be "loaded" before use. This patch ensures that happens under the fallback condition also.
--- tools/perf/util/event.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/event.c +1 -0
@@ -788,6 +788,7 @@ try_again: cpumode == PERF_RECORD_MISC_USER && machine && mg != &machine->kmaps) { mg = &machine->kmaps; + load_map = true; goto try_again; } }else {
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 12/33 perf symbols: Fix missing GNU IFUNC symbols
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Symbols of type STT_GNU_IFUNC are functions so accept them as such.
--- tools/perf/util/symbol-elf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/symbol-elf.c +2 -1
@@ -49,7 +49,8 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)static inline int elf_sym__is_function (const GElf_Sym *sym) { -return elf_sym__type (sym) ==STT_FUNC && +return (elf_sym__type (sym) ==STT_FUNC || +elf_sym__type (sym) ==STT_GNU_IFUNC ) && sym->st_name !=0 && sym->st_shndx !=SHN_UNDEF ; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 13/33 perf inject: Fix build id injection
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Build Ids won't be injected unless the build id feature flag is set.
--- tools/perf/builtin-inject.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/builtin-inject.c +3 -0
@@ -389,6 +389,9 @@ static int __cmd_inject(struct perf_inject *inject) ret =perf_session__process_events (session, &inject->tool);if (!file_out->is_pipe) { +if (inject->build_ids) +perf_header__set_feat (&session->header, +HEADER_BUILD_ID ); session->header.data_size = inject->bytes_written;perf_session__write_header (session, session->evlist, file_out->fd, true); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 14/33 perf callchain: Fix appending a callchain from a previous sample
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
hist_entry__append_callchain() must check if the sample has a callcahin or it will append the callchain from a previous sample.
--- tools/perf/util/callchain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/callchain.c +1 -1
@@ -626,7 +626,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parentint hist_entry__append_callchain (struct hist_entry *he,struct perf_sample *sample) { -if (!symbol_conf.use_callchain) +if (!symbol_conf.use_callchain || sample->callchain ==NULL )return 0 ;return callchain_append (he->callchain, &callchain_cursor, sample->period); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 15/33 perf buildid-cache: Apply force option to copying kcore
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Currently a copy of kcore is not made if there is one already with the same modules at the same addresses.
Change this to make a copy anyway if the force (-f) option is also used.
--- tools/perf/builtin-buildid-cache.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/perf/builtin-buildid-cache.c +5 -3
@@ -125,7 +125,8 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,return ret; } -static int build_id_cache__add_kcore (const char *filename,const char *debugdir) +static int build_id_cache__add_kcore (const char *filename,const char *debugdir, +bool force) {char dir[32 ], sbuildid[BUILD_ID_SIZE *2 +1 ];char from_dir[PATH_MAX ], to_dir[PATH_MAX ];
@@ -144,7 +145,8 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir)scnprintf (to_dir,sizeof (to_dir),"%s/[kernel.kcore]/%s" , debugdir, sbuildid); -if (!build_id_cache__kcore_existing (from_dir, to_dir,sizeof (to_dir))) { +if (!force && + !build_id_cache__kcore_existing (from_dir, to_dir,sizeof (to_dir))) {pr_debug ("same kcore found in %s\n" , to_dir);return 0 ; }
@@ -389,7 +391,7 @@ int cmd_buildid_cache(int argc, const char **argv, }if (kcore_filename && -build_id_cache__add_kcore (kcore_filename, debugdir)) +build_id_cache__add_kcore (kcore_filename, debugdir, force))pr_warning ("Couldn't add %s\n" , kcore_filename);return ret;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 16/33 perf symbols: Record whether a dso is 64-bit
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Add a flag to 'struct dso' to record if the dso is 64-bit or not. Update the flag when reading the ELF.
This is needed for instruction decoding. For example, x86 instruction decoding depends on whether or not the 64-bit instruction set is used.
--- tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 1 + tools/perf/util/symbol-elf.c | 3 +++ tools/perf/util/symbol-minimal.c | 22 ++++++++++++++++++++++ tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 1 + 6 files changed, 29 insertions(+)
tools/perf/util/dso.c +1 -0
@@ -703,6 +703,7 @@ struct dso *dso__new(const char *name) dso->data.fd =-1 ; dso->symtab_type =DSO_BINARY_TYPE__NOT_FOUND ; dso->binary_type =DSO_BINARY_TYPE__NOT_FOUND ; + dso->is_64_bit = (sizeof (void *) ==8 ); dso->loaded =0 ; dso->rel =0 ; dso->sorted_by_name =0 ;
tools/perf/util/dso.h +1 -0
@@ -90,6 +90,7 @@ struct dso { u8 annotate_warned:1; u8 short_name_allocated:1; u8 long_name_allocated:1; + u8 is_64_bit:1;u8 sorted_by_name;u8 loaded;u8 rel;
tools/perf/util/symbol-elf.c +3 -0
@@ -599,6 +599,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, goto out_elf_end; } + ss->is_64_bit = (gelf_getclass (elf) ==ELFCLASS64 ); + ss->symtab =elf_section_by_name (elf, &ehdr, &ss->symshdr,".symtab" ,NULL );if (ss->symshdr.sh_type !=SHT_SYMTAB )
@@ -699,6 +701,7 @@ int dso__load_sym(struct dso *dso, struct map *map,bool remap_kernel = false, adjust_kernel_syms = false; dso->symtab_type = syms_ss->type; + dso->is_64_bit = syms_ss->is_64_bit; dso->rel = syms_ss->ehdr.e_type ==ET_REL ;/*
tools/perf/util/symbol-minimal.c +22 -0
@@ -288,6 +288,23 @@ int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,return 0 ; } +static int fd__is_64_bit (int fd) +{ +u8 e_ident[EI_NIDENT ]; + +if (lseek (fd,0 ,SEEK_SET )) +return -1 ; + +if (readn (fd, e_ident,sizeof (e_ident)) !=sizeof (e_ident)) +return -1 ; + +if (memcmp (e_ident,ELFMAG ,SELFMAG ) || + e_ident[EI_VERSION ] !=EV_CURRENT ) +return -1 ; + +return e_ident[EI_CLASS ] ==ELFCLASS64 ; +} + int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, struct symsrc *ss, struct symsrc *runtime_ss __maybe_unused,
@@ -295,6 +312,11 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, int kmodule __maybe_unused) {unsigned char *build_id[BUILD_ID_SIZE ]; +int ret; + + ret =fd__is_64_bit (ss->fd); +if (ret >=0 ) + dso->is_64_bit = ret;if (filename__read_build_id (ss->name, build_id,BUILD_ID_SIZE ) >0 ) {dso__set_build_id (dso, build_id);
tools/perf/util/symbol.c +1 -0
@@ -1065,6 +1065,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, &is_64_bit);if (err) goto out_err; + dso->is_64_bit = is_64_bit;if (list_empty (&md.maps)) { err = -EINVAL ;
tools/perf/util/symbol.h +1 -0
@@ -216,6 +216,7 @@ struct symsrc {GElf_Shdr dynshdr;bool adjust_symbols; +bool is_64_bit;#endif };
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 17/33 perf symbols: Do not attempt to read data from kallsyms
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Record kallsyms binary type so that tools will not attempt to read binary data from it.
--- tools/perf/util/symbol.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/symbol.c +2 -0
@@ -1664,6 +1664,7 @@ do_kallsyms:free (kallsyms_allocated_filename);if (err >0 && !dso__is_kcore (dso)) { + dso->binary_type =DSO_BINARY_TYPE__KALLSYMS ;dso__set_long_name (dso,"[kernel.kallsyms]" , false);map__fixup_start (map);map__fixup_end (map);
@@ -1711,6 +1712,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,if (err >0 )pr_debug ("Using %s for symbols\n" , kallsyms_filename);if (err >0 && !dso__is_kcore (dso)) { + dso->binary_type =DSO_BINARY_TYPE__GUEST_KALLSYMS ;machine__mmap_name (machine, path,sizeof (path));dso__set_long_name (dso,strdup (path), true);map__fixup_start (map);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 18/33 perf symbols: Add ability to iterate over a dso's symbols
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Expose dso__first_symbol() and dso__next_symbol() to make it possible to iterate over a dso's symbols.
--- tools/perf/util/symbol.c | 17 ++++++++++++++++- tools/perf/util/symbol.h | 3 +++ 2 files changed, 19 insertions(+), 1 deletion(-)
tools/perf/util/symbol.c +16 -1
@@ -342,6 +342,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)return NULL ; } +static struct symbol *symbols__next (struct symbol *sym) +{ +struct rb_node *n =rb_next (&sym->rb_node); + +if (n) + return rb_entry(n, struct symbol, rb_node); + +return NULL ; +} +struct symbol_name_rb_node {struct rb_node rb_node;struct symbol sym;
@@ -412,11 +422,16 @@ struct symbol *dso__find_symbol(struct dso *dso,return symbols__find (&dso->symbols[type], addr); } -static struct symbol *dso__first_symbol (struct dso *dso,enum map_type type) +struct symbol *dso__first_symbol (struct dso *dso,enum map_type type) {return symbols__first (&dso->symbols[type]); } +struct symbol *dso__next_symbol (struct symbol *sym) +{ +return symbols__next (sym); +} +struct symbol *dso__find_symbol_by_name (struct dso *dso,enum map_type type,const char *name) {
tools/perf/util/symbol.h +3 -0
@@ -240,6 +240,9 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,struct symbol *dso__find_symbol_by_name (struct dso *dso,enum map_type type,const char *name); +struct symbol *dso__first_symbol (struct dso *dso,enum map_type type); +struct symbol *dso__next_symbol (struct symbol *sym); +int filename__read_build_id (const char *filename,void *bf,size_t size);int sysfs__read_build_id (const char *filename,void *bf,size_t size); int modules__parse(const char *filename, void *arg,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 19/33 perf session: Flag if the event stream is entirely in memory
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Flag if the event stream is a file that has been mmapped in one go.
This is useful, for example, if a tool needs to keep an event for later reference. If the new flag is set, a pointer to the event can be retained, otherwise the event must be copied.
--- tools/perf/util/session.c | 9 ++++++++- tools/perf/util/session.h | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-)
tools/perf/util/session.c +8 -1
@@ -1297,8 +1297,10 @@ int __perf_session__process_events(struct perf_session *session,ui_progress__init (&prog, file_size,"Processing events..." ); mmap_size =MMAP_SIZE ; -if (mmap_size > file_size) +if (mmap_size > file_size) { mmap_size = file_size; + session->one_mmap = true; + }memset (mmaps,0 ,sizeof (mmaps));
@@ -1320,6 +1322,10 @@ remap: mmaps[map_idx] = buf; map_idx = (map_idx +1 ) & (ARRAY_SIZE (mmaps) -1 ); file_pos = file_offset + head; +if (session->one_mmap) { + session->one_mmap_addr = buf; + session->one_mmap_offset = file_offset; + } more: event =fetch_mmaped_event (session, head, mmap_size, buf);
@@ -1365,6 +1371,7 @@ out_err:ui_progress__finish ();perf_session__warn_about_errors (session, tool);perf_session_free_sample_buffers (session); + session->one_mmap = false;return err; }
tools/perf/util/session.h +3 -0
@@ -36,6 +36,9 @@ struct perf_session {struct trace_event tevent;struct events_stats stats;bool repipe; +bool one_mmap; +void *one_mmap_addr; +u64 one_mmap_offset;struct ordered_samples ordered_samples;struct perf_data_file *file; };
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 20/33 perf evlist: Pass mmap parameters in a struct
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
In preparation for adding more mmap parameters, pass existing parameters in a struct.
--- tools/perf/util/evlist.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-)
tools/perf/util/evlist.c +26 -20
@@ -606,12 +606,17 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)return evlist->mmap !=NULL ?0 : -ENOMEM ; } -static int __perf_evlist__mmap (struct perf_evlist *evlist, -int idx,int prot,int mask,int fd) +struct mmap_params { +int prot; +int mask; +}; + +static int __perf_evlist__mmap (struct perf_evlist *evlist,int idx, +struct mmap_params *mp,int fd) { evlist->mmap[idx].prev =0 ; - evlist->mmap[idx].mask = mask; - evlist->mmap[idx].base =mmap (NULL , evlist->mmap_len, prot, + evlist->mmap[idx].mask = mp->mask; + evlist->mmap[idx].base =mmap (NULL , evlist->mmap_len, mp->prot,MAP_SHARED , fd,0 );if (evlist->mmap[idx].base ==MAP_FAILED ) { pr_debug2("failed to mmap perf event ring buffer, error %d\n",
@@ -625,8 +630,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, }static int perf_evlist__mmap_per_evsel (struct perf_evlist *evlist,int idx, -int prot,int mask,int cpu,int thread, -int *output) +struct mmap_params *mp,int cpu, +int thread,int *output) {struct perf_evsel *evsel;
@@ -635,8 +640,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,if (*output ==-1 ) { *output = fd; -if (__perf_evlist__mmap (evlist, idx, prot, mask, - *output) <0 ) +if (__perf_evlist__mmap (evlist, idx, mp, *output) <0 )return -1 ; }else {if (ioctl (fd,PERF_EVENT_IOC_SET_OUTPUT , *output) !=0 )
@@ -651,8 +655,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,return 0 ; } -static int perf_evlist__mmap_per_cpu (struct perf_evlist *evlist,int prot, -int mask) +static int perf_evlist__mmap_per_cpu (struct perf_evlist *evlist, +struct mmap_params *mp) {int cpu, thread;int nr_cpus =cpu_map__nr (evlist->cpus);
@@ -663,8 +667,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,int output =-1 ;for (thread =0 ; thread < nr_threads; thread++) { -if (perf_evlist__mmap_per_evsel (evlist, cpu, prot, mask, - cpu, thread, &output)) +if (perf_evlist__mmap_per_evsel (evlist, cpu, mp, cpu, + thread, &output)) goto out_unmap; } }
@@ -677,8 +681,8 @@ out_unmap:return -1 ; } -static int perf_evlist__mmap_per_thread (struct perf_evlist *evlist,int prot, -int mask) +static int perf_evlist__mmap_per_thread (struct perf_evlist *evlist, +struct mmap_params *mp) {int thread;int nr_threads =thread_map__nr (evlist->threads);
@@ -687,8 +691,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,for (thread =0 ; thread < nr_threads; thread++) {int output =-1 ; -if (perf_evlist__mmap_per_evsel (evlist, thread, prot, mask,0 , - thread, &output)) +if (perf_evlist__mmap_per_evsel (evlist, thread, mp,0 , thread, + &output)) goto out_unmap; }
@@ -793,7 +797,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;const struct thread_map *threads = evlist->threads; -int prot =PROT_READ | (overwrite ?0 :PROT_WRITE ), mask; +struct mmap_params mp = { + .prot =PROT_READ | (overwrite ?0 :PROT_WRITE ), + };if (evlist->mmap ==NULL &&perf_evlist__alloc_mmap (evlist) <0 )return -ENOMEM ;
@@ -804,7 +810,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, evlist->overwrite = overwrite; evlist->mmap_len =perf_evlist__mmap_size (pages);pr_debug ("mmap size %zuB\n" , evlist->mmap_len); - mask = evlist->mmap_len - page_size -1 ; + mp.mask = evlist->mmap_len - page_size -1 ;evlist__for_each (evlist, evsel) { if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -814,9 +820,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, }if (cpu_map__empty (cpus)) -return perf_evlist__mmap_per_thread (evlist, prot, mask); +return perf_evlist__mmap_per_thread (evlist, &mp); -return perf_evlist__mmap_per_cpu (evlist, prot, mask); +return perf_evlist__mmap_per_cpu (evlist, &mp); }int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 21/33 perf tools: Add feature test for __sync_val_compare_and_swap
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Add a feature test for __sync_val_compare_and_swap() and __sync_bool_compare_and_swap()
--- tools/perf/config/Makefile | 6 ++++++ tools/perf/config/feature-checks/Makefile | 4 ++++ tools/perf/config/feature-checks/test-all.c | 5 +++++ .../config/feature-checks/test-sync-compare-and-swap.c | 14 ++++++++++++++ 4 files changed, 29 insertions(+) create mode 100644 tools/perf/config/feature-checks/test-sync-compare-and-swap.c
tools/perf/config/Makefile +6 -0
@@ -164,6 +164,7 @@ CORE_FEATURE_TESTS = \ backtrace \ dwarf \ fortify-source \ + sync-compare-and-swap \ glibc \ gtk2 \ gtk2-infobar \
@@ -199,6 +200,7 @@ LIB_FEATURE_TESTS = \ VF_FEATURE_TESTS = \ backtrace \ fortify-source \ + sync-compare-and-swap \ gtk2-infobar \ libelf-getphdrnum \ libelf-mmap \
@@ -272,6 +274,10 @@ CFLAGS += -I$(LIB_INCLUDE) CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE +ifeq ($(feature-sync-compare-and-swap), 1) + CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT +endif + ifndef NO_BIONIC $(call feature_check,bionic) ifeq ($(feature-bionic), 1)
tools/perf/config/feature-checks/Makefile +4 -0
@@ -5,6 +5,7 @@ FILES= \ test-bionic.bin \ test-dwarf.bin \ test-fortify-source.bin \ + test-sync-compare-and-swap.bin \ test-glibc.bin \ test-gtk2.bin \ test-gtk2-infobar.bin \
@@ -141,6 +142,9 @@ test-timerfd.bin: test-libdw-dwarf-unwind.bin: $(BUILD) +test-sync-compare-and-swap.bin: + $(BUILD) -Werror + -include *.d ###############################
tools/perf/config/feature-checks/test-all.c +5 -0
@@ -89,6 +89,10 @@# include "test-libdw-dwarf-unwind.c" #undef main +#define main main_test_sync_compare_and_swap +# include "test-sync-compare-and-swap.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -111,6 +115,7 @@ int main(int argc, char *argv[])main_test_timerfd ();main_test_stackprotector_all ();main_test_libdw_dwarf_unwind (); +main_test_sync_compare_and_swap (argc, argv);return 0 ; }
tools/perf/config/feature-checks/test-sync-compare-and-swap.c new file +14 -0
@@ -0,0 +1,14 @@ +#include <stdint.h> + +volatile uint64_t x; + +int main (int argc,char *argv[]) +{ +uint64_t old, new = argc; + + argv = argv; +do { + old =__sync_val_compare_and_swap (&x,0 ,0 ); + }while (!__sync_bool_compare_and_swap (&x, old, new)); +return old == new; +}
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 22/33 perf tools: Add option macro OPT_CALLBACK_OPTARG
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Add an option macro that is the same as OPT_CALLBACK except that the argument is optional and it is possible to associate additional data with it.
--- tools/perf/util/parse-options.h | 5 +++++ 1 file changed, 5 insertions(+)
tools/perf/util/parse-options.h +5 -0
@@ -98,6 +98,7 @@ struct option {parse_opt_cb *callback;intptr_t defval;bool *set; +void *data; };#define check_vtype (v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
@@ -131,6 +132,10 @@ struct option { { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} +#define OPT_CALLBACK_OPTARG (s, l, v, d, a, h, f) \ + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ + .value = (v), (a), .help = (h), .callback = (f), \ + .flags = PARSE_OPT_OPTARG, .data = (d) }/* parse_options() will filter out the processed options and leave the * non-option argments in argv[].
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 23/33 perf evsel: Add 'no_aux_samples' option
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Add an option to prevent additional samples being added to a selected event by perf_evsel__config().
This is needed when using the sched_switch tracepoint to follow object code execution. Since sched_switch will be used only for switch information, additional sampling is wasteful.
--- tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-)
tools/perf/util/evsel.c +3 -3
@@ -623,7 +623,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) attr->mmap_data = track; } -if (opts->call_graph_enabled) +if (opts->call_graph_enabled && !evsel->no_aux_samples)perf_evsel__config_callgraph (evsel, opts);if (target__has_cpu (&opts->target))
@@ -637,7 +637,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) target__has_cpu(&opts->target) || per_cpu))perf_evsel__set_sample_bit (evsel,TIME ); -if (opts->raw_samples) { +if (opts->raw_samples && !evsel->no_aux_samples) {perf_evsel__set_sample_bit (evsel,TIME );perf_evsel__set_sample_bit (evsel,RAW );perf_evsel__set_sample_bit (evsel,CPU );
@@ -650,7 +650,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) attr->watermark =0 ; attr->wakeup_events =1 ; } -if (opts->branch_stack) { +if (opts->branch_stack && !evsel->no_aux_samples) {perf_evsel__set_sample_bit (evsel,BRANCH_STACK ); attr->branch_sample_type = opts->branch_stack; }
tools/perf/util/evsel.h +1 -0
@@ -83,6 +83,7 @@ struct perf_evsel {int is_pos;bool supported;bool needs_swap; +bool no_aux_samples;/* parse modifier helper */ int exclude_GH;int nr_members;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 24/33 perf evsel: Add 'immediate' option
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Add an option to cause a selected event to be enabled immediately when configured by perf_evsel__config().
This is needed when using the sched_switch tracepoint to follow object code execution. By having sched_switch enabled immediately the first sched_switch event precedes the start of other tracing.
--- tools/perf/util/evsel.c | 5 +++++ tools/perf/util/evsel.h | 1 + 2 files changed, 6 insertions(+)
tools/perf/util/evsel.c +5 -0
@@ -681,6 +681,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)if (target__none (&opts->target) &&perf_evsel__is_group_leader (evsel) && !opts->initial_delay) attr->enable_on_exec =1 ; + +if (evsel->immediate) { + attr->disabled =0 ; + attr->enable_on_exec =0 ; + } }int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads)
tools/perf/util/evsel.h +1 -0
@@ -84,6 +84,7 @@ struct perf_evsel {bool supported;bool needs_swap;bool no_aux_samples; +bool immediate;/* parse modifier helper */ int exclude_GH;int nr_members;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 25/33 perf machine: Fix map groups of threads with unknown pids
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Events like sched_switch do not provide a pid (tgid) which can result in threads with an unknown pid. If the pid is later discovered, join the map groups.
Note the thread's map groups should be empty because they are populated by MMAP events which do provide the pid and tid.
--- tools/perf/util/machine.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- tools/perf/util/map.c | 14 ++++++++++++ tools/perf/util/map.h | 1 + 3 files changed, 66 insertions(+), 6 deletions(-)
tools/perf/util/machine.c +51 -6
@@ -272,6 +272,52 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)return ; } +static void machine__update_thread_pid (struct machine *machine, +struct thread *th,pid_t pid) +{ +struct thread *leader; + +if (pid == th->pid_ || pid ==-1 || th->pid_ !=-1 ) +return ; + + th->pid_ = pid; + +if (th->pid_ == th->tid) +return ; + + leader =machine__findnew_thread (machine, th->pid_, th->pid_); +if (!leader) + goto out_err; + +if (!leader->mg) + leader->mg =map_groups__new (); + +if (!leader->mg) + goto out_err; + +if (th->mg == leader->mg) +return ; + +if (th->mg) { +/* +* Maps are created from MMAP events which provide the pid and +* tid. Consequently there never should be any maps on a thread +* with an unknown pid. Just print an error if there are. +*/ +if (!map_groups__empty (th->mg)) +pr_err ("Discarding thread maps for %d:%d\n" , + th->pid_, th->tid); +map_groups__delete (th->mg); + } + + th->mg =map_groups__get (leader->mg); + +return ; + +out_err: +pr_err ("Failed to join map groups for %d:%d\n" , th->pid_, th->tid); +} +static struct thread *__machine__findnew_thread (struct machine *machine,pid_t pid,pid_t tid,bool create)
@@ -285,10 +331,10 @@ static struct thread *__machine__findnew_thread(struct machine *machine,* so most of the time we dont have to look up * the full rbtree: */ -if (machine->last_match && machine->last_match->tid == tid) { -if (pid !=-1 && pid != machine->last_match->pid_) - machine->last_match->pid_ = pid; -return machine->last_match; + th = machine->last_match; +if (th && th->tid == tid) { +machine__update_thread_pid (machine, th, pid); +return th; }while (*p !=NULL ) {
@@ -297,8 +343,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,if (th->tid == tid) { machine->last_match = th; -if (pid !=-1 && pid != th->pid_) - th->pid_ = pid; +machine__update_thread_pid (machine, th, pid);return th; }
tools/perf/util/map.c +14 -0
@@ -454,6 +454,20 @@ void map_groups__exit(struct map_groups *mg) } } +bool map_groups__empty (struct map_groups *mg) +{ +int i; + +for (i =0 ; i <MAP__NR_TYPES ; ++i) { +if (maps__first (&mg->maps[i])) +return false; +if (!list_empty (&mg->removed_maps[i])) +return false; + } + +return true; +} +struct map_groups *map_groups__new (void ) {struct map_groups *mg =malloc (sizeof (*mg));
tools/perf/util/map.h +1 -0
@@ -66,6 +66,7 @@ struct map_groups {struct map_groups *map_groups__new (void );void map_groups__delete (struct map_groups *mg); +bool map_groups__empty (struct map_groups *mg);static inline struct map_groups *map_groups__get (struct map_groups *mg) {
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 26/33 perf thread: Allow deletion of a thread with no map groups
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
It needs to be possible to call thread__delete() on a thread with no map groups.
This is needed for a subsequent patch which deletes a thread on the error path before map groups have been attached.
--- tools/perf/util/thread.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/thread.c +4 -2
@@ -60,8 +60,10 @@ void thread__delete(struct thread *thread) {struct comm *comm, *tmp; -map_groups__put (thread->mg); - thread->mg =NULL ; +if (thread->mg) { +map_groups__put (thread->mg); + thread->mg =NULL ; + }list_for_each_entry_safe (comm, tmp, &thread->comm_list, list) {list_del (&comm->list);comm__free (comm);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 27/33 perf machine: Fix leak of 'struct thread' on error path
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
__machine__findnew_thread() creates a 'struct thread' but does not free it on the error path. Fix it.
--- tools/perf/util/machine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/machine.c +3 -1
@@ -370,8 +370,10 @@ static struct thread *__machine__findnew_thread(struct machine *machine,* within thread__init_map_groups to find the thread * leader and that would screwed the rb tree. */ -if (thread__init_map_groups (th, machine)) +if (thread__init_map_groups (th, machine)) { +thread__delete (th);return NULL ; + } }return th;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 28/33 perf tools: Remove verbose from functions prototypes
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
And use verbose as an global object in following functions:
__map_groups__fprintf_maps __map_groups__fprintf_removed_maps map_groups__fprintf_maps map_groups__fprintf
Also making map_groups__fprintf_maps static.
--- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/map.c | 24 ++++++++++++------------ tools/perf/util/map.h | 9 ++++----- tools/perf/util/thread.c | 4 ++-- 4 files changed, 19 insertions(+), 20 deletions(-)
tools/perf/ui/stdio/hist.c +1 -1
@@ -479,7 +479,7 @@ print_entries:if (h->ms.map ==NULL && verbose >1 ) {__map_groups__fprintf_maps (h->thread->mg, -MAP__FUNCTION , verbose, fp); +MAP__FUNCTION , fp);fprintf (fp,"%.10s end\n" , graph_dotted_line); } }
tools/perf/util/map.c +12 -12
@@ -12,6 +12,7 @@#include "vdso.h" #include "build-id.h" #include "util.h" +#include "debug.h" #include <linux/string.h> const char *map_type__name[MAP__NR_TYPES ] = {
@@ -568,8 +569,8 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)return ams->sym ?0 :-1 ; } -size_t __map_groups__fprintf_maps (struct map_groups *mg, -enum map_type type,int verbose,FILE *fp) +size_t __map_groups__fprintf_maps (struct map_groups *mg,enum map_type type, +FILE *fp) {size_t printed =fprintf (fp,"%s:\n" , map_type__name[type]);struct rb_node *nd;
@@ -587,17 +588,16 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg,return printed; } -size_t map_groups__fprintf_maps (struct map_groups *mg,int verbose,FILE *fp) +static size_t map_groups__fprintf_maps (struct map_groups *mg,FILE *fp) {size_t printed =0 , i;for (i =0 ; i <MAP__NR_TYPES ; ++i) - printed +=__map_groups__fprintf_maps (mg, i, verbose, fp); + printed +=__map_groups__fprintf_maps (mg, i, fp);return printed; }static size_t __map_groups__fprintf_removed_maps (struct map_groups *mg, -enum map_type type, -int verbose,FILE *fp) +enum map_type type,FILE *fp) {struct map *pos;size_t printed =0 ;
@@ -614,23 +614,23 @@ static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, }static size_t map_groups__fprintf_removed_maps (struct map_groups *mg, -int verbose,FILE *fp) +FILE *fp) {size_t printed =0 , i;for (i =0 ; i <MAP__NR_TYPES ; ++i) - printed +=__map_groups__fprintf_removed_maps (mg, i, verbose, fp); + printed +=__map_groups__fprintf_removed_maps (mg, i, fp);return printed; } -size_t map_groups__fprintf (struct map_groups *mg,int verbose,FILE *fp) +size_t map_groups__fprintf (struct map_groups *mg,FILE *fp) { -size_t printed =map_groups__fprintf_maps (mg, verbose, fp); +size_t printed =map_groups__fprintf_maps (mg, fp); printed +=fprintf (fp,"Removed maps:\n" ); -return printed +map_groups__fprintf_removed_maps (mg, verbose, fp); +return printed +map_groups__fprintf_removed_maps (mg, fp); }int map_groups__fixup_overlappings (struct map_groups *mg,struct map *map, -int verbose,FILE *fp) +FILE *fp) {struct rb_root *root = &mg->maps[map->type];struct rb_node *next =rb_first (root);
tools/perf/util/map.h +4 -5
@@ -142,8 +142,8 @@ void map__fixup_end(struct map *map);void map__reloc_vmlinux (struct map *map); -size_t __map_groups__fprintf_maps (struct map_groups *mg, -enum map_type type,int verbose,FILE *fp); +size_t __map_groups__fprintf_maps (struct map_groups *mg,enum map_type type, +FILE *fp);void maps__insert (struct rb_root *maps,struct map *map);void maps__remove (struct rb_root *maps,struct map *map);struct map *maps__find (struct rb_root *maps,u64 addr);
@@ -153,8 +153,7 @@ void map_groups__init(struct map_groups *mg);void map_groups__exit (struct map_groups *mg);int map_groups__clone (struct map_groups *mg,struct map_groups *parent,enum map_type type); -size_t map_groups__fprintf (struct map_groups *mg,int verbose,FILE *fp); -size_t map_groups__fprintf_maps (struct map_groups *mg,int verbose,FILE *fp); +size_t map_groups__fprintf (struct map_groups *mg,FILE *fp);int maps__set_kallsyms_ref_reloc_sym (struct map **maps,const char *symbol_name,u64 addr);
@@ -211,7 +210,7 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *mg, }int map_groups__fixup_overlappings (struct map_groups *mg,struct map *map, -int verbose,FILE *fp); +FILE *fp);struct map *map_groups__find_by_name (struct map_groups *mg,enum map_type type,const char *name);
tools/perf/util/thread.c +2 -2
@@ -129,12 +129,12 @@ int thread__comm_len(struct thread *thread)size_t thread__fprintf (struct thread *thread,FILE *fp) {return fprintf (fp,"Thread %d %s\n" , thread->tid,thread__comm_str (thread)) + -map_groups__fprintf (thread->mg, verbose, fp); +map_groups__fprintf (thread->mg, fp); }void thread__insert_map (struct thread *thread,struct map *map) { -map_groups__fixup_overlappings (thread->mg, map, verbose, stderr); +map_groups__fixup_overlappings (thread->mg, map, stderr);map_groups__insert (thread->mg, map); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 29/33 perf tools: Move pr_* debug macros into debug object
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Moving pr_* debug macros to have it with in same object as debug variables, becase we will change them to use verbose variable in next patch.
--- tools/perf/arch/x86/tests/dwarf-unwind.c | 1 + tools/perf/arch/x86/util/unwind-libunwind.c | 1 + tools/perf/builtin-evlist.c | 1 + tools/perf/builtin-help.c | 1 + tools/perf/builtin-timechart.c | 1 + tools/perf/tests/dso-data.c | 1 + tools/perf/tests/evsel-roundtrip-name.c | 1 + tools/perf/tests/evsel-tp-sched.c | 1 + tools/perf/tests/open-syscall-tp-fields.c | 1 + tools/perf/tests/parse-events.c | 1 + tools/perf/tests/parse-no-sample-id-all.c | 1 + tools/perf/tests/sample-parsing.c | 1 + tools/perf/tests/thread-mg-share.c | 1 + tools/perf/util/data.c | 1 + tools/perf/util/debug.h | 20 ++++++++++++++++++++ tools/perf/util/include/linux/kernel.h | 21 --------------------- tools/perf/util/pstack.c | 1 + .../perf/util/scripting-engines/trace-event-perl.c | 1 + .../util/scripting-engines/trace-event-python.c | 1 + tools/perf/util/trace-event-info.c | 1 + tools/perf/util/trace-event-read.c | 1 + tools/perf/util/unwind-libdw.c | 1 + tools/perf/util/unwind-libunwind.c | 1 + tools/perf/util/util.c | 1 + tools/perf/util/vdso.c | 1 + 25 files changed, 43 insertions(+), 21 deletions(-)
tools/perf/arch/x86/tests/dwarf-unwind.c +1 -0
@@ -3,6 +3,7 @@#include "thread.h" #include "map.h" #include "event.h" +#include "debug.h" #include "tests/tests.h" #define STACK_SIZE 8192
tools/perf/arch/x86/util/unwind-libunwind.c +1 -0
@@ -3,6 +3,7 @@#include <libunwind.h> #include "perf_regs.h" #include "../../util/unwind.h" +#include "../../util/debug.h" #ifdef HAVE_ARCH_X86_64_SUPPORT int libunwind__arch_reg_id (int regnum)
tools/perf/builtin-evlist.c +1 -0
@@ -15,6 +15,7 @@#include "util/parse-options.h" #include "util/session.h" #include "util/data.h" +#include "util/debug.h" static int __cmd_evlist (const char *file_name,struct perf_attr_details *details) {
tools/perf/builtin-help.c +1 -0
@@ -11,6 +11,7 @@#include "util/parse-options.h" #include "util/run-command.h" #include "util/help.h" +#include "util/debug.h" static struct man_viewer_list { struct man_viewer_list *next;
tools/perf/builtin-timechart.c +1 -0
@@ -37,6 +37,7 @@#include "util/svghelper.h" #include "util/tool.h" #include "util/data.h" +#include "util/debug.h" #define SUPPORT_OLD_POWER_EVENTS 1#define PWR_EVENT_EXIT -1
tools/perf/tests/dso-data.c +1 -0
@@ -10,6 +10,7 @@#include "machine.h" #include "symbol.h" #include "tests.h" +#include "debug.h" static char *test_file (int size) {
tools/perf/tests/evsel-roundtrip-name.c +1 -0
@@ -2,6 +2,7 @@#include "evsel.h" #include "parse-events.h" #include "tests.h" +#include "debug.h" static int perf_evsel__roundtrip_cache_name_test (void ) {
tools/perf/tests/evsel-tp-sched.c +1 -0
@@ -1,6 +1,7 @@#include <traceevent/event-parse.h> #include "evsel.h" #include "tests.h" +#include "debug.h" static int perf_evsel__test_field (struct perf_evsel *evsel,const char *name,int size,bool should_be_signed)
tools/perf/tests/open-syscall-tp-fields.c +1 -0
@@ -3,6 +3,7 @@#include "evsel.h" #include "thread_map.h" #include "tests.h" +#include "debug.h" int test__syscall_open_tp_fields (void ) {
tools/perf/tests/parse-events.c +1 -0
@@ -5,6 +5,7 @@#include <api/fs/fs.h> #include <api/fs/debugfs.h> #include "tests.h" +#include "debug.h" #include <linux/hw_breakpoint.h> #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
tools/perf/tests/parse-no-sample-id-all.c +1 -0
@@ -7,6 +7,7 @@#include "evlist.h" #include "header.h" #include "util.h" +#include "debug.h" static int process_event (struct perf_evlist **pevlist,union perf_event *event) {
tools/perf/tests/sample-parsing.c +1 -0
@@ -4,6 +4,7 @@#include "util.h" #include "event.h" #include "evsel.h" +#include "debug.h" #include "tests.h"
tools/perf/tests/thread-mg-share.c +1 -0
@@ -2,6 +2,7 @@#include "machine.h" #include "thread.h" #include "map.h" +#include "debug.h" int test__thread_mg_share (void ) {
tools/perf/util/data.c +1 -0
@@ -7,6 +7,7 @@#include "data.h" #include "util.h" +#include "debug.h" static bool check_pipe (struct perf_data_file *file) {
tools/perf/util/debug.h +20 -0
@@ -11,6 +11,24 @@extern int verbose;extern bool quiet, dump_trace; +#ifndef pr_fmt +#define pr_fmt (fmt) fmt +#endif + +#define pr_err (fmt, ...) \ + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_warning (fmt, ...) \ + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_info (fmt, ...) \ + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_debug (fmt, ...) \ + eprintf(1, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_debugN (n, fmt, ...) \ + eprintf(n, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_debug2 (fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_debug3 (fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) +#define pr_debug4 (fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) +int dump_printf (const char *fmt, ...) __attribute__((format (printf,1 ,2 )));void trace_event (union perf_event *event);
@@ -19,4 +37,6 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));void pr_stat (const char *fmt, ...); +int eprintf (int level,const char *fmt, ...) __attribute__((format (printf,2 ,3 ))); +#endif /* __PERF_DEBUG_H */
tools/perf/util/include/linux/kernel.h +0 -21
@@ -94,27 +94,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)return (i >= ssize) ? (ssize -1 ) : i; } -int eprintf (int level, -const char *fmt, ...) __attribute__((format (printf,2 ,3 ))); - -#ifndef pr_fmt -#define pr_fmt (fmt) fmt -#endif - -#define pr_err (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_warning (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_info (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_debug (fmt, ...) \ - eprintf(1, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_debugN (n, fmt, ...) \ - eprintf(n, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_debug2 (fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_debug3 (fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_debug4 (fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) -/* * This looks more complex than it should be. But we need to * get the type for the ~ right in round_down (it needs to be
tools/perf/util/pstack.c +1 -0
@@ -6,6 +6,7 @@#include "util.h" #include "pstack.h" +#include "debug.h" #include <linux/kernel.h> #include <stdlib.h>
tools/perf/util/scripting-engines/trace-event-perl.c +1 -0
@@ -34,6 +34,7 @@#include "../event.h" #include "../trace-event.h" #include "../evsel.h" +#include "../debug.h" void boot_Perf__Trace__Context(pTHX_ CV *cv); void boot_DynaLoader(pTHX_ CV *cv);
tools/perf/util/scripting-engines/trace-event-python.c +1 -0
@@ -27,6 +27,7 @@#include <errno.h> #include "../../perf.h" +#include "../debug.h" #include "../evsel.h" #include "../util.h" #include "../event.h"
tools/perf/util/trace-event-info.c +1 -0
@@ -40,6 +40,7 @@#include "trace-event.h" #include <api/fs/debugfs.h> #include "evsel.h" +#include "debug.h" #define VERSION "0.5"
tools/perf/util/trace-event-read.c +1 -0
@@ -36,6 +36,7 @@#include "../perf.h" #include "util.h" #include "trace-event.h" +#include "debug.h" static int input_fd;
tools/perf/util/unwind-libdw.c +1 -0
@@ -3,6 +3,7 @@#include <elfutils/libdwfl.h> #include <inttypes.h> #include <errno.h> +#include "debug.h" #include "unwind.h" #include "unwind-libdw.h" #include "machine.h"
tools/perf/util/unwind-libunwind.c +1 -0
@@ -30,6 +30,7 @@#include "unwind.h" #include "symbol.h" #include "util.h" +#include "debug.h" extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
tools/perf/util/util.c +1 -0
@@ -1,5 +1,6 @@#include "../perf.h" #include "util.h" +#include "debug.h" #include <api/fs/fs.h> #include <sys/mman.h> #ifdef HAVE_BACKTRACE_SUPPORT
tools/perf/util/vdso.c +1 -0
@@ -12,6 +12,7 @@#include "util.h" #include "symbol.h" #include "linux/string.h" +#include "debug.h" static bool vdso_found;static char vdso_file[] ="/tmp/perf-vdso.so-XXXXXX" ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 30/33 perf tools: Factor eprintf to allow different debug variables
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
This way we can easily reuse current debug functions for another debug variables other than verbose.
--- tools/perf/util/debug.c | 12 ++++++------ tools/perf/util/debug.h | 12 ++++++------ tools/perf/util/python.c | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-)
tools/perf/util/debug.c +6 -6
@@ -16,11 +16,11 @@int verbose;bool dump_trace = false, quiet = false; -static int _eprintf (int level,const char *fmt,va_list args) +static int _eprintf (int level,int var,const char *fmt,va_list args) {int ret =0 ; -if (verbose >= level) { +if (var >= level) {if (use_browser >=1 )ui_helpline__vshow (fmt, args);else
@@ -30,13 +30,13 @@ static int _eprintf(int level, const char *fmt, va_list args)return ret; } -int eprintf (int level,const char *fmt, ...) +int eprintf (int level,int var,const char *fmt, ...) {va_list args;int ret;va_start (args, fmt); - ret =_eprintf (level, fmt, args); + ret =_eprintf (level, var, fmt, args);va_end (args);return ret;
@@ -51,9 +51,9 @@ void pr_stat(const char *fmt, ...)va_list args;va_start (args, fmt); -_eprintf (1 , fmt, args); +_eprintf (1 , verbose, fmt, args);va_end (args); -eprintf (1 ,"\n" ); +eprintf (1 , verbose,"\n" ); }int dump_printf (const char *fmt, ...)
tools/perf/util/debug.h +6 -6
@@ -16,15 +16,15 @@ extern bool quiet, dump_trace;#endif #define pr_err (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)#define pr_warning (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)#define pr_info (fmt, ...) \ - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)#define pr_debug (fmt, ...) \ - eprintf(1, pr_fmt(fmt), ##__VA_ARGS__) + eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__)#define pr_debugN (n, fmt, ...) \ - eprintf(n, pr_fmt(fmt), ##__VA_ARGS__) + eprintf(n, verbose, pr_fmt(fmt), ##__VA_ARGS__)#define pr_debug2 (fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)#define pr_debug3 (fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)#define pr_debug4 (fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
@@ -37,6 +37,6 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));void pr_stat (const char *fmt, ...); -int eprintf (int level,const char *fmt, ...) __attribute__((format (printf,2 ,3 ))); +int eprintf (int level,int var,const char *fmt, ...) __attribute__((format (printf,3 ,4 )));#endif /* __PERF_DEBUG_H */
tools/perf/util/python.c +2 -2
@@ -14,12 +14,12 @@*/ int verbose; -int eprintf (int level,const char *fmt, ...) +int eprintf (int level,int var,const char *fmt, ...) {va_list args;int ret =0 ; -if (verbose >= level) { +if (var >= level) {va_start (args, fmt); ret =vfprintf (stderr, fmt, args);va_end (args);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 31/33 perf tools: Add --debug optionto set debug variable
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding --debug option as a way to setup debug variables. Starting with support for verbose, more will come.
It's possible to use it now with report command:
$ perf --debug verbose ... $ perf --debug verbose=2 ...
I'll need this support to add separated debug variable for ordered events change in order to separate debug output out of standard verbose stream.
--- tools/perf/Documentation/perf.txt | 10 ++++++++- tools/perf/perf.c | 13 +++++++++++- tools/perf/util/debug.c | 44 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/debug.h | 2 ++ 4 files changed, 67 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf.txt +9 -1
@@ -8,7 +8,15 @@ perf - Performance analysis tools for Linux SYNOPSIS -------- [verse] -'perf' [--version] [--help] COMMAND [ARGS] +'perf' [--version] [--help] [OPTIONS] COMMAND [ARGS] + +OPTIONS +------- +--debug:: + Setup debug variable (just verbose for now) in value + range (0, 10). Use like: + --debug verbose # sets verbose = 1 + --debug verbose=2 # sets verbose = 2 DESCRIPTION -----------
tools/perf/perf.c +12 -1
@@ -13,11 +13,12 @@#include "util/quote.h" #include "util/run-command.h" #include "util/parse-events.h" +#include "util/debug.h" #include <api/fs/debugfs.h> #include <pthread.h> const char perf_usage_string[] = -"perf [--version] [--help] COMMAND [ARGS]" ; +"perf [--version] [--debug variable[=VALUE]] [--help] COMMAND [ARGS]" ;const char perf_more_info_string[] ="See 'perf help COMMAND' for more information on a specific command." ;
@@ -212,6 +213,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)printf ("%s " , p->cmd); }exit (0 ); + }else if (!strcmp (cmd,"--debug" )) { +if (*argc <2 ) { +fprintf (stderr,"No variable specified for --debug.\n" ); +usage (perf_usage_string); + } +if (perf_debug_option ((*argv)[1 ])) +usage (perf_usage_string); + + (*argv)++; + (*argc)--; }else {fprintf (stderr,"Unknown option: %s\n" , cmd);usage (perf_usage_string);
tools/perf/util/debug.c +44 -0
47 lines not on this page · raw message
tools/perf/util/debug.h +2 -0
@@ -39,4 +39,6 @@ void pr_stat(const char *fmt, ...);int eprintf (int level,int var,const char *fmt, ...) __attribute__((format (printf,3 ,4 ))); +int perf_debug_option (const char *str); +#endif /* __PERF_DEBUG_H */
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 32/33 perf tools: Remove needless getopt.h includes
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
We don't use getopt.h interfaces.
--- tools/perf/util/probe-finder.c | 1 - tools/perf/util/trace-event-read.c | 1 - 2 files changed, 2 deletions(-)
tools/perf/util/probe-finder.c +0 -1
@@ -26,7 +26,6 @@#include <errno.h> #include <stdio.h> #include <unistd.h> -#include <getopt.h> #include <stdlib.h> #include <string.h> #include <stdarg.h>
tools/perf/util/trace-event-read.c +0 -1
@@ -22,7 +22,6 @@#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <getopt.h> #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h>
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 33/33 perf tools: Allow TSC conversion on any arch
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
It is possible to record a perf.data file on one architecture and process it on another.
Consequently, TSC conversion functions need to be moved out of the arch directory.
--- tools/perf/Makefile.perf | 2 ++ tools/perf/arch/x86/util/tsc.c | 22 +--------------------- tools/perf/arch/x86/util/tsc.h | 3 --- tools/perf/tests/perf-time-to-tsc.c | 3 +-- tools/perf/util/tsc.c | 25 +++++++++++++++++++++++++ tools/perf/util/tsc.h | 11 +++++++++++ 6 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 tools/perf/util/tsc.c create mode 100644 tools/perf/util/tsc.h
tools/perf/Makefile.perf +2 -0
@@ -295,6 +295,7 @@ LIB_H += util/intlist.h LIB_H += util/perf_regs.h LIB_H += util/unwind.h LIB_H += util/vdso.h +LIB_H += util/tsc.h LIB_H += ui/helpline.h LIB_H += ui/progress.h LIB_H += ui/util.h
@@ -374,6 +375,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o LIB_OBJS += $(OUTPUT)util/record.o LIB_OBJS += $(OUTPUT)util/srcline.o LIB_OBJS += $(OUTPUT)util/data.o +LIB_OBJS += $(OUTPUT)util/tsc.o LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/helpline.o
tools/perf/arch/x86/util/tsc.c +1 -21
@@ -6,29 +6,9 @@#include "../../perf.h" #include <linux/types.h> #include "../../util/debug.h" +#include "../../util/tsc.h" #include "tsc.h" -u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc) -{ -u64 t, quot, rem; - - t = ns - tc->time_zero; - quot = t / tc->time_mult; - rem = t % tc->time_mult; -return (quot << tc->time_shift) + - (rem << tc->time_shift) / tc->time_mult; -} - -u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc) -{ -u64 quot, rem; - - quot = cyc >> tc->time_shift; - rem = cyc & ((1 << tc->time_shift) -1 ); -return tc->time_zero + quot * tc->time_mult + - ((rem * tc->time_mult) >> tc->time_shift); -} -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc) {
tools/perf/arch/x86/util/tsc.h +0 -3
@@ -14,7 +14,4 @@ struct perf_event_mmap_page;int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc); -u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc); -u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc); -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
tools/perf/tests/perf-time-to-tsc.c +1 -2
@@ -8,10 +8,9 @@#include "evsel.h" #include "thread_map.h" #include "cpumap.h" +#include "tsc.h" #include "tests.h" -#include "../arch/x86/util/tsc.h" -#define CHECK__ (x) { \ while ((x) < 0) { \ pr_debug(#x " failed!\n"); \
tools/perf/util/tsc.c new file +25 -0
@@ -0,0 +1,25 @@ +#include <linux/compiler.h> +#include <linux/types.h> + +#include "tsc.h" + +u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc) +{ +u64 t, quot, rem; + + t = ns - tc->time_zero; + quot = t / tc->time_mult; + rem = t % tc->time_mult; +return (quot << tc->time_shift) + + (rem << tc->time_shift) / tc->time_mult; +} + +u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc) +{ +u64 quot, rem; + + quot = cyc >> tc->time_shift; + rem = cyc & ((1 << tc->time_shift) -1 ); +return tc->time_zero + quot * tc->time_mult + + ((rem * tc->time_mult) >> tc->time_shift); +}
tools/perf/util/tsc.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef __PERF_TSC_H +#define __PERF_TSC_H + +#include <linux/types.h> + +#include "../arch/x86/util/tsc.h" + +u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc); +u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc); + +#endif
Signature · 1 line
1.9.3
Quoted 164 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
ff2ebe46e15bd49d52b9c2f3fc77f3a9d94eac7b:Merge tag 'perf-core-for-mingo' of
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perfinto perf/core (2014-07-16 13:48:13 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingofor you to fetch changes up to
0b437860818dc717f6a9e8a5089223a8414f5fff:perf tools: Allow TSC conversion on any arch (2014-07-17 12:59:00 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:User visible:
o Support S/390 in 'perf kvm stat' (Alexander Yarygin)
Developer Stuff:
o Various fixes and prep work related to supporting Intel PT (Adrian Hunter)
o Introduce multiple debug variables control (Jiri Olsa)
o Add callchain and additional sample information for python scripts (Joseph Schuchart)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Adrian Hunter (21):
perf machine: Fix the value used for unknown pids perf script: DisplayPERF_RECORD_MISC_COMM_EXECflag perf record: Selectcomm_execflag if supported
perf tools: Fix missing kernel map load
perf symbols: Fix missing GNU IFUNC symbols
perf inject: Fix build id injection
perf callchain: Fix appending a callchain from a previous sample perf buildid-cache: Apply force option to copying kcore perf symbols: Record whether a dso is 64-bit
perf symbols: Do not attempt to read data from kallsyms perf symbols: Add ability to iterate over a dso's symbols perf session: Flag if the event stream is entirely in memory perf evlist: Pass mmap parameters in a struct
perf tools: Add feature test for__sync_val_compare_and_swapperf tools: Add option macroOPT_CALLBACK_OPTARG
perf evsel: Add 'no_aux_samples' option
perf evsel: Add 'immediate' option
perf machine: Fix map groups of threads with unknown pids perf thread: Allow deletion of a thread with no map groups perf machine: Fix leak of 'struct thread' on error path perf tools: Allow TSC conversion on any archAlexander Yarygin (4):
perf kvm: Use defines of kvm events perf kvm: Move arch specific code intoarch/perf kvm: Addskip_event()for --duration option perf kvm: Add stat support on s390Jiri Olsa (5):
perf tools: Remove verbose from functions prototypes perf tools: Move pr_* debug macros into debug object perf tools: Factor eprintf to allow different debug variables perf tools: Add --debug optionto set debug variable perf tools: Remove needlessgetopt.hincludesJoseph Schuchart (3):
perf script: Add missing calls toPy_DECREFfor return values perf script: Add callchain to generic and tracepoint events perf script: Provide additional sample information on generic eventsarch/s390/include/uapi/asm/Kbuild | 1 + arch/s390/include/uapi/asm/kvm_perf.h | 25 ++ arch/x86/include/uapi/asm/Kbuild | 1 + arch/x86/include/uapi/asm/kvm_perf.h | 16 + tools/perf/Documentation/perf-kvm.txt | 16 +- tools/perf/Documentation/perf.txt | 10 +- tools/perf/MANIFEST | 3 + tools/perf/Makefile.perf | 3 + tools/perf/arch/s390/Makefile | 2 + tools/perf/arch/s390/util/kvm-stat.c | 105 ++++++ tools/perf/arch/x86/Makefile | 1 + tools/perf/arch/x86/tests/dwarf-unwind.c | 1 + tools/perf/arch/x86/util/kvm-stat.c | 156 +++++++++ tools/perf/arch/x86/util/tsc.c | 22 +- tools/perf/arch/x86/util/tsc.h | 3 - tools/perf/arch/x86/util/unwind-libunwind.c | 1 + tools/perf/builtin-buildid-cache.c | 8 +- tools/perf/builtin-evlist.c | 1 + tools/perf/builtin-help.c | 1 + tools/perf/builtin-inject.c | 3 + tools/perf/builtin-kvm.c | 384 ++++++--------------- tools/perf/builtin-sched.c | 12 +- tools/perf/builtin-timechart.c | 1 + tools/perf/config/Makefile | 6 + tools/perf/config/feature-checks/Makefile | 4 + tools/perf/config/feature-checks/test-all.c | 5 + .../feature-checks/test-sync-compare-and-swap.c | 14 + tools/perf/perf.c | 13 +- .../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +- tools/perf/scripts/python/check-perf-trace.py | 4 +- .../perf/scripts/python/failed-syscalls-by-pid.py | 2 +- tools/perf/scripts/python/futex-contention.py | 4 +- tools/perf/scripts/python/net_dropmonitor.py | 2 +- tools/perf/scripts/python/netdev-times.py | 26 +- tools/perf/scripts/python/sched-migration.py | 41 ++- tools/perf/scripts/python/sctop.py | 2 +- tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +- tools/perf/scripts/python/syscall-counts.py | 2 +- tools/perf/tests/dso-data.c | 1 + tools/perf/tests/evsel-roundtrip-name.c | 1 + tools/perf/tests/evsel-tp-sched.c | 1 + tools/perf/tests/open-syscall-tp-fields.c | 1 + tools/perf/tests/parse-events.c | 1 + tools/perf/tests/parse-no-sample-id-all.c | 1 + tools/perf/tests/perf-time-to-tsc.c | 3 +- tools/perf/tests/sample-parsing.c | 1 + tools/perf/tests/thread-mg-share.c | 1 + tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/callchain.c | 2 +- tools/perf/util/data.c | 1 + tools/perf/util/debug.c | 56 ++- tools/perf/util/debug.h | 22 ++ tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 1 + tools/perf/util/event.c | 10 +- tools/perf/util/evlist.c | 46 +-- tools/perf/util/evsel.c | 14 +- tools/perf/util/evsel.h | 2 + tools/perf/util/include/linux/kernel.h | 21 -- tools/perf/util/kvm-stat.h | 140 ++++++++ tools/perf/util/machine.c | 63 +++- tools/perf/util/map.c | 38 +- tools/perf/util/map.h | 10 +- tools/perf/util/parse-options.h | 5 + tools/perf/util/probe-finder.c | 1 - tools/perf/util/pstack.c | 1 + tools/perf/util/python.c | 4 +- tools/perf/util/record.c | 18 +- .../perf/util/scripting-engines/trace-event-perl.c | 1 + .../util/scripting-engines/trace-event-python.c | 140 +++++++- tools/perf/util/session.c | 14 +- tools/perf/util/session.h | 3 + tools/perf/util/symbol-elf.c | 6 +- tools/perf/util/symbol-minimal.c | 22 ++ tools/perf/util/symbol.c | 20 +- tools/perf/util/symbol.h | 4 + tools/perf/util/thread.c | 12 +- tools/perf/util/trace-event-info.c | 1 + tools/perf/util/trace-event-read.c | 2 +- tools/perf/util/tsc.c | 25 ++ tools/perf/util/tsc.h | 11 + tools/perf/util/unwind-libdw.c | 1 + tools/perf/util/unwind-libunwind.c | 1 + tools/perf/util/util.c | 1 + tools/perf/util/vdso.c | 1 + 85 files changed, 1170 insertions(+), 470 deletions(-)
Quoted 8 lines
create mode 100644 arch/s390/include/uapi/asm/kvm_perf.h create mode 100644 arch/x86/include/uapi/asm/kvm_perf.h create mode 100644 tools/perf/arch/s390/util/kvm-stat.c create mode 100644 tools/perf/arch/x86/util/kvm-stat.c create mode 100644 tools/perf/config/feature-checks/test-sync-compare-and-swap.c create mode 100644 tools/perf/util/kvm-stat.h create mode 100644 tools/perf/util/tsc.c create mode 100644 tools/perf/util/tsc.h
Pulled, thanks a lot Arnaldo!
Ingo