linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Jiri Olsa <jolsa@redhat.com>, LKML <linux-kernel@vger.kernel.org>,
	David Ahern <dsahern@gmail.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Andi Kleen <andi@firstfloor.org>,
	Stephane Eranian <eranian@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>
Subject: [PATCH/RFC 05/16] perf top: Show warning messages in the display thread
Date: Thu, 10 Dec 2015 16:53:24 +0900	[thread overview]
Message-ID: <1449734015-9148-6-git-send-email-namhyung@kernel.org> (raw)
In-Reply-To: <1449734015-9148-1-git-send-email-namhyung@kernel.org>

Currently perf top shows warning dialog during processing samples
which means it interrupts the processing.  So it'd be better if reader
threads just save the warning information and display thread show the
message.  Now warning is managed to have their priority so that higher
priority messages don't get overwritten by lower messages.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-top.c | 224 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 162 insertions(+), 62 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7a237719037a..aafcf27c437e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -143,68 +143,90 @@ static void __zero_source_counters(struct hist_entry *he)
 	symbol__annotate_zero_histograms(sym);
 }
 
-static void ui__warn_map_erange(struct perf_top *top __maybe_unused,
-				struct addr_location *al)
+static int perf_top__check_map_erange(struct perf_top *top __maybe_unused,
+				  struct addr_location *al)
+{
+	return al->map->erange_warned;
+}
+
+static void perf_top__warn_map_erange(struct perf_top *top __maybe_unused,
+				      struct addr_location *al)
 {
 	struct map *map = al->map;
 	struct symbol *sym = al->sym;
 	u64 ip = al->addr;
+	struct utsname uts;
+	int err = uname(&uts);
 
-	if (!map->erange_warned) {
-		struct utsname uts;
-		int err = uname(&uts);
-
-		ui__warning("Out of bounds address found:\n\n"
-			    "Addr:   %" PRIx64 "\n"
-			    "DSO:    %s %c\n"
-			    "Map:    %" PRIx64 "-%" PRIx64 "\n"
-			    "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
-			    "Arch:   %s\n"
-			    "Kernel: %s\n"
-			    "Tools:  %s\n\n"
-			    "Not all samples will be on the annotation output.\n\n"
-			    "Please report to linux-kernel@vger.kernel.org\n",
-			    ip, map->dso->long_name, dso__symtab_origin(map->dso),
-			    map->start, map->end, sym->start, sym->end,
-			    sym->binding == STB_GLOBAL ? 'g' :
-			    sym->binding == STB_LOCAL  ? 'l' : 'w', sym->name,
-			    err ? "[unknown]" : uts.machine,
-			    err ? "[unknown]" : uts.release, perf_version_string);
-		if (use_browser <= 0)
-			sleep(5);
-
-		map->erange_warned = true;
+	if (!map || !sym) {
+		ui__warning("Out of bounds address found\n");
+		return;
 	}
+
+	ui__warning("Out of bounds address found:\n\n"
+		    "Addr:   %" PRIx64 "\n"
+		    "DSO:    %s %c\n"
+		    "Map:    %" PRIx64 "-%" PRIx64 "\n"
+		    "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
+		    "Arch:   %s\n"
+		    "Kernel: %s\n"
+		    "Tools:  %s\n\n"
+		    "Not all samples will be on the annotation output.\n\n"
+		    "Please report to linux-kernel@vger.kernel.org\n",
+		    ip, map->dso->long_name, dso__symtab_origin(map->dso),
+		    map->start, map->end, sym->start, sym->end,
+		    sym->binding == STB_GLOBAL ? 'g' :
+		    sym->binding == STB_LOCAL  ? 'l' : 'w', sym->name,
+		    err ? "[unknown]" : uts.machine,
+		    err ? "[unknown]" : uts.release, perf_version_string);
+
+	map->erange_warned = true;
 }
 
-static void ui__warn_enomem(struct perf_top *top, struct addr_location *al)
+static int perf_top__check_enomem(struct perf_top *top,
+				  struct addr_location *al __maybe_unused)
 {
-	if (!top->enomem_warned) {
-		ui__warning("Not enough memory for annotating '%s' symbol!\n",
-			    al->sym->name);
+	return top->enomem_warned;
+}
+static void perf_top__warn_enomem(struct perf_top *top,
+				  struct addr_location *al)
+{
+	ui__warning("Not enough memory for annotating '%s' symbol!\n",
+		    al->sym ? al->sym->name : "unknown");
 
-		if (use_browser <= 0)
-			sleep(5);
-		top->enomem_warned = true;
-	}
+	top->enomem_warned = true;
+}
+
+static int perf_top__check_kptr_restrict(struct perf_top *top,
+					 struct addr_location *al __maybe_unused)
+{
+	return top->kptr_restrict_warned;
 }
 
-static void ui__warn_kptr_restrict(struct perf_top *top, struct addr_location *al)
+static void perf_top__warn_kptr_restrict(struct perf_top *top,
+					 struct addr_location *al)
 {
-	if (!top->kptr_restrict_warned) {
-		ui__warning(
+	ui__warning(
 "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
 "Check /proc/sys/kernel/kptr_restrict.\n\n"
 "Kernel%s samples will not be resolved.\n",
-			  al->map && !RB_EMPTY_ROOT(&al->map->dso->symbols[MAP__FUNCTION]) ?
-			  " modules" : "");
-		if (use_browser <= 0)
-			sleep(5);
-		top->kptr_restrict_warned = true;
-	}
+		    al->map && !RB_EMPTY_ROOT(&al->map->dso->symbols[MAP__FUNCTION]) ?
+		    " modules" : "");
+
+	top->kptr_restrict_warned = true;
+}
+
+static int perf_top__check_vmlinux(struct perf_top *top,
+				   struct addr_location *al)
+{
+	if (!RB_EMPTY_ROOT(&al->map->dso->symbols[MAP__FUNCTION]))
+		return true;
+
+	return top->kptr_restrict_warned || top->vmlinux_warned;
 }
 
-static void ui__warn_vmlinux(struct perf_top *top, struct addr_location *al)
+static void perf_top__warn_vmlinux(struct perf_top *top,
+				   struct addr_location *al)
 {
 	const char *msg = "Kernel samples will not be resolved.\n";
 	/*
@@ -218,22 +240,96 @@ static void ui__warn_vmlinux(struct perf_top *top, struct addr_location *al)
 	 * --hide-kernel-symbols, even if the user specifies an
 	 * invalid --vmlinux ;-)
 	 */
-	if (!top->kptr_restrict_warned && !top->vmlinux_warned &&
-	    RB_EMPTY_ROOT(&al->map->dso->symbols[MAP__FUNCTION])) {
-		if (symbol_conf.vmlinux_name) {
-			char serr[256];
-			dso__strerror_load(al->map->dso, serr, sizeof(serr));
-			ui__warning("The %s file can't be used: %s\n%s",
-				    symbol_conf.vmlinux_name, serr, msg);
-		} else {
-			ui__warning("A vmlinux file was not found.\n%s",
-				    msg);
-		}
+	if (symbol_conf.vmlinux_name) {
+		char serr[256];
+		dso__strerror_load(al->map->dso, serr, sizeof(serr));
+		ui__warning("The %s file can't be used: %s\n%s",
+			    symbol_conf.vmlinux_name, serr, msg);
+	} else {
+		ui__warning("A vmlinux file was not found.\n%s", msg);
+	}
+	top->vmlinux_warned = true;
+}
+
+static struct addr_location warn_al;
+static pthread_mutex_t warn_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static enum warn_request {
+	WARN_NONE,
+	WARN_ENOMEM,
+	WARN_ERANGE,
+	WARN_VMLINUX,
+	WARN_KPTR_RESTRICT,
+	WARN_MAX,
+} wreq = WARN_NONE;
+
+static struct perf_top__warning {
+	int (*check)(struct perf_top *top, struct addr_location *al);
+	void (*warn)(struct perf_top *top, struct addr_location *al);
+} warnings[] = {
+	{ NULL, NULL },
+
+#define W(item)  { perf_top__check_ ## item, perf_top__warn_ ## item }
+
+	W(enomem),
+	W(map_erange),
+	W(vmlinux),
+	W(kptr_restrict),
+
+#undef W
+};
+
+static void perf_top__request_warning(struct perf_top *top,
+				      struct addr_location *al,
+				      enum warn_request req)
+{
+	pthread_mutex_lock(&warn_mutex);
+
+	if (req > wreq && !warnings[req].check(top, al)) {
+		map__zput(warn_al.map);
+
+		wreq = req;
+		warn_al = *al;
 
-		if (use_browser <= 0)
-			sleep(5);
-		top->vmlinux_warned = true;
+		map__get(warn_al.map);
 	}
+
+	pthread_mutex_unlock(&warn_mutex);
+}
+
+static void perf_top__show_warning(struct perf_top *top)
+{
+	enum warn_request req;
+	struct addr_location al;
+
+	pthread_mutex_lock(&warn_mutex);
+
+retry:
+	BUG_ON(wreq < 0 || wreq >= WARN_MAX);
+
+	req = wreq;
+	al = warn_al;
+	warn_al.map = NULL;
+
+	pthread_mutex_unlock(&warn_mutex);
+
+	if (req == WARN_NONE)
+		return;
+
+	warnings[req].warn(top, &al);
+	map__put(al.map);
+
+	if (use_browser <= 0)
+		sleep(5);
+
+	pthread_mutex_lock(&warn_mutex);
+
+	if (req < wreq)
+		goto retry;
+
+	wreq = WARN_NONE;
+
+	pthread_mutex_unlock(&warn_mutex);
 }
 
 static void perf_top__record_precise_ip(struct perf_top *top,
@@ -267,9 +363,9 @@ static void perf_top__record_precise_ip(struct perf_top *top,
 		pthread_mutex_unlock(&he->hists->lock);
 
 		if (err == -ERANGE)
-			ui__warn_map_erange(top, al);
+			perf_top__request_warning(top, al, WARN_ERANGE);
 		else if (err == -ENOMEM)
-			ui__warn_enomem(top, al);
+			perf_top__request_warning(top, al, WARN_ENOMEM);
 
 		pthread_mutex_lock(&he->hists->lock);
 	}
@@ -358,6 +454,8 @@ static void perf_top__print_sym_table(struct perf_top *top)
 	putchar('\n');
 	hists__fprintf(hists, false, top->print_entries - printed, win_width,
 		       top->min_percent, stdout);
+
+	perf_top__show_warning(top);
 }
 
 static void prompt_integer(int *target, const char *msg)
@@ -624,6 +722,8 @@ static void perf_top__sort_new_samples(void *arg)
 
 	hists__collapse_resort(hists, NULL);
 	hists__output_resort(hists, NULL);
+
+	perf_top__show_warning(t);
 }
 
 static void *display_thread_tui(void *arg)
@@ -794,10 +894,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
 		return;
 
 	if (symbol_conf.kptr_restrict && al.cpumode == PERF_RECORD_MISC_KERNEL)
-		ui__warn_kptr_restrict(top, &al);
+		perf_top__request_warning(top, &al, WARN_KPTR_RESTRICT);
 
 	if (al.sym == NULL && al.map == machine->vmlinux_maps[MAP__FUNCTION])
-		ui__warn_vmlinux(top, &al);
+		perf_top__request_warning(top, &al, WARN_VMLINUX);
 
 	if (al.sym == NULL || !al.sym->ignore) {
 		struct hists *hists = evsel__hists(evsel);
-- 
2.6.2


  parent reply	other threads:[~2015-12-10  7:54 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-10  7:53 [PATCHSET 00/16] perf top: Add multi-thread support (v1) Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 01/16] perf top: Delete half-processed hist entries when exit Namhyung Kim
2015-12-10  9:55   ` 平松雅巳 / HIRAMATU,MASAMI
2015-12-10 18:57     ` Arnaldo Carvalho de Melo
2015-12-14  8:15   ` [tip:perf/core] " tip-bot for Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 02/16] perf top: Fix and cleanup perf_top__record_precise_ip() Namhyung Kim
2015-12-10 19:04   ` Arnaldo Carvalho de Melo
2015-12-11  2:27     ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 03/16] perf top: Factor out warnings about kernel addresses and symbols Namhyung Kim
2015-12-10 19:07   ` Arnaldo Carvalho de Melo
2015-12-14  1:44     ` Namhyung Kim
2015-12-14  2:02       ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 04/16] perf top: Factor out warnings in perf_top__record_precise_ip() Namhyung Kim
2015-12-10  7:53 ` Namhyung Kim [this message]
2015-12-10  7:53 ` [PATCH/RFC 06/16] perf top: Get rid of access to hists->lock " Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 07/16] perf hists: Pass hists struct to hist_entry_iter struct Namhyung Kim
2015-12-13 23:15   ` Jiri Olsa
2015-12-14  1:45     ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 08/16] perf tools: Export a couple of hist functions Namhyung Kim
2015-12-13 23:17   ` Jiri Olsa
2015-12-10  7:53 ` [PATCH/RFC 09/16] perf tools: Update hist entry's hists pointer Namhyung Kim
2015-12-13 23:23   ` Jiri Olsa
2015-12-13 23:28     ` Jiri Olsa
2015-12-14  1:51       ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 10/16] perf hist: Add events_stats__add() and hists__add_stats() Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 11/16] perf top: Implement basic parallel processing Namhyung Kim
2015-12-14  9:23   ` Jiri Olsa
2015-12-14  9:35     ` Jiri Olsa
2015-12-15  2:08       ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 12/16] perf tools: Reduce lock contention when processing events Namhyung Kim
2015-12-14  8:43   ` Jiri Olsa
2015-12-15  2:03     ` Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 13/16] perf top: Protect the seen list using mutex Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 14/16] perf top: Separate struct perf_top_stats Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 15/16] perf top: Add --num-thread option Namhyung Kim
2015-12-10  7:53 ` [PATCH/RFC 16/16] perf tools: Skip dso front cache for multi-threaded lookup Namhyung Kim
2015-12-10  8:01 ` [PATCHSET 00/16] perf top: Add multi-thread support (v1) Ingo Molnar
2015-12-10  8:49   ` Namhyung Kim
2015-12-11  8:11     ` Ingo Molnar
2015-12-11 15:01       ` David Ahern
2015-12-14  1:12         ` Namhyung Kim
2015-12-14  9:26         ` Peter Zijlstra
2015-12-14  9:38           ` Ingo Molnar
2015-12-14 14:55             ` David Ahern
2015-12-14 16:26               ` Arnaldo Carvalho de Melo
2015-12-14 16:41                 ` Peter Zijlstra
2015-12-14 17:52                   ` Arnaldo Carvalho de Melo
2015-12-14 16:38             ` Namhyung Kim
2015-12-14 16:56               ` Peter Zijlstra
2015-12-14 17:11                 ` Namhyung Kim
2015-12-14 14:46           ` David Ahern
2015-12-14 17:06             ` Namhyung Kim
2015-12-14 17:54               ` Arnaldo Carvalho de Melo
2015-12-14 16:25           ` Namhyung Kim
2015-12-14 16:44             ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1449734015-9148-6-git-send-email-namhyung@kernel.org \
    --to=namhyung@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=andi@firstfloor.org \
    --cc=dsahern@gmail.com \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).