Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL New Arnaldo Carvalho de Melo 2 participants 13 messages Jun 19, 2015 perf events

lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 79928928c5a27d58ae48285d2a3f7aa835db7547:

Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-06-18 09:40:46 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

for you to fetch changes up to 9d9cad763ca79dd3697e9f2d1df648e37496582b:

perf tools: Configurable per thread proc map processing time out (2015-06-19 18:27:13 -0300)

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

User visible:

- Replace CTRL+z with 'f' as hotkey for enable/disable events (Arnaldo Carvalho de Melo)

- Do not exit when 'f' is pressed in 'report' mode (Arnaldo Carvalho de Melo)

- Tell the user how to unfreeze events after pressing 'f' in 'perf top' (Arnaldo Carvalho de Melo)

- React to unassigned hotkey pressing in 'top/report' (Arnaldo Carvalho de Melo)

- Display total number of samples with --show-total-period in 'annotate' (Martin Liška)

- Add timeout to make procfs mmap processing more robust (Kan Liang)

- Fix sort__sym_cmp to also compare end of symbol (Yannick Brosseau)

Infrastructure:

- Ensure thread-stack is flushed (Adrian Hunter)

----------------------------------------------------------------
Adrian Hunter (1):
perf tools: Ensure thread-stack is flushed

Arnaldo Carvalho de Melo (6):
perf annotate: Rename source_line_percent to source_line_samples perf top: Replace CTRL+z with 'f' as hotkey for enable/disable events perf hists browser: Do not exit when 'f' is pressed in 'report' mode perf hists browser: Honour the help line provided by builtin-{top,report}.c perf top: Tell the user how to unfreeze events after pressing 'f' perf hists browser: React to unassigned hotkey pressing

Kan Liang (2):
perf tools: Add time out to force stop proc map processing perf tools: Configurable per thread proc map processing time out

Martin Liška (1):
perf annotate: Display total number of samples with --show-total-period

Yannick Brosseau (1):
perf report: Fix sort__sym_cmp to also compare end of symbol

 include/uapi/linux/perf_event.h          |  4 +++
 tools/perf/Documentation/perf-kvm.txt    |  6 ++++
 tools/perf/Documentation/perf-record.txt |  5 +++
 tools/perf/Documentation/perf-top.txt    |  6 ++++
 tools/perf/Documentation/perf-trace.txt  |  5 +++
 tools/perf/builtin-annotate.c            |  2 ++
 tools/perf/builtin-kvm.c                 |  5 ++-
 tools/perf/builtin-record.c              |  6 +++-
 tools/perf/builtin-top.c                 | 15 ++++++--
 tools/perf/builtin-trace.c               |  6 +++-
 tools/perf/perf.h                        |  1 +
 tools/perf/tests/code-reading.c          |  2 +-
 tools/perf/tests/dwarf-unwind.c          |  2 +-
 tools/perf/tests/mmap-thread-lookup.c    |  4 +--
 tools/perf/ui/browsers/annotate.c        | 60 +++++++++++++++++++++++---------
 tools/perf/ui/browsers/hists.c           | 15 ++++----
 tools/perf/util/annotate.c               | 52 ++++++++++++++++++---------
 tools/perf/util/annotate.h               |  7 ++--
 tools/perf/util/event.c                  | 46 +++++++++++++++++++-----
 tools/perf/util/event.h                  | 10 ++++--
 tools/perf/util/machine.c                | 28 +++++++++++++--
 tools/perf/util/machine.h                | 12 +++++--
 tools/perf/util/session.c                | 33 ++++++++++++++++++
 tools/perf/util/sort.c                   |  8 ++---
 tools/perf/util/thread-stack.c           | 18 +++++++---
 tools/perf/util/thread-stack.h           |  1 +
 26 files changed, 278 insertions(+), 81 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/

author maintainer
#1 lore raw

PATCH 1/11 perf tools: Ensure thread-stack is flushed

From: Adrian Hunter <[email protected]>

The thread-stack represents a thread's current stack. When a thread exits there can still be many functions on the stack e.g. exit() can be called many levels deep, so all the callers will never return. To get that information output, the thread-stack must be flushed.

Previously it was assumed the thread-stack would be flushed when the struct thread was deleted. With thread ref-counting it is no longer clear when that will be, if ever. So instead explicitly flush all the thread-stacks at the end of a session.

---
 tools/perf/util/machine.c      | 21 +++++++++++++++++++++
 tools/perf/util/machine.h      |  3 +++
 tools/perf/util/session.c      | 20 ++++++++++++++++++++
 tools/perf/util/thread-stack.c | 18 +++++++++++++-----
 tools/perf/util/thread-stack.h |  1 +
 5 files changed, 58 insertions(+), 5 deletions(-)
tools/perf/util/machine.c +21 -0
index 132e35765101..8b3b1937cb9e 100644
@@ -1890,6 +1890,27 @@ int machine__for_each_thread(struct machine *machine,
 	return rc;
 }
 
+int machines__for_each_thread(struct machines *machines,
+			      int (*fn)(struct thread *thread, void *p),
+			      void *priv)
+{
+	struct rb_node *nd;
+	int rc = 0;
+
+	rc = machine__for_each_thread(&machines->host, fn, priv);
+	if (rc != 0)
+		return rc;
+
+	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
+		struct machine *machine = rb_entry(nd, struct machine, rb_node);
+
+		rc = machine__for_each_thread(machine, fn, priv);
+		if (rc != 0)
+			return rc;
+	}
+	return rc;
+}
+
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
 				  perf_event__handler_t process, bool data_mmap)
tools/perf/util/machine.h +3 -0
index ca267c41f28d..cea62f6fb144 100644
@@ -216,6 +216,9 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
 int machine__for_each_thread(struct machine *machine,
 			     int (*fn)(struct thread *thread, void *p),
 			     void *priv);
+int machines__for_each_thread(struct machines *machines,
+			      int (*fn)(struct thread *thread, void *p),
+			      void *priv);
 
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
tools/perf/util/session.c +20 -0
index e1cd17c2afab..c371336d1eb2 100644
@@ -16,6 +16,7 @@
 #include "perf_regs.h"
 #include "asm/bug.h"
 #include "auxtrace.h"
+#include "thread-stack.h"
 
 static int perf_session__deliver_event(struct perf_session *session,
 				       union perf_event *event,
@@ -1361,6 +1362,19 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
 	events_stats__auxtrace_error_warn(stats);
 }
 
+static int perf_session__flush_thread_stack(struct thread *thread,
+					    void *p __maybe_unused)
+{
+	return thread_stack__flush(thread);
+}
+
+static int perf_session__flush_thread_stacks(struct perf_session *session)
+{
+	return machines__for_each_thread(&session->machines,
+					 perf_session__flush_thread_stack,
+					 NULL);
+}
+
 volatile int session_done;
 
 static int __perf_session__process_pipe_events(struct perf_session *session)
@@ -1450,6 +1464,9 @@ done:
 	if (err)
 		goto out_err;
 	err = auxtrace__flush_events(session, tool);
+	if (err)
+		goto out_err;
+	err = perf_session__flush_thread_stacks(session);
 out_err:
 	free(buf);
 	perf_session__warn_about_errors(session);
@@ -1600,6 +1617,9 @@ out:
 	if (err)
 		goto out_err;
 	err = auxtrace__flush_events(session, tool);
+	if (err)
+		goto out_err;
+	err = perf_session__flush_thread_stacks(session);
 out_err:
 	ui_progress__finish();
 	perf_session__warn_about_errors(session);
tools/perf/util/thread-stack.c +13 -5
index 9ed59a452d1f..679688e70ae7 100644
@@ -219,7 +219,7 @@ static int thread_stack__call_return(struct thread *thread,
 	return crp->process(&cr, crp->data);
 }
 
-static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
+static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts)
 {
 	struct call_return_processor *crp = ts->crp;
 	int err;
@@ -242,6 +242,14 @@ static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
 	return 0;
 }
 
+int thread_stack__flush(struct thread *thread)
+{
+	if (thread->ts)
+		return __thread_stack__flush(thread, thread->ts);
+
+	return 0;
+}
+
 int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
 			u64 to_ip, u16 insn_len, u64 trace_nr)
 {
@@ -264,7 +272,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
 	 */
 	if (trace_nr != thread->ts->trace_nr) {
 		if (thread->ts->trace_nr)
-			thread_stack__flush(thread, thread->ts);
+			__thread_stack__flush(thread, thread->ts);
 		thread->ts->trace_nr = trace_nr;
 	}
 
@@ -297,7 +305,7 @@ void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
 
 	if (trace_nr != thread->ts->trace_nr) {
 		if (thread->ts->trace_nr)
-			thread_stack__flush(thread, thread->ts);
+			__thread_stack__flush(thread, thread->ts);
 		thread->ts->trace_nr = trace_nr;
 	}
 }
@@ -305,7 +313,7 @@ void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
 void thread_stack__free(struct thread *thread)
 {
 	if (thread->ts) {
-		thread_stack__flush(thread, thread->ts);
+		__thread_stack__flush(thread, thread->ts);
 		zfree(&thread->ts->stack);
 		zfree(&thread->ts);
 	}
@@ -689,7 +697,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
 
 	/* Flush stack on exec */
 	if (ts->comm != comm && thread->pid_ == thread->tid) {
-		err = thread_stack__flush(thread, ts);
+		err = __thread_stack__flush(thread, ts);
 		if (err)
 			return err;
 		ts->comm = comm;
tools/perf/util/thread-stack.h +1 -0
index b843bbef8ba2..e1528f1374c3 100644
@@ -96,6 +96,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
 void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
 void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
 			  size_t sz, u64 ip);
+int thread_stack__flush(struct thread *thread);
 void thread_stack__free(struct thread *thread);
 
 struct call_return_processor *
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#2 lore raw

PATCH 2/11 perf annotate: Display total number of samples with --show-total-period

In reply to Arnaldo Carvalho de Melo

From: Martin Liška <[email protected]>

To compare two records on an instruction base, with --show-total-period option provided, display total number of samples that belong to a line in assembly language.

New hot key 't' is introduced for 'perf annotate' TUI.

---
 tools/perf/builtin-annotate.c     |  2 ++
 tools/perf/ui/browsers/annotate.c | 60 ++++++++++++++++++++++++++++-----------
 tools/perf/util/annotate.c        | 28 ++++++++++++++----
 tools/perf/util/annotate.h        |  3 +-
 4 files changed, 70 insertions(+), 23 deletions(-)
tools/perf/builtin-annotate.c +2 -0
index 4e08c2d2090e..2c1bec39c30e 100644
@@ -329,6 +329,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 		   "objdump binary to use for disassembly and annotations"),
 	OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
 		    "Show event group information together"),
+	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
+		    "Show a column with the sum of periods"),
 	OPT_END()
 	};
 	int ret = hists__init();
tools/perf/ui/browsers/annotate.c +43 -17

135 lines not on this page · raw message

tools/perf/util/annotate.c +23 -5
index bf8043009909..12914b66d347 100644
@@ -654,10 +654,11 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
 }
 
 double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
-			    s64 end, const char **path)
+			    s64 end, const char **path, u64 *nr_samples)
 {
 	struct source_line *src_line = notes->src->lines;
 	double percent = 0.0;
+	*nr_samples = 0;
 
 	if (src_line) {
 		size_t sizeof_src_line = sizeof(*src_line) +
@@ -671,6 +672,7 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
 				*path = src_line->path;
 
 			percent += src_line->p[evidx].percent;
+			*nr_samples += src_line->p[evidx].samples;
 			offset++;
 		}
 	} else {
@@ -680,8 +682,10 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
 		while (offset < end)
 			hits += h->addr[offset++];
 
-		if (h->sum)
+		if (h->sum) {
+			*nr_samples = hits;
 			percent = 100.0 * hits / h->sum;
+		}
 	}
 
 	return percent;
@@ -696,8 +700,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
 
 	if (dl->offset != -1) {
 		const char *path = NULL;
+		u64 nr_samples;
 		double percent, max_percent = 0.0;
 		double *ppercents = &percent;
+		u64 *psamples = &nr_samples;
 		int i, nr_percent = 1;
 		const char *color;
 		struct annotation *notes = symbol__annotation(sym);
@@ -710,8 +716,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
 		if (perf_evsel__is_group_event(evsel)) {
 			nr_percent = evsel->nr_members;
 			ppercents = calloc(nr_percent, sizeof(double));
-			if (ppercents == NULL)
+			psamples = calloc(nr_percent, sizeof(u64));
+			if (ppercents == NULL || psamples == NULL) {
 				return -1;
+			}
 		}
 
 		for (i = 0; i < nr_percent; i++) {
@@ -719,9 +727,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
 					notes->src->lines ? i : evsel->idx + i,
 					offset,
 					next ? next->offset : (s64) len,
-					&path);
+					&path, &nr_samples);
 
 			ppercents[i] = percent;
+			psamples[i] = nr_samples;
 			if (percent > max_percent)
 				max_percent = percent;
 		}
@@ -759,8 +768,14 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
 
 		for (i = 0; i < nr_percent; i++) {
 			percent = ppercents[i];
+			nr_samples = psamples[i];
 			color = get_percent_color(percent);
-			color_fprintf(stdout, color, " %7.2f", percent);
+
+			if (symbol_conf.show_total_period)
+				color_fprintf(stdout, color, " %7" PRIu64,
+					      nr_samples);
+			else
+				color_fprintf(stdout, color, " %7.2f", percent);
 		}
 
 		printf(" :	");
@@ -770,6 +785,9 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
 		if (ppercents != &percent)
 			free(ppercents);
 
+		if (psamples != &nr_samples)
+			free(psamples);
+
 	} else if (max_lines && printed >= max_lines)
 		return 1;
 	else {
tools/perf/util/annotate.h +2 -1
index cadbdc90a5cb..c8c18cadcd17 100644
@@ -72,7 +72,7 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
 size_t disasm__fprintf(struct list_head *head, FILE *fp);
 double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
-			    s64 end, const char **path);
+			    s64 end, const char **path, u64 *nr_samples);
 
 struct sym_hist {
 	u64		sum;
@@ -82,6 +82,7 @@ struct sym_hist {
 struct source_line_percent {
 	double		percent;
 	double		percent_sum;
+	double          samples;
 };
 
 struct source_line {
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#3 lore raw

PATCH 3/11 perf annotate: Rename source_line_percent to source_line_samples

In reply to Arnaldo Carvalho de Melo

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

To better reflect the purpose of this struct, that is to hold info about samples, its total number and is percentage.

---
 tools/perf/util/annotate.c | 26 +++++++++++++-------------
 tools/perf/util/annotate.h |  6 +++---
 2 files changed, 16 insertions(+), 16 deletions(-)
tools/perf/util/annotate.c +13 -13
index 12914b66d347..03b7bc70eb66 100644
@@ -662,7 +662,7 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
 
 	if (src_line) {
 		size_t sizeof_src_line = sizeof(*src_line) +
-				sizeof(src_line->p) * (src_line->nr_pcnt - 1);
+				sizeof(src_line->samples) * (src_line->nr_pcnt - 1);
 
 		while (offset < end) {
 			src_line = (void *)notes->src->lines +
@@ -671,8 +671,8 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
 			if (*path == NULL)
 				*path = src_line->path;
 
-			percent += src_line->p[evidx].percent;
-			*nr_samples += src_line->p[evidx].samples;
+			percent += src_line->samples[evidx].percent;
+			*nr_samples += src_line->samples[evidx].nr;
 			offset++;
 		}
 	} else {
@@ -1121,7 +1121,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
 		ret = strcmp(iter->path, src_line->path);
 		if (ret == 0) {
 			for (i = 0; i < src_line->nr_pcnt; i++)
-				iter->p[i].percent_sum += src_line->p[i].percent;
+				iter->samples[i].percent_sum += src_line->samples[i].percent;
 			return;
 		}
 
@@ -1132,7 +1132,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
 	}
 
 	for (i = 0; i < src_line->nr_pcnt; i++)
-		src_line->p[i].percent_sum = src_line->p[i].percent;
+		src_line->samples[i].percent_sum = src_line->samples[i].percent;
 
 	rb_link_node(&src_line->node, parent, p);
 	rb_insert_color(&src_line->node, root);
@@ -1143,9 +1143,9 @@ static int cmp_source_line(struct source_line *a, struct source_line *b)
 	int i;
 
 	for (i = 0; i < a->nr_pcnt; i++) {
-		if (a->p[i].percent_sum == b->p[i].percent_sum)
+		if (a->samples[i].percent_sum == b->samples[i].percent_sum)
 			continue;
-		return a->p[i].percent_sum > b->p[i].percent_sum;
+		return a->samples[i].percent_sum > b->samples[i].percent_sum;
 	}
 
 	return 0;
@@ -1197,7 +1197,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
 	int i;
 
 	sizeof_src_line = sizeof(*src_line) +
-			  (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
+			  (sizeof(src_line->samples) * (src_line->nr_pcnt - 1));
 
 	for (i = 0; i < len; i++) {
 		free_srcline(src_line->path);
@@ -1229,7 +1229,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
 			h_sum += h->sum;
 		}
 		nr_pcnt = evsel->nr_members;
-		sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->p);
+		sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
 	}
 
 	if (!h_sum)
@@ -1249,10 +1249,10 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
 
 		for (k = 0; k < nr_pcnt; k++) {
 			h = annotation__histogram(notes, evidx + k);
-			src_line->p[k].percent = 100.0 * h->addr[i] / h->sum;
+			src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum;
 
-			if (src_line->p[k].percent > percent_max)
-				percent_max = src_line->p[k].percent;
+			if (src_line->samples[k].percent > percent_max)
+				percent_max = src_line->samples[k].percent;
 		}
 
 		if (percent_max <= 0.5)
@@ -1292,7 +1292,7 @@ static void print_summary(struct rb_root *root, const char *filename)
 
 		src_line = rb_entry(node, struct source_line, node);
 		for (i = 0; i < src_line->nr_pcnt; i++) {
-			percent = src_line->p[i].percent_sum;
+			percent = src_line->samples[i].percent_sum;
 			color = get_percent_color(percent);
 			color_fprintf(stdout, color, " %7.2f", percent);
 
tools/perf/util/annotate.h +3 -3
index c8c18cadcd17..7e78e6c27078 100644
@@ -79,17 +79,17 @@ struct sym_hist {
 	u64		addr[0];
 };
 
-struct source_line_percent {
+struct source_line_samples {
 	double		percent;
 	double		percent_sum;
-	double          samples;
+	double          nr;
 };
 
 struct source_line {
 	struct rb_node	node;
 	char		*path;
 	int		nr_pcnt;
-	struct source_line_percent p[1];
+	struct source_line_samples samples[1];
 };
 
 /** struct annotated_source - symbols with hits have this attached as in sannotation
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#4 lore raw

PATCH 4/11 perf top: Replace CTRL+z with 'f' as hotkey for enable/disable events

In reply to Arnaldo Carvalho de Melo

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

I.e. 'freeze'/'unfreeze', this is because CTRL+z has a well known action, i.e. suspend the app, perf needs to follow that convention, that will be done on a separate patch, tho.

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-top.c       | 2 +-
 tools/perf/ui/browsers/hists.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
tools/perf/builtin-top.c +1 -1
index 72d8a7ae5986..ccf569ab08aa 100644
@@ -591,7 +591,7 @@ static void *display_thread_tui(void *arg)
 							top->min_percent,
 							&top->session->header.env);
 
-		if (key != CTRL('z'))
+		if (key != 'f')
 			break;
 
 		perf_evlist__toggle_enable(top->evlist);
tools/perf/ui/browsers/hists.c +2 -2
index 8f7c4d49d327..764f7cabd6f2 100644
@@ -1736,7 +1736,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 	"t             Zoom into current Thread\n"
 	"V             Verbose (DSO names in callchains, etc)\n"
 	"z             Toggle zeroing of samples\n"
-	"CTRL+z        Enable/Disable events\n"
+	"f             Enable/Disable events\n"
 	"/             Filter symbol by name";
 
 	if (browser == NULL)
@@ -1901,7 +1901,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 			/* Fall thru */
 		case 'q':
 		case CTRL('c'):
-		case CTRL('z'):
+		case 'f':
 			goto out_free_stack;
 		default:
 			continue;
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#5 lore raw

PATCH 5/11 perf hists browser: Do not exit when 'f' is pressed in 'report' mode

In reply to Arnaldo Carvalho de Melo

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

The 'f' hotkey is only used when in 'top', dynamic mode, to enable/disable events, currently not making sense in the 'report', static mode, where we can't go from showing the histogram entries created from a perf.data file to adding more events after recreating the evlist created from the perf.data file, albeit possible, this is not implemented right now.

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/ui/browsers/hists.c | 3 +++
 1 file changed, 3 insertions(+)
tools/perf/ui/browsers/hists.c +3 -0
index 764f7cabd6f2..79a093a7d221 100644
@@ -1901,7 +1901,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 			/* Fall thru */
 		case 'q':
 		case CTRL('c'):
+			goto out_free_stack;
 		case 'f':
+			if (is_report_browser(hbt))
+				continue;
 			goto out_free_stack;
 		default:
 			continue;
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#6 lore raw

PATCH 6/11 perf hists browser: Honour the help line provided by builtin-{top,report}.c

In reply to Arnaldo Carvalho de Melo

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

The hists_browser was replacing whatever helpline provided by 'top' or 'report' with a static "Press '?' for help on key bindings", fix it.

Now the message passed by top appears at the bottom of the screen:

"For a higher level overview, try: perf top --sort comm,dso"

As well the message that will be added when the user presses 'f' to disable the events, something along the lines of "press f again to re-enable...".

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/ui/browsers/hists.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
tools/perf/ui/browsers/hists.c +3 -4
index 79a093a7d221..e2b500b26527 100644
@@ -424,7 +424,7 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
 		"Or reduce the sampling frequency.");
 }
 
-static int hist_browser__run(struct hist_browser *browser)
+static int hist_browser__run(struct hist_browser *browser, const char *help)
 {
 	int key;
 	char title[160];
@@ -436,8 +436,7 @@ static int hist_browser__run(struct hist_browser *browser)
 
 	hists__browser_title(browser->hists, hbt, title, sizeof(title));
 
-	if (ui_browser__show(&browser->b, title,
-			     "Press '?' for help on key bindings") < 0)
+	if (ui_browser__show(&browser->b, title, help) < 0)
 		return -1;
 
 	while (1) {
@@ -1773,7 +1772,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
 		nr_options = 0;
 
-		key = hist_browser__run(browser);
+		key = hist_browser__run(browser, helpline);
 
 		if (browser->he_selection != NULL) {
 			thread = hist_browser__selected_thread(browser);
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#7 lore raw

PATCH 7/11 perf top: Tell the user how to unfreeze events after pressing 'f'

In reply to Arnaldo Carvalho de Melo

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

When the user presses 'f' to disable events the visual cues are, well, the percentages not changing and the number of events freezing.

Be more explicit by changing the help line at the bottom of the screen to show the following messages when 'f' is pressed:

"Press 'f' again to re-enable the events"

And then, when 'f' is pressed again:

"Press 'f' to disable the events or 'h'

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-top.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
tools/perf/builtin-top.c +7 -1
index ccf569ab08aa..70a9505aae83 100644
@@ -599,7 +599,13 @@ static void *display_thread_tui(void *arg)
 		 * No need to refresh, resort/decay histogram entries
 		 * if we are not collecting samples:
 		 */
-		hbt.refresh = top->evlist->enabled ? top->delay_secs : 0;
+		if (top->evlist->enabled) {
+			hbt.refresh = top->delay_secs;
+			help = "Press 'f' to disable the events or 'h' to see other hotkeys";
+		} else {
+			help = "Press 'f' again to re-enable the events";
+			hbt.refresh = 0;
+		}
 	}
 
 	done = 1;
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#8 lore raw

PATCH 8/11 perf hists browser: React to unassigned hotkey pressing

In reply to Arnaldo Carvalho de Melo

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

When that happens we were just ignoring the key press, now this message is presented in the bottom line (the help line):

"Press '?' for help on key bindings"

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/ui/browsers/hists.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
tools/perf/ui/browsers/hists.c +4 -3
index e2b500b26527..c42adb600091 100644
@@ -1902,10 +1902,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 		case CTRL('c'):
 			goto out_free_stack;
 		case 'f':
-			if (is_report_browser(hbt))
-				continue;
-			goto out_free_stack;
+			if (!is_report_browser(hbt))
+				goto out_free_stack;
+			/* Fall thru */
 		default:
+			helpline = "Press '?' for help on key bindings";
 			continue;
 		}
 
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#9 lore raw

PATCH 9/11 perf report: Fix sort__sym_cmp to also compare end of symbol

In reply to Arnaldo Carvalho de Melo

From: Yannick Brosseau <[email protected]>

When using a map file from a JIT, due to memory reuse, we can obtain multiple symbols with the same start address but a different length.

The symbols__find does check for the end so not doing it in sort__sym_cmp was causing the hist_entry in the annotate part of a report to match to the wrong entry, causing a fatal error.

---
 tools/perf/util/sort.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
tools/perf/util/sort.c +3 -5
index 09d4696fd9a1..4c65a143a34c 100644
@@ -182,18 +182,16 @@ static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
 
 static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
 {
-	u64 ip_l, ip_r;
-
 	if (!sym_l || !sym_r)
 		return cmp_null(sym_l, sym_r);
 
 	if (sym_l == sym_r)
 		return 0;
 
-	ip_l = sym_l->start;
-	ip_r = sym_r->start;
+	if (sym_l->start != sym_r->start)
+		return (int64_t)(sym_r->start - sym_l->start);
 
-	return (int64_t)(ip_r - ip_l);
+	return (int64_t)(sym_r->end - sym_l->end);
 }
 
 static int64_t
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#10 lore raw

PATCH 10/11 perf tools: Add time out to force stop proc map processing

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

System wide sampling like 'perf top' or 'perf record -a' read all threads /proc/xxx/maps before sampling. If there are any threads which generating a keeping growing huge maps, perf will do infinite loop during synthesizing. Nothing will be sampled.

This patch fixes this issue by adding per-thread timeout to force stop this kind of endless proc map processing.

PERF_RECORD_MISC_PROC_MAP_PARSE_TIME_OUT is introduced to indicate that the mmap record are truncated by time out. User will get warning notification when truncated mmap records are detected.

---
 include/uapi/linux/perf_event.h |  4 ++++
 tools/perf/util/event.c         | 18 ++++++++++++++++++
 tools/perf/util/event.h         |  1 +
 tools/perf/util/session.c       | 11 +++++++++++
 4 files changed, 34 insertions(+)
include/uapi/linux/perf_event.h +4 -0
index 613ed9ad588f..d97f84c080da 100644
@@ -566,6 +566,10 @@ struct perf_event_mmap_page {
 #define PERF_RECORD_MISC_GUEST_USER		(5 << 0)
 
 /*
+ * Indicates that /proc/PID/maps parsing are truncated by time out.
+ */
+#define PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT	(1 << 12)
+/*
  * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on
  * different events so can reuse the same bit position.
  */
tools/perf/util/event.c +18 -0
index 793b1503d437..416ba80c628f 100644
@@ -213,6 +213,8 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
 	return 0;
 }
 
+#define PROC_MAP_PARSE_TIMEOUT	(500 * 1000000ULL)
+
 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 				       union perf_event *event,
 				       pid_t pid, pid_t tgid,
@@ -222,6 +224,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 {
 	char filename[PATH_MAX];
 	FILE *fp;
+	unsigned long long t;
+	bool truncation = false;
 	int rc = 0;
 
 	if (machine__is_default_guest(machine))
@@ -240,6 +244,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 	}
 
 	event->header.type = PERF_RECORD_MMAP2;
+	t = rdclock();
 
 	while (1) {
 		char bf[BUFSIZ];
@@ -253,6 +258,12 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
 
+		if ((rdclock() - t) > PROC_MAP_PARSE_TIMEOUT) {
+			pr_warning("Reading %s time out.\n", filename);
+			truncation = true;
+			goto out;
+		}
+
 		/* ensure null termination since stack will be reused. */
 		strcpy(execname, "");
 
@@ -301,6 +312,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
 		}
 
+out:
+		if (truncation)
+			event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
+
 		if (!strcmp(execname, ""))
 			strcpy(execname, anonstr);
 
@@ -319,6 +334,9 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			rc = -1;
 			break;
 		}
+
+		if (truncation)
+			break;
 	}
 
 	fclose(fp);
tools/perf/util/event.h +1 -0
index 5dc51ada05df..39868f529cab 100644
@@ -265,6 +265,7 @@ struct events_stats {
 	u32 nr_unknown_id;
 	u32 nr_unprocessable_samples;
 	u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
+	u32 nr_proc_map_timeout;
 };
 
 struct attr_event {
tools/perf/util/session.c +11 -0
index c371336d1eb2..2d882fd1f1b9 100644
@@ -1064,6 +1064,8 @@ static int machines__deliver_event(struct machines *machines,
 	case PERF_RECORD_MMAP:
 		return tool->mmap(tool, event, sample, machine);
 	case PERF_RECORD_MMAP2:
+		if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)
+			++evlist->stats.nr_proc_map_timeout;
 		return tool->mmap2(tool, event, sample, machine);
 	case PERF_RECORD_COMM:
 		return tool->comm(tool, event, sample, machine);
@@ -1360,6 +1362,15 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
 		ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
 
 	events_stats__auxtrace_error_warn(stats);
+
+	if (stats->nr_proc_map_timeout != 0) {
+		ui__warning("%d map information files for pre-existing threads were\n"
+			    "not processed, if there are samples for addresses they\n"
+			    "will not be resolved, you may find out which are these\n"
+			    "threads by running with -v and redirecting the output\n"
+			    "to a file.\n",
+			    stats->nr_proc_map_timeout);
+	}
 }
 
 static int perf_session__flush_thread_stack(struct thread *thread,
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
author maintainer
#11 lore raw

PATCH 11/11 perf tools: Configurable per thread proc map processing time out

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

The time out to limit the individual proc map processing was hard code to 500ms. This patch introduce a new option --proc-map-timeout to make the time limit configurable.

---
 tools/perf/Documentation/perf-kvm.txt    |  6 ++++++
 tools/perf/Documentation/perf-record.txt |  5 +++++
 tools/perf/Documentation/perf-top.txt    |  6 ++++++
 tools/perf/Documentation/perf-trace.txt  |  5 +++++
 tools/perf/builtin-kvm.c                 |  5 ++++-
 tools/perf/builtin-record.c              |  6 +++++-
 tools/perf/builtin-top.c                 |  5 ++++-
 tools/perf/builtin-trace.c               |  6 +++++-
 tools/perf/perf.h                        |  1 +
 tools/perf/tests/code-reading.c          |  2 +-
 tools/perf/tests/dwarf-unwind.c          |  2 +-
 tools/perf/tests/mmap-thread-lookup.c    |  4 ++--
 tools/perf/util/event.c                  | 36 ++++++++++++++++++++------------
 tools/perf/util/event.h                  |  9 +++++---
 tools/perf/util/machine.c                |  7 ++++---
 tools/perf/util/machine.h                |  9 +++++---
 tools/perf/util/session.c                |  4 +++-
 17 files changed, 87 insertions(+), 31 deletions(-)
tools/perf/Documentation/perf-kvm.txt +6 -0
index 6252e776009c..6a5bb2b17039 100644
@@ -151,6 +151,12 @@ STAT LIVE OPTIONS
        Show events other than HLT (x86 only) or Wait state (s390 only)
        that take longer than duration usecs.
 
+--proc-map-timeout::
+	When processing pre-existing threads /proc/XXX/mmap, it may take
+	a long time, because the file may be huge. A time out is needed
+	in such cases.
+	This option sets the time out limit. The default value is 500 ms.
+
 SEE ALSO
 --------
 linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1],
tools/perf/Documentation/perf-record.txt +5 -0
index 6fdf78625c51..9b9d9d086680 100644
@@ -271,6 +271,11 @@ AUX area tracing event. Optionally the number of bytes to capture per
 snapshot can be specified. In Snapshot Mode, trace data is captured only when
 signal SIGUSR2 is received.
 
+--proc-map-timeout::
+When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
+because the file may be huge. A time out is needed in such cases.
+This option sets the time out limit. The default value is 500 ms.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/Documentation/perf-top.txt +6 -0
index 9e5b07eb7d35..776aec4d0927 100644
@@ -201,6 +201,12 @@ Default is to monitor all CPUS.
 	Force each column width to the provided list, for large terminal
 	readability.  0 means no limit (default behavior).
 
+--proc-map-timeout::
+	When processing pre-existing threads /proc/XXX/mmap, it may take
+	a long time, because the file may be huge. A time out is needed
+	in such cases.
+	This option sets the time out limit. The default value is 500 ms.
+
 
 INTERACTIVE PROMPTING KEYS
 --------------------------
tools/perf/Documentation/perf-trace.txt +5 -0
index 1db9c8b79880..7ea078658a87 100644
@@ -121,6 +121,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
 --event::
 	Trace other events, see 'perf list' for a complete list.
 
+--proc-map-timeout::
+	When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
+	because the file may be huge. A time out is needed in such cases.
+	This option sets the time out limit. The default value is 500 ms.
+
 PAGEFAULTS
 ----------
 
tools/perf/builtin-kvm.c +4 -1
index 15fecd3dc5d8..74878cd75078 100644
@@ -1311,6 +1311,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
 			"show events other than"
 			" HLT (x86 only) or Wait state (s390 only)"
 			" that take longer than duration usecs"),
