Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL New Arnaldo Carvalho de Melo 2 participants 35 messages Jul 17, 2014 – Jul 18, 2014

Subsystems (5)
x86 perf events s390 KVM x86 +1 more subsystems
lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

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/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
author maintainer
#1 lore raw

PATCH 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
index 09409c44f9a5..3dec769cadf7 100644
@@ -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
new file mode 100644
index 000000000000..3bb964f88aa1
@@ -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
index 45da209b6ed3..02b485d619cd 100644
@@ -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
index 41dbeaf8cc11..6d73346ef2a6 100644
@@ -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
author maintainer
#2 lore raw

PATCH 2/33 perf kvm: Move arch specific code into arch/

In reply to Arnaldo Carvalho de Melo

From: 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
index 9670a16fa577..90c498378a54 100644
@@ -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
index d3939014a877..9b21881db52f 100644
@@ -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
author maintainer
#3 lore raw

PATCH 3/33 perf kvm: Add skip_event() for --duration option

In reply to Arnaldo Carvalho de Melo

From: 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
index 2f8d2c1af5ca..14e4e668fad7 100644
@@ -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
index 75ee8c1a6baf..fc2d63d3e791 100644
@@ -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
index d0d9fb1ae52a..ba937caa28ac 100644
@@ -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
author maintainer
#4 lore raw

PATCH 4/33 perf kvm: Add stat support on s390

In reply to Arnaldo Carvalho de Melo

From: 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
index 6a9a9eb645f5..0e2b54db82bc 100644
@@ -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
new file mode 100644
index 000000000000..397282727e21
@@ -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
index 52276a6d2b75..6e689dc89a2f 100644
@@ -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
index 02b485d619cd..344c4d3d0a4a 100644
@@ -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
index 744e629797be..798ac7379c5f 100644
@@ -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
index ba937caa28ac..0b5a8cd2ee79 100644
@@ -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
author maintainer
#5 lore raw

PATCH 5/33 perf script: Add missing calls to Py_DECREF for return values

In reply to Arnaldo Carvalho de Melo

From: 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
index e55b65a65558..b6c1a69f2b18 100644
@@ -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
author maintainer
#6 lore raw

PATCH 6/33 perf script: Add callchain to generic and tracepoint events

In reply to Arnaldo Carvalho de Melo

From: 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
index de7211e4fa47..38dfb720fb6f 100644
@@ -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
index 4647a7694cf6..334599c6032c 100644
@@ -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
index 266a8364bce5..cafeff3d74db 100644
@@ -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
index 11e70a388d41..0f5cf437b602 100644
@@ -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
index b5740599aabd..0b6ce8c253e8 100755
@@ -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
index 9aa0a32972e8..4d21ef2d601d 100644
@@ -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
index c9f3058b7dd4..61621b93affb 100644
@@ -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
index cf2054c529c9..daf314cc5dd3 100644
@@ -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
index 92b29381bd39..e66a7730aeb5 100644
@@ -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
author maintainer
#7 lore raw

PATCH 7/33 perf script: Provide additional sample information on generic events

In reply to Arnaldo Carvalho de Melo

From: 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
index cf65404472cb..b366b48646ca 100644
@@ -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
author maintainer
#8 lore raw

PATCH 8/33 perf machine: Fix the value used for unknown pids

In reply to Arnaldo Carvalho de Melo

From: 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
index c38d06c04775..b7f555add0c8 100644
@@ -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
index e9b943acaa5e..5b8087728f28 100644
@@ -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
index 64a186edc7be..c2f4ca917469 100644
@@ -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
index 2fde0d5e40b5..7a32f447a8e7 100644
@@ -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
author maintainer
#9 lore raw

PATCH 9/33 perf script: Display PERF_RECORD_MISC_COMM_EXEC flag

In reply to Arnaldo Carvalho de Melo

From: 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
index d0281bdfa582..198c4cc313a1 100644
@@ -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
index 8606175fe1e8..b760d32aae06 100644
@@ -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
author maintainer
#10 lore raw

PATCH 10/33 perf record: Select comm_exec flag if supported

In reply to Arnaldo Carvalho de Melo

From: 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
index 049e0a09ccd3..165723152cfb 100644
@@ -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
author maintainer
#11 lore raw

PATCH 11/33 perf tools: Fix missing kernel map load

In reply to Arnaldo Carvalho de Melo

From: 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
index 198c4cc313a1..7e0e8ae568ec 100644
@@ -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
author maintainer
#12 lore raw

PATCH 12/33 perf symbols: Fix missing GNU IFUNC symbols

In reply to Arnaldo Carvalho de Melo

From: 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
index 6864661a79dd..dce5ccf61f11 100644
@@ -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
author maintainer
#13 lore raw

PATCH 13/33 perf inject: Fix build id injection

In reply to Arnaldo Carvalho de Melo

From: 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
index 16c7c11ad06e..cf6a605a13e8 100644
@@ -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
author maintainer
#14 lore raw

PATCH 14/33 perf callchain: Fix appending a callchain from a previous sample

In reply to Arnaldo Carvalho de Melo

From: 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
index 48b6d3f50012..437ee09727e6 100644
@@ -626,7 +626,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
 
 int 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
author maintainer
#15 lore raw

PATCH 15/33 perf buildid-cache: Apply force option to copying kcore

In reply to Arnaldo Carvalho de Melo

From: 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
index b22dbb16f877..2a2c78f80876 100644
@@ -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
author maintainer
#16 lore raw

PATCH 16/33 perf symbols: Record whether a dso is 64-bit

In reply to Arnaldo Carvalho de Melo

From: 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
index 819f10414f08..fc006fed8877 100644
@@ -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
index ad553ba257bf..c239e86541a3 100644
@@ -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
index dce5ccf61f11..cef8f426356e 100644
@@ -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
index bd15f490d04f..101f55d407d0 100644
@@ -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
index 2e6a2e219eb9..ae2e4464afa7 100644
@@ -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
index a81877b1dee0..436169dd1d84 100644
@@ -216,6 +216,7 @@ struct symsrc {
 	GElf_Shdr dynshdr;
 
 	bool adjust_symbols;
+	bool is_64_bit;
 #endif
 };
 
Signature · 1 line
1.9.3
author maintainer
#17 lore raw

PATCH 17/33 perf symbols: Do not attempt to read data from kallsyms

In reply to Arnaldo Carvalho de Melo

From: 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
index ae2e4464afa7..156ae36dfcfc 100644
@@ -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
author maintainer
#18 lore raw

PATCH 18/33 perf symbols: Add ability to iterate over a dso's symbols

In reply to Arnaldo Carvalho de Melo

From: 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
index 156ae36dfcfc..eb06746b06b2 100644
@@ -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
index 436169dd1d84..ee2d3ccd3ad1 100644
@@ -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
author maintainer
#19 lore raw

PATCH 19/33 perf session: Flag if the event stream is entirely in memory

In reply to Arnaldo Carvalho de Melo

From: 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
index c2f4ca917469..eac14ce0ae8d 100644
@@ -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
index 3140f8ae6148..0321013bd9fd 100644
@@ -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
author maintainer
#20 lore raw

PATCH 20/33 perf evlist: Pass mmap parameters in a struct

In reply to Arnaldo Carvalho de Melo

From: 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
index c51223ac25f4..814e954c1318 100644
@@ -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
author maintainer
#21 lore raw

PATCH 21/33 perf tools: Add feature test for __sync_val_compare_and_swap

In reply to Arnaldo Carvalho de Melo

From: 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
index b7f42d577c4e..1f67aa02d240 100644
@@ -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
index 64c84e5f0514..6088f8d8a434 100644
@@ -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
index fe5c1e5c952f..a7d022e161c0 100644
@@ -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
new file mode 100644
index 000000000000..c34d4ca4af56
@@ -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
author maintainer
#22 lore raw

PATCH 22/33 perf tools: Add option macro OPT_CALLBACK_OPTARG

In reply to Arnaldo Carvalho de Melo

From: 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
index d8dac8ac5f37..b59ba858e73d 100644
@@ -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
author maintainer
#23 lore raw

PATCH 23/33 perf evsel: Add 'no_aux_samples' option

In reply to Arnaldo Carvalho de Melo

From: 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
index b760d32aae06..40626e5fc1c0 100644
@@ -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
index a52e9a5bb2d0..8dfec05bcec2 100644
@@ -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
author maintainer
#24 lore raw

PATCH 24/33 perf evsel: Add 'immediate' option

In reply to Arnaldo Carvalho de Melo

From: 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
index 40626e5fc1c0..90f58cdd0fb0 100644
@@ -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
index 8dfec05bcec2..d7f93ce0ebc1 100644
@@ -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
author maintainer
#25 lore raw

PATCH 25/33 perf machine: Fix map groups of threads with unknown pids

In reply to Arnaldo Carvalho de Melo

From: 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
index 5b8087728f28..5484fa4385fc 100644
@@ -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
index 25c571f4cba6..7af14807ee90 100644
@@ -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
index 7758c72522ef..5806a906198b 100644
@@ -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
author maintainer
#26 lore raw

PATCH 26/33 perf thread: Allow deletion of a thread with no map groups

In reply to Arnaldo Carvalho de Melo

From: 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
index 7a32f447a8e7..b9c36ef42d2f 100644
@@ -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
author maintainer
#27 lore raw

PATCH 27/33 perf machine: Fix leak of 'struct thread' on error path

In reply to Arnaldo Carvalho de Melo

From: 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
index 5484fa4385fc..93c8b6fbc799 100644
@@ -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
author maintainer
#28 lore raw

PATCH 28/33 perf tools: Remove verbose from functions prototypes

In reply to Arnaldo Carvalho de Melo

From: 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.

Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 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
index 90122abd3721..40af0acb4fe9 100644
@@ -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
index 7af14807ee90..845f627e45f4 100644
@@ -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
index 5806a906198b..22d13a219590 100644
@@ -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
index b9c36ef42d2f..9692c06a9e21 100644
@@ -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
author maintainer
#29 lore raw

PATCH 29/33 perf tools: Move pr_* debug macros into debug object

In reply to Arnaldo Carvalho de Melo

From: 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.

Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
[ Add missing debug.h include in python scripting glue and in the libdw unwind lib ]
---
 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
index 9f89f899ccc7..d8bbf7ad1681 100644
@@ -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
index 3261f68c6a7c..db25e93d989c 100644
@@ -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
index c99e0de7e54a..66e12f55c052 100644
@@ -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
index 178b88ae3d2f..0384d930480b 100644
@@ -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
index 04c9c53becad..2f1a5220c090 100644
@@ -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
index 630808cd7cc2..caaf37f079b1 100644
@@ -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
index 465cdbc345cf..b8d8341b383e 100644
@@ -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
index 35d7fdb2328d..52162425c969 100644
@@ -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
index c505ef2af245..0785b64ffd6c 100644
@@ -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
index deba66955f8c..5941927a4b7f 100644
@@ -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
index 905019f9b740..2c63ea658541 100644
@@ -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
index 7ae8d17db3d9..ca292f9a4ae2 100644
@@ -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
index 2b2e0dbe114f..b028499dd3cf 100644
@@ -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
index ee370a7f2444..29d720cf5844 100644
@@ -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
index 443694c36b03..8a8ceb3ccde9 100644
@@ -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
index 9844c31b7c2b..09e8e7aea7c6 100644
@@ -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
index daa17aeb6c63..a126e6cc6e73 100644
@@ -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
index af7da565a750..b2dba9c0a3a1 100644
@@ -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
index b366b48646ca..cbce2545da45 100644
@@ -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
index c3bba883f5c3..eb72716017ac 100644
@@ -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
index e113e180c48f..ea3fd7fc6f5c 100644
@@ -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
index 5ec80a575b50..7419768c38b1 100644
@@ -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
index 25578b98f5c5..92b56db52471 100644
@@ -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
index e4132aeeb780..e52e7461911b 100644
@@ -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
index 0ddb3b8a89ec..290582452da3 100644
@@ -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
author maintainer
#30 lore raw

PATCH 30/33 perf tools: Factor eprintf to allow different debug variables

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

This way we can easily reuse current debug functions for another debug variables other than verbose.

Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 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
index 299b55586502..c208d6f56e63 100644
@@ -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
index 8a8ceb3ccde9..1cb808123242 100644
@@ -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
index 122669c18ff4..12aa9b0d0ba1 100644
@@ -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
author maintainer
#31 lore raw

PATCH 31/33 perf tools: Add --debug optionto set debug variable

In reply to Arnaldo Carvalho de Melo

From: 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.

Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 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
index 0eeb247dc7d2..d240bb2e5b22 100644
@@ -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
index 95c58fc15284..eed3fb2a3af0 100644
@@ -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
index 1cb808123242..89fb6b0f7ab2 100644
@@ -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
author maintainer
#32 lore raw

PATCH 32/33 perf tools: Remove needless getopt.h includes

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

We don't use getopt.h interfaces.

Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 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
index 98e304766416..dca9145d704c 100644
@@ -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
index ea3fd7fc6f5c..54d9e9b548a8 100644
@@ -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
author maintainer
#33 lore raw

PATCH 33/33 perf tools: Allow TSC conversion on any arch

In reply to Arnaldo Carvalho de Melo

From: 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
index 90c498378a54..3308b22a1660 100644
@@ -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
index 40021fa3129b..3655f24c3170 100644
@@ -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
index 2affe0366b59..2edc4d31065c 100644
@@ -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
index 3b7cd4d32dcb..0372f6edca20 100644
@@ -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
new file mode 100644
index 000000000000..ef4749836ce9
@@ -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
new file mode 100644
index 000000000000..4eca84887c8a
@@ -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
#34 lore raw
In reply to Arnaldo Carvalho de Melo
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/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(-)
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