The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3)
@ 2013-12-26  5:37 Namhyung Kim
  2013-12-26  5:37 ` [PATCH 1/8] perf ui/tui: Protect windows by ui__lock Namhyung Kim
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

Hello,

I reordered the patches so that it can be applied more smoothly.
Patch 1-2 are general cleanup/fix and not related to this patchset.
Patch 3 implements the header window for perf report.  And the rest is
for the new log window.

 * changes from v2)
  - fix segfault on log window w/ filter (Jiri)
  - split and sort help messages (Ingo)
  - optimize log window update w/ filter
  - fix help/input window display


I put the patches on 'perf/tui-v3' branch in my tree:

  git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git

Any feedbacks are more than welcome, thanks
Namhyung


Namhyung Kim (8):
  perf ui/tui: Protect windows by ui__lock
  perf ui/tui: Split help message for perf top and report
  perf ui/tui: Implement header window
  perf tools: Introduce struct perf_log
  perf tools: Save message when pr_*() was called
  perf ui/tui: Implement log window
  perf ui/tui: Filter messages in log window
  perf ui/tui: Remember last log line for filtering

 tools/perf/Makefile.perf        |   3 +
 tools/perf/perf.c               |   3 +
 tools/perf/ui/browser.h         |   3 +
 tools/perf/ui/browsers/header.c | 127 ++++++++++++++++++++++
 tools/perf/ui/browsers/hists.c  |  60 ++++++----
 tools/perf/ui/browsers/log.c    | 235 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/ui/tui/util.c        |  19 +++-
 tools/perf/util/debug.c         |   6 +
 tools/perf/util/debug.h         |  16 +++
 tools/perf/util/log.c           | 111 +++++++++++++++++++
 10 files changed, 561 insertions(+), 22 deletions(-)
 create mode 100644 tools/perf/ui/browsers/header.c
 create mode 100644 tools/perf/ui/browsers/log.c
 create mode 100644 tools/perf/util/log.c

-- 
1.7.11.7


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/8] perf ui/tui: Protect windows by ui__lock
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
@ 2013-12-26  5:37 ` Namhyung Kim
  2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2013-12-26  5:37 ` [PATCH 2/8] perf ui/tui: Split help message for perf top and report Namhyung Kim
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Sometimes perf top TUI breaks display with concurrent help/input
window and pr_* messages since they're not protected by ui__lock.
You can check it by pressing (and not releasing) 'h' key on a
"perf top -vvv" TUI session.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/tui/util.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index 092902e30cee..bf890f72fe80 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 		t = sep + 1;
 	}
 
+	pthread_mutex_lock(&ui__lock);
+
 	max_len += 2;
 	nr_lines += 8;
 	y = SLtt_Screen_Rows / 2 - nr_lines / 2;
@@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 	SLsmg_write_nstring((char *)exit_msg, max_len);
 	SLsmg_refresh();
 
+	pthread_mutex_unlock(&ui__lock);
+
 	x += 2;
 	len = 0;
 	key = ui__getch(delay_secs);
 	while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+		pthread_mutex_lock(&ui__lock);
+
 		if (key == K_BKSPC) {
-			if (len == 0)
+			if (len == 0) {
+				pthread_mutex_unlock(&ui__lock);
 				goto next_key;
+			}
 			SLsmg_gotorc(y, x + --len);
 			SLsmg_write_char(' ');
 		} else {
@@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 		}
 		SLsmg_refresh();
 
+		pthread_mutex_unlock(&ui__lock);
+
 		/* XXX more graceful overflow handling needed */
 		if (len == sizeof(buf) - 1) {
 			ui_helpline__push("maximum size of symbol name reached!");
@@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text,
 		t = sep + 1;
 	}
 
+	pthread_mutex_lock(&ui__lock);
+
 	max_len += 2;
 	nr_lines += 4;
 	y = SLtt_Screen_Rows / 2 - nr_lines / 2,
@@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text,
 	SLsmg_gotorc(y + nr_lines - 1, x);
 	SLsmg_write_nstring((char *)exit_msg, max_len);
 	SLsmg_refresh();
+
+	pthread_mutex_unlock(&ui__lock);
+
 	return ui__getch(delay_secs);
 }
 
@@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args)
 	if (vasprintf(&s, format, args) > 0) {
 		int key;
 
-		pthread_mutex_lock(&ui__lock);
 		key = ui__question_window(title, s, "Press any key...", 0);
-		pthread_mutex_unlock(&ui__lock);
 		free(s);
 		return key;
 	}
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/8] perf ui/tui: Split help message for perf top and report
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
  2013-12-26  5:37 ` [PATCH 1/8] perf ui/tui: Protect windows by ui__lock Namhyung Kim
