Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL In review Arnaldo Carvalho de Melo 3 participants 31 messages Mar 12, 2015 – Mar 13, 2015 perf events

lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

Please consider pulling, more to come, will continue tomorrow,

- Arnaldo

The following changes since commit 94ac003b665fc04f13a7ab3b2be896b9b9503451:

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-03-03 07:17:53 +0100)

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 7afa95d95b7b4c17f3c648f58f8c8abdcb619b85:

perf data: Add tracepoint events fields CTF conversion support (2015-03-12 16:10:41 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

. Fix UI bug after zoom into thread/dso/symbol and another, after fold/unfold,
in the TUI hists browser (He Kuang)

. Fixes for 'perf probe' handle aliased symbols, for instance in glibc (Masami Hiramatsu, Namhyung Kim)

- 'perf kmem' improvements and fixes: (Namhyung Kim)
- Fix segfault when invalid sort key is given
- Allow -v option
- Fix alignment of slab result table

- 'perf stat' improvements and fixes: (Andi Kleen)
- Output running time and run/enabled ratio in CSV mode
- Fix IPC and other formulas with -A
- Always correctly indent ratio column

. Add tracepoint events fields CTF conversion support to 'perf data' (Sebastian Andrzej Siewior)

Infrastructure:

. Output feature detection's gcc output to a file, to help in debugging (Arnaldo Carvalho de Melo)

. Fix 'perf probe' compiles due to declarations using perf_probe_point (David Ahern)

. Fix possible double free on error in 'perf probe' (He Kuang)

. Remove superfluous thread->comm_set setting (Jiri Olsa)

. Fix libbabeltrace detection (Jiri Olsa)

. More work on separating ordered_events code out of perf_session (Arnaldo Carvalho de Melo)

----------------------------------------------------------------
Andi Kleen (3):
perf stat: Output running time and run/enabled ratio in CSV mode perf stat: Fix IPC and other formulas with -A
perf stat: Always correctly indent ratio column

Arnaldo Carvalho de Melo (6):
perf ordered_events: Untangle from perf_session perf ordered_events: Shorten function signatures perf ordered_events: Allow tools to specify a deliver method perf tools: tool->finished_round() doesn't need perf_session perf ordered_events: Adopt queue() method
perf tools: Output feature detection's gcc output to a file

David Ahern (1):
perf probe: Fix compiles due to declarations using perf_probe_point

He Kuang (3):
perf probe: Fix possible double free on error
perf hists browser: Fix UI bug after zoom into thread/dso/symbol perf hists browser: Fix UI bug after fold/unfold

Jiri Olsa (2):
perf tools: Remove superfluous thread->comm_set setting perf build: Fix libbabeltrace detection

Masami Hiramatsu (3):
perf probe: Fix to handle aliased symbols in glibc
perf probe: Fix --line to handle aliased symbols in glibc Revert "perf probe: Fix to fall back to find probe point in symbols"

Namhyung Kim (5):
perf symbols: Allow symbol alias when loading map for symbol name perf probe: Allow weak symbols to be probed
perf kmem: Fix segfault when invalid sort key is given perf kmem: Allow -v option
perf kmem: Fix alignment of slab result table

Sebastian Andrzej Siewior (1):
perf data: Add tracepoint events fields CTF conversion support

 tools/perf/Documentation/perf-kmem.txt             |   4 +
 tools/perf/Makefile.perf                           |   1 +
 tools/perf/builtin-annotate.c                      |   2 +-
 tools/perf/builtin-buildid-list.c                  |   2 +-
 tools/perf/builtin-diff.c                          |   2 +-
 tools/perf/builtin-inject.c                        |  15 +-
 tools/perf/builtin-kmem.c                          |  17 +-
 tools/perf/builtin-kvm.c                           |  13 +-
 tools/perf/builtin-lock.c                          |   2 +-
 tools/perf/builtin-mem.c                           |   2 +-
 tools/perf/builtin-record.c                        |   4 +-
 tools/perf/builtin-report.c                        |   2 +-
 tools/perf/builtin-sched.c                         |   2 +-
 tools/perf/builtin-script.c                        |   2 +-
 tools/perf/builtin-stat.c                          |  89 ++++----
 tools/perf/builtin-timechart.c                     |   2 +-
 tools/perf/builtin-trace.c                         |   2 +-
 tools/perf/config/Makefile                         |   2 +-
 .../config/feature-checks/test-libbabeltrace.c     |   1 +
 tools/perf/ui/browsers/hists.c                     |  19 ++
 tools/perf/util/data-convert-bt.c                  | 246 ++++++++++++++++++++-
 tools/perf/util/hist.c                             |   1 +
 tools/perf/util/ordered-events.c                   |  57 +++--
 tools/perf/util/ordered-events.h                   |  27 ++-
 tools/perf/util/probe-event.c                      | 194 +++++++++++++---
 tools/perf/util/session.c                          | 140 ++++++------
 tools/perf/util/session.h                          |  16 +-
 tools/perf/util/symbol-elf.c                       |   3 +-
 tools/perf/util/symbol.h                           |   1 +
 tools/perf/util/thread.c                           |   1 -
 tools/perf/util/tool.h                             |   8 +-
 31 files changed, 672 insertions(+), 207 deletions(-)
author maintainer
#1 lore raw

PATCH 1/24 perf ordered_events: Untangle from perf_session

From: Arnaldo Carvalho de Melo <[email protected]>

For use by tools that are not perf.data based, as maybe 'perf trace' in live mode.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/util/ordered-events.c | 17 +++++++++--------
 tools/perf/util/ordered-events.h |  8 +++++---
 tools/perf/util/session.c        | 37 ++++++++++++++++++++++++++-----------
 tools/perf/util/session.h        |  3 ++-
 4 files changed, 42 insertions(+), 23 deletions(-)
tools/perf/util/ordered-events.c +9 -8
index 077ddd25189f..e6ab630dd374 100644
@@ -153,10 +153,11 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
 	free_dup_event(oe, event->event);
 }
 