+		OPT_UINTEGER(0, "proc-map-timeout", &kvm->opts.proc_map_timeout,
+				"per thread proc mmap processing timeout in ms"),
 		OPT_END()
 	};
 	const char * const live_usage[] = {
@@ -1338,6 +1340,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
 	kvm->opts.target.uses_mmap = false;
 	kvm->opts.target.uid_str = NULL;
 	kvm->opts.target.uid = UINT_MAX;
+	kvm->opts.proc_map_timeout = 500;
 
 	symbol__init(NULL);
 	disable_buildid_cache();
@@ -1393,7 +1396,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
 	perf_session__set_id_hdr_size(kvm->session);
 	ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
 	machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
-				    kvm->evlist->threads, false);
+				    kvm->evlist->threads, false, kvm->opts.proc_map_timeout);
 	err = kvm_live_open_events(kvm);
 	if (err)
 		goto out;
tools/perf/builtin-record.c +5 -1
index 4d6cdeb94fe1..de165a1b9240 100644
@@ -598,7 +598,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	}
 
 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
-					    process_synthesized_event, opts->sample_address);
+					    process_synthesized_event, opts->sample_address,
+					    opts->proc_map_timeout);
 	if (err != 0)
 		goto out_child;
 
@@ -959,6 +960,7 @@ static struct record record = {
 			.uses_mmap   = true,
 			.default_per_cpu = true,
 		},
+		.proc_map_timeout     = 500,
 	},
 	.tool = {
 		.sample		= process_sample_event,
@@ -1066,6 +1068,8 @@ struct option __record_options[] = {
 	parse_clockid),
 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
 			  "opts", "AUX area tracing Snapshot Mode", ""),
+	OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
+			"per thread proc mmap processing timeout in ms"),
 	OPT_END()
 };
 
tools/perf/builtin-top.c +4 -1
index 70a9505aae83..619a8696fda7 100644
@@ -977,7 +977,7 @@ static int __cmd_top(struct perf_top *top)
 		goto out_delete;
 
 	machine__synthesize_threads(&top->session->machines.host, &opts->target,
-				    top->evlist->threads, false);
+				    top->evlist->threads, false, opts->proc_map_timeout);
 	ret = perf_top__start_counters(top);
 	if (ret)
 		goto out_delete;
@@ -1087,6 +1087,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 			.target		= {
 				.uses_mmap   = true,
 			},
+			.proc_map_timeout    = 500,
 		},
 		.max_stack	     = PERF_MAX_STACK_DEPTH,
 		.sym_pcnt_filter     = 5,
@@ -1186,6 +1187,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
 		   "width[,width...]",
 		   "don't try to adjust column width, use these fixed values"),
+	OPT_UINTEGER(0, "proc-map-timeout", &opts->proc_map_timeout,
+			"per thread proc mmap processing timeout in ms"),
 	OPT_END()
 	};
 	const char * const top_usage[] = {
tools/perf/builtin-trace.c +5 -1
index 4bf805b2fbf6..de5d277d1ad7 100644
@@ -1518,7 +1518,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
 		return -ENOMEM;
 
 	err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
-					    evlist->threads, trace__tool_process, false);
+					    evlist->threads, trace__tool_process, false,
+					    trace->opts.proc_map_timeout);
 	if (err)
 		symbol__exit();
 
@@ -2747,6 +2748,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 			.user_interval = ULLONG_MAX,
 			.no_buffering  = true,
 			.mmap_pages    = UINT_MAX,
+			.proc_map_timeout  = 500,
 		},
 		.output = stdout,
 		.show_comm = true,
@@ -2796,6 +2798,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "Trace pagefaults", parse_pagefaults, "maj"),
 	OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
 	OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
+	OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
+			"per thread proc mmap processing timeout in ms"),
 	OPT_END()
 	};
 	const char * const trace_subcommands[] = { "record", NULL };
tools/perf/perf.h +1 -0
index aa79fb8a16d4..4a5827fff799 100644
@@ -69,6 +69,7 @@ struct record_opts {
 	unsigned     initial_delay;
 	bool         use_clockid;
 	clockid_t    clockid;
+	unsigned int proc_map_timeout;
 };
 
 struct option;
tools/perf/tests/code-reading.c +1 -1
index e2a432b67d52..22f8a00446e1 100644
@@ -451,7 +451,7 @@ static int do_test_code_reading(bool try_kcore)
 	}
 
 	ret = perf_event__synthesize_thread_map(NULL, threads,
-						perf_event__process, machine, false);
+						perf_event__process, machine, false, 500);
 	if (ret < 0) {
 		pr_debug("perf_event__synthesize_thread_map failed\n");
 		goto out_err;
tools/perf/tests/dwarf-unwind.c +1 -1
index 9b748e1ad46e..40b36c462427 100644
@@ -28,7 +28,7 @@ static int init_live_machine(struct machine *machine)
 	pid_t pid = getpid();
 
 	return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
-						  mmap_handler, machine, true);
+						  mmap_handler, machine, true, 500);
 }
 
 #define MAX_STACK 8
tools/perf/tests/mmap-thread-lookup.c +2 -2
index 264e215c0d36..7f48efa7e295 100644
@@ -129,7 +129,7 @@ static int synth_all(struct machine *machine)
 {
 	return perf_event__synthesize_threads(NULL,
 					      perf_event__process,
-					      machine, 0);
+					      machine, 0, 500);
 }
 
 static int synth_process(struct machine *machine)
@@ -141,7 +141,7 @@ static int synth_process(struct machine *machine)
 
 	err = perf_event__synthesize_thread_map(NULL, map,
 						perf_event__process,
-						machine, 0);
+						machine, 0, 500);
 
 	thread_map__delete(map);
 	return err;
tools/perf/util/event.c +23 -13
index 416ba80c628f..d7d986d8f23e 100644
@@ -213,19 +213,19 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
 	return 0;
 }
 
-#define PROC_MAP_PARSE_TIMEOUT	(500 * 1000000ULL)
-
 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 				       union perf_event *event,
 				       pid_t pid, pid_t tgid,
 				       perf_event__handler_t process,
 				       struct machine *machine,
-				       bool mmap_data)
+				       bool mmap_data,
+				       unsigned int proc_map_timeout)
 {
 	char filename[PATH_MAX];
 	FILE *fp;
 	unsigned long long t;
 	bool truncation = false;
+	unsigned long long timeout = proc_map_timeout * 1000000ULL;
 	int rc = 0;
 
 	if (machine__is_default_guest(machine))
@@ -258,8 +258,11 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
 
-		if ((rdclock() - t) > PROC_MAP_PARSE_TIMEOUT) {
-			pr_warning("Reading %s time out.\n", filename);
+		if ((rdclock() - t) > timeout) {
+			pr_warning("Reading %s time out. "
+				   "You may want to increase "
+				   "the time limit by --proc-map-timeout\n",
+				   filename);
 			truncation = true;
 			goto out;
 		}
@@ -404,7 +407,9 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 				      pid_t pid, int full,
 					  perf_event__handler_t process,
 				      struct perf_tool *tool,
-				      struct machine *machine, bool mmap_data)
+				      struct machine *machine,
+				      bool mmap_data,
+				      unsigned int proc_map_timeout)
 {
 	char filename[PATH_MAX];
 	DIR *tasks;
@@ -421,7 +426,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 			return -1;
 
 		return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
-							  process, machine, mmap_data);
+							  process, machine, mmap_data,
+							  proc_map_timeout);
 	}
 
 	if (machine__is_default_guest(machine))
@@ -462,7 +468,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 		if (_pid == pid) {
 			/* process the parent's maps too */
 			rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
-						process, machine, mmap_data);
+						process, machine, mmap_data, proc_map_timeout);
 			if (rc)
 				break;
 		}
@@ -476,7 +482,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct machine *machine,
-				      bool mmap_data)
+				      bool mmap_data,
+				      unsigned int proc_map_timeout)
 {
 	union perf_event *comm_event, *mmap_event, *fork_event;
 	int err = -1, thread, j;
@@ -499,7 +506,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 					       fork_event,
 					       threads->map[thread], 0,
 					       process, tool, machine,
-					       mmap_data)) {
+					       mmap_data, proc_map_timeout)) {
 			err = -1;
 			break;
 		}
@@ -525,7 +532,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 						       fork_event,
 						       comm_event->comm.pid, 0,
 						       process, tool, machine,
-						       mmap_data)) {
+						       mmap_data, proc_map_timeout)) {
 				err = -1;
 				break;
 			}
@@ -542,7 +549,9 @@ out:
 
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
-				   struct machine *machine, bool mmap_data)
+				   struct machine *machine,
+				   bool mmap_data,
+				   unsigned int proc_map_timeout)
 {
 	DIR *proc;
 	char proc_path[PATH_MAX];
@@ -582,7 +591,8 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
  		 * one thread couldn't be synthesized.
  		 */
 		__event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
-					   1, process, tool, machine, mmap_data);
+					   1, process, tool, machine, mmap_data,
+					   proc_map_timeout);
 	}
 
 	err = 0;
tools/perf/util/event.h +6 -3
index 39868f529cab..c53f36384b64 100644
@@ -384,10 +384,12 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
-				      struct machine *machine, bool mmap_data);
+				      struct machine *machine, bool mmap_data,
+				      unsigned int proc_map_timeout);
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
-				   struct machine *machine, bool mmap_data);
+				   struct machine *machine, bool mmap_data,
+				   unsigned int proc_map_timeout);
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine);
@@ -469,7 +471,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 				       pid_t pid, pid_t tgid,
 				       perf_event__handler_t process,
 				       struct machine *machine,
-				       bool mmap_data);
+				       bool mmap_data,
+				       unsigned int proc_map_timeout);
 
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
tools/perf/util/machine.c +4 -3
index 8b3b1937cb9e..4744673aff1b 100644
@@ -1913,12 +1913,13 @@ int machines__for_each_thread(struct machines *machines,
 
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
-				  perf_event__handler_t process, bool data_mmap)
+				  perf_event__handler_t process, bool data_mmap,
+				  unsigned int proc_map_timeout)
 {
 	if (target__has_task(target))
-		return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
+		return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout);
 	else if (target__has_cpu(target))
-		return perf_event__synthesize_threads(tool, process, machine, data_mmap);
+		return perf_event__synthesize_threads(tool, process, machine, data_mmap, proc_map_timeout);
 	/* command specified */
 	return 0;
 }
tools/perf/util/machine.h +6 -3
index cea62f6fb144..887798e511e9 100644
@@ -222,13 +222,16 @@ int machines__for_each_thread(struct machines *machines,
 
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
-				  perf_event__handler_t process, bool data_mmap);
+				  perf_event__handler_t process, bool data_mmap,
+				  unsigned int proc_map_timeout);
 static inline
 int machine__synthesize_threads(struct machine *machine, struct target *target,
-				struct thread_map *threads, bool data_mmap)
+				struct thread_map *threads, bool data_mmap,
+				unsigned int proc_map_timeout)
 {
 	return __machine__synthesize_threads(machine, NULL, target, threads,
-					     perf_event__process, data_mmap);
+					     perf_event__process, data_mmap,
+					     proc_map_timeout);
 }
 
 pid_t machine__get_current_tid(struct machine *machine, int cpu);
tools/perf/util/session.c +3 -1
index 2d882fd1f1b9..aa482c10469d 100644
@@ -1368,7 +1368,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
 			    "not processed, if there are samples for addresses they\n"
 			    "will not be resolved, you may find out which are these\n"
 			    "threads by running with -v and redirecting the output\n"
-			    "to a file.\n",
+			    "to a file.\n"
+			    "The time limit to process proc map is too short?\n"
+			    "Increase it by --proc-map-timeout\n",
 			    stats->nr_proc_map_timeout);
 	}
 }
Signature · 5 lines
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/
#12 lore raw
In reply to Arnaldo Carvalho de Melo
Quoted 84 lines · Arnaldo Carvalho de Melo

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 79928928c5a27d58ae48285d2a3f7aa835db7547:

Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-06-18 09:40:46 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

for you to fetch changes up to 9d9cad763ca79dd3697e9f2d1df648e37496582b:

perf tools: Configurable per thread proc map processing time out (2015-06-19 18:27:13 -0300)

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

User visible:

- Replace CTRL+z with 'f' as hotkey for enable/disable events (Arnaldo Carvalho de Melo)

- Do not exit when 'f' is pressed in 'report' mode (Arnaldo Carvalho de Melo)

- Tell the user how to unfreeze events after pressing 'f' in 'perf top' (Arnaldo Carvalho de Melo)

- React to unassigned hotkey pressing in 'top/report' (Arnaldo Carvalho de Melo)

- Display total number of samples with --show-total-period in 'annotate' (Martin Liška)

- Add timeout to make procfs mmap processing more robust (Kan Liang)

- Fix sort__sym_cmp to also compare end of symbol (Yannick Brosseau)

Infrastructure:

- Ensure thread-stack is flushed (Adrian Hunter)

----------------------------------------------------------------
Adrian Hunter (1):
perf tools: Ensure thread-stack is flushed

Arnaldo Carvalho de Melo (6):
perf annotate: Rename source_line_percent to source_line_samples perf top: Replace CTRL+z with 'f' as hotkey for enable/disable events perf hists browser: Do not exit when 'f' is pressed in 'report' mode perf hists browser: Honour the help line provided by builtin-{top,report}.c perf top: Tell the user how to unfreeze events after pressing 'f' perf hists browser: React to unassigned hotkey pressing

Kan Liang (2):
perf tools: Add time out to force stop proc map processing perf tools: Configurable per thread proc map processing time out

Martin Liška (1):
perf annotate: Display total number of samples with --show-total-period

Yannick Brosseau (1):
perf report: Fix sort__sym_cmp to also compare end of symbol

 include/uapi/linux/perf_event.h          |  4 +++
 tools/perf/Documentation/perf-kvm.txt    |  6 ++++
 tools/perf/Documentation/perf-record.txt |  5 +++
 tools/perf/Documentation/perf-top.txt    |  6 ++++
 tools/perf/Documentation/perf-trace.txt  |  5 +++
 tools/perf/builtin-annotate.c            |  2 ++
 tools/perf/builtin-kvm.c                 |  5 ++-
 tools/perf/builtin-record.c              |  6 +++-
 tools/perf/builtin-top.c                 | 15 ++++++--
 tools/perf/builtin-trace.c               |  6 +++-
 tools/perf/perf.h                        |  1 +
 tools/perf/tests/code-reading.c          |  2 +-
 tools/perf/tests/dwarf-unwind.c          |  2 +-
 tools/perf/tests/mmap-thread-lookup.c    |  4 +--
 tools/perf/ui/browsers/annotate.c        | 60 +++++++++++++++++++++++---------
 tools/perf/ui/browsers/hists.c           | 15 ++++----
 tools/perf/util/annotate.c               | 52 ++++++++++++++++++---------
 tools/perf/util/annotate.h               |  7 ++--
 tools/perf/util/event.c                  | 46 +++++++++++++++++++-----
Quoted 8 lines
 tools/perf/util/event.h                  | 10 ++++--
 tools/perf/util/machine.c                | 28 +++++++++++++--
 tools/perf/util/machine.h                | 12 +++++--
 tools/perf/util/session.c                | 33 ++++++++++++++++++
 tools/perf/util/sort.c                   |  8 ++---
 tools/perf/util/thread-stack.c           | 18 +++++++---
 tools/perf/util/thread-stack.h           |  1 +
 26 files changed, 278 insertions(+), 81 deletions(-)

Pulled, thanks a lot Arnaldo!

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/