@ 2013-12-26  5:37 ` Namhyung Kim
  2013-12-26 14:05   ` Arnaldo Carvalho de Melo
  2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2013-12-26  5:37 ` [PATCH 3/8] perf ui/tui: Implement header window Namhyung Kim
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Some hotkeys don't work for perf top so split help messages for them.
It'll be helpful to a future modification.  Also sort the message by
alphabetical order of the hotkey.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/browsers/hists.c | 49 ++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a440e03cd8c2..d43ec79ea4e3 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1400,6 +1400,35 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 	char script_opt[64];
 	int delay_secs = hbt ? hbt->refresh : 0;
 
+#define HIST_BROWSER_HELP_COMMON					\
+	"h/?/F1        Show this window\n"				\
+	"UP/DOWN/PGUP\n"						\
+	"PGDN/SPACE    Navigate\n"					\
+	"q/ESC/CTRL+C  Exit browser\n\n"				\
+	"For multiple event sessions:\n\n"				\
+	"TAB/UNTAB     Switch events\n\n"				\
+	"For symbolic views (--sort has sym):\n\n"			\
+	"->            Zoom into DSO/Threads & Annotate current symbol\n" \
+	"<-            Zoom out\n"					\
+	"a             Annotate current symbol\n"			\
+	"C             Collapse all callchains\n"			\
+	"d             Zoom into current DSO\n"				\
+	"E             Expand all callchains\n"				\
+
+	/* help messages are sorted by lexical order of the hotkey */
+	const char report_help[] = HIST_BROWSER_HELP_COMMON
+	"P             Print histograms to perf.hist.N\n"
+	"r             Run available scripts\n"
+	"s             Switch to another data file in PWD\n"
+	"t             Zoom into current Thread\n"
+	"V             Verbose (DSO names in callchains, etc)\n"
+	"/             Filter symbol by name";
+	const char top_help[] = HIST_BROWSER_HELP_COMMON
+	"P             Print histograms to perf.hist.N\n"
+	"t             Zoom into current Thread\n"
+	"V             Verbose (DSO names in callchains, etc)\n"
+	"/             Filter symbol by name";
+
 	if (browser == NULL)
 		return -1;
 
@@ -1488,25 +1517,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 		case 'h':
 		case '?':
 			ui_browser__help_window(&browser->b,
-					"h/?/F1        Show this window\n"
-					"UP/DOWN/PGUP\n"
-					"PGDN/SPACE    Navigate\n"
-					"q/ESC/CTRL+C  Exit browser\n\n"
-					"For multiple event sessions:\n\n"
-					"TAB/UNTAB Switch events\n\n"
-					"For symbolic views (--sort has sym):\n\n"
-					"->            Zoom into DSO/Threads & Annotate current symbol\n"
-					"<-            Zoom out\n"
-					"a             Annotate current symbol\n"
-					"C             Collapse all callchains\n"
-					"E             Expand all callchains\n"
-					"d             Zoom into current DSO\n"
-					"t             Zoom into current Thread\n"
-					"r             Run available scripts('perf report' only)\n"
-					"s             Switch to another data file in PWD ('perf report' only)\n"
-					"P             Print histograms to perf.hist.N\n"
-					"V             Verbose (DSO names in callchains, etc)\n"
-					"/             Filter symbol by name");
+				is_report_browser(hbt) ? report_help : top_help);
 			continue;
 		case K_ENTER:
 		case K_RIGHT:
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/8] perf ui/tui: Implement header window
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
  2013-12-26  5:37 ` [PATCH 1/8] perf ui/tui: Protect windows by ui__lock Namhyung Kim
  2013-12-26  5:37 ` [PATCH 2/8] perf ui/tui: Split help message for perf top and report Namhyung Kim
@ 2013-12-26  5:37 ` Namhyung Kim
  2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2013-12-26  5:38 ` [PATCH 4/8] perf tools: Introduce struct perf_log Namhyung Kim
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Implement a simple, full-screen header window which shows session
header (metadata) information.  Press 'i' key to display the header
window.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Makefile.perf        |   1 +
 tools/perf/ui/browser.h         |   2 +
 tools/perf/ui/browsers/header.c | 127 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/ui/browsers/hists.c  |   6 ++
 4 files changed, 136 insertions(+)
 create mode 100644 tools/perf/ui/browsers/header.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 97a2145e4cc6..3638b0bd20dc 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -489,6 +489,7 @@ ifndef NO_SLANG
   LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
   LIB_OBJS += $(OUTPUT)ui/browsers/map.o
   LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/header.o
   LIB_OBJS += $(OUTPUT)ui/tui/setup.o
   LIB_OBJS += $(OUTPUT)ui/tui/util.o
   LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 7d45d2f53601..118cca29dd26 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text);
 bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
 int ui_browser__input_window(const char *title, const char *text, char *input,
 			     const char *exit_msg, int delay_sec);
+struct perf_session_env;
+int tui__header_window(struct perf_session_env *env);
 
 void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
 unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
new file mode 100644
index 000000000000..89c16b988618
--- /dev/null
+++ b/tools/perf/ui/browsers/header.c
@@ -0,0 +1,127 @@
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/browser.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/libslang.h"
+#include "util/header.h"
+#include "util/session.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+				   void *entry, int row)
+{
+	char **arg = entry;
+	char *str = *arg;
+	char empty[] = " ";
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	unsigned long offset = (unsigned long)browser->priv;
+
+	if (offset >= strlen(str))
+		str = empty;
+	else
+		str = str + offset;
+
+	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+						       HE_COLORSET_NORMAL);
+
+	slsmg_write_nstring(str, browser->width);
+}
+
+static int list_menu__run(struct ui_browser *menu)
+{
+	int key;
+	unsigned long offset;
+	const char help[] =
+	"h/?/F1        Show this window\n"
+	"UP/DOWN/PGUP\n"
+	"PGDN/SPACE\n"
+	"LEFT/RIGHT    Navigate\n"
+	"q/ESC/CTRL+C  Exit browser";
+
+	if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
+		return -1;
+
+	while (1) {
+		key = ui_browser__run(menu, 0);
+
+		switch (key) {
+		case K_RIGHT:
+			offset = (unsigned long)menu->priv;
+			offset += 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_LEFT:
+			offset = (unsigned long)menu->priv;
+			if (offset >= 10)
+				offset -= 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_F1:
+		case 'h':
+		case '?':
+			ui_browser__help_window(menu, help);
+			continue;
+		case K_ESC:
+		case 'q':
+		case CTRL('c'):
+			key = -1;
+			break;
+		default:
+			continue;
+		}
+
+		break;
+	}
+
+	ui_browser__hide(menu);
+	return key;
+}
+
+static int ui__list_menu(int argc, char * const argv[])
+{
+	struct ui_browser menu = {
+		.entries    = (void *)argv,
+		.refresh    = ui_browser__argv_refresh,
+		.seek	    = ui_browser__argv_seek,
+		.write	    = ui_browser__argv_write,
+		.nr_entries = argc,
+	};
+
+	return list_menu__run(&menu);
+}
+
+int tui__header_window(struct perf_session_env *env)
+{
+	int i, argc = 0;
+	char **argv;
+	struct perf_session *session;
+	char *ptr, *pos;
+	size_t size;
+	FILE *fp = open_memstream(&ptr, &size);
+
+	session = container_of(env, struct perf_session, header.env);
+	perf_header__fprintf_info(session, fp, true);
+	fclose(fp);
+
+	for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
+		argc++;
+
+	argv = calloc(argc + 1, sizeof(*argv));
+	if (argv == NULL)
+		goto out;
+
+	argv[0] = pos = ptr;
+	for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
+		*pos++ = '\0';
+		argv[i] = pos;
+	}
+
+	BUG_ON(i != argc + 1);
+
+	ui__list_menu(argc, argv);
+
+out:
+	free(argv);
+	free(ptr);
+	return 0;
+}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index d43ec79ea4e3..0d9dd99507ee 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1417,6 +1417,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
 	/* help messages are sorted by lexical order of the hotkey */
 	const char report_help[] = HIST_BROWSER_HELP_COMMON
+	"i             Show header information\n"
 	"P             Print histograms to perf.hist.N\n"
 	"r             Run available scripts\n"
 	"s             Switch to another data file in PWD\n"
@@ -1513,6 +1514,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 			if (is_report_browser(hbt))
 				goto do_data_switch;
 			continue;
+		case 'i':
+			/* env->arch is NULL for live-mode (i.e. perf top) */
+			if (env->arch)
+				tui__header_window(env);
+			continue;
 		case K_F1:
 		case 'h':
 		case '?':
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/8] perf tools: Introduce struct perf_log
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
                   ` (2 preceding siblings ...)
  2013-12-26  5:37 ` [PATCH 3/8] perf ui/tui: Implement header window Namhyung Kim
@ 2013-12-26  5:38 ` Namhyung Kim
  2013-12-26 14:50   ` Arnaldo Carvalho de Melo
  2013-12-26 14:51   ` David Ahern
  2013-12-26  5:38 ` [PATCH 5/8] perf tools: Save message when pr_*() was called Namhyung Kim
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Add new functions to save error messages in a temp file.  It'll be
used by some UI front-ends to see the messages.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Makefile.perf |   1 +
 tools/perf/perf.c        |   3 ++
 tools/perf/util/debug.h  |  15 +++++++
 tools/perf/util/log.c    | 105 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 124 insertions(+)
 create mode 100644 tools/perf/util/log.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3638b0bd20dc..49c5c998009e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -372,6 +372,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
 LIB_OBJS += $(OUTPUT)util/record.o
 LIB_OBJS += $(OUTPUT)util/srcline.o
 LIB_OBJS += $(OUTPUT)util/data.o
+LIB_OBJS += $(OUTPUT)util/log.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 431798a4110d..bdf7bd8e4394 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -10,6 +10,7 @@
 
 #include "util/exec_cmd.h"
 #include "util/cache.h"
+#include "util/debug.h"
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
@@ -524,6 +525,7 @@ int main(int argc, const char **argv)
 	 */
 	pthread__block_sigwinch();
 
+	perf_log_init();
 	while (1) {
 		static int done_help;
 		int was_alias = run_argv(&argc, &argv);
@@ -543,6 +545,7 @@ int main(int argc, const char **argv)
 		} else
 			break;
 	}
+	perf_log_exit();
 
 	fprintf(stderr, "Failed to run command '%s': %s\n",
 		cmd, strerror(errno));
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 443694c36b03..ea160abc2ae0 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -19,4 +19,19 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 
 void pr_stat(const char *fmt, ...);
 
+struct perf_log {
+	FILE *fp;
+	off_t *linemap;
+	u32 lines;
+	u32 nr_alloc;
+	bool seen_newline;
+};
+
+extern struct perf_log perf_log;
+
+int perf_log_init(void);
+int perf_log_exit(void);
+void perf_log_add(const char *msg);
+void perf_log_addv(const char *fmt, va_list ap);
+
 #endif	/* __PERF_DEBUG_H */
diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
new file mode 100644
index 000000000000..3838d49f82de
--- /dev/null
+++ b/tools/perf/util/log.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "util/debug.h"
+
+#define LINEMAP_GROW  128
+
+struct perf_log perf_log = {
+	.seen_newline = true,
+};
+
+int perf_log_init(void)
+{
+	FILE *fp;
+	char name[] = "/tmp/perf-log-XXXXXX";
+	int fd = mkstemp(name);
+
+	if (fd < 0)
+		return -1;
+
+	fp = fdopen(fd, "r+");
+	if (fp == NULL) {
+		close(fd);
+		return -1;
+	}
+
+	perf_log.fp = fp;
+
+	return 0;
+}
+
+int perf_log_exit(void)
+{
+	FILE *fp = perf_log.fp;
+	if (fp)
+		fclose(fp);
+
+	free(perf_log.linemap);
+
+	perf_log.fp = NULL;
+	perf_log.linemap = NULL;
+	return 0;
+}
+
+static int grow_linemap(struct perf_log *log)
+{
+	off_t *newmap;
+	int newsize = log->nr_alloc + LINEMAP_GROW;
+
+	newmap = realloc(log->linemap, newsize * sizeof(*log->linemap));
+	if (newmap == NULL)
+		return -1;
+
+	log->nr_alloc = newsize;
+	log->linemap = newmap;
+	return 0;
+}
+
+static int __add_to_linemap(struct perf_log *log, off_t idx)
+{
+	if (log->lines == log->nr_alloc)
+		if (grow_linemap(log) < 0)
+			return -1;
+
+	log->linemap[log->lines++] = idx;
+	return 0;
+}
+
+static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
+{
+	const char *pos;
+
+	if (strlen(msg) == 0)
+		return;
+
+	if (log->seen_newline) {
+		if (__add_to_linemap(log, base) < 0)
+			return;
+	}
+
+	if ((pos = strchr(msg, '\n')) != NULL) {
+		log->seen_newline = true;
+		pos++;
+		add_to_linemap(log, pos, base + (pos - msg));
+	} else {
+		log->seen_newline = false;
+	}
+}
+
+void perf_log_add(const char *msg)
+{
+	FILE *fp = perf_log.fp;
+	off_t offset = ftello(fp);
+
+	add_to_linemap(&perf_log, msg, offset);
+
+	fwrite(msg, 1, strlen(msg), fp);
+}
+
+void perf_log_addv(const char *fmt, va_list ap)
+{
+	char buf[4096];
+
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	perf_log_add(buf);
+}
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/8] perf tools: Save message when pr_*() was called
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
                   ` (3 preceding siblings ...)
  2013-12-26  5:38 ` [PATCH 4/8] perf tools: Introduce struct perf_log Namhyung Kim
@ 2013-12-26  5:38 ` Namhyung Kim
  2013-12-26  5:38 ` [PATCH 6/8] perf ui/tui: Implement log window Namhyung Kim
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

The message will be saved in a temp file so that it can be shown at a
UI dialog at any time.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/debug.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 299b55586502..f55b499c93fb 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -19,12 +19,18 @@ bool dump_trace = false, quiet = false;
 static int _eprintf(int level, const char *fmt, va_list args)
 {
 	int ret = 0;
+	va_list ap;
 
 	if (verbose >= level) {
+		va_copy(ap, args);
+
 		if (use_browser >= 1)
 			ui_helpline__vshow(fmt, args);
 		else
 			ret = vfprintf(stderr, fmt, args);
+
+		perf_log_addv(fmt, ap);
+		va_end(ap);
 	}
 
 	return ret;
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 6/8] perf ui/tui: Implement log window
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
                   ` (4 preceding siblings ...)
  2013-12-26  5:38 ` [PATCH 5/8] perf tools: Save message when pr_*() was called Namhyung Kim
@ 2013-12-26  5:38 ` Namhyung Kim
  2013-12-26  5:38 ` [PATCH 7/8] perf ui/tui: Filter messages in " Namhyung Kim
  2013-12-26  5:38 ` [PATCH 8/8] perf ui/tui: Remember last log line for filtering Namhyung Kim
  7 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Implement a simple, full-screen log window which shows error messages