-static int __ordered_events__flush(struct perf_session *s,
+static int __ordered_events__flush(struct ordered_events *oe,
+				   struct machines *machines,
+				   struct perf_evlist *evlist,
 				   struct perf_tool *tool)
 {
-	struct ordered_events *oe = &s->ordered_events;
 	struct list_head *head = &oe->events;
 	struct ordered_event *tmp, *iter;
 	struct perf_sample sample;
@@ -179,12 +180,12 @@ static int __ordered_events__flush(struct perf_session *s,
 		if (iter->timestamp > limit)
 			break;
 
-		ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
+		ret = perf_evlist__parse_sample(evlist, iter->event, &sample);
 		if (ret)
 			pr_err("Can't parse sample, err = %d\n", ret);
 		else {
-			ret = perf_session__deliver_event(s, iter->event, &sample, tool,
-							  iter->file_offset);
+			ret = machines__deliver_event(machines, evlist, iter->event,
+						      &sample, tool, iter->file_offset);
 			if (ret)
 				return ret;
 		}
@@ -204,10 +205,10 @@ static int __ordered_events__flush(struct perf_session *s,
 	return 0;
 }
 
-int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
+int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
+			  struct perf_evlist *evlist, struct perf_tool *tool,
 			  enum oe_flush how)
 {
-	struct ordered_events *oe = &s->ordered_events;
 	static const char * const str[] = {
 		"NONE",
 		"FINAL",
@@ -251,7 +252,7 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
 		   str[how], oe->nr_events);
 	pr_oe_time(oe->max_timestamp, "max_timestamp\n");
 
-	err = __ordered_events__flush(s, tool);
+	err = __ordered_events__flush(oe, machines, evlist, tool);
 
 	if (!err) {
 		if (how == OE_FLUSH__ROUND)
tools/perf/util/ordered-events.h +5 -3
index 7b8f9b011f38..e09f2433c6d6 100644
@@ -2,9 +2,10 @@
 #define __ORDERED_EVENTS_H
 
 #include <linux/types.h>
-#include "tool.h"
 
-struct perf_session;
+struct perf_tool;
+struct perf_evlist;
+struct machines;
 
 struct ordered_event {
 	u64			timestamp;
@@ -40,7 +41,8 @@ struct ordered_events {
 struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
 					  union perf_event *event);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
-int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
+int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
+			  struct perf_evlist *evlist, struct perf_tool *tool,
 			  enum oe_flush how);
 void ordered_events__init(struct ordered_events *oe);
 void ordered_events__free(struct ordered_events *oe);
tools/perf/util/session.c +26 -11
index ed4e5cf2bd9d..23be146bd2fc 100644
@@ -512,7 +512,11 @@ static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event __maybe_unused,
 				  struct perf_session *session)
 {
-	return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
+	struct ordered_events *oe = &session->ordered_events;
+	struct perf_evlist *evlist = session->evlist;
+	struct machines *machines = &session->machines;
+
+	return ordered_events__flush(oe, machines, evlist, tool, OE_FLUSH__ROUND);
 }
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
@@ -520,6 +524,9 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 			     u64 file_offset)
 {
 	struct ordered_events *oe = &s->ordered_events;
+	struct perf_evlist *evlist = s->evlist;
+	struct machines *machines = &s->machines;
+
 	u64 timestamp = sample->time;
 	struct ordered_event *new;
 
@@ -536,7 +543,7 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 
 	new = ordered_events__new(oe, timestamp, event);
 	if (!new) {
-		ordered_events__flush(s, tool, OE_FLUSH__HALF);
+		ordered_events__flush(oe, machines, evlist, tool, OE_FLUSH__HALF);
 		new = ordered_events__new(oe, timestamp, event);
 	}
 
@@ -886,12 +893,12 @@ static int
 					    &sample->read.one, machine);
 }
 
-int perf_session__deliver_event(struct perf_session *session,
+int machines__deliver_event(struct machines *machines,
+				struct perf_evlist *evlist,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_tool *tool, u64 file_offset)
 {
-	struct perf_evlist *evlist = session->evlist;
 	struct perf_evsel *evsel;
 	struct machine *machine;
 
@@ -899,7 +906,7 @@ int perf_session__deliver_event(struct perf_session *session,
 
 	evsel = perf_evlist__id2evsel(evlist, sample->id);
 
-	machine = machines__find_for_cpumode(&session->machines, event, sample);
+	machine = machines__find_for_cpumode(machines, event, sample);
 
 	switch (event->header.type) {
 	case PERF_RECORD_SAMPLE:
@@ -984,12 +991,14 @@ int perf_session__deliver_synth_event(struct perf_session *session,
 				      struct perf_sample *sample,
 				      struct perf_tool *tool)
 {
-	events_stats__inc(&session->evlist->stats, event->header.type);
+	struct perf_evlist *evlist = session->evlist;
+
+	events_stats__inc(&evlist->stats, event->header.type);
 
 	if (event->header.type >= PERF_RECORD_USER_TYPE_START)
 		return perf_session__process_user_event(session, event, tool, 0);
 
-	return perf_session__deliver_event(session, event, sample, tool, 0);
+	return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
 }
 
 static void event_swap(union perf_event *event, bool sample_id_all)
@@ -1090,8 +1099,8 @@ static s64 perf_session__process_event(struct perf_session *session,
 			return ret;
 	}
 
-	return perf_session__deliver_event(session, event, &sample, tool,
-					   file_offset);
+	return machines__deliver_event(&session->machines, evlist, event,
+				       &sample, tool, file_offset);
 }
 
 void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1167,6 +1176,9 @@ volatile int session_done;
 static int __perf_session__process_pipe_events(struct perf_session *session,
 					       struct perf_tool *tool)
 {
+	struct ordered_events *oe = &session->ordered_events;
+	struct perf_evlist *evlist = session->evlist;
+	struct machines *machines = &session->machines;
 	int fd = perf_data_file__fd(session->file);
 	union perf_event *event;
 	uint32_t size, cur_size = 0;
@@ -1246,7 +1258,7 @@ more:
 		goto more;
 done:
 	/* do the final flush for ordered samples */
-	err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
+	err = ordered_events__flush(oe, machines, evlist, tool, OE_FLUSH__FINAL);
 out_err:
 	free(buf);
 	perf_tool__warn_about_errors(tool, &session->evlist->stats);
@@ -1298,6 +1310,9 @@ static int __perf_session__process_events(struct perf_session *session,
 					  u64 data_offset, u64 data_size,
 					  u64 file_size, struct perf_tool *tool)
 {
+	struct ordered_events *oe = &session->ordered_events;
+	struct perf_evlist *evlist = session->evlist;
+	struct machines *machines = &session->machines;
 	int fd = perf_data_file__fd(session->file);
 	u64 head, page_offset, file_offset, file_pos, size;
 	int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1391,7 +1406,7 @@ more:
 
 out:
 	/* do the final flush for ordered samples */
-	err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
+	err = ordered_events__flush(oe, machines, evlist, tool, OE_FLUSH__FINAL);
 out_err:
 	ui_progress__finish();
 	perf_tool__warn_about_errors(tool, &session->evlist->stats);
tools/perf/util/session.h +2 -1
index fe859f379ca7..c08fa6be5bf3 100644
@@ -57,7 +57,8 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
-int perf_session__deliver_event(struct perf_session *session,
+int machines__deliver_event(struct machines *machines,
+				struct perf_evlist *evlist,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_tool *tool, u64 file_offset);
Signature · 1 line
1.9.3
author maintainer
#2 lore raw

PATCH 2/24 perf ordered_events: Shorten function signatures

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

By keeping pointers to machines, evlist and tool in ordered_events.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/builtin-annotate.c     |  2 +-
 tools/perf/builtin-buildid-list.c |  2 +-
 tools/perf/builtin-diff.c         |  2 +-
 tools/perf/builtin-inject.c       |  6 ++--
 tools/perf/builtin-kmem.c         |  2 +-
 tools/perf/builtin-kvm.c          |  6 ++--
 tools/perf/builtin-lock.c         |  2 +-
 tools/perf/builtin-mem.c          |  2 +-
 tools/perf/builtin-record.c       |  4 +--
 tools/perf/builtin-report.c       |  2 +-
 tools/perf/builtin-sched.c        |  2 +-
 tools/perf/builtin-script.c       |  2 +-
 tools/perf/builtin-timechart.c    |  2 +-
 tools/perf/builtin-trace.c        |  2 +-
 tools/perf/util/data-convert-bt.c |  4 +--
 tools/perf/util/ordered-events.c  | 23 +++++++-------
 tools/perf/util/ordered-events.h  | 10 +++---
 tools/perf/util/session.c         | 65 ++++++++++++++++-----------------------
 tools/perf/util/session.h         | 11 +++----
 19 files changed, 68 insertions(+), 83 deletions(-)
tools/perf/builtin-annotate.c +1 -1
index 747f86103599..71bf7451c0ca 100644
@@ -208,7 +208,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
 			goto out;
 	}
 
-	ret = perf_session__process_events(session, &ann->tool);
+	ret = perf_session__process_events(session);
 	if (ret)
 		goto out;
 
tools/perf/builtin-buildid-list.c +1 -1
index ed3873b3e238..feb420f74c2d 100644
@@ -74,7 +74,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
 	 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
 	 */
 	if (with_hits || perf_data_file__is_pipe(&file))
-		perf_session__process_events(session, &build_id__mark_dso_hit_ops);
+		perf_session__process_events(session);
 
 	perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
 	perf_session__delete(session);
tools/perf/builtin-diff.c +1 -1
index 74aada554b12..f800fc95f5d7 100644
@@ -747,7 +747,7 @@ static int __cmd_diff(void)
 			goto out_delete;
 		}
 
-		ret = perf_session__process_events(d->session, &tool);
+		ret = perf_session__process_events(d->session);
 		if (ret) {
 			pr_err("Failed to process %s\n", d->file.path);
 			goto out_delete;
tools/perf/builtin-inject.c +3 -3
index a13641e066f5..2563f07ec0e5 100644
@@ -359,8 +359,6 @@ static int __cmd_inject(struct perf_inject *inject)
 	} else if (inject->sched_stat) {
 		struct perf_evsel *evsel;
 
-		inject->tool.ordered_events = true;
-
 		evlist__for_each(session->evlist, evsel) {
 			const char *name = perf_evsel__name(evsel);
 
@@ -379,7 +377,7 @@ static int __cmd_inject(struct perf_inject *inject)
 	if (!file_out->is_pipe)
 		lseek(fd, session->header.data_offset, SEEK_SET);
 
-	ret = perf_session__process_events(session, &inject->tool);
+	ret = perf_session__process_events(session);
 
 	if (!file_out->is_pipe) {
 		if (inject->build_ids)
@@ -458,6 +456,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 		return -1;
 	}
 
+	inject.tool.ordered_events = inject.sched_stat;
+
 	file.path = inject.input_name;
 	inject.session = perf_session__new(&file, true, &inject.tool);
 	if (inject.session == NULL)
tools/perf/builtin-kmem.c +1 -1
index f295141025bc..62f165a9fa40 100644
@@ -426,7 +426,7 @@ static int __cmd_kmem(struct perf_session *session)
 	}
 
 	setup_pager();
-	err = perf_session__process_events(session, &perf_kmem);
+	err = perf_session__process_events(session);
 	if (err != 0)
 		goto out;
 	sort_result();
tools/perf/builtin-kvm.c +3 -3
index 0894a817f67e..802b8f53fa9a 100644
@@ -730,9 +730,9 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
 			return -1;
 		}
 
-		err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
+		err = perf_session__queue_event(kvm->session, event, &sample, 0);
 		/*
-		 * FIXME: Here we can't consume the event, as perf_session_queue_event will
+		 * FIXME: Here we can't consume the event, as perf_session__queue_event will
 		 *        point to it, and it'll get possibly overwritten by the kernel.
 		 */
 		perf_evlist__mmap_consume(kvm->evlist, idx);
@@ -1066,7 +1066,7 @@ static int read_events(struct perf_kvm_stat *kvm)
 	if (ret < 0)
 		return ret;
 
-	return perf_session__process_events(kvm->session, &kvm->tool);
+	return perf_session__process_events(kvm->session);
 }
 
 static int parse_target_str(struct perf_kvm_stat *kvm)
tools/perf/builtin-lock.c +1 -1
index e7ec71589da6..7893a9bba2a7 100644
@@ -878,7 +878,7 @@ static int __cmd_report(bool display_info)
 	if (select_key())
 		goto out_delete;
 
-	err = perf_session__process_events(session, &eops);
+	err = perf_session__process_events(session);
 	if (err)
 		goto out_delete;
 
tools/perf/builtin-mem.c +1 -1
index 9b5663950a4d..46c69318de84 100644
@@ -141,7 +141,7 @@ static int report_raw_events(struct perf_mem *mem)
 
 	printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
 
-	err = perf_session__process_events(session, &mem->tool);
+	err = perf_session__process_events(session);
 	if (err)
 		return err;
 
tools/perf/builtin-record.c +2 -2
index 4fdad06d37db..5a2ff510b75b 100644
@@ -225,7 +225,7 @@ static int process_buildids(struct record *rec)
 	 */
 	symbol_conf.ignore_vmlinux_buildid = true;
 
-	return perf_session__process_events(session, &rec->tool);
+	return perf_session__process_events(session);
 }
 
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -343,7 +343,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);
 
-	session = perf_session__new(file, false, NULL);
+	session = perf_session__new(file, false, tool);
 	if (session == NULL) {
 		pr_err("Perf session creation failed.\n");
 		return -1;
tools/perf/builtin-report.c +1 -1
index fb350343b1d7..52f74e1367e9 100644
@@ -482,7 +482,7 @@ static int __cmd_report(struct report *rep)
 	if (ret)
 		return ret;
 
-	ret = perf_session__process_events(session, &rep->tool);
+	ret = perf_session__process_events(session);
 	if (ret)
 		return ret;
 
tools/perf/builtin-sched.c +1 -1
index a3ebf1d3c29d..3b3a5bb97059 100644
@@ -1467,7 +1467,7 @@ static int perf_sched__read_events(struct perf_sched *sched)
 		goto out_delete;
 
 	if (perf_session__has_traces(session, "record -R")) {
-		int err = perf_session__process_events(session, &sched->tool);
+		int err = perf_session__process_events(session);
 		if (err) {
 			pr_err("Failed to process events, error %d", err);
 			goto out_delete;
tools/perf/builtin-script.c +1 -1
index ce304dfd962a..c7e6750923ef 100644
@@ -800,7 +800,7 @@ static int __cmd_script(struct perf_script *script)
 		script->tool.mmap2 = process_mmap2_event;
 	}
 
-	ret = perf_session__process_events(script->session, &script->tool);
+	ret = perf_session__process_events(script->session);
 
 	if (debug_mode)
 		pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
tools/perf/builtin-timechart.c +1 -1
index f3bb1a4bf060..51440d1fc722 100644
@@ -1623,7 +1623,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
 		goto out_delete;
 	}
 
-	ret = perf_session__process_events(session, &tchart->tool);
+	ret = perf_session__process_events(session);
 	if (ret)
 		goto out_delete;
 
tools/perf/builtin-trace.c +1 -1
index 211614fba217..6969ba98ff2f 100644
@@ -2408,7 +2408,7 @@ static int trace__replay(struct trace *trace)
 
 	setup_pager();
 
-	err = perf_session__process_events(session, &trace->tool);
+	err = perf_session__process_events(session);
 	if (err)
 		pr_err("Failed to process events, error %d", err);
 
tools/perf/util/data-convert-bt.c +2 -2
index e372e03ff480..1afd381b2346 100644
@@ -579,7 +579,7 @@ int bt_convert__perf2ctf(const char *input, const char *path)
 		return -1;
 
 	/* perf.data session */
-	session = perf_session__new(&file, 0, NULL);
+	session = perf_session__new(&file, 0, &c.tool);
 	if (!session)
 		goto free_writer;
 
@@ -591,7 +591,7 @@ int bt_convert__perf2ctf(const char *input, const char *path)
 	if (setup_events(cw, session))
 		goto free_session;
 
-	err = perf_session__process_events(session, &c.tool);
+	err = perf_session__process_events(session);
 	if (!err)
 		err = bt_ctf_stream_flush(cw->stream);
 
tools/perf/util/ordered-events.c +11 -12
index e6ab630dd374..bad46ce16591 100644
@@ -153,10 +153,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
 	free_dup_event(oe, event->event);
 }
 
-static int __ordered_events__flush(struct ordered_events *oe,
-				   struct machines *machines,
-				   struct perf_evlist *evlist,
-				   struct perf_tool *tool)
+static int __ordered_events__flush(struct ordered_events *oe)
 {
 	struct list_head *head = &oe->events;
 	struct ordered_event *tmp, *iter;
@@ -180,12 +177,12 @@ static int __ordered_events__flush(struct ordered_events *oe,
 		if (iter->timestamp > limit)
 			break;
 
-		ret = perf_evlist__parse_sample(evlist, iter->event, &sample);
+		ret = perf_evlist__parse_sample(oe->evlist, iter->event, &sample);
 		if (ret)
 			pr_err("Can't parse sample, err = %d\n", ret);
 		else {
-			ret = machines__deliver_event(machines, evlist, iter->event,
-						      &sample, tool, iter->file_offset);
+			ret = machines__deliver_event(oe->machines, oe->evlist, iter->event,
+						      &sample, oe->tool, iter->file_offset);
 			if (ret)
 				return ret;
 		}
@@ -205,9 +202,7 @@ static int __ordered_events__flush(struct ordered_events *oe,
 	return 0;
 }
 
-int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlist, struct perf_tool *tool,
-			  enum oe_flush how)
+int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
 {
 	static const char * const str[] = {
 		"NONE",
@@ -252,7 +247,7 @@ int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
 		   str[how], oe->nr_events);
 	pr_oe_time(oe->max_timestamp, "max_timestamp\n");
 
-	err = __ordered_events__flush(oe, machines, evlist, tool);
+	err = __ordered_events__flush(oe);
 
 	if (!err) {
 		if (how == OE_FLUSH__ROUND)
@@ -268,13 +263,17 @@ int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
 	return err;
 }
 
-void ordered_events__init(struct ordered_events *oe)
+void ordered_events__init(struct ordered_events *oe, struct machines *machines,
+			  struct perf_evlist *evlist, struct perf_tool *tool)
 {
 	INIT_LIST_HEAD(&oe->events);
 	INIT_LIST_HEAD(&oe->cache);
 	INIT_LIST_HEAD(&oe->to_free);
 	oe->max_alloc_size = (u64) -1;
 	oe->cur_alloc_size = 0;
+	oe->evlist	   = evlist;
+	oe->machines	   = machines;
+	oe->tool	   = tool;
 }
 
 void ordered_events__free(struct ordered_events *oe)
tools/perf/util/ordered-events.h +6 -4
index e09f2433c6d6..ef7d73ecb0d0 100644
@@ -32,6 +32,9 @@ struct ordered_events {
 	struct list_head	to_free;
 	struct ordered_event	*buffer;
 	struct ordered_event	*last;
+	struct machines		*machines;
+	struct perf_evlist	*evlist;
+	struct perf_tool	*tool;
 	int			buffer_idx;
 	unsigned int		nr_events;
 	enum oe_flush		last_flush_type;
@@ -41,10 +44,9 @@ struct ordered_events {
 struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
 					  union perf_event *event);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
-int ordered_events__flush(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlist, struct perf_tool *tool,
-			  enum oe_flush how);
-void ordered_events__init(struct ordered_events *oe);
+int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
+void ordered_events__init(struct ordered_events *oe, struct machines *machines,
+			  struct perf_evlist *evlsit, struct perf_tool *tool);
 void ordered_events__free(struct ordered_events *oe);
 
 static inline
tools/perf/util/session.c +26 -39

191 lines not on this page · raw message

tools/perf/util/session.h +4 -7
index c08fa6be5bf3..06e0777e9803 100644
@@ -48,12 +48,10 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
 			     union perf_event **event_ptr,
 			     struct perf_sample *sample);
 
-int perf_session__process_events(struct perf_session *session,
-				 struct perf_tool *tool);
+int perf_session__process_events(struct perf_session *session);
 
-int perf_session_queue_event(struct perf_session *s, union perf_event *event,
-			     struct perf_tool *tool, struct perf_sample *sample,
-			     u64 file_offset);
+int perf_session__queue_event(struct perf_session *s, union perf_event *event,
+			      struct perf_sample *sample, u64 file_offset);
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
@@ -126,8 +124,7 @@ extern volatile int session_done;
 
 int perf_session__deliver_synth_event(struct perf_session *session,
 				      union perf_event *event,
-				      struct perf_sample *sample,
-				      struct perf_tool *tool);
+				      struct perf_sample *sample);
 
 int perf_event__process_id_index(struct perf_tool *tool,
 				 union perf_event *event,
Signature · 1 line
1.9.3
author maintainer
#3 lore raw

PATCH 3/24 perf ordered_events: Allow tools to specify a deliver method

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

So that we can simplify the deliver method to pass just:

(ordered_events, ordered_event, sample);

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/util/ordered-events.c |  7 ++++---
 tools/perf/util/ordered-events.h | 11 ++++++++++-
 tools/perf/util/session.c        | 30 +++++++++++++++++++++++-------
 tools/perf/util/session.h        |  6 ------
 4 files changed, 37 insertions(+), 17 deletions(-)
tools/perf/util/ordered-events.c +4 -3
index bad46ce16591..0d8cea91d2c9 100644
@@ -181,8 +181,7 @@ static int __ordered_events__flush(struct ordered_events *oe)
 		if (ret)
 			pr_err("Can't parse sample, err = %d\n", ret);
 		else {
-			ret = machines__deliver_event(oe->machines, oe->evlist, iter->event,
-						      &sample, oe->tool, iter->file_offset);
+			ret = oe->deliver(oe, iter, &sample);
 			if (ret)
 				return ret;
 		}
@@ -264,7 +263,8 @@ int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
 }
 
 void ordered_events__init(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlist, struct perf_tool *tool)
+			  struct perf_evlist *evlist, struct perf_tool *tool,
+			  ordered_events__deliver_t deliver)
 {
 	INIT_LIST_HEAD(&oe->events);
 	INIT_LIST_HEAD(&oe->cache);
@@ -274,6 +274,7 @@ void ordered_events__init(struct ordered_events *oe, struct machines *machines,
 	oe->evlist	   = evlist;
 	oe->machines	   = machines;
 	oe->tool	   = tool;
+	oe->deliver	   = deliver;
 }
 
 void ordered_events__free(struct ordered_events *oe)
tools/perf/util/ordered-events.h +10 -1
index ef7d73ecb0d0..c6cf0bafbb2c 100644
@@ -5,6 +5,7 @@
 
 struct perf_tool;
 struct perf_evlist;
+struct perf_sample;
 struct machines;
 
 struct ordered_event {
@@ -21,6 +22,12 @@ enum oe_flush {
 	OE_FLUSH__HALF,
 };
 
+struct ordered_events;
+
+typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
+					 struct ordered_event *event,
+					 struct perf_sample *sample);
+
 struct ordered_events {
 	u64			last_flush;
 	u64			next_flush;
@@ -35,6 +42,7 @@ struct ordered_events {
 	struct machines		*machines;
 	struct perf_evlist	*evlist;
 	struct perf_tool	*tool;
+	ordered_events__deliver_t deliver;
 	int			buffer_idx;
 	unsigned int		nr_events;
 	enum oe_flush		last_flush_type;
@@ -46,7 +54,8 @@ struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timesta
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
 int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
 void ordered_events__init(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlsit, struct perf_tool *tool);
+			  struct perf_evlist *evlsit, struct perf_tool *tool,
+			  ordered_events__deliver_t deliver);
 void ordered_events__free(struct ordered_events *oe);
 
 static inline
tools/perf/util/session.c +23 -7
index c6dd89f62fc4..e2f318a3f17a 100644
@@ -16,6 +16,12 @@
 #include "perf_regs.h"
 #include "asm/bug.h"
 
+static int machines__deliver_event(struct machines *machines,
+				   struct perf_evlist *evlist,
+				   union perf_event *event,
+				   struct perf_sample *sample,
+				   struct perf_tool *tool, u64 file_offset);
+
 static int perf_session__open(struct perf_session *session)
 {
 	struct perf_data_file *file = session->file;
@@ -86,6 +92,14 @@ static void perf_session__set_comm_exec(struct perf_session *session)
 	machines__set_comm_exec(&session->machines, comm_exec);
 }
 
+static int ordered_events__deliver_event(struct ordered_events *oe,
+					 struct ordered_event *event,
+					 struct perf_sample *sample)
+{
+	return machines__deliver_event(oe->machines, oe->evlist, event->event,
+				       sample, oe->tool, event->file_offset);
+}
+
 struct perf_session *perf_session__new(struct perf_data_file *file,
 				       bool repipe, struct perf_tool *tool)
 {
@@ -125,8 +139,10 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 	    tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
 		tool->ordered_events = false;
-	} else
-		ordered_events__init(&session->ordered_events, &session->machines, session->evlist, tool);
+	} else {
+		ordered_events__init(&session->ordered_events, &session->machines,
+				     session->evlist, tool, ordered_events__deliver_event);
+	}
 
 	return session;
 
@@ -888,11 +904,11 @@ static int
 					    &sample->read.one, machine);
 }
 
-int machines__deliver_event(struct machines *machines,
-				struct perf_evlist *evlist,
-				union perf_event *event,
-				struct perf_sample *sample,
-				struct perf_tool *tool, u64 file_offset)
+static int machines__deliver_event(struct machines *machines,
+				   struct perf_evlist *evlist,
+				   union perf_event *event,
+				   struct perf_sample *sample,
+				   struct perf_tool *tool, u64 file_offset)
 {
 	struct perf_evsel *evsel;
 	struct machine *machine;
tools/perf/util/session.h +0 -6
index 06e0777e9803..1310998f8318 100644
@@ -55,12 +55,6 @@ int perf_session__queue_event(struct perf_session *s, union perf_event *event,
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
-int machines__deliver_event(struct machines *machines,
-				struct perf_evlist *evlist,
-				union perf_event *event,
-				struct perf_sample *sample,
-				struct perf_tool *tool, u64 file_offset);
-
 int perf_session__resolve_callchain(struct perf_session *session,
 				    struct perf_evsel *evsel,
 				    struct thread *thread,
Signature · 1 line
1.9.3
author maintainer
#4 lore raw

PATCH 4/24 perf tools: tool->finished_round() doesn't need perf_session

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

It is all about flushing the ordered queue or piping it thru, no need for a perf_session pointer.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/builtin-inject.c |  9 ++++++++-
 tools/perf/builtin-kvm.c    |  7 +++++--
 tools/perf/util/session.c   | 24 +++++++++++++++---------
 tools/perf/util/tool.h      |  8 ++++++--
 4 files changed, 34 insertions(+), 14 deletions(-)
tools/perf/builtin-inject.c +8 -1
index 2563f07ec0e5..ea46df25368c 100644
@@ -53,6 +53,13 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
 	return 0;
 }
 
+static int perf_event__repipe_oe_synth(struct perf_tool *tool,
+				       union perf_event *event,
+				       struct ordered_events *oe __maybe_unused)
+{
+	return perf_event__repipe_synth(tool, event);
+}
+
 static int perf_event__repipe_op2_synth(struct perf_tool *tool,
 					union perf_event *event,
 					struct perf_session *session
@@ -406,7 +413,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 			.unthrottle	= perf_event__repipe,
 			.attr		= perf_event__repipe_attr,
 			.tracing_data	= perf_event__repipe_op2_synth,
-			.finished_round	= perf_event__repipe_op2_synth,
+			.finished_round	= perf_event__repipe_oe_synth,
 			.build_id	= perf_event__repipe_op2_synth,
 			.id_index	= perf_event__repipe_op2_synth,
 		},
tools/perf/builtin-kvm.c +5 -2
index 802b8f53fa9a..643722f40075 100644
@@ -18,6 +18,7 @@
 #include "util/stat.h"
 #include "util/top.h"
 #include "util/data.h"
+#include "util/ordered-events.h"
 
 #include <sys/prctl.h>
 #ifdef HAVE_TIMERFD_SUPPORT
@@ -783,8 +784,10 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
 
 	/* flush queue after each round in which we processed events */
 	if (ntotal) {
-		kvm->session->ordered_events.next_flush = flush_time;
-		err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
+		struct ordered_events *oe = &kvm->session->ordered_events;
+
+		oe->next_flush = flush_time;
+		err = ordered_events__flush(oe, OE_FLUSH__ROUND);
 		if (err) {
 			if (kvm->lost_events)
 				pr_info("\nLost events: %" PRIu64 "\n\n",
tools/perf/util/session.c +15 -9
index e2f318a3f17a..703a370ae5b6 100644
@@ -225,10 +225,17 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
+				 union perf_event *event __maybe_unused,
+				 struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
 				       union perf_event *event __maybe_unused,
-				       struct perf_session *perf_session
-				       __maybe_unused)
+				       struct ordered_events *oe __maybe_unused)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -236,7 +243,7 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
 
 static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event,
-				  struct perf_session *session);
+				  struct ordered_events *oe);
 
 static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
 				 union perf_event *event __maybe_unused,
@@ -274,7 +281,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 	if (tool->tracing_data == NULL)
 		tool->tracing_data = process_event_synth_tracing_data_stub;
 	if (tool->build_id == NULL)
-		tool->build_id = process_finished_round_stub;
+		tool->build_id = process_build_id_stub;
 	if (tool->finished_round == NULL) {
 		if (tool->ordered_events)
 			tool->finished_round = process_finished_round;
@@ -526,10 +533,8 @@ static perf_event__swap_op perf_event__swap_ops[] = {
  */
 static int process_finished_round(struct perf_tool *tool __maybe_unused,
 				  union perf_event *event __maybe_unused,
-				  struct perf_session *session)
+				  struct ordered_events *oe)
 {
-	struct ordered_events *oe = &session->ordered_events;
-
 	return ordered_events__flush(oe, OE_FLUSH__ROUND);
 }
 
@@ -961,7 +966,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 					    union perf_event *event,
 					    u64 file_offset)
 {
-	struct perf_tool *tool = session->ordered_events.tool;
+	struct ordered_events *oe = &session->ordered_events;
+	struct perf_tool *tool = oe->tool;
 	int fd = perf_data_file__fd(session->file);
 	int err;
 
@@ -989,7 +995,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 	case PERF_RECORD_HEADER_BUILD_ID:
 		return tool->build_id(tool, event, session);
 	case PERF_RECORD_FINISHED_ROUND:
-		return tool->finished_round(tool, event, session);
+		return tool->finished_round(tool, event, oe);
 	case PERF_RECORD_ID_INDEX:
 		return tool->id_index(tool, event, session);
 	default:
tools/perf/util/tool.h +6 -2
index bb2708bbfaca..51d9e56c0f84 100644
@@ -10,6 +10,7 @@ struct perf_evsel;
 struct perf_sample;
 struct perf_tool;
 struct machine;
+struct ordered_events;
 
 typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
 			    struct perf_sample *sample,
@@ -25,6 +26,9 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
 typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
 			 struct perf_session *session);
 
+typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
+			struct ordered_events *oe);
+
 struct perf_tool {
 	event_sample	sample,
 			read;
@@ -38,8 +42,8 @@ struct perf_tool {
 			unthrottle;
 	event_attr_op	attr;
 	event_op2	tracing_data;
-	event_op2	finished_round,
-			build_id,
+	event_oe	finished_round;
+	event_op2	build_id,
 			id_index;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
Signature · 1 line
1.9.3
author maintainer
#5 lore raw

PATCH 5/24 perf tools: Remove superfluous thread->comm_set setting

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

It is set by calling thread__set_comm right before the removed line.

Cc Adrian Hunter <[email protected]>
Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/util/thread.c | 1 -
 1 file changed, 1 deletion(-)
tools/perf/util/thread.c +0 -1
index a5dbba95107f..1c8fbc9588c5 100644
@@ -206,7 +206,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 		err = thread__set_comm(thread, comm, timestamp);
 		if (err)
 			return err;
-		thread->comm_set = true;
 	}
 
 	thread->ppid = parent->tid;
Signature · 1 line
1.9.3
author maintainer
#6 lore raw

PATCH 6/24 perf ordered_events: Adopt queue() method

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Quoted 1 line

From perf_session, will be used in 'trace'.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/perf/util/ordered-events.c | 34 ++++++++++++++++++++++++++++++++--
 tools/perf/util/ordered-events.h |  4 ++--
 tools/perf/util/session.c        | 28 +---------------------------
 3 files changed, 35 insertions(+), 31 deletions(-)
tools/perf/util/ordered-events.c +32 -2
index 0d8cea91d2c9..6002fa3fcf77 100644
@@ -131,8 +131,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
 	return new;
 }
 
-struct ordered_event *
-ordered_events__new(struct ordered_events *oe, u64 timestamp,
+static struct ordered_event *
+ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
 		    union perf_event *event)
 {
 	struct ordered_event *new;
@@ -153,6 +153,36 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
 	free_dup_event(oe, event->event);
 }
 
+int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
+			  struct perf_sample *sample, u64 file_offset)
+{
+	u64 timestamp = sample->time;
+	struct ordered_event *oevent;
+
+	if (!timestamp || timestamp == ~0ULL)
+		return -ETIME;
+
+	if (timestamp < oe->last_flush) {
+		pr_oe_time(timestamp,      "out of order event\n");
+		pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
+			   oe->last_flush_type);
+
+		oe->evlist->stats.nr_unordered_events++;
+	}
+
+	oevent = ordered_events__new_event(oe, timestamp, event);
+	if (!oevent) {
+		ordered_events__flush(oe, OE_FLUSH__HALF);
+		oevent = ordered_events__new_event(oe, timestamp, event);
+	}
+
+	if (!oevent)
+		return -ENOMEM;
+
+	oevent->file_offset = file_offset;
+	return 0;
+}
+
 static int __ordered_events__flush(struct ordered_events *oe)
 {
 	struct list_head *head = &oe->events;
tools/perf/util/ordered-events.h +2 -2
index c6cf0bafbb2c..173e13f28c08 100644
@@ -49,8 +49,8 @@ struct ordered_events {
 	bool                    copy_on_queue;
 };
 
-struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
-					  union perf_event *event);
+int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
+			  struct perf_sample *sample, u64 file_offset);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
 int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
 void ordered_events__init(struct ordered_events *oe, struct machines *machines,
tools/perf/util/session.c +1 -27
index 703a370ae5b6..adf0740c563b 100644
@@ -541,33 +541,7 @@ static int process_finished_round(struct perf_tool *tool __maybe_unused,
 int perf_session__queue_event(struct perf_session *s, union perf_event *event,
 			      struct perf_sample *sample, u64 file_offset)
 {
-	struct ordered_events *oe = &s->ordered_events;
-
-	u64 timestamp = sample->time;
-	struct ordered_event *new;
-
-	if (!timestamp || timestamp == ~0ULL)
-		return -ETIME;
-
-	if (timestamp < oe->last_flush) {
-		pr_oe_time(timestamp,      "out of order event\n");
-		pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
-			   oe->last_flush_type);
-
-		s->evlist->stats.nr_unordered_events++;
-	}
-
-	new = ordered_events__new(oe, timestamp, event);
-	if (!new) {
-		ordered_events__flush(oe, OE_FLUSH__HALF);
-		new = ordered_events__new(oe, timestamp, event);
-	}
-
-	if (!new)
-		return -ENOMEM;
-
-	new->file_offset = file_offset;
-	return 0;
+	return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
 }
 
 static void callchain__lbr_callstack_printf(struct perf_sample *sample)
Signature · 1 line
1.9.3
author maintainer
#7 lore raw

PATCH 7/24 perf probe: Fix to handle aliased symbols in glibc

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Fix perf probe to handle aliased symbols correctly in glibc. In the glibc, several symbols are defined as an alias of __libc_XXX, e.g. malloc is an alias of __libc_malloc.

In such cases, dwarf has no subroutine instances of the alias functions (e.g. no "malloc" instance), but the map has that symbol and its address.

Thus, if we search the alieased symbol in debuginfo, we always fail to find it, but it is in the map.

To solve this problem, this fails back to address-based alternative search, which searches the symbol in the map, translates its address to alternative (correct) function name by using debuginfo, and retry to find the alternative function point from debuginfo.

This adds fail-back process to --vars, --lines and --add options. So, now you can use those on malloc@libc :)

Without this patch;
-----

  # ./perf probe -x /usr/lib64/libc-2.17.so -V malloc
  Failed to find the address of malloc
    Error: Failed to show vars.
  # ./perf probe -x /usr/lib64/libc-2.17.so -a "malloc bytes"
  Probe point 'malloc' not found in debuginfo.
    Error: Failed to add events.
  -----

With this patch;
-----

  # ./perf probe -x /usr/lib64/libc-2.17.so -V malloc
  Available variables at malloc
          @<__libc_malloc+0>
                  size_t  bytes
  # ./perf probe -x /usr/lib64/libc-2.17.so -a "malloc bytes"
  Added new event:
    probe_libc:malloc    (on malloc in /usr/lib64/libc-2.17.so with bytes)

You can now use it in all perf tools, such as:

perf record -e probe_libc:malloc -aR sleep 1
-----

---
 tools/perf/util/probe-event.c | 140 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 124 insertions(+), 16 deletions(-)
tools/perf/util/probe-event.c +124 -16
index 1c570c2fa7cc..b8f45782126a 100644
@@ -178,6 +178,25 @@ static struct map *kernel_get_module_map(const char *module)
 	return NULL;
 }
 
+static struct map *get_target_map(const char *target, bool user)
+{
+	/* Init maps of given executable or kernel */
+	if (user)
+		return dso__new_map(target);
+	else
+		return kernel_get_module_map(target);
+}
+
+static void put_target_map(struct map *map, bool user)
+{
+	if (map && user) {
+		/* Only the user map needs to be released */
+		dso__delete(map->dso);
+		map__delete(map);
+	}
+}
+
+
 static struct dso *kernel_get_module_dso(const char *module)
 {
 	struct dso *dso;
@@ -249,6 +268,13 @@ out:
 	return ret;
 }
 
+static void clear_perf_probe_point(struct perf_probe_point *pp)
+{
+	free(pp->file);
+	free(pp->function);
+	free(pp->lazy_line);
+}
+
 static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 {
 	int i;
@@ -258,6 +284,74 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 }
 
 #ifdef HAVE_DWARF_SUPPORT
+/*
+ * Some binaries like glibc have special symbols which are on the symbol
+ * table, but not in the debuginfo. If we can find the address of the
+ * symbol from map, we can translate the address back to the probe point.
+ */
+static int find_alternative_probe_point(struct debuginfo *dinfo,
+					struct perf_probe_point *pp,
+					struct perf_probe_point *result,
+					const char *target, bool uprobes)
+{
+	struct map *map = NULL;
+	struct symbol *sym;
+	u64 address = 0;
+	int ret = -ENOENT;
+
+	/* This can work only for function-name based one */
+	if (!pp->function || pp->file)
+		return -ENOTSUP;
+
+	map = get_target_map(target, uprobes);
+	if (!map)
+		return -EINVAL;
+
+	/* Find the address of given function */
+	map__for_each_symbol_by_name(map, pp->function, sym) {
+		if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) {
+			address = sym->start;
+			break;
+		}
+	}
+	if (!address) {
+		ret = -ENOENT;
+		goto out;
+	}
+	pr_debug("Symbol %s address found : %lx\n", pp->function, address);
+
+	ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
+					  result);
+	if (ret <= 0)
+		ret = (!ret) ? -ENOENT : ret;
+	else {
+		result->offset += pp->offset;
+		result->line += pp->line;
+		ret = 0;
+	}
+
+out:
+	put_target_map(map, uprobes);
+	return ret;
+
+}
+
+static int get_alternative_probe_event(struct debuginfo *dinfo,
+				       struct perf_probe_event *pev,
+				       struct perf_probe_point *tmp,
+				       const char *target)
+{
+	int ret;
+
+	memcpy(tmp, &pev->point, sizeof(*tmp));
+	memset(&pev->point, 0, sizeof(pev->point));
+	ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
+					   target, pev->uprobes);
+	if (ret < 0)
+		memcpy(&pev->point, tmp, sizeof(*tmp));
+
+	return ret;
+}
 
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module, bool silent)
@@ -466,6 +560,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 					  int max_tevs, const char *target)
 {
 	bool need_dwarf = perf_probe_event_need_dwarf(pev);
+	struct perf_probe_point tmp;
 	struct debuginfo *dinfo;
 	int ntevs, ret = 0;
 
@@ -482,6 +577,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 	/* Searching trace events corresponding to a probe event */
 	ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
 
+	if (ntevs == 0)	{  /* Not found, retry with an alternative */
+		ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+		if (!ret) {
+			ntevs = debuginfo__find_trace_events(dinfo, pev,
+							     tevs, max_tevs);
+			/*
+			 * Write back to the original probe_event for
+			 * setting appropriate (user given) event name
+			 */
+			clear_perf_probe_point(&pev->point);
+			memcpy(&pev->point, &tmp, sizeof(tmp));
+		}
+	}
+
 	debuginfo__delete(dinfo);
 
 	if (ntevs > 0) {	/* Succeeded to find trace events */
@@ -719,12 +828,13 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
 static int show_available_vars_at(struct debuginfo *dinfo,
 				  struct perf_probe_event *pev,
 				  int max_vls, struct strfilter *_filter,
-				  bool externs)
+				  bool externs, const char *target)
 {
 	char *buf;
 	int ret, i, nvars;
 	struct str_node *node;
 	struct variable_list *vls = NULL, *vl;
+	struct perf_probe_point tmp;
 	const char *var;
 
 	buf = synthesize_perf_probe_point(&pev->point);
@@ -734,6 +844,15 @@ static int show_available_vars_at(struct debuginfo *dinfo,
 
 	ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
 						max_vls, externs);
+	if (!ret) {  /* Not found, retry with an alternative */
+		ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+		if (!ret) {
+			ret = debuginfo__find_available_vars_at(dinfo, pev,
+						&vls, max_vls, externs);
+			/* Release the old probe_point */
+			clear_perf_probe_point(&tmp);
+		}
+	}
 	if (ret <= 0) {
 		if (ret == 0 || ret == -ENOENT) {
 			pr_err("Failed to find the address of %s\n", buf);
@@ -796,7 +915,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
 
 	for (i = 0; i < npevs && ret >= 0; i++)
 		ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
-					     externs);
+					     externs, module);
 
 	debuginfo__delete(dinfo);
 out:
@@ -1742,15 +1861,12 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
 
 void clear_perf_probe_event(struct perf_probe_event *pev)
 {
-	struct perf_probe_point *pp = &pev->point;
 	struct perf_probe_arg_field *field, *next;
 	int i;
 
 	free(pev->event);
 	free(pev->group);
-	free(pp->file);
-	free(pp->function);
-	free(pp->lazy_line);
+	clear_perf_probe_point(&pev->point);
 
 	for (i = 0; i < pev->nargs; i++) {
 		free(pev->args[i].name);
@@ -2367,11 +2483,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
 	int num_matched_functions;
 	int ret, i;
 
-	/* Init maps of given executable or kernel */
-	if (pev->uprobes)
-		map = dso__new_map(target);
-	else
-		map = kernel_get_module_map(target);
+	map = get_target_map(target, pev->uprobes);
 	if (!map) {
 		ret = -EINVAL;
 		goto out;
@@ -2464,11 +2576,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
 	}
 
 out:
-	if (map && pev->uprobes) {
-		/* Only when using uprobe(exec) map needs to be released */
-		dso__delete(map->dso);
-		map__delete(map);
-	}
+	put_target_map(map, pev->uprobes);
 	return ret;
 
 nomem_out:
Signature · 1 line
1.9.3
author maintainer
#8 lore raw

PATCH 8/24 perf probe: Fix --line to handle aliased symbols in glibc

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Fix perf probe --line to handle aliased symbols correctly in glibc.

This makes line_range search failing back to address-based alternative search as same as --add and --vars.

Without this patch;
-----

  # ./perf probe -x /usr/lib64/libc-2.17.so -L malloc
  Specified source line is not found.
    Error: Failed to show lines.
  -----

With this patch;
-----

  # ./perf probe -x /usr/lib64/libc-2.17.so -L malloc
  <__libc_malloc@/usr/src/debug/glibc-2.17-c758a686/malloc/malloc.c:0>
        0  __libc_malloc(size_t bytes)
        1  {
             mstate ar_ptr;
             void *victim;
             __malloc_ptr_t (*hook) (size_t, const __malloc_ptr_t)
        6      = force_reg (__malloc_hook);
        7    if (__builtin_expect (hook != NULL, 0))
        8      return (*hook)(bytes, RETURN_ADDRESS (0));

       10    arena_lookup(ar_ptr);

       12    arena_lock(ar_ptr, bytes);

-----

Note that this actually shows __libc_malloc, since it is the real instance of malloc. User can use both __libc_malloc and malloc for --line.

---
 tools/perf/util/probe-event.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)
tools/perf/util/probe-event.c +33 -2
index b8f45782126a..4cfd1211a2ae 100644
@@ -353,6 +353,31 @@ static int get_alternative_probe_event(struct debuginfo *dinfo,
 	return ret;
 }
 
+static int get_alternative_line_range(struct debuginfo *dinfo,
+				      struct line_range *lr,
+				      const char *target, bool user)
+{
+	struct perf_probe_point pp = { 0 }, result = { 0 };
+	int ret, len = 0;
+
+	pp.function = lr->function;
+	pp.file = lr->file;
+	pp.line = lr->start;
+	if (lr->end != INT_MAX)
+		len = lr->end - lr->start;
+	ret = find_alternative_probe_point(dinfo, &pp, &result,
+					   target, user);
+	if (!ret) {
+		lr->function = result.function;
+		lr->file = result.file;
+		lr->start = result.line;
+		if (lr->end != INT_MAX)
+			lr->end = lr->start + len;
+		clear_perf_probe_point(&pp);
+	}
+	return ret;
+}
+
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module, bool silent)
 {
@@ -734,7 +759,8 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
  * Show line-range always requires debuginfo to find source file and
  * line number.
  */
-static int __show_line_range(struct line_range *lr, const char *module)
+static int __show_line_range(struct line_range *lr, const char *module,
+			     bool user)
 {
 	int l = 1;
 	struct int_node *ln;
@@ -750,6 +776,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
 		return -ENOENT;
 
 	ret = debuginfo__find_line_range(dinfo, lr);
+	if (!ret) {	/* Not found, retry with an alternative */
+		ret = get_alternative_line_range(dinfo, lr, module, user);
+		if (!ret)
+			ret = debuginfo__find_line_range(dinfo, lr);
+	}
 	debuginfo__delete(dinfo);
 	if (ret == 0 || ret == -ENOENT) {
 		pr_warning("Specified source line is not found.\n");
@@ -819,7 +850,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
 	ret = init_symbol_maps(user);
 	if (ret < 0)
 		return ret;
-	ret = __show_line_range(lr, module);
+	ret = __show_line_range(lr, module, user);
 	exit_symbol_maps();
 
 	return ret;
Signature · 1 line
1.9.3
author maintainer
#9 lore raw

PATCH 9/24 Revert "perf probe: Fix to fall back to find probe point in symbols"

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

This reverts commit 906451b98b67 ("perf probe: Fix to fall back to find probe point in symbols").

Since 'perf probe' now retries with the address of given symbol searched from map before this path, this fall back routine isn't needed anymore.

---
 tools/perf/util/probe-event.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/probe-event.c +2 -4
index 4cfd1211a2ae..c379ea0edfd5 100644
@@ -630,11 +630,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 	}
 
 	if (ntevs == 0)	{	/* No error but failed to find probe point. */
-		pr_warning("Probe point '%s' not found in debuginfo.\n",
+		pr_warning("Probe point '%s' not found.\n",
 			   synthesize_perf_probe_point(&pev->point));
-		if (need_dwarf)
-			return -ENOENT;
-		return 0;
+		return -ENOENT;
 	}
 	/* Error path : ntevs < 0 */
 	pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
Signature · 1 line
1.9.3
author maintainer
#10 lore raw

PATCH 10/24 perf symbols: Allow symbol alias when loading map for symbol name

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

When perf probe tries to add a probe in a binary using symbol name, it sometimes failed since some symbols were discard during loading dso.

When it resolves an address to symbol, it'd be better to have just one symbol at given address. But for finding address from symbol, it'd be better to keep all names (including aliases).

So allow tools to state that they want to allow aliases via symbol_conf.allow_aliases.

Cc David Ahern <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Naohiro Aota <[email protected]>
Cc Peter Zijlstra <[email protected]>
[ Original patch passwd allow_alias to many functions, use symbol_conf.allow_aliases instead ]
---
 tools/perf/util/probe-event.c | 1 +
 tools/perf/util/symbol-elf.c  | 3 ++-
 tools/perf/util/symbol.h      | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +1 -0
index c379ea0edfd5..9feba0e3343e 100644
@@ -80,6 +80,7 @@ static int init_symbol_maps(bool user_only)
 	int ret;
 
 	symbol_conf.sort_by_name = true;
+	symbol_conf.allow_aliases = true;
 	ret = symbol__init(NULL);
 	if (ret < 0) {
 		pr_debug("Failed to init symbol map.\n");
tools/perf/util/symbol-elf.c +2 -1
index ada16762fac2..62742e46c010 100644
@@ -1048,7 +1048,8 @@ new_symbol:
 	 * For misannotated, zeroed, ASM function sizes.
 	 */
 	if (nr > 0) {
-		symbols__fixup_duplicate(&dso->symbols[map->type]);
+		if (!symbol_conf.allow_aliases)
+			symbols__fixup_duplicate(&dso->symbols[map->type]);
 		symbols__fixup_end(&dso->symbols[map->type]);
 		if (kmap) {
 			/*
tools/perf/util/symbol.h +1 -0
index 1650dcb3a67b..efdaaa544041 100644
@@ -87,6 +87,7 @@ struct symbol_conf {
 			ignore_vmlinux_buildid,
 			show_kernel_path,
 			use_modules,
+			allow_aliases,
 			sort_by_name,
 			show_nr_samples,
 			show_total_period,
Signature · 1 line
1.9.3
author maintainer
#11 lore raw

PATCH 11/24 perf probe: Allow weak symbols to be probed

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

It currently prevents adding probes in weak symbols. But there're cases that given name is an only weak symbol so that we cannot add probe.

  $ perf probe -x /usr/lib/libc.so.6 -a calloc
  Failed to find symbol calloc in /usr/lib/libc-2.21.so
    Error: Failed to add events.
  $ nm /usr/lib/libc.so.6 | grep calloc
  000000000007b1f0 t __calloc
  000000000007b1f0 T __libc_calloc
  000000000007b1f0 W calloc

This change will result in duplicate probes when strong and weak symbols co-exist in a binary. But I think it's not a big problem since probes at the weak symbol will never be hit anyway.

---
 tools/perf/util/probe-event.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
tools/perf/util/probe-event.c +4 -8
index 9feba0e3343e..8af8e7f55254 100644
@@ -310,10 +310,8 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
 
 	/* Find the address of given function */
 	map__for_each_symbol_by_name(map, pp->function, sym) {
-		if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) {
-			address = sym->start;
-			break;
-		}
+		address = sym->start;
+		break;
 	}
 	if (!address) {
 		ret = -ENOENT;
@@ -2485,8 +2483,7 @@ static int find_probe_functions(struct map *map, char *name)
 	struct symbol *sym;
 
 	map__for_each_symbol_by_name(map, name, sym) {
-		if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL)
-			found++;
+		found++;
 	}
 
 	return found;
@@ -2846,8 +2843,7 @@ static struct strfilter *available_func_filter;
 static int filter_available_functions(struct map *map __maybe_unused,
 				      struct symbol *sym)
 {
-	if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
-	    strfilter__compare(available_func_filter, sym->name))
+	if (strfilter__compare(available_func_filter, sym->name))
 		return 0;
 	return 1;
 }
Signature · 1 line
1.9.3
author maintainer
#12 lore raw

PATCH 12/24 perf build: Fix libbabeltrace detection

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

Following patch added -Werror for feature builds:

b49f1a4be701 perf tools: Improve feature test debuggability

and exposed a problem in the libbabeltrace feature build, because it was including wrong header and gcc couldn't find the used symbol definition.

Adding proper header and keeping the old one as it is needed also (libbabeltrace quirk).

---
 tools/perf/config/feature-checks/test-libbabeltrace.c | 1 +
 1 file changed, 1 insertion(+)
tools/perf/config/feature-checks/test-libbabeltrace.c +1 -0
index 3b7dd68a4d52..9cf802a04885 100644
@@ -1,5 +1,6 @@
 
 #include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-ir/stream-class.h>
 
 int main(void)
 {
Signature · 1 line
1.9.3
author maintainer
#13 lore raw

PATCH 13/24 perf tools: Output feature detection's gcc output to a file

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

So that we can debug feature detection problems.

It will appear on $(OUTPUT)feature-checks/.make-libbabeltrace.output, using the libbabeltrace feature test.

Whole process:

[acme@ssdandy linux]$ make -C tools/perf install-bin
make: Entering directory `/home/acme/git/linux/tools/perf'
BUILD: Doing 'make -j8' parallel build
config/Makefile:425: No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR config/Makefile:709: No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev

Auto-detecting system features:

  ...                         dwarf: [ on  ]
  ...                         glibc: [ on  ]
  ...                          gtk2: [ on  ]
  ...                      libaudit: [ on  ]
  ...                        libbfd: [ on  ]
  ...                        libelf: [ on  ]
  ...                       libnuma: [ on  ]
  ...                       libperl: [ on  ]
  ...                     libpython: [ on  ]
  ...                      libslang: [ on  ]
  ...                     libunwind: [ OFF ]
  ...            libdw-dwarf-unwind: [ on  ]
  ...                 libbabeltrace: [ OFF ]
  <SNIP>
  [acme@ssdandy linux]$ find tools/perf -name ".make-*.output" | grep lib | tail -5
  tools/perf/config/feature-checks/.make-libdw-dwarf-unwind.output
  tools/perf/config/feature-checks/.make-libbabeltrace.output
  tools/perf/config/feature-checks/.make-zlib.output
  tools/perf/config/feature-checks/.make-liberty.output
  tools/perf/config/feature-checks/.make-liberty-z.output
  [acme@ssdandy linux]$
  [acme@ssdandy linux]$ cat tools/perf/config/feature-checks/.make-libbabeltrace.output
  make[1]: Entering directory `/home/acme/git/linux/tools/perf/config/feature-checks'
  gcc -MD  -Wall -Werror -o test-libbabeltrace.bin test-libbabeltrace.c -Wl,-z,noexecstack  -lbabeltrace-ctf # -lbabeltrace provided by
  test-libbabeltrace.c:2:42: fatal error: babeltrace/ctf-writer/writer.h: No such file or directory
    #include <babeltrace/ctf-writer/writer.h>
                                          ^

compilation terminated.
make[1]: *** [test-libbabeltrace.bin] Error 1
make[1]: Leaving directory `/home/acme/git/linux/tools/perf/config/feature-checks' [acme@ssdandy linux]$

So the libbabeltrace feature will not be builtin, but if we do what is required for it to be built, namely point where we have it installed:

[acme@ssdandy linux]$ time make -C tools/perf LIBBABELTRACE_DIR=/opt/libbabeltrace install-bin
make: Entering directory `/home/acme/git/linux/tools/perf'
BUILD: Doing 'make -j8' parallel build
config/Makefile:425: No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR

Auto-detecting system features:

  ...                         dwarf: [ on  ]
  ...                         glibc: [ on  ]
  ...                          gtk2: [ on  ]
  ...                      libaudit: [ on  ]
  ...                        libbfd: [ on  ]
  ...                        libelf: [ on  ]
  ...                       libnuma: [ on  ]
  ...                       libperl: [ on  ]
  ...                     libpython: [ on  ]
  ...                      libslang: [ on  ]
  ...                     libunwind: [ OFF ]
  ...            libdw-dwarf-unwind: [ on  ]
  ...                 libbabeltrace: [ on  ]
  ...                          zlib: [ on  ]

... DWARF post unwind library: libdw
<SNIP>
[acme@ssdandy linux]$ find tools/perf -name ".make-libbabel*.output" | grep lib | tail -5
tools/perf/config/feature-checks/.make-libbabeltrace.output
[acme@ssdandy linux]$ cat tools/perf/config/feature-checks/.make-libbabeltrace.output
make[1]: Entering directory `/home/acme/git/linux/tools/perf/config/feature-checks'
gcc -MD -I/opt/libbabeltrace/include -Wall -Werror -o test-libbabeltrace.bin test-libbabeltrace.c -Wl,-z,noexecstack -L/opt/libbabeltrace/lib -lbabeltrace-ctf # -lbabeltrace provided by make[1]: Leaving directory `/home/acme/git/linux/tools/perf/config/feature-checks'
[acme@ssdandy linux]$

Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jeremie Galarneau <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Sebastian Andrzej Siewior <[email protected]>
Cc Tom Zanussi <[email protected]>
Cc Wang Nan <[email protected]>
---
 tools/perf/Makefile.perf   | 1 +
 tools/perf/config/Makefile | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
tools/perf/Makefile.perf +1 -0
index ec4c063ed9f3..933d70345f87 100644
@@ -529,6 +529,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
 	$(Q)$(RM) .config-detected
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
 	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
+	$(call QUIET_CLEAN, feature-detect) $(RM) $(OUTPUT)config/feature-checks/.make-*.output
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 	$(python-clean)
 
tools/perf/config/Makefile +1 -1
index d44c64d64465..bd097187724b 100644
@@ -184,7 +184,7 @@ endif
 
 feature_check = $(eval $(feature_check_code))
 define feature_check_code
-  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
+  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin > $(OUTPUT)config/feature-checks/.make-$(1).output 2>&1 && echo 1 || echo 0)
 endef
 
 feature_set = $(eval $(feature_set_code))
Signature · 1 line
1.9.3
author maintainer
#14 lore raw

PATCH 14/24 perf probe: Fix possible double free on error

In reply to Arnaldo Carvalho de Melo

From: He Kuang <[email protected]>

A double free occurred when get source file path failed. If lr->path failed to assign a new value, it will be freed as the old path and then be freed again during line_range__clear(), and causes this:

  $ perf probe -L do_execve -k vmlinux
  *** Error in `/usr/bin/perf': double free or corruption (fasttop):
      0x0000000000a9ac50 ***
  ======= Backtrace: =========
  ../lib64/libc.so.6(+0x6eeef)[0x7ffff5e44eef]
  ../lib64/libc.so.6(+0x78cae)[0x7ffff5e4ecae]
  ../lib64/libc.so.6(+0x79987)[0x7ffff5e4f987]
  ../bin/perf[0x4ab41f]
  ...

This patch fix this problem.

---
 tools/perf/util/probe-event.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +5 -1
index 8af8e7f55254..e2bf620f98cb 100644
@@ -790,7 +790,11 @@ static int __show_line_range(struct line_range *lr, const char *module,
 	/* Convert source file path */
 	tmp = lr->path;
 	ret = get_real_path(tmp, lr->comp_dir, &lr->path);
-	free(tmp);	/* Free old path */
+
+	/* Free old path when new path is assigned */
+	if (tmp != lr->path)
+		free(tmp);
+
 	if (ret < 0) {
 		pr_warning("Failed to find source file path.\n");
 		return ret;
Signature · 1 line
1.9.3
author maintainer
#15 lore raw

PATCH 15/24 perf hists browser: Fix UI bug after zoom into thread/dso/symbol

In reply to Arnaldo Carvalho de Melo

From: He Kuang <[email protected]>

When zoom into thread/dso/symbol, the fold/unfold stat is cleared in hists__filter_by_thread/dso/symbol(), but h->nr_rows is not cleared. So if we toggle fold stat on the unfold entires, nr_entries got a wrong value.

This bug can be reproduced as follows:

$ perf record -g -e syscalls:sys_enter_open ls
$ perf report

Children Self Command Shared Object Symbol
================================================================

  +   50.00%     0.00%  ls       ld64.so  [.]  _dl_get_ready_to_run
  -   50.00%     0.00%  ls       ld64.so  [.]  _dl_load_shared_library

_dl_load_shared_library <= [Zoom into thread/dso] _dl_get_ready_to_run
_start
...

In the new thread hists, all entries reset to fold, if we unfold the same entry as we previously unfolded, nr_entries got wrong value, and we can't move down cursor to bottom row.

Thread: ls
Children Self Command Shared Object Symbol
================================================================

  +   50.00%     0.00%  ls       ld64.so  [.]  _dl_get_ready_to_run
  -   50.00%     0.00%  ls       ld64.so  [.]  _dl_load_shared_library

_dl_load_shared_library
_dl_get_ready_to_run <= [cursor may stop here, can't move down] _start
...

This patch clear h->nr_rows to fix this bug.

---
 tools/perf/util/hist.c | 1 +
 1 file changed, 1 insertion(+)
tools/perf/util/hist.c +1 -0
index 95f5ab707b74..d9a6d35eda17 100644
@@ -1171,6 +1171,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
 	/* force fold unfiltered entry for simplicity */
 	h->ms.unfolded = false;
 	h->row_offset = 0;
+	h->nr_rows = 0;
 
 	hists->stats.nr_non_filtered_samples += h->stat.nr_events;
 
Signature · 1 line
1.9.3
author maintainer
#16 lore raw

PATCH 16/24 perf probe: Fix compiles due to declarations using perf_probe_point

In reply to Arnaldo Carvalho de Melo

From: David Ahern <[email protected]>

perf fails to build with gcc "(GCC) 4.4.7 20120313 (Red Hat 4.4.7-4.0.9)" (a.k.a., RHEL6 / CentOS 6 / OL 6):

cc1: warnings being treated as errors
util/probe-event.c: In function ‘get_alternative_line_range’:
util/probe-event.c:359: error: missing initializer util/probe-event.c:359: error: (near initialization for ‘pp.file’) util/probe-event.c:359: error: missing initializer util/probe-event.c:359: error: (near initialization for ‘result.function’)

Fix by bringing in initializers to declaration.

---
 tools/perf/util/probe-event.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/probe-event.c +6 -4
index e2bf620f98cb..f272a711ad15 100644
@@ -356,12 +356,14 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
 				      struct line_range *lr,
 				      const char *target, bool user)
 {
-	struct perf_probe_point pp = { 0 }, result = { 0 };
+	struct perf_probe_point pp = { .function = lr->function,
+				       .file = lr->file,
+				       .line = lr->start };
+	struct perf_probe_point result;
 	int ret, len = 0;
 
-	pp.function = lr->function;
-	pp.file = lr->file;
-	pp.line = lr->start;
+	memset(&result, 0, sizeof(result));
+
 	if (lr->end != INT_MAX)
 		len = lr->end - lr->start;
 	ret = find_alternative_probe_point(dinfo, &pp, &result,
Signature · 1 line
1.9.3
author maintainer
#17 lore raw

PATCH 17/24 perf hists browser: Fix UI bug after fold/unfold

In reply to Arnaldo Carvalho de Melo

From: He Kuang <[email protected]>

In perf hists browser, the fold/unfold stat of each hist entry is recorded but hb->nr_callchain_rows loses its value after zoom out and zoom in back. This causes a wrong row cursor range that restrict user to move down anymore.

This bug can be reproduced as follows:

  $ perf record -g -e syscalls:* ls
  $ perf report

Available samples
================================================================
2 syscalls:sys_enter_mprotect <= [enter one of the entries] 2 syscalls:sys_exit_mprotect
13 syscalls:sys_enter_brk
...

In the hists brower, unfold some of the items, now the cursor can reach to any rows:

Children Self Command Shared Object Symbol
================================================================
- 100.00% 100.00% ls libuClibc-0.9.33.2.so [.] lstat64
- lstat64

       16.67% 0x6469702e64
       8.33% 0x646970
       8.33% 0x617461
       8.33% 0x65
  -   16.67%     0.00%  ls       [unknown]              [.]0x6469702e64
     0x6469702e64 <= [cursor can reach to bottom line, everything is ok]

Now, zoom back to "Available samples" and enter again:

Children Self Command Shared Object Symbol
================================================================
- 100.00% 100.00% ls libuClibc-0.9.33.2.so [.] lstat64
- lstat64

       16.67% 0x6469702e64
       8.33% 0x646970
       8.33% 0x617461 <= [cursor may stop here, can't move down anymore]
       8.33% 0x65
  -   16.67%     0.00%  ls       [unknown]              [.]0x6469702e64
     0x6469702e64

This patch recalculates hb->nr_callchain_rows to fix the bug.

---
 tools/perf/ui/browsers/hists.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
tools/perf/ui/browsers/hists.c +19 -0
index ad312d91caed..49eddeb81458 100644
@@ -48,6 +48,24 @@ static bool hist_browser__has_filter(struct hist_browser *hb)
 	return hists__has_filter(hb->hists) || hb->min_pcnt;
 }
 
+static int hist_browser__get_folding(struct hist_browser *browser)
+{
+	struct rb_node *nd;
+	struct hists *hists = browser->hists;
+	int unfolded_rows = 0;
+
+	for (nd = rb_first(&hists->entries);
+	     (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
+	     nd = rb_next(nd)) {
+		struct hist_entry *he =
+			rb_entry(nd, struct hist_entry, rb_node);
+
+		if (he->ms.unfolded)
+			unfolded_rows += he->nr_rows;
+	}
+	return unfolded_rows;
+}
+
 static u32 hist_browser__nr_entries(struct hist_browser *hb)
 {
 	u32 nr_entries;
@@ -57,6 +75,7 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
 	else
 		nr_entries = hb->hists->nr_entries;
 
+	hb->nr_callchain_rows = hist_browser__get_folding(hb);
 	return nr_entries + hb->nr_callchain_rows;
 }
 
Signature · 1 line
1.9.3
author maintainer
#18 lore raw

PATCH 18/24 perf stat: Output running time and run/enabled ratio in CSV mode

In reply to Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

The information how much a counter ran in 'perf stat' can be quite interesting for other tools to judge how trustworthy a measurement is.

Currently it is only output in non CSV mode.

This patches make perf stat always output the running time and the enabled/running ratio in CSV mode.

This adds two new fields at the end for each line. I assume that existing tools ignore new fields at the end, so it's on by default.

Only CSV mode is affected, no difference otherwise.

v2: Add extra print_running function
v3: Avoid printing nan
v4: Remove some elses and add brackets.
v5: Move non CSV case into print_running

---
 tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++++-----------------------
 1 file changed, 24 insertions(+), 23 deletions(-)
tools/perf/builtin-stat.c +24 -23
index d28949d210cc..765e2204f6bf 100644
@@ -769,6 +769,18 @@ static int run_perf_stat(int argc, const char **argv)
 	return ret;
 }
 
+static void print_running(u64 run, u64 ena)
+{
+	if (csv_output) {
+		fprintf(output, "%s%" PRIu64 "%s%.2f",
+					csv_sep,
+					run,
+					csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena)
+		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);
+}
+
 static void print_noise_pct(double total, double avg)
 {
 	double pct = rel_stddev_stats(total, avg);
@@ -1252,6 +1264,7 @@ static void print_aggr(char *prefix)
 					fprintf(output, "%s%s",
 						csv_sep, counter->cgrp->name);
 
+				print_running(run, ena);
 				fputc('\n', output);
 				continue;
 			}
@@ -1262,13 +1275,10 @@ static void print_aggr(char *prefix)
 			else
 				abs_printout(id, nr, counter, uval);
 
-			if (!csv_output) {
+			if (!csv_output)
 				print_noise(counter, 1.0);
 
-				if (run != ena)
-					fprintf(output, "  (%.2f%%)",
-						100.0 * run / ena);
-			}
+			print_running(run, ena);
 			fputc('\n', output);
 		}
 	}
@@ -1284,6 +1294,10 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 	double avg = avg_stats(&ps->res_stats[0]);
 	int scaled = counter->counts->scaled;
 	double uval;
+	double avg_enabled, avg_running;
+
+	avg_enabled = avg_stats(&ps->res_stats[1]);
+	avg_running = avg_stats(&ps->res_stats[2]);
 
 	if (prefix)
 		fprintf(output, "%s", prefix);
@@ -1303,6 +1317,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 		if (counter->cgrp)
 			fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
 
+		print_running(avg_running, avg_enabled);
 		fputc('\n', output);
 		return;
 	}
@@ -1316,19 +1331,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 
 	print_noise(counter, avg);
 
-	if (csv_output) {
-		fputc('\n', output);
-		return;
-	}
-
-	if (scaled) {
-		double avg_enabled, avg_running;
-
-		avg_enabled = avg_stats(&ps->res_stats[1]);
-		avg_running = avg_stats(&ps->res_stats[2]);
-
-		fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
-	}
+	print_running(avg_running, avg_enabled);
 	fprintf(output, "\n");
 }
 
@@ -1370,6 +1373,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 				fprintf(output, "%s%s",
 					csv_sep, counter->cgrp->name);
 
+			print_running(run, ena);
 			fputc('\n', output);
 			continue;
 		}
@@ -1381,13 +1385,10 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 		else
 			abs_printout(cpu, 0, counter, uval);
 
-		if (!csv_output) {
+		if (!csv_output)
 			print_noise(counter, 1.0);
+		print_running(run, ena);
 
-			if (run != ena)
-				fprintf(output, "  (%.2f%%)",
-					100.0 * run / ena);
-		}
 		fputc('\n', output);
 	}
 }
Signature · 1 line
1.9.3
#19 lore raw

Re: [PATCH 18/24] perf stat: Output running time and run/enabled ratio in CSV mode

Quoted 38 lines · Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

The information how much a counter ran in 'perf stat' can be quite interesting for other tools to judge how trustworthy a measurement is.

Currently it is only output in non CSV mode.

This patches make perf stat always output the running time and the enabled/running ratio in CSV mode.

This adds two new fields at the end for each line. I assume that existing tools ignore new fields at the end, so it's on by default.

Only CSV mode is affected, no difference otherwise.

v2: Add extra print_running function
v3: Avoid printing nan
v4: Remove some elses and add brackets.
v5: Move non CSV case into print_running

---
 tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++++-----------------------
 1 file changed, 24 insertions(+), 23 deletions(-)
tools/perf/builtin-stat.c +0 -0
index d28949d210cc..765e2204f6bf 100644
@@ -769,6 +769,18 @@ static int run_perf_stat(int argc, const char **argv)
 	return ret;
 }
 

tools/perf/builtin-stat.c static int run_perf_stat(int argc, const char **argv) · line 781

Quoted 10 lines
tools/perf/builtin-stat.c +10 -0
+static void print_running(u64 run, u64 ena)
+{
+	if (csv_output) {
+		fprintf(output, "%s%" PRIu64 "%s%.2f",
+					csv_sep,
+					run,
+					csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena)
+		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);

That's not the standard pattern for 'else if' branches, but:

	} else {
		if ()
			...
	}

to make it stand apart more from a simple 'else' branch.

Thanks,

Ingo

author maintainer
#20 lore raw

Re: [PATCH 18/24] perf stat: Output running time and run/enabled ratio in CSV mode

Em Fri, Mar 13, 2015 at 08:34:41AM +0100, Ingo Molnar escreveu:

Quoted 15 lines · Arnaldo Carvalho de Melo

tools/perf/builtin-stat.c static int run_perf_stat(int argc, const char **argv) · line 781

Quoted 11 lines

From: Andi Kleen <[email protected]>

tools/perf/builtin-stat.c +10 -0
+static void print_running(u64 run, u64 ena)
+{
+	if (csv_output) {
+		fprintf(output, "%s%" PRIu64 "%s%.2f",
+					csv_sep,
+					run,
+					csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena)
+		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);

That's not the standard pattern for 'else if' branches, but:

Quoted 6 lines
	} else {
		if ()
			...
	}

to make it stand apart more from a simple 'else' branch.

I think it is preferred to make it match the if branch if it uses curly braces, i.e. make it look:

	} else if () {
	}

i.e switch like series of else if, to avoid too much indentation for such constructs.

Fixed it and the other file, redid the perf-core-for-mingo tag, pushed.

- Arnaldo

#21 lore raw

Re: [PATCH 18/24] perf stat: Output running time and run/enabled ratio in CSV mode

Quoted 26 lines · Arnaldo Carvalho de Melo

Em Fri, Mar 13, 2015 at 08:34:41AM +0100, Ingo Molnar escreveu:

Quoted 15 lines · Arnaldo Carvalho de Melo

tools/perf/builtin-stat.c static int run_perf_stat(int argc, const char **argv) · line 781

Quoted 11 lines

From: Andi Kleen <[email protected]>

tools/perf/builtin-stat.c +10 -0
+static void print_running(u64 run, u64 ena)
+{
+	if (csv_output) {
+		fprintf(output, "%s%" PRIu64 "%s%.2f",
+					csv_sep,
+					run,
+					csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena)
+		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);

That's not the standard pattern for 'else if' branches, but:

Quoted 6 lines
	} else {
		if ()
			...
	}

to make it stand apart more from a simple 'else' branch.

I think it is preferred to make it match the if branch if it uses curly braces, i.e. make it look:

Quoted 8 lines
	} else if () {
	}

i.e switch like series of else if, to avoid too much indentation for such constructs.

Fixed it and the other file, redid the perf-core-for-mingo tag, pushed.

Pulled into tip:perf/core, thanks a lot Arnaldo!

Ingo

author maintainer
#22 lore raw

PATCH 19/24 perf stat: Fix IPC and other formulas with -A

In reply to Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

perf stat didn't compute the IPC and other formulas for individual CPUs with -A. Fix this for the easy -A case. As before, --per-core and --per-socket do not handle it, they simply print nothing.

---
 tools/perf/builtin-stat.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)
tools/perf/builtin-stat.c +19 -17
index 765e2204f6bf..e78c68df2152 100644
@@ -353,39 +353,40 @@ static struct perf_evsel *nth_evsel(int n)
  * more semantic information such as miss/hit ratios,
  * instruction rates, etc:
  */
-static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
+static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
+				int cpu)
 {
 	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
-		update_stats(&runtime_nsecs_stats[0], count[0]);
+		update_stats(&runtime_nsecs_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-		update_stats(&runtime_cycles_stats[0], count[0]);
+		update_stats(&runtime_cycles_stats[cpu], count[0]);
 	else if (transaction_run &&
 		 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
-		update_stats(&runtime_cycles_in_tx_stats[0], count[0]);
+		update_stats(&runtime_cycles_in_tx_stats[cpu], count[0]);
 	else if (transaction_run &&
 		 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
-		update_stats(&runtime_transaction_stats[0], count[0]);
+		update_stats(&runtime_transaction_stats[cpu], count[0]);
 	else if (transaction_run &&
 		 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
-		update_stats(&runtime_elision_stats[0], count[0]);
+		update_stats(&runtime_elision_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
-		update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
+		update_stats(&runtime_stalled_cycles_front_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
-		update_stats(&runtime_stalled_cycles_back_stats[0], count[0]);
+		update_stats(&runtime_stalled_cycles_back_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
-		update_stats(&runtime_branches_stats[0], count[0]);
+		update_stats(&runtime_branches_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
-		update_stats(&runtime_cacherefs_stats[0], count[0]);
+		update_stats(&runtime_cacherefs_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
-		update_stats(&runtime_l1_dcache_stats[0], count[0]);
+		update_stats(&runtime_l1_dcache_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
-		update_stats(&runtime_l1_icache_stats[0], count[0]);
+		update_stats(&runtime_l1_icache_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
-		update_stats(&runtime_ll_cache_stats[0], count[0]);
+		update_stats(&runtime_ll_cache_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
-		update_stats(&runtime_dtlb_cache_stats[0], count[0]);
+		update_stats(&runtime_dtlb_cache_stats[cpu], count[0]);
 	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
-		update_stats(&runtime_itlb_cache_stats[0], count[0]);
+		update_stats(&runtime_itlb_cache_stats[cpu], count[0]);
 }
 
 static void zero_per_pkg(struct perf_evsel *counter)
@@ -447,7 +448,8 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
 			perf_evsel__compute_deltas(evsel, cpu, count);
 		perf_counts_values__scale(count, scale, NULL);
 		evsel->counts->cpu[cpu] = *count;
-		update_shadow_stats(evsel, count->values);
+		if (aggr_mode == AGGR_NONE)
+			update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
 		aggr->val += count->val;
@@ -495,7 +497,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
 	/*
 	 * Save the full runtime - to allow normalization during printout:
 	 */
-	update_shadow_stats(counter, count);
+	update_shadow_stats(counter, count, 0);
 
 	return 0;
 }
Signature · 1 line
1.9.3
author maintainer
#23 lore raw

PATCH 20/24 perf stat: Always correctly indent ratio column

In reply to Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

When cycles or instructions do not print anything, as in being, --per-socket or --per-core modi, the ratio column was not correctly indented for them. This lead to some ratios not lining up with the others. Always indent correctly when nothing is printed.

---
 tools/perf/builtin-stat.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/builtin-stat.c +4 -2
index e78c68df2152..41b296fff307 100644
@@ -1093,7 +1093,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 		if (total) {
 			ratio = avg / total;
 			fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
-		}
+		} else
+			fprintf(output, "                                   ");
 		total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
 		total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
 
@@ -1162,7 +1163,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 		if (total) {
 			ratio = avg / total;
 			fprintf(output, " # %8.3f GHz                    ", ratio);
-		}
+		} else
+			fprintf(output, "                                   ");
 	} else if (transaction_run &&
 		   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
 		total = avg_stats(&runtime_cycles_stats[cpu]);
Signature · 1 line
1.9.3
#24 lore raw

Re: [PATCH 20/24] perf stat: Always correctly indent ratio column

Quoted 19 lines · Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

When cycles or instructions do not print anything, as in being, --per-socket or --per-core modi, the ratio column was not correctly indented for them. This lead to some ratios not lining up with the others. Always indent correctly when nothing is printed.

---
 tools/perf/builtin-stat.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/builtin-stat.c +0 -0
index e78c68df2152..41b296fff307 100644

tools/perf/builtin-stat.c static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) · line 1097

Quoted 6 lines
tools/perf/builtin-stat.c +2 -1
@@ -1093,7 +1093,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 		if (total) {
 			ratio = avg / total;
 			fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
-		}
+		} else
+			fprintf(output, "                                   ");

The standard pattern is symmetric curly braces.

tools/perf/builtin-stat.c static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) · line 1167

Quoted 7 lines
tools/perf/builtin-stat.c +2 -1
@@ -1162,7 +1163,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 		if (total) {
 			ratio = avg / total;
 			fprintf(output, " # %8.3f GHz                    ", ratio);
-		}
+		} else
+			fprintf(output, "                                   ");

Ditto...

Thanks,

Ingo

author maintainer
#25 lore raw

PATCH 21/24 perf kmem: Fix segfault when invalid sort key is given

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

When it tries to free 'str', it was already updated by strsep() - so it needs to save the original pointer.

  # perf kmem stat -s xxx,hit
    Error: Unknown --sort key: 'xxx'
  *** Error in `perf': free(): invalid pointer: 0x0000000000e9e7b6 ***
  ======= Backtrace: =========
  /usr/lib/libc.so.6(+0x7198e)[0x7fc7e6e0d98e]
  /usr/lib/libc.so.6(+0x76dee)[0x7fc7e6e12dee]
  /usr/lib/libc.so.6(+0x775cb)[0x7fc7e6e135cb]
  ./perf[0x44a1b5]
  ./perf[0x490b20]
  ./perf(parse_options_step+0x173)[0x491773]
  ./perf(parse_options_subcommand+0xa7)[0x491fb7]
  ./perf(cmd_kmem+0x2bc)[0x44ae4c]
  ./perf[0x47aa13]
  ./perf(main+0x60a)[0x427a9a]
  /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7fc7e6dbc800]
  ./perf(_start+0x29)[0x427bb9]
---
 tools/perf/builtin-kmem.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-kmem.c +2 -1
index 62f165a9fa40..1e69ea57a1cc 100644
@@ -559,6 +559,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
 {
 	char *tok;
 	char *str = strdup(arg);
+	char *pos = str;
 
 	if (!str) {
 		pr_err("%s: strdup failed\n", __func__);
@@ -566,7 +567,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
 	}
 
 	while (true) {
-		tok = strsep(&str, ",");
+		tok = strsep(&pos, ",");
 		if (!tok)
 			break;
 		if (sort_dimension__add(tok, sort_list) < 0) {
Signature · 1 line
1.9.3
author maintainer
#26 lore raw

PATCH 22/24 perf kmem: Allow -v option

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

Current perf kmem fails when -v option is used. As it's very useful for debugging, let's allow it.

---
 tools/perf/Documentation/perf-kmem.txt | 4 ++++
 tools/perf/builtin-kmem.c              | 2 ++
 2 files changed, 6 insertions(+)
tools/perf/Documentation/perf-kmem.txt +4 -0
index 7c8fbbf3f61c..150253cc3c97 100644
@@ -25,6 +25,10 @@ OPTIONS
 --input=<file>::
 	Select the input file (default: perf.data unless stdin is a fifo)
 
+-v::
+--verbose::
+        Be more verbose. (show symbol address, etc)
+
 --caller::
 	Show per-callsite statistics
 
tools/perf/builtin-kmem.c +2 -0
index 1e69ea57a1cc..02b76976b288 100644
@@ -663,6 +663,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char * const default_sort_order = "frag,hit,bytes";
 	const struct option kmem_options[] = {
 	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_INCR('v', "verbose", &verbose,
+		    "be more verbose (show symbol address, etc)"),
 	OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
 			   "show per-callsite statistics", parse_caller_opt),
 	OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
Signature · 1 line
1.9.3
author maintainer
#27 lore raw

PATCH 23/24 perf kmem: Fix alignment of slab result table

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

Its table was a bit misaligned. Fix it.

Before:

  # perf kmem stat --caller -l 10
  ------------------------------------------------------------------------------------------------------
   Callsite                           | Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag
  ------------------------------------------------------------------------------------------------------
   radeon_cs_parser_init.part.1+11a   |      2080/260   |      1504/188   |        8 |        0 | 27.692%
   radeon_cs_parser_init.part.1+e1    |       384/96    |       288/72    |        4 |        0 | 25.000%
   radeon_cs_parser_init.part.1+93    |       128/32    |        96/24    |        4 |        0 | 25.000%
   load_elf_binary+a39                |       512/512   |       392/392   |        1 |        0 | 23.438%
   __alloc_skb+89                     |      6144/877   |      4800/685   |        7 |        6 | 21.875%
   radeon_fence_emit+5c               |      1152/192   |       912/152   |        6 |        0 | 20.833%
   radeon_cs_parser_relocs+ad         |      8192/2048  |      6624/1656  |        4 |        0 | 19.141%
   radeon_sa_bo_new+78                |      1280/64    |      1120/56    |       20 |        0 | 12.500%
   load_elf_binary+2c4                |        32/32    |        28/28    |        1 |        0 | 12.500%
   anon_vma_prepare+101               |       576/72    |       512/64    |        8 |        0 | 11.111%
   ...                                | ...             | ...             | ...    | ...      | ...
  ------------------------------------------------------------------------------------------------------

After:

---------------------------------------------------------------------------------------------------------
Callsite | Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag
---------------------------------------------------------------------------------------------------------

   radeon_cs_parser_init.part.1+11a   |      2080/260   |      1504/188   |        8 |         0 | 27.692%
   radeon_cs_parser_init.part.1+e1    |       384/96    |       288/72    |        4 |         0 | 25.000%
   radeon_cs_parser_init.part.1+93    |       128/32    |        96/24    |        4 |         0 | 25.000%
   load_elf_binary+a39                |       512/512   |       392/392   |        1 |         0 | 23.438%
   __alloc_skb+89                     |      6144/877   |      4800/685   |        7 |         6 | 21.875%
   radeon_fence_emit+5c               |      1152/192   |       912/152   |        6 |         0 | 20.833%
   radeon_cs_parser_relocs+ad         |      8192/2048  |      6624/1656  |        4 |         0 | 19.141%
   radeon_sa_bo_new+78                |      1280/64    |      1120/56    |       20 |         0 | 12.500%
   load_elf_binary+2c4                |        32/32    |        28/28    |        1 |         0 | 12.500%
   anon_vma_prepare+101               |       576/72    |       512/64    |        8 |         0 | 11.111%
   ...                                | ...             | ...             | ...      | ...       | ...

---------------------------------------------------------------------------------------------------------

---
 tools/perf/builtin-kmem.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
tools/perf/builtin-kmem.c +5 -5
index 02b76976b288..8c85aeb3327a 100644
@@ -275,10 +275,10 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
 	struct rb_node *next;
 	struct machine *machine = &session->machines.host;
 
-	printf("%.102s\n", graph_dotted_line);
+	printf("%.105s\n", graph_dotted_line);
 	printf(" %-34s |",  is_caller ? "Callsite": "Alloc Ptr");
 	printf(" Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag\n");
-	printf("%.102s\n", graph_dotted_line);
+	printf("%.105s\n", graph_dotted_line);
 
 	next = rb_first(root);
 
@@ -304,7 +304,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
 			snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
 		printf(" %-34s |", buf);
 
-		printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n",
+		printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
 		       (unsigned long long)data->bytes_alloc,
 		       (unsigned long)data->bytes_alloc / data->hit,
 		       (unsigned long long)data->bytes_req,
@@ -317,9 +317,9 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
 	}
 
 	if (n_lines == -1)
-		printf(" ...                                | ...             | ...             | ...    | ...      | ...   \n");
+		printf(" ...                                | ...             | ...             | ...      | ...       | ...   \n");
 
-	printf("%.102s\n", graph_dotted_line);
+	printf("%.105s\n", graph_dotted_line);
 }
 
 static void print_summary(void)
Signature · 1 line
1.9.3
author maintainer
#28 lore raw

PATCH 24/24 perf data: Add tracepoint events fields CTF conversion support

In reply to Arnaldo Carvalho de Melo

From: Sebastian Andrzej Siewior <[email protected]>

Adding support to convert tracepoint event fields into CTF event fields.

We parse each tracepoint event for CTF conversion and add tracepoint fields as regular CTF event fields, so they appear in babeltrace output like:

  $ babeltrace ./ctf-data/
  ...
  [09:02:00.950703057] (+?.?????????) sched:sched_stat_runtime: { }, { perf_ip = ... SNIP ... common_type = 298, common_flags = 1, \
  common_preempt_count = 0, common_pid = 31813, comm = "perf", pid = 31813, runtime = 458800, vruntime = 52059858071 }
  ...
---
 tools/perf/util/data-convert-bt.c | 242 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 242 insertions(+)
tools/perf/util/data-convert-bt.c +242 -0
index 1afd381b2346..c6d62268cc2a 100644
@@ -126,6 +126,177 @@ FUNC_VALUE_SET(s64)
 FUNC_VALUE_SET(u64)
 __FUNC_VALUE_SET(u64_hex, u64)
 
+static struct bt_ctf_field_type*
+get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
+{
+	unsigned long flags = field->flags;
+
+	if (flags & FIELD_IS_STRING)
+		return cw->data.string;
+
+	if (!(flags & FIELD_IS_SIGNED)) {
+		/* unsigned long are mostly pointers */
+		if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
+			return cw->data.u64_hex;
+	}
+
+	if (flags & FIELD_IS_SIGNED) {
+		if (field->size == 8)
+			return cw->data.s64;
+		else
+			return cw->data.s32;
+	}
+
+	if (field->size == 8)
+		return cw->data.u64;
+	else
+		return cw->data.u32;
+}
+
+static int add_tracepoint_field_value(struct ctf_writer *cw,
+				      struct bt_ctf_event_class *event_class,
+				      struct bt_ctf_event *event,
+				      struct perf_sample *sample,
+				      struct format_field *fmtf)
+{
+	struct bt_ctf_field_type *type;
+	struct bt_ctf_field *array_field;
+	struct bt_ctf_field *field;
+	const char *name = fmtf->name;
+	void *data = sample->raw_data;
+	unsigned long long value_int;
+	unsigned long flags = fmtf->flags;
+	unsigned int n_items;
+	unsigned int i;
+	unsigned int offset;
+	unsigned int len;
+	int ret;
+
+	offset = fmtf->offset;
+	len = fmtf->size;
+	if (flags & FIELD_IS_STRING)
+		flags &= ~FIELD_IS_ARRAY;
+
+	if (flags & FIELD_IS_DYNAMIC) {
+		unsigned long long tmp_val;
+
+		tmp_val = pevent_read_number(fmtf->event->pevent,
+				data + offset, len);
+		offset = tmp_val;
+		len = offset >> 16;
+		offset &= 0xffff;
+	}
+
+	if (flags & FIELD_IS_ARRAY) {
+
+		type = bt_ctf_event_class_get_field_by_name(
+				event_class, name);
+		array_field = bt_ctf_field_create(type);
+		bt_ctf_field_type_put(type);
+		if (!array_field) {
+			pr_err("Failed to create array type %s\n", name);
+			return -1;
+		}
+
+		len = fmtf->size / fmtf->arraylen;
+		n_items = fmtf->arraylen;
+	} else {
+		n_items = 1;
+		array_field = NULL;
+	}
+
+	type = get_tracepoint_field_type(cw, fmtf);
+
+	for (i = 0; i < n_items; i++) {
+		if (!(flags & FIELD_IS_STRING))
+			value_int = pevent_read_number(
+					fmtf->event->pevent,
+					data + offset + i * len, len);
+
+		if (flags & FIELD_IS_ARRAY)
+			field = bt_ctf_field_array_get_field(array_field, i);
+		else
+			field = bt_ctf_field_create(type);
+
+		if (!field) {
+			pr_err("failed to create a field %s\n", name);
+			return -1;
+		}
+
+		if (flags & FIELD_IS_STRING)
+			ret = bt_ctf_field_string_set_value(field,
+					data + offset + i * len);
+		else if (!(flags & FIELD_IS_SIGNED))
+			ret = bt_ctf_field_unsigned_integer_set_value(
+					field, value_int);
+		else
+			ret = bt_ctf_field_signed_integer_set_value(
+					field, value_int);
+		if (ret) {
+			pr_err("failed to set file value %s\n", name);
+			goto err_put_field;
+		}
+		if (!(flags & FIELD_IS_ARRAY)) {
+			ret = bt_ctf_event_set_payload(event, name, field);
+			if (ret) {
+				pr_err("failed to set payload %s\n", name);
+				goto err_put_field;
+			}
+		}
+		bt_ctf_field_put(field);
+	}
+	if (flags & FIELD_IS_ARRAY) {
+		ret = bt_ctf_event_set_payload(event, name, array_field);
+		if (ret) {
+			pr_err("Failed add payload array %s\n", name);
+			return -1;
+		}
+		bt_ctf_field_put(array_field);
+	}
+	return 0;
+
+err_put_field:
+	bt_ctf_field_put(field);
+	return -1;
+}
+
+static int add_tracepoint_fields_values(struct ctf_writer *cw,
+					struct bt_ctf_event_class *event_class,
+					struct bt_ctf_event *event,
+					struct format_field *fields,
+					struct perf_sample *sample)
+{
+	struct format_field *field;
+	int ret;
+
+	for (field = fields; field; field = field->next) {
+		ret = add_tracepoint_field_value(cw, event_class, event, sample,
+				field);
+		if (ret)
+			return -1;
+	}
+	return 0;
+}
+
+static int add_tracepoint_values(struct ctf_writer *cw,
+				 struct bt_ctf_event_class *event_class,
+				 struct bt_ctf_event *event,
+				 struct perf_evsel *evsel,
+				 struct perf_sample *sample)
+{
+	struct format_field *common_fields = evsel->tp_format->format.common_fields;
+	struct format_field *fields        = evsel->tp_format->format.fields;
+	int ret;
+
+	ret = add_tracepoint_fields_values(cw, event_class, event,
+					   common_fields, sample);
+	if (!ret)
+		ret = add_tracepoint_fields_values(cw, event_class, event,
+						   fields, sample);
+
+	return ret;
+}
+
 static int add_generic_values(struct ctf_writer *cw,
 			      struct bt_ctf_event *event,
 			      struct perf_evsel *evsel,
@@ -246,11 +417,76 @@ static int process_sample_event(struct perf_tool *tool,
 	if (ret)
 		return -1;
 
+	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+		ret = add_tracepoint_values(cw, event_class, event,
+					    evsel, sample);
+		if (ret)
+			return -1;
+	}
+
 	bt_ctf_stream_append_event(cw->stream, event);
 	bt_ctf_event_put(event);
 	return 0;
 }
 
+static int add_tracepoint_fields_types(struct ctf_writer *cw,
+				       struct format_field *fields,
+				       struct bt_ctf_event_class *event_class)
+{
+	struct format_field *field;
+	int ret;
+
+	for (field = fields; field; field = field->next) {
+		struct bt_ctf_field_type *type;
+		unsigned long flags = field->flags;
+
+		pr2("  field '%s'\n", field->name);
+
+		type = get_tracepoint_field_type(cw, field);
+		if (!type)
+			return -1;
+
+		/*
+		 * A string is an array of chars. For this we use the string
+		 * type and don't care that it is an array. What we don't
+		 * support is an array of strings.
+		 */
+		if (flags & FIELD_IS_STRING)
+			flags &= ~FIELD_IS_ARRAY;
+
+		if (flags & FIELD_IS_ARRAY)
+			type = bt_ctf_field_type_array_create(type, field->arraylen);
+
+		ret = bt_ctf_event_class_add_field(event_class, type,
+				field->name);
+
+		if (flags & FIELD_IS_ARRAY)
+			bt_ctf_field_type_put(type);
+
+		if (ret) {
+			pr_err("Failed to add field '%s\n", field->name);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int add_tracepoint_types(struct ctf_writer *cw,
+				struct perf_evsel *evsel,
+				struct bt_ctf_event_class *class)
+{
+	struct format_field *common_fields = evsel->tp_format->format.common_fields;
+	struct format_field *fields        = evsel->tp_format->format.fields;
+	int ret;
+
+	ret = add_tracepoint_fields_types(cw, common_fields, class);
+	if (!ret)
+		ret = add_tracepoint_fields_types(cw, fields, class);
+
+	return ret;
+}
+
 static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
 			     struct bt_ctf_event_class *event_class)
 {
@@ -328,6 +564,12 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
 	if (ret)
 		goto err;
 
+	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+		ret = add_tracepoint_types(cw, evsel, event_class);
+		if (ret)
+			goto err;
+	}
+
 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
 	if (ret) {
 		pr("Failed to add event class into stream.\n");
Signature · 1 line
1.9.3
#29 lore raw
In reply to Arnaldo Carvalho de Melo
Quoted 3 lines · Arnaldo Carvalho de Melo

Infrastructure:

. Fix libbabeltrace detection (Jiri Olsa)

So this still doesn't seem to work for me:

... libbabeltrace: [ OFF ]

it should really not be included in the default build until the required library features are more widely available in distros.

I think we should only use library features by default that are available in the latest Fedora, SuSE and Ubuntu distros. We want them to build and package perf and there's little point in adding features that won't work on packaged up perf.

Thanks,

Ingo

#30 lore raw
Quoted 5 lines · Ingo Molnar
Quoted 1 line · Arnaldo Carvalho de Melo

Infrastructure:

Quoted 8 lines
Quoted 1 line

. Fix libbabeltrace detection (Jiri Olsa)

So this still doesn't seem to work for me:

... libbabeltrace: [ OFF ]

it should really not be included in the default build until the required library features are more widely available in distros.

the patch that moves babeltrace out of default
check wasn't pulled in yet:

http://marc.info/?l=linux-kernel&m=142606453815125&w=2

also note there's another bug in test-all that prevents the test-all speed up, fixed by this patch:

http://marc.info/?l=linux-kernel&m=142606452415123&w=2

Quoted 5 lines

I think we should only use library features by default that are available in the latest Fedora, SuSE and Ubuntu distros. We want them to build and package perf and there's little point in adding features that won't work on packaged up perf.

I think we should have the possibility to work and commit new features even if the support is not yet in the main distros

for such features we could:
- leave those features out of the default features check like we'll do for babeltrace
- maybe use some sort of EXPERIMENTAL config option dependency once we have the .config file support ;-)

jirka