saved so far.  Press 'l' (lower-case 'L') key to display the log
window.  It'll be used usually with -v option.

Protect updating log by ui__lock to prevent the linemap reallocation
during log window refresh (it led to a segfault) and add
linemap_changed member to perf_log in order to detect the change.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Makefile.perf       |   1 +
 tools/perf/ui/browser.h        |   1 +
 tools/perf/ui/browsers/hists.c |   5 ++
 tools/perf/ui/browsers/log.c   | 132 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/debug.h        |   1 +
 tools/perf/util/log.c          |   8 ++-
 6 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/ui/browsers/log.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 49c5c998009e..7cce69b9911a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -491,6 +491,7 @@ ifndef NO_SLANG
   LIB_OBJS += $(OUTPUT)ui/browsers/map.o
   LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
   LIB_OBJS += $(OUTPUT)ui/browsers/header.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/log.o
   LIB_OBJS += $(OUTPUT)ui/tui/setup.o
   LIB_OBJS += $(OUTPUT)ui/tui/util.o
   LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 118cca29dd26..1f676c8ec4f3 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -61,6 +61,7 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 			     const char *exit_msg, int delay_sec);
 struct perf_session_env;
 int tui__header_window(struct perf_session_env *env);
+int tui__log_window(void);
 
 void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
 unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 0d9dd99507ee..828b0113a213 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1418,6 +1418,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 	/* help messages are sorted by lexical order of the hotkey */
 	const char report_help[] = HIST_BROWSER_HELP_COMMON
 	"i             Show header information\n"
+	"l             Show log messages\n"
 	"P             Print histograms to perf.hist.N\n"
 	"r             Run available scripts\n"
 	"s             Switch to another data file in PWD\n"
@@ -1425,6 +1426,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 	"V             Verbose (DSO names in callchains, etc)\n"
 	"/             Filter symbol by name";
 	const char top_help[] = HIST_BROWSER_HELP_COMMON
+	"l             Show log messages\n"
 	"P             Print histograms to perf.hist.N\n"
 	"t             Zoom into current Thread\n"
 	"V             Verbose (DSO names in callchains, etc)\n"
@@ -1519,6 +1521,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 			if (env->arch)
 				tui__header_window(env);
 			continue;
+		case 'l':
+			tui__log_window();
+			continue;
 		case K_F1:
 		case 'h':
 		case '?':
diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
new file mode 100644
index 000000000000..c64aeb8f9aac
--- /dev/null
+++ b/tools/perf/ui/browsers/log.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+
+#include "perf.h"
+#include "util/util.h"
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/browser.h"
+#include "ui/libslang.h"
+#include "ui/keysyms.h"
+
+static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
+				  off_t offset __maybe_unused,
+				  int whence __maybe_unused)
+{
+	/* do nothing */
+}
+
+static void ui_browser__file_write(struct ui_browser *browser,
+				   void *entry, int row)
+{
+	char buf[1024];
+	char empty[] = " ";
+	FILE *fp = perf_log.fp;
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	off_t *linemap = perf_log.linemap;
+	unsigned int idx = *(unsigned int *)entry;
+	unsigned long offset = (unsigned long)browser->priv;
+
+	fseek(fp, linemap[idx], SEEK_SET);
+	if (fgets(buf, sizeof(buf), fp) == NULL)
+		return;
+
+	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+						       HE_COLORSET_NORMAL);
+
+	if (offset < strlen(buf))
+		slsmg_write_nstring(&buf[offset], browser->width);
+	else
+		slsmg_write_nstring(empty, browser->width);
+}
+
+static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
+{
+	unsigned int row = 0;
+	unsigned int idx = browser->top_idx;
+	fpos_t pos;
+
+	fgetpos(perf_log.fp, &pos);
+
+	if (perf_log.linemap_changed) {
+		/* update log window with new linemap */
+		browser->entries = perf_log.linemap;
+		browser->nr_entries = perf_log.lines;
+		perf_log.linemap_changed = false;
+	}
+
+	while (idx < browser->nr_entries) {
+		ui_browser__gotorc(browser, row, 0);
+		browser->write(browser, &idx, row);
+		if (++row == browser->height)
+			break;
+
+		++idx;
+	}
+
+	fsetpos(perf_log.fp, &pos);
+	return row;
+}
+
+static int log_menu__run(struct ui_browser *menu)
+{
+	int key;
+	unsigned long offset;
+	const char help[] =
+	"h/?/F1        Show this window\n"
+	"UP/DOWN/PGUP\n"
+	"PGDN/SPACE\n"
+	"LEFT/RIGHT    Navigate\n"
+	"q/ESC/CTRL+C  Exit browser";
+
+	if (ui_browser__show(menu, "Log messages", "Press 'q' to exit") < 0)
+		return -1;
+
+	while (1) {
+		key = ui_browser__run(menu, 0);
+
+		switch (key) {
+		case K_RIGHT:
+			offset = (unsigned long)menu->priv;
+			offset += 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_LEFT:
+			offset = (unsigned long)menu->priv;
+			if (offset >= 10)
+				offset -= 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_F1:
+		case 'h':
+		case '?':
+			ui_browser__help_window(menu, help);
+			continue;
+		case K_ESC:
+		case 'q':
+		case CTRL('c'):
+			key = -1;
+			break;
+		default:
+			continue;
+		}
+
+		break;
+	}
+
+	ui_browser__hide(menu);
+	return key;
+}
+
+int tui__log_window(void)
+{
+	struct ui_browser log_menu = {
+		.refresh    = ui_browser__file_refresh,
+		.seek	    = ui_browser__file_seek,
+		.write	    = ui_browser__file_write,
+		.nr_entries = perf_log.lines,
+	};
+
+	return log_menu__run(&log_menu);
+}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index ea160abc2ae0..bc3affed682e 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -25,6 +25,7 @@ struct perf_log {
 	u32 lines;
 	u32 nr_alloc;
 	bool seen_newline;
+	bool linemap_changed;
 };
 
 extern struct perf_log perf_log;
diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
index 3838d49f82de..aee71da25a24 100644
--- a/tools/perf/util/log.c
+++ b/tools/perf/util/log.c
@@ -89,11 +89,17 @@ static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
 void perf_log_add(const char *msg)
 {
 	FILE *fp = perf_log.fp;
-	off_t offset = ftello(fp);
+	off_t offset;
+
+	pthread_mutex_lock(&ui__lock);
+	offset = ftello(fp);
 
 	add_to_linemap(&perf_log, msg, offset);
 
 	fwrite(msg, 1, strlen(msg), fp);
+
+	perf_log.linemap_changed = true;
+	pthread_mutex_unlock(&ui__lock);
 }
 
 void perf_log_addv(const char *fmt, va_list ap)
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 7/8] perf ui/tui: Filter messages in log window
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
                   ` (5 preceding siblings ...)
  2013-12-26  5:38 ` [PATCH 6/8] perf ui/tui: Implement log window Namhyung Kim
@ 2013-12-26  5:38 ` Namhyung Kim
  2013-12-26  5:38 ` [PATCH 8/8] perf ui/tui: Remember last log line for filtering Namhyung Kim
  7 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

Press '/' key to input filter string like main hist browser does.

Requested-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/browsers/log.c | 117 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 103 insertions(+), 14 deletions(-)

diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
index c64aeb8f9aac..62343e0578bb 100644
--- a/tools/perf/ui/browsers/log.c
+++ b/tools/perf/ui/browsers/log.c
@@ -10,6 +10,14 @@
 #include "ui/libslang.h"
 #include "ui/keysyms.h"
 
+struct log_browser_data {
+	unsigned long offset;
+	u32 alloc;
+	char filter[64];
+};
+
+static void __log_menu__filter(struct ui_browser *menu, char *filter);
+
 static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
 				  off_t offset __maybe_unused,
 				  int whence __maybe_unused)
@@ -23,10 +31,11 @@ static void ui_browser__file_write(struct ui_browser *browser,
 	char buf[1024];
 	char empty[] = " ";
 	FILE *fp = perf_log.fp;
+	struct log_browser_data *lbd = browser->priv;
 	bool current_entry = ui_browser__is_current_entry(browser, row);
-	off_t *linemap = perf_log.linemap;
+	off_t *linemap = browser->entries;
 	unsigned int idx = *(unsigned int *)entry;
-	unsigned long offset = (unsigned long)browser->priv;
+	unsigned long offset = lbd->offset;
 
 	fseek(fp, linemap[idx], SEEK_SET);
 	if (fgets(buf, sizeof(buf), fp) == NULL)
@@ -45,14 +54,14 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
 {
 	unsigned int row = 0;
 	unsigned int idx = browser->top_idx;
+	struct log_browser_data *lbd = browser->priv;
 	fpos_t pos;
 
 	fgetpos(perf_log.fp, &pos);
 
 	if (perf_log.linemap_changed) {
 		/* update log window with new linemap */
-		browser->entries = perf_log.linemap;
-		browser->nr_entries = perf_log.lines;
+		__log_menu__filter(browser, lbd->filter);
 		perf_log.linemap_changed = false;
 	}
 
@@ -69,16 +78,81 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
 	return row;
 }
 
+static void __log_menu__filter(struct ui_browser *menu, char *filter)
+{
+	char buf[1024];
+	struct log_browser_data *lbd = menu->priv;
+	off_t *linemap = NULL;
+	u32 lines = 0;
+	u32 alloc = 0;
+	u32 i;
+
+	if (*filter == '\0') {
+		linemap = perf_log.linemap;
+		lines = perf_log.lines;
+		goto out;
+	}
+
+	for (i = 0; i < perf_log.lines; i++) {
+		fseek(perf_log.fp, perf_log.linemap[i], SEEK_SET);
+		if (fgets(buf, sizeof(buf), perf_log.fp) == NULL)
+			goto error;
+
+		if (strstr(buf, filter) == NULL)
+			continue;
+
+		if (lines == alloc) {
+			off_t *map;
+
+			map = realloc(linemap, (alloc + 128) * sizeof(*map));
+			if (map == NULL)
+				goto error;
+
+			linemap = map;
+			alloc += 128;
+		}
+
+		linemap[lines++] = perf_log.linemap[i];
+	}
+
+out:
+	if (lbd->alloc) {
+		BUG_ON(menu->entries == perf_log.linemap);
+		free(menu->entries);
+	}
+	lbd->alloc = alloc;
+
+	menu->entries = linemap;
+	ui_browser__update_nr_entries(menu, lines);
+	return;
+
+error:
+	free(linemap);
+}
+
+static void log_menu__filter(struct ui_browser *menu, char *filter)
+{
+	fpos_t pos;
+
+	pthread_mutex_lock(&ui__lock);
+	fgetpos(perf_log.fp, &pos);
+	__log_menu__filter(menu, filter);
+	fsetpos(perf_log.fp, &pos);
+	perf_log.linemap_changed = false;
+	pthread_mutex_unlock(&ui__lock);
+}
+
 static int log_menu__run(struct ui_browser *menu)
 {
 	int key;
-	unsigned long offset;
+	struct log_browser_data *lbd = menu->priv;
 	const char help[] =
 	"h/?/F1        Show this window\n"
 	"UP/DOWN/PGUP\n"
 	"PGDN/SPACE\n"
 	"LEFT/RIGHT    Navigate\n"
-	"q/ESC/CTRL+C  Exit browser";
+	"q/ESC/CTRL+C  Exit browser\n\n"
+	"/             Filter log message";
 
 	if (ui_browser__show(menu, "Log messages", "Press 'q' to exit") < 0)
 		return -1;
@@ -88,21 +162,25 @@ static int log_menu__run(struct ui_browser *menu)
 
 		switch (key) {
 		case K_RIGHT:
-			offset = (unsigned long)menu->priv;
-			offset += 10;
-			menu->priv = (void *)offset;
+			lbd->offset += 10;
 			continue;
 		case K_LEFT:
-			offset = (unsigned long)menu->priv;
-			if (offset >= 10)
-				offset -= 10;
-			menu->priv = (void *)offset;
+			if (lbd->offset >= 10)
+				lbd->offset -= 10;
 			continue;
 		case K_F1:
 		case 'h':
 		case '?':
 			ui_browser__help_window(menu, help);
 			continue;
+		case '/':
+			if (ui_browser__input_window("Symbol to filter",
+					"Please enter the name of symbol you want to see",
+					lbd->filter, "ENTER: OK, ESC: Cancel",
+					0) == K_ENTER) {
+				log_menu__filter(menu, lbd->filter);
+			}
+			continue;
 		case K_ESC:
 		case 'q':
 		case CTRL('c'):
@@ -121,12 +199,23 @@ static int log_menu__run(struct ui_browser *menu)
 
 int tui__log_window(void)
 {
+	struct log_browser_data lbd = {
+		.filter	    = "",
+	};
 	struct ui_browser log_menu = {
 		.refresh    = ui_browser__file_refresh,
 		.seek	    = ui_browser__file_seek,
 		.write	    = ui_browser__file_write,
+		.entries    = perf_log.linemap,
 		.nr_entries = perf_log.lines,
+		.priv	    = &lbd,
 	};
+	int key;
+
+	key = log_menu__run(&log_menu);
 
-	return log_menu__run(&log_menu);
+	if (lbd.alloc)
+		free(log_menu.entries);
+
+	return key;
 }
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 8/8] perf ui/tui: Remember last log line for filtering
  2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
                   ` (6 preceding siblings ...)
  2013-12-26  5:38 ` [PATCH 7/8] perf ui/tui: Filter messages in " Namhyung Kim
@ 2013-12-26  5:38 ` Namhyung Kim
  7 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2013-12-26  5:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

From: Namhyung Kim <namhyung.kim@lge.com>

When updating log window with filter string, no need to search all
logs everytime.  Just save the last offset and update from there.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/ui/browsers/log.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/tools/perf/ui/browsers/log.c b/tools/perf/ui/browsers/log.c
index 62343e0578bb..6491c353eef7 100644
--- a/tools/perf/ui/browsers/log.c
+++ b/tools/perf/ui/browsers/log.c
@@ -13,10 +13,11 @@
 struct log_browser_data {
 	unsigned long offset;
 	u32 alloc;
+	u32 last_log_line;
 	char filter[64];
 };
 
-static void __log_menu__filter(struct ui_browser *menu, char *filter);
+static void __log_menu__filter(struct ui_browser *menu, char *filter, bool update);
 
 static void ui_browser__file_seek(struct ui_browser *browser __maybe_unused,
 				  off_t offset __maybe_unused,
@@ -61,7 +62,7 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
 
 	if (perf_log.linemap_changed) {
 		/* update log window with new linemap */
-		__log_menu__filter(browser, lbd->filter);
+		__log_menu__filter(browser, lbd->filter, true);
 		perf_log.linemap_changed = false;
 	}
 
@@ -78,14 +79,15 @@ static unsigned int ui_browser__file_refresh(struct ui_browser *browser)
 	return row;
 }
 
-static void __log_menu__filter(struct ui_browser *menu, char *filter)
+static void __log_menu__filter(struct ui_browser *menu, char *filter, bool update)
 {
 	char buf[1024];
 	struct log_browser_data *lbd = menu->priv;
 	off_t *linemap = NULL;
 	u32 lines = 0;
 	u32 alloc = 0;
-	u32 i;
+	u32 last = 0;
+	u32 i = 0;
 
 	if (*filter == '\0') {
 		linemap = perf_log.linemap;
@@ -93,7 +95,14 @@ static void __log_menu__filter(struct ui_browser *menu, char *filter)
 		goto out;
 	}
 
-	for (i = 0; i < perf_log.lines; i++) {
+	if (update) {
+		linemap = menu->entries;
+		lines = menu->nr_entries;
+		alloc = lbd->alloc;
+		last = lbd->last_log_line;
+	}
+
+	for (i = last; i < perf_log.lines; i++) {
 		fseek(perf_log.fp, perf_log.linemap[i], SEEK_SET);
 		if (fgets(buf, sizeof(buf), perf_log.fp) == NULL)
 			goto error;
@@ -120,7 +129,12 @@ out:
 		BUG_ON(menu->entries == perf_log.linemap);
 		free(menu->entries);
 	}
+
 	lbd->alloc = alloc;
+	lbd->last_log_line = i;
+
+	if (!update)
+		ui_browser__reset_index(menu);
 
 	menu->entries = linemap;
 	ui_browser__update_nr_entries(menu, lines);
@@ -136,7 +150,7 @@ static void log_menu__filter(struct ui_browser *menu, char *filter)
 
 	pthread_mutex_lock(&ui__lock);
 	fgetpos(perf_log.fp, &pos);
-	__log_menu__filter(menu, filter);
+	__log_menu__filter(menu, filter, false);
 	fsetpos(perf_log.fp, &pos);
 	perf_log.linemap_changed = false;
 	pthread_mutex_unlock(&ui__lock);
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/8] perf ui/tui: Split help message for perf top and report
  2013-12-26  5:37 ` [PATCH 2/8] perf ui/tui: Split help message for perf top and report Namhyung Kim
@ 2013-12-26 14:05   ` Arnaldo Carvalho de Melo
  2013-12-26 14:12     ` Arnaldo Carvalho de Melo
  2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
  1 sibling, 1 reply; 18+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-12-26 14:05 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

Em Thu, Dec 26, 2013 at 02:37:58PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> Some hotkeys don't work for perf top so split help messages for them.
> It'll be helpful to a future modification.  Also sort the message by
> alphabetical order of the hotkey.
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/ui/browsers/hists.c | 49 ++++++++++++++++++++++++++----------------
>  1 file changed, 30 insertions(+), 19 deletions(-)
> 
> diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
> index a440e03cd8c2..d43ec79ea4e3 100644
> --- a/tools/perf/ui/browsers/hists.c
> +++ b/tools/perf/ui/browsers/hists.c
> @@ -1400,6 +1400,35 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
>  	char script_opt[64];
>  	int delay_secs = hbt ? hbt->refresh : 0;
>  
> +#define HIST_BROWSER_HELP_COMMON					\
> +	"h/?/F1        Show this window\n"				\
> +	"UP/DOWN/PGUP\n"						\
> +	"PGDN/SPACE    Navigate\n"					\
> +	"q/ESC/CTRL+C  Exit browser\n\n"				\
> +	"For multiple event sessions:\n\n"				\
> +	"TAB/UNTAB     Switch events\n\n"				\
> +	"For symbolic views (--sort has sym):\n\n"			\
> +	"->            Zoom into DSO/Threads & Annotate current symbol\n" \
> +	"<-            Zoom out\n"					\
> +	"a             Annotate current symbol\n"			\
> +	"C             Collapse all callchains\n"			\
> +	"d             Zoom into current DSO\n"				\
> +	"E             Expand all callchains\n"				\
> +
> +	/* help messages are sorted by lexical order of the hotkey */
> +	const char report_help[] = HIST_BROWSER_HELP_COMMON
> +	"P             Print histograms to perf.hist.N\n"
> +	"r             Run available scripts\n"
> +	"s             Switch to another data file in PWD\n"
> +	"t             Zoom into current Thread\n"
> +	"V             Verbose (DSO names in callchains, etc)\n"
> +	"/             Filter symbol by name";
> +	const char top_help[] = HIST_BROWSER_HELP_COMMON
> +	"P             Print histograms to perf.hist.N\n"
> +	"t             Zoom into current Thread\n"
> +	"V             Verbose (DSO names in callchains, etc)\n"
> +	"/             Filter symbol by name";
> +
>  	if (browser == NULL)
  		return -1;

This wastes space, why not have the HIST_BROWSER_HELP_COMMON as a

	const char common_help[] = ...

and then use:
		ui_browser_helo(..., "%s%s", common_help,
				is_report_browser(hbt) ? report_help : top_help);

?

- Arnaldo

>  
> @@ -1488,25 +1517,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
>  		case 'h':
>  		case '?':
>  			ui_browser__help_window(&browser->b,
> -					"h/?/F1        Show this window\n"
> -					"UP/DOWN/PGUP\n"
> -					"PGDN/SPACE    Navigate\n"
> -					"q/ESC/CTRL+C  Exit browser\n\n"
> -					"For multiple event sessions:\n\n"
> -					"TAB/UNTAB Switch events\n\n"
> -					"For symbolic views (--sort has sym):\n\n"
> -					"->            Zoom into DSO/Threads & Annotate current symbol\n"
> -					"<-            Zoom out\n"
> -					"a             Annotate current symbol\n"
> -					"C             Collapse all callchains\n"
> -					"E             Expand all callchains\n"
> -					"d             Zoom into current DSO\n"
> -					"t             Zoom into current Thread\n"
> -					"r             Run available scripts('perf report' only)\n"
> -					"s             Switch to another data file in PWD ('perf report' only)\n"
> -					"P             Print histograms to perf.hist.N\n"
> -					"V             Verbose (DSO names in callchains, etc)\n"
> -					"/             Filter symbol by name");
> +				is_report_browser(hbt) ? report_help : top_help);
>  			continue;
>  		case K_ENTER:
>  		case K_RIGHT:
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/8] perf ui/tui: Split help message for perf top and report
  2013-12-26 14:05   ` Arnaldo Carvalho de Melo
@ 2013-12-26 14:12     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 18+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-12-26 14:12 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

Em Thu, Dec 26, 2013 at 11:05:21AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Thu, Dec 26, 2013 at 02:37:58PM +0900, Namhyung Kim escreveu:
> > Some hotkeys don't work for perf top so split help messages for them.
> > It'll be helpful to a future modification.  Also sort the message by
> > alphabetical order of the hotkey.

> > +++ b/tools/perf/ui/browsers/hists.c
> > @@ -1400,6 +1400,35 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
> >  	char script_opt[64];
> >  	int delay_secs = hbt ? hbt->refresh : 0;
> >  
> > +#define HIST_BROWSER_HELP_COMMON					\
> > +	"h/?/F1        Show this window\n"				\
> > +	"UP/DOWN/PGUP\n"						\
> > +	"PGDN/SPACE    Navigate\n"					\
> > +	"q/ESC/CTRL+C  Exit browser\n\n"				\
> > +	"For multiple event sessions:\n\n"				\
> > +	"TAB/UNTAB     Switch events\n\n"				\
> > +	"For symbolic views (--sort has sym):\n\n"			\
> > +	"->            Zoom into DSO/Threads & Annotate current symbol\n" \
> > +	"<-            Zoom out\n"					\
> > +	"a             Annotate current symbol\n"			\
> > +	"C             Collapse all callchains\n"			\
> > +	"d             Zoom into current DSO\n"				\
> > +	"E             Expand all callchains\n"				\
> > +
> > +	/* help messages are sorted by lexical order of the hotkey */
> > +	const char report_help[] = HIST_BROWSER_HELP_COMMON
> > +	"P             Print histograms to perf.hist.N\n"
> > +	"r             Run available scripts\n"
> > +	"s             Switch to another data file in PWD\n"
> > +	"t             Zoom into current Thread\n"
> > +	"V             Verbose (DSO names in callchains, etc)\n"
> > +	"/             Filter symbol by name";
> > +	const char top_help[] = HIST_BROWSER_HELP_COMMON
> > +	"P             Print histograms to perf.hist.N\n"
> > +	"t             Zoom into current Thread\n"
> > +	"V             Verbose (DSO names in callchains, etc)\n"
> > +	"/             Filter symbol by name";
> > +
> >  	if (browser == NULL)
>   		return -1;
> 
> This wastes space, why not have the HIST_BROWSER_HELP_COMMON as a
> 
> 	const char common_help[] = ...
> 
> and then use:
> 		ui_browser__help(..., "%s%s", common_help,
> 				is_report_browser(hbt) ? report_help : top_help);
> 
> ?

Because ui__help_window doesn't support va_arg, ok, applying this one
and later we can remove this space wastage when we make it support
variadic arguments.

- Arnaldo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] perf tools: Introduce struct perf_log
  2013-12-26  5:38 ` [PATCH 4/8] perf tools: Introduce struct perf_log Namhyung Kim
@ 2013-12-26 14:50   ` Arnaldo Carvalho de Melo
  2014-01-03  8:23     ` Namhyung Kim
  2013-12-26 14:51   ` David Ahern
  1 sibling, 1 reply; 18+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-12-26 14:50 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

Em Thu, Dec 26, 2013 at 02:38:00PM +0900, Namhyung Kim escreveu:
> From: Namhyung Kim <namhyung.kim@lge.com>
> 
> Add new functions to save error messages in a temp file.  It'll be
> used by some UI front-ends to see the messages.
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/Makefile.perf |   1 +
>  tools/perf/perf.c        |   3 ++
>  tools/perf/util/debug.h  |  15 +++++++
>  tools/perf/util/log.c    | 105 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 124 insertions(+)
>  create mode 100644 tools/perf/util/log.c
> 
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 3638b0bd20dc..49c5c998009e 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -372,6 +372,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
>  LIB_OBJS += $(OUTPUT)util/record.o
>  LIB_OBJS += $(OUTPUT)util/srcline.o
>  LIB_OBJS += $(OUTPUT)util/data.o
> +LIB_OBJS += $(OUTPUT)util/log.o
>  
>  LIB_OBJS += $(OUTPUT)ui/setup.o
>  LIB_OBJS += $(OUTPUT)ui/helpline.o
> diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> index 431798a4110d..bdf7bd8e4394 100644
> --- a/tools/perf/perf.c
> +++ b/tools/perf/perf.c
> @@ -10,6 +10,7 @@
>  
>  #include "util/exec_cmd.h"
>  #include "util/cache.h"
> +#include "util/debug.h"
>  #include "util/quote.h"
>  #include "util/run-command.h"
>  #include "util/parse-events.h"
> @@ -524,6 +525,7 @@ int main(int argc, const char **argv)
>  	 */
>  	pthread__block_sigwinch();
>  
> +	perf_log_init();
>  	while (1) {
>  		static int done_help;
>  		int was_alias = run_argv(&argc, &argv);
> @@ -543,6 +545,7 @@ int main(int argc, const char **argv)
>  		} else
>  			break;
>  	}
> +	perf_log_exit();
>  
>  	fprintf(stderr, "Failed to run command '%s': %s\n",
>  		cmd, strerror(errno));
> diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
> index 443694c36b03..ea160abc2ae0 100644
> --- a/tools/perf/util/debug.h
> +++ b/tools/perf/util/debug.h
> @@ -19,4 +19,19 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
>  
>  void pr_stat(const char *fmt, ...);
>  
> +struct perf_log {
> +	FILE *fp;
> +	off_t *linemap;
> +	u32 lines;
> +	u32 nr_alloc;
> +	bool seen_newline;
> +};
> +
> +extern struct perf_log perf_log;
> +
> +int perf_log_init(void);
> +int perf_log_exit(void);
> +void perf_log_add(const char *msg);
> +void perf_log_addv(const char *fmt, va_list ap);

The convention in tools/perf/ has been to use class__method, i.e. in the
above case we would have:

int perf_log__init(void);
int perf_log__exit(void);
void perf_log__add(const char *msg);
void perf_log__addv(const char *fmt, va_list ap);


But I have some questions about the implementation, will we go on
allocating memory for each and every line?

Can't we just come out with a simple ui_file_browser class that would
then be usable for any file, including this one?

The ui_file_browser__seek() method would have to go on reading lines and
seeking newlines, with the ui_file_browser__seek(browser, 0, SEEK_SET)
would map directly to fseek(log_fp, 0, SEEK_SET), etc.

It should handle "live" files, like the one we're feeding log lines,
etc.

The way you implemented it will grow memory consumption without limits, no?

- Arnaldo

>  #endif	/* __PERF_DEBUG_H */
> diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
> new file mode 100644
> index 000000000000..3838d49f82de
> --- /dev/null
> +++ b/tools/perf/util/log.c
> @@ -0,0 +1,105 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include "util/debug.h"
> +
> +#define LINEMAP_GROW  128
> +
> +struct perf_log perf_log = {
> +	.seen_newline = true,
> +};
> +
> +int perf_log_init(void)
> +{
> +	FILE *fp;
> +	char name[] = "/tmp/perf-log-XXXXXX";
> +	int fd = mkstemp(name);
> +
> +	if (fd < 0)
> +		return -1;
> +
> +	fp = fdopen(fd, "r+");
> +	if (fp == NULL) {
> +		close(fd);
> +		return -1;
> +	}
> +
> +	perf_log.fp = fp;
> +
> +	return 0;
> +}
> +
> +int perf_log_exit(void)
> +{
> +	FILE *fp = perf_log.fp;
> +	if (fp)
> +		fclose(fp);
> +
> +	free(perf_log.linemap);
> +
> +	perf_log.fp = NULL;
> +	perf_log.linemap = NULL;
> +	return 0;
> +}
> +
> +static int grow_linemap(struct perf_log *log)
> +{
> +	off_t *newmap;
> +	int newsize = log->nr_alloc + LINEMAP_GROW;
> +
> +	newmap = realloc(log->linemap, newsize * sizeof(*log->linemap));
> +	if (newmap == NULL)
> +		return -1;
> +
> +	log->nr_alloc = newsize;
> +	log->linemap = newmap;
> +	return 0;
> +}
> +
> +static int __add_to_linemap(struct perf_log *log, off_t idx)
> +{
> +	if (log->lines == log->nr_alloc)
> +		if (grow_linemap(log) < 0)
> +			return -1;
> +
> +	log->linemap[log->lines++] = idx;
> +	return 0;
> +}
> +
> +static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
> +{
> +	const char *pos;
> +
> +	if (strlen(msg) == 0)
> +		return;
> +
> +	if (log->seen_newline) {
> +		if (__add_to_linemap(log, base) < 0)
> +			return;
> +	}
> +
> +	if ((pos = strchr(msg, '\n')) != NULL) {
> +		log->seen_newline = true;
> +		pos++;
> +		add_to_linemap(log, pos, base + (pos - msg));
> +	} else {
> +		log->seen_newline = false;
> +	}
> +}
> +
> +void perf_log_add(const char *msg)
> +{
> +	FILE *fp = perf_log.fp;
> +	off_t offset = ftello(fp);
> +
> +	add_to_linemap(&perf_log, msg, offset);
> +
> +	fwrite(msg, 1, strlen(msg), fp);
> +}
> +
> +void perf_log_addv(const char *fmt, va_list ap)
> +{
> +	char buf[4096];
> +
> +	vsnprintf(buf, sizeof(buf), fmt, ap);
> +	perf_log_add(buf);
> +}
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] perf tools: Introduce struct perf_log
  2013-12-26  5:38 ` [PATCH 4/8] perf tools: Introduce struct perf_log Namhyung Kim
  2013-12-26 14:50   ` Arnaldo Carvalho de Melo
@ 2013-12-26 14:51   ` David Ahern
  2014-01-03  8:49     ` Namhyung Kim
  1 sibling, 1 reply; 18+ messages in thread
From: David Ahern @ 2013-12-26 14:51 UTC (permalink / raw)
  To: Namhyung Kim, Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa

On 12/26/13, 12:38 AM, Namhyung Kim wrote:
> diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
> new file mode 100644
> index 000000000000..3838d49f82de
> --- /dev/null
> +++ b/tools/perf/util/log.c
> @@ -0,0 +1,105 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include "util/debug.h"
> +
> +#define LINEMAP_GROW  128
> +
> +struct perf_log perf_log = {
> +	.seen_newline = true,
> +};
> +
> +int perf_log_init(void)

Why return int if the rc is not checked? Failure here is not going to 
stop the perf command right?

> +{
> +	FILE *fp;
> +	char name[] = "/tmp/perf-log-XXXXXX";
> +	int fd = mkstemp(name);
> +
> +	if (fd < 0)
> +		return -1;
> +
> +	fp = fdopen(fd, "r+");
> +	if (fp == NULL) {
> +		close(fd);
> +		return -1;
> +	}
> +
> +	perf_log.fp = fp;

Add 'unlink(name);' here to ensure the file is removed regardless of how 
perf terminates.

> +
> +	return 0;
> +}
> +
> +int perf_log_exit(void)
> +{
> +	FILE *fp = perf_log.fp;
> +	if (fp)
> +		fclose(fp);
> +
> +	free(perf_log.linemap);
> +
> +	perf_log.fp = NULL;
> +	perf_log.linemap = NULL;
> +	return 0;
> +}
> +
> +static int grow_linemap(struct perf_log *log)
> +{
> +	off_t *newmap;
> +	int newsize = log->nr_alloc + LINEMAP_GROW;
> +
> +	newmap = realloc(log->linemap, newsize * sizeof(*log->linemap));
> +	if (newmap == NULL)
> +		return -1;
> +
> +	log->nr_alloc = newsize;
> +	log->linemap = newmap;
> +	return 0;
> +}

What's the point of linemap?

> +
> +static int __add_to_linemap(struct perf_log *log, off_t idx)
> +{
> +	if (log->lines == log->nr_alloc)
> +		if (grow_linemap(log) < 0)
> +			return -1;
> +
> +	log->linemap[log->lines++] = idx;
> +	return 0;
> +}
> +
> +static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
> +{
> +	const char *pos;
> +
> +	if (strlen(msg) == 0)
> +		return;
> +
> +	if (log->seen_newline) {
> +		if (__add_to_linemap(log, base) < 0)
> +			return;
> +	}
> +
> +	if ((pos = strchr(msg, '\n')) != NULL) {
> +		log->seen_newline = true;
> +		pos++;
> +		add_to_linemap(log, pos, base + (pos - msg));
> +	} else {
> +		log->seen_newline = false;
> +	}
> +}
> +
> +void perf_log_add(const char *msg)
> +{
> +	FILE *fp = perf_log.fp;

Don't assume every user of libperf calls perf_log_init() or that the 
file was actually created. i.e., add 'if (fp == NULL) return;'


> +	off_t offset = ftello(fp);
> +
> +	add_to_linemap(&perf_log, msg, offset);
> +
> +	fwrite(msg, 1, strlen(msg), fp);

And if write fails?

> +}
> +
> +void perf_log_addv(const char *fmt, va_list ap)
> +{
> +	char buf[4096];

Add as an optimization add the fp != NULL check here too. Don't need to 
do the vsnprintf only to drop it.

> +
> +	vsnprintf(buf, sizeof(buf), fmt, ap);
> +	perf_log_add(buf);
> +}
>

What limits the size of the file - other than the obvious out of space 
in /tmp? Allow the file to grow without bounds in case a user wants the 
messages seems dangerous.

What about using a circular buffer instead?

David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] perf tools: Introduce struct perf_log
  2013-12-26 14:50   ` Arnaldo Carvalho de Melo
@ 2014-01-03  8:23     ` Namhyung Kim
  0 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2014-01-03  8:23 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern

Hi Arnaldo,

On Thu, 26 Dec 2013 11:50:51 -0300, Arnaldo Carvalho de Melo wrote:
> Em Thu, Dec 26, 2013 at 02:38:00PM +0900, Namhyung Kim escreveu:
>> From: Namhyung Kim <namhyung.kim@lge.com>
>> 
>> Add new functions to save error messages in a temp file.  It'll be
>> used by some UI front-ends to see the messages.

[SNIP]
>> +struct perf_log {
>> +	FILE *fp;
>> +	off_t *linemap;
>> +	u32 lines;
>> +	u32 nr_alloc;
>> +	bool seen_newline;
>> +};
>> +
>> +extern struct perf_log perf_log;
>> +
>> +int perf_log_init(void);
>> +int perf_log_exit(void);
>> +void perf_log_add(const char *msg);
>> +void perf_log_addv(const char *fmt, va_list ap);
>
> The convention in tools/perf/ has been to use class__method, i.e. in the
> above case we would have:
>
> int perf_log__init(void);
> int perf_log__exit(void);
> void perf_log__add(const char *msg);
> void perf_log__addv(const char *fmt, va_list ap);

Okay.  (I wasn't follow the convention since the functions do not pass
the perf_log as an argument, but I agree it's better to follow it.)
Will change.

>
>
> But I have some questions about the implementation, will we go on
> allocating memory for each and every line?

Yes, it needs an offset for each line in order to find starting point.

>
> Can't we just come out with a simple ui_file_browser class that would
> then be usable for any file, including this one?

Yes we can do it if need be.  Do you think of another use case?

>
> The ui_file_browser__seek() method would have to go on reading lines and
> seeking newlines, with the ui_file_browser__seek(browser, 0, SEEK_SET)
> would map directly to fseek(log_fp, 0, SEEK_SET), etc.

It supposed to.  But in this case, the ->seek() method is called in
ui_browser__run() which is not protected by ui__lock.  So it's possible
that new log message alters file position if it's called after ->seek()
method was executed.

If it's guaranteed that there's no concurrent access to the file, we can
move fseek() to the ->seek() method IMHO.

>
> It should handle "live" files, like the one we're feeding log lines,
> etc.
>
> The way you implemented it will grow memory consumption without
> limits, no?

Right, it'll consume 8 bytes for each line of the file.  What's the
reasonable limitation?

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] perf tools: Introduce struct perf_log
  2013-12-26 14:51   ` David Ahern
@ 2014-01-03  8:49     ` Namhyung Kim
  0 siblings, 0 replies; 18+ messages in thread
From: Namhyung Kim @ 2014-01-03  8:49 UTC (permalink / raw)
  To: David Ahern
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Ingo Molnar, Namhyung Kim, LKML, Jiri Olsa

Hi David,

On Thu, 26 Dec 2013 09:51:25 -0500, David Ahern wrote:
> On 12/26/13, 12:38 AM, Namhyung Kim wrote:
>> diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c
>> new file mode 100644
>> index 000000000000..3838d49f82de
>> --- /dev/null
>> +++ b/tools/perf/util/log.c
>> @@ -0,0 +1,105 @@
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include "util/debug.h"
>> +
>> +#define LINEMAP_GROW  128
>> +
>> +struct perf_log perf_log = {
>> +	.seen_newline = true,
>> +};
>> +
>> +int perf_log_init(void)
>
> Why return int if the rc is not checked? Failure here is not going to
> stop the perf command right?

Right.  I'll add a debug print if it's failed.

>
>> +{
>> +	FILE *fp;
>> +	char name[] = "/tmp/perf-log-XXXXXX";
>> +	int fd = mkstemp(name);
>> +
>> +	if (fd < 0)
>> +		return -1;
>> +
>> +	fp = fdopen(fd, "r+");
>> +	if (fp == NULL) {
>> +		close(fd);
>> +		return -1;
>> +	}
>> +
>> +	perf_log.fp = fp;
>
> Add 'unlink(name);' here to ensure the file is removed regardless of
> how perf terminates.

Ah, okay.  I thought the mkstemp() unlinked the file after open()
returns.  It seems this is what tmpfile(3) does.  I'll switch to
tmpfile() then.

>
>> +
>> +	return 0;
>> +}
>> +
>> +int perf_log_exit(void)
>> +{
>> +	FILE *fp = perf_log.fp;
>> +	if (fp)
>> +		fclose(fp);
>> +
>> +	free(perf_log.linemap);
>> +
>> +	perf_log.fp = NULL;
>> +	perf_log.linemap = NULL;
>> +	return 0;
>> +}
>> +
>> +static int grow_linemap(struct perf_log *log)
>> +{
>> +	off_t *newmap;
>> +	int newsize = log->nr_alloc + LINEMAP_GROW;
>> +
>> +	newmap = realloc(log->linemap, newsize * sizeof(*log->linemap));
>> +	if (newmap == NULL)
>> +		return -1;
>> +
>> +	log->nr_alloc = newsize;
>> +	log->linemap = newmap;
>> +	return 0;
>> +}
>
> What's the point of linemap?

To save an offset of each line.  We need to keep it in order to move to
an arbitraty line in the browser.

>
>> +
>> +static int __add_to_linemap(struct perf_log *log, off_t idx)
>> +{
>> +	if (log->lines == log->nr_alloc)
>> +		if (grow_linemap(log) < 0)
>> +			return -1;
>> +
>> +	log->linemap[log->lines++] = idx;
>> +	return 0;
>> +}
>> +
>> +static void add_to_linemap(struct perf_log *log, const char *msg, off_t base)
>> +{
>> +	const char *pos;
>> +
>> +	if (strlen(msg) == 0)
>> +		return;
>> +
>> +	if (log->seen_newline) {
>> +		if (__add_to_linemap(log, base) < 0)
>> +			return;
>> +	}
>> +
>> +	if ((pos = strchr(msg, '\n')) != NULL) {
>> +		log->seen_newline = true;
>> +		pos++;
>> +		add_to_linemap(log, pos, base + (pos - msg));
>> +	} else {
>> +		log->seen_newline = false;
>> +	}
>> +}
>> +
>> +void perf_log_add(const char *msg)
>> +{
>> +	FILE *fp = perf_log.fp;
>
> Don't assume every user of libperf calls perf_log_init() or that the
> file was actually created. i.e., add 'if (fp == NULL) return;'

Okay.

>
>
>> +	off_t offset = ftello(fp);
>> +
>> +	add_to_linemap(&perf_log, msg, offset);
>> +
>> +	fwrite(msg, 1, strlen(msg), fp);
>
> And if write fails?

Hmm.. it's a problem.  We might go back to original linemap position for
a failure case.  I'll save the offset and line number and restore them.

>
>> +}
>> +
>> +void perf_log_addv(const char *fmt, va_list ap)
>> +{
>> +	char buf[4096];
>
> Add as an optimization add the fp != NULL check here too. Don't need
> to do the vsnprintf only to drop it.

Okay.

>
>> +
>> +	vsnprintf(buf, sizeof(buf), fmt, ap);
>> +	perf_log_add(buf);
>> +}
>>
>
> What limits the size of the file - other than the obvious out of space
> in /tmp? Allow the file to grow without bounds in case a user wants
> the messages seems dangerous.

Hmm. I don't have an idea what the reasonable size.  It's a temp file
anyway and usually it contains not much data - well, 'perf top -vvv' is
different and might need some surgery.

>
> What about using a circular buffer instead?

Instead of a file?  Yes, it's possible but I think it might not be a
good choice for the browser since it could alter the index during the
circulation so that the browser can confuse to update the entries.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf ui/tui: Protect windows by ui__lock
  2013-12-26  5:37 ` [PATCH 1/8] perf ui/tui: Protect windows by ui__lock Namhyung Kim
@ 2014-01-12 18:39   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-01-12 18:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, paulus, hpa, mingo, a.p.zijlstra,
	namhyung.kim, namhyung, jolsa, dsahern, tglx

Commit-ID:  5c743cf573e6974befe917ed4a36d42b39ef1ce0
Gitweb:     http://git.kernel.org/tip/5c743cf573e6974befe917ed4a36d42b39ef1ce0
Author:     Namhyung Kim <namhyung.kim@lge.com>
AuthorDate: Thu, 26 Dec 2013 14:37:57 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Dec 2013 11:22:01 -0300

perf ui/tui: Protect windows by ui__lock

Sometimes perf top TUI breaks display with concurrent help/input window
and pr_* messages since they're not protected by ui__lock.

You can check it by pressing (and not releasing) 'h' key on a "perf top
-vvv" TUI session.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1388036284-32342-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/ui/tui/util.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index 092902e..bf890f7 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 		t = sep + 1;
 	}
 
+	pthread_mutex_lock(&ui__lock);
+
 	max_len += 2;
 	nr_lines += 8;
 	y = SLtt_Screen_Rows / 2 - nr_lines / 2;
@@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 	SLsmg_write_nstring((char *)exit_msg, max_len);
 	SLsmg_refresh();
 
+	pthread_mutex_unlock(&ui__lock);
+
 	x += 2;
 	len = 0;
 	key = ui__getch(delay_secs);
 	while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+		pthread_mutex_lock(&ui__lock);
+
 		if (key == K_BKSPC) {
-			if (len == 0)
+			if (len == 0) {
+				pthread_mutex_unlock(&ui__lock);
 				goto next_key;
+			}
 			SLsmg_gotorc(y, x + --len);
 			SLsmg_write_char(' ');
 		} else {
@@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
 		}
 		SLsmg_refresh();
 
+		pthread_mutex_unlock(&ui__lock);
+
 		/* XXX more graceful overflow handling needed */
 		if (len == sizeof(buf) - 1) {
 			ui_helpline__push("maximum size of symbol name reached!");
@@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text,
 		t = sep + 1;
 	}
 
+	pthread_mutex_lock(&ui__lock);
+
 	max_len += 2;
 	nr_lines += 4;
 	y = SLtt_Screen_Rows / 2 - nr_lines / 2,
@@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text,
 	SLsmg_gotorc(y + nr_lines - 1, x);
 	SLsmg_write_nstring((char *)exit_msg, max_len);
 	SLsmg_refresh();
+
+	pthread_mutex_unlock(&ui__lock);
+
 	return ui__getch(delay_secs);
 }
 
@@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args)
 	if (vasprintf(&s, format, args) > 0) {
 		int key;
 
-		pthread_mutex_lock(&ui__lock);
 		key = ui__question_window(title, s, "Press any key...", 0);
-		pthread_mutex_unlock(&ui__lock);
 		free(s);
 		return key;
 	}

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf ui/tui: Split help message for perf top and report
  2013-12-26  5:37 ` [PATCH 2/8] perf ui/tui: Split help message for perf top and report Namhyung Kim
  2013-12-26 14:05   ` Arnaldo Carvalho de Melo
@ 2014-01-12 18:39   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-01-12 18:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, paulus, hpa, mingo, a.p.zijlstra,
	namhyung.kim, namhyung, jolsa, dsahern, tglx

Commit-ID:  e8e684a58b9bddde3fdb1a65cd26eb7a3e1e746e
Gitweb:     http://git.kernel.org/tip/e8e684a58b9bddde3fdb1a65cd26eb7a3e1e746e
Author:     Namhyung Kim <namhyung.kim@lge.com>
AuthorDate: Thu, 26 Dec 2013 14:37:58 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Dec 2013 11:22:02 -0300

perf ui/tui: Split help message for perf top and report

Some hotkeys don't work for perf top so split help messages for them.

It'll be helpful to a future modification.  Also sort the message by
alphabetical order of the hotkey.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1388036284-32342-3-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/ui/browsers/hists.c | 49 ++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a440e03..d43ec79 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1400,6 +1400,35 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 	char script_opt[64];
 	int delay_secs = hbt ? hbt->refresh : 0;
 
+#define HIST_BROWSER_HELP_COMMON					\
+	"h/?/F1        Show this window\n"				\
+	"UP/DOWN/PGUP\n"						\
+	"PGDN/SPACE    Navigate\n"					\
+	"q/ESC/CTRL+C  Exit browser\n\n"				\
+	"For multiple event sessions:\n\n"				\
+	"TAB/UNTAB     Switch events\n\n"				\
+	"For symbolic views (--sort has sym):\n\n"			\
+	"->            Zoom into DSO/Threads & Annotate current symbol\n" \
+	"<-            Zoom out\n"					\
+	"a             Annotate current symbol\n"			\
+	"C             Collapse all callchains\n"			\
+	"d             Zoom into current DSO\n"				\
+	"E             Expand all callchains\n"				\
+
+	/* help messages are sorted by lexical order of the hotkey */
+	const char report_help[] = HIST_BROWSER_HELP_COMMON
+	"P             Print histograms to perf.hist.N\n"
+	"r             Run available scripts\n"
+	"s             Switch to another data file in PWD\n"
+	"t             Zoom into current Thread\n"
+	"V             Verbose (DSO names in callchains, etc)\n"
+	"/             Filter symbol by name";
+	const char top_help[] = HIST_BROWSER_HELP_COMMON
+	"P             Print histograms to perf.hist.N\n"
+	"t             Zoom into current Thread\n"
+	"V             Verbose (DSO names in callchains, etc)\n"
+	"/             Filter symbol by name";
+
 	if (browser == NULL)
 		return -1;
 
@@ -1488,25 +1517,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 		case 'h':
 		case '?':
 			ui_browser__help_window(&browser->b,
-					"h/?/F1        Show this window\n"
-					"UP/DOWN/PGUP\n"
-					"PGDN/SPACE    Navigate\n"
-					"q/ESC/CTRL+C  Exit browser\n\n"
-					"For multiple event sessions:\n\n"
-					"TAB/UNTAB Switch events\n\n"
-					"For symbolic views (--sort has sym):\n\n"
-					"->            Zoom into DSO/Threads & Annotate current symbol\n"
-					"<-            Zoom out\n"
-					"a             Annotate current symbol\n"
-					"C             Collapse all callchains\n"
-					"E             Expand all callchains\n"
-					"d             Zoom into current DSO\n"
-					"t             Zoom into current Thread\n"
-					"r             Run available scripts('perf report' only)\n"
-					"s             Switch to another data file in PWD ('perf report' only)\n"
-					"P             Print histograms to perf.hist.N\n"
-					"V             Verbose (DSO names in callchains, etc)\n"
-					"/             Filter symbol by name");
+				is_report_browser(hbt) ? report_help : top_help);
 			continue;
 		case K_ENTER:
 		case K_RIGHT:

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf ui/tui: Implement header window
  2013-12-26  5:37 ` [PATCH 3/8] perf ui/tui: Implement header window Namhyung Kim
@ 2014-01-12 18:39   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-01-12 18:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, paulus, hpa, mingo, a.p.zijlstra,
	namhyung.kim, namhyung, jolsa, dsahern, tglx

Commit-ID:  6dd601354f14b5cd7a0a4103811e52ccec22ac53
Gitweb:     http://git.kernel.org/tip/6dd601354f14b5cd7a0a4103811e52ccec22ac53
Author:     Namhyung Kim <namhyung.kim@lge.com>
AuthorDate: Thu, 26 Dec 2013 14:37:59 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Dec 2013 11:22:02 -0300

perf ui/tui: Implement header window

Implement a simple, full-screen header window which shows session header
(metadata) information.  Press 'i' key to display the header window.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1388036284-32342-4-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.perf        |   1 +
 tools/perf/ui/browser.h         |   2 +
 tools/perf/ui/browsers/header.c | 127 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/ui/browsers/hists.c  |   6 ++
 4 files changed, 136 insertions(+)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 97a2145..3638b0b 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -489,6 +489,7 @@ ifndef NO_SLANG
   LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
   LIB_OBJS += $(OUTPUT)ui/browsers/map.o
   LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/header.o
   LIB_OBJS += $(OUTPUT)ui/tui/setup.o
   LIB_OBJS += $(OUTPUT)ui/tui/util.o
   LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 7d45d2f..118cca2 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text);
 bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
 int ui_browser__input_window(const char *title, const char *text, char *input,
 			     const char *exit_msg, int delay_sec);
+struct perf_session_env;
+int tui__header_window(struct perf_session_env *env);
 
 void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
 unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
new file mode 100644
index 0000000..89c16b9
--- /dev/null
+++ b/tools/perf/ui/browsers/header.c
@@ -0,0 +1,127 @@
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/browser.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/libslang.h"
+#include "util/header.h"
+#include "util/session.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+				   void *entry, int row)
+{
+	char **arg = entry;
+	char *str = *arg;
+	char empty[] = " ";
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	unsigned long offset = (unsigned long)browser->priv;
+
+	if (offset >= strlen(str))
+		str = empty;
+	else
+		str = str + offset;
+
+	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+						       HE_COLORSET_NORMAL);
+
+	slsmg_write_nstring(str, browser->width);
+}
+
+static int list_menu__run(struct ui_browser *menu)
+{
+	int key;
+	unsigned long offset;
+	const char help[] =
+	"h/?/F1        Show this window\n"
+	"UP/DOWN/PGUP\n"
+	"PGDN/SPACE\n"
+	"LEFT/RIGHT    Navigate\n"
+	"q/ESC/CTRL+C  Exit browser";
+
+	if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
+		return -1;
+
+	while (1) {
+		key = ui_browser__run(menu, 0);
+
+		switch (key) {
+		case K_RIGHT:
+			offset = (unsigned long)menu->priv;
+			offset += 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_LEFT:
+			offset = (unsigned long)menu->priv;
+			if (offset >= 10)
+				offset -= 10;
+			menu->priv = (void *)offset;
+			continue;
+		case K_F1:
+		case 'h':
+		case '?':
+			ui_browser__help_window(menu, help);
+			continue;
+		case K_ESC:
+		case 'q':
+		case CTRL('c'):
+			key = -1;
+			break;
+		default:
+			continue;
+		}
+
+		break;
+	}
+
+	ui_browser__hide(menu);
+	return key;
+}
+
+static int ui__list_menu(int argc, char * const argv[])
+{
+	struct ui_browser menu = {
+		.entries    = (void *)argv,
+		.refresh    = ui_browser__argv_refresh,
+		.seek	    = ui_browser__argv_seek,
+		.write	    = ui_browser__argv_write,
+		.nr_entries = argc,
+	};
+
+	return list_menu__run(&menu);
+}
+
+int tui__header_window(struct perf_session_env *env)
+{
+	int i, argc = 0;
+	char **argv;
+	struct perf_session *session;
+	char *ptr, *pos;
+	size_t size;
+	FILE *fp = open_memstream(&ptr, &size);
+
+	session = container_of(env, struct perf_session, header.env);
+	perf_header__fprintf_info(session, fp, true);
+	fclose(fp);
+
+	for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
+		argc++;
+
+	argv = calloc(argc + 1, sizeof(*argv));
+	if (argv == NULL)
+		goto out;
+
+	argv[0] = pos = ptr;
+	for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
+		*pos++ = '\0';
+		argv[i] = pos;
+	}
+
+	BUG_ON(i != argc + 1);
+
+	ui__list_menu(argc, argv);
+
+out:
+	free(argv);
+	free(ptr);
+	return 0;
+}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index d43ec79..0d9dd99 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1417,6 +1417,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
 	/* help messages are sorted by lexical order of the hotkey */
 	const char report_help[] = HIST_BROWSER_HELP_COMMON
+	"i             Show header information\n"
 	"P             Print histograms to perf.hist.N\n"
 	"r             Run available scripts\n"
 	"s             Switch to another data file in PWD\n"
@@ -1513,6 +1514,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 			if (is_report_browser(hbt))
 				goto do_data_switch;
 			continue;
+		case 'i':
+			/* env->arch is NULL for live-mode (i.e. perf top) */
+			if (env->arch)
+				tui__header_window(env);
+			continue;
 		case K_F1:
 		case 'h':
 		case '?':

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-01-12 18:40 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-26  5:37 [PATCHSET 0/8] perf tools: A couple of TUI improvements (v3) Namhyung Kim
2013-12-26  5:37 ` [PATCH 1/8] perf ui/tui: Protect windows by ui__lock Namhyung Kim
2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
2013-12-26  5:37 ` [PATCH 2/8] perf ui/tui: Split help message for perf top and report Namhyung Kim
2013-12-26 14:05   ` Arnaldo Carvalho de Melo
2013-12-26 14:12     ` Arnaldo Carvalho de Melo
2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
2013-12-26  5:37 ` [PATCH 3/8] perf ui/tui: Implement header window Namhyung Kim
2014-01-12 18:39   ` [tip:perf/core] " tip-bot for Namhyung Kim
2013-12-26  5:38 ` [PATCH 4/8] perf tools: Introduce struct perf_log Namhyung Kim
2013-12-26 14:50   ` Arnaldo Carvalho de Melo
2014-01-03  8:23     ` Namhyung Kim
2013-12-26 14:51   ` David Ahern
2014-01-03  8:49     ` Namhyung Kim
2013-12-26  5:38 ` [PATCH 5/8] perf tools: Save message when pr_*() was called Namhyung Kim
2013-12-26  5:38 ` [PATCH 6/8] perf ui/tui: Implement log window Namhyung Kim
2013-12-26  5:38 ` [PATCH 7/8] perf ui/tui: Filter messages in " Namhyung Kim
2013-12-26  5:38 ` [PATCH 8/8] perf ui/tui: Remember last log line for filtering Namhyung Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox