Commit c392c4c6 authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core

parents 841bca13 46e3e055
...@@ -277,7 +277,7 @@ static void hist_entry__print_hits(struct hist_entry *self) ...@@ -277,7 +277,7 @@ static void hist_entry__print_hits(struct hist_entry *self)
printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum);
} }
static void annotate_sym(struct hist_entry *he) static int hist_entry__tty_annotate(struct hist_entry *he)
{ {
struct map *map = he->ms.map; struct map *map = he->ms.map;
struct dso *dso = map->dso; struct dso *dso = map->dso;
...@@ -288,7 +288,7 @@ static void annotate_sym(struct hist_entry *he) ...@@ -288,7 +288,7 @@ static void annotate_sym(struct hist_entry *he)
struct objdump_line *pos, *n; struct objdump_line *pos, *n;
if (hist_entry__annotate(he, &head) < 0) if (hist_entry__annotate(he, &head) < 0)
return; return -1;
if (full_paths) if (full_paths)
d_filename = filename; d_filename = filename;
...@@ -317,31 +317,60 @@ static void annotate_sym(struct hist_entry *he) ...@@ -317,31 +317,60 @@ static void annotate_sym(struct hist_entry *he)
if (print_line) if (print_line)
free_source_line(he, len); free_source_line(he, len);
return 0;
} }
static void hists__find_annotations(struct hists *self) static void hists__find_annotations(struct hists *self)
{ {
struct rb_node *nd; struct rb_node *first = rb_first(&self->entries), *nd = first;
int key = KEY_RIGHT;
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { while (nd) {
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
struct sym_priv *priv; struct sym_priv *priv;
if (he->ms.sym == NULL) if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
continue; goto find_next;
priv = symbol__priv(he->ms.sym); priv = symbol__priv(he->ms.sym);
if (priv->hist == NULL) if (priv->hist == NULL) {
find_next:
if (key == KEY_LEFT)
nd = rb_prev(nd);
else
nd = rb_next(nd);
continue; continue;
}
annotate_sym(he); if (use_browser) {
key = hist_entry__tui_annotate(he);
if (is_exit_key(key))
break;
switch (key) {
case KEY_RIGHT:
case '\t':
nd = rb_next(nd);
break;
case KEY_LEFT:
if (nd == first)
continue;
nd = rb_prev(nd);
default:
break;
}
} else {
hist_entry__tty_annotate(he);
nd = rb_next(nd);
/* /*
* Since we have a hist_entry per IP for the same symbol, free * Since we have a hist_entry per IP for the same
* he->ms.sym->hist to signal we already processed this symbol. * symbol, free he->ms.sym->hist to signal we already
* processed this symbol.
*/ */
free(priv->hist); free(priv->hist);
priv->hist = NULL; priv->hist = NULL;
} }
}
} }
static struct perf_event_ops event_ops = { static struct perf_event_ops event_ops = {
...@@ -416,6 +445,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) ...@@ -416,6 +445,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
{ {
argc = parse_options(argc, argv, options, annotate_usage, 0); argc = parse_options(argc, argv, options, annotate_usage, 0);
setup_browser();
symbol_conf.priv_size = sizeof(struct sym_priv); symbol_conf.priv_size = sizeof(struct sym_priv);
symbol_conf.try_vmlinux_path = true; symbol_conf.try_vmlinux_path = true;
...@@ -435,8 +466,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) ...@@ -435,8 +466,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
sym_hist_filter = argv[0]; sym_hist_filter = argv[0];
} }
setup_pager();
if (field_sep && *field_sep == '.') { if (field_sep && *field_sep == '.') {
pr_err("'.' is the only non valid --field-separator argument\n"); pr_err("'.' is the only non valid --field-separator argument\n");
return -1; return -1;
......
...@@ -992,14 +992,14 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) ...@@ -992,14 +992,14 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
char *filename = dso__build_id_filename(dso, NULL, 0); char *filename = dso__build_id_filename(dso, NULL, 0);
char command[PATH_MAX * 2]; char command[PATH_MAX * 2];
FILE *file; FILE *file;
int err = -1; int err = 0;
u64 len; u64 len;
if (filename == NULL) { if (filename == NULL) {
if (dso->has_build_id) { if (dso->has_build_id) {
pr_err("Can't annotate %s: not enough memory\n", pr_err("Can't annotate %s: not enough memory\n",
sym->name); sym->name);
return -1; return -ENOMEM;
} }
/* /*
* If we don't have build-ids, well, lets hope that this * If we don't have build-ids, well, lets hope that this
...@@ -1009,14 +1009,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) ...@@ -1009,14 +1009,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
} }
if (dso->origin == DSO__ORIG_KERNEL) { if (dso->origin == DSO__ORIG_KERNEL) {
if (dso->annotate_warned) { if (dso->annotate_warned)
err = 0;
goto out_free_filename; goto out_free_filename;
} err = -ENOENT;
dso->annotate_warned = 1; dso->annotate_warned = 1;
pr_err("Can't annotate %s: No vmlinux file was found in the " pr_err("Can't annotate %s: No vmlinux file was found in the "
"path:\n", sym->name); "path\n", sym->name);
vmlinux_path__fprintf(stderr);
goto out_free_filename; goto out_free_filename;
} }
...@@ -1046,7 +1044,6 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) ...@@ -1046,7 +1044,6 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
break; break;
pclose(file); pclose(file);
err = 0;
out_free_filename: out_free_filename:
if (dso->has_build_id) if (dso->has_build_id)
free(filename); free(filename);
......
...@@ -102,8 +102,18 @@ static inline int hists__browse(struct hists *self __used, ...@@ -102,8 +102,18 @@ static inline int hists__browse(struct hists *self __used,
{ {
return 0; return 0;
} }
static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
{
return 0;
}
#define KEY_LEFT -1
#define KEY_RIGHT -2
#else #else
#include <newt.h>
int hists__browse(struct hists *self, const char *helpline, int hists__browse(struct hists *self, const char *helpline,
const char *input_name); const char *input_name);
int hist_entry__tui_annotate(struct hist_entry *self);
#define KEY_LEFT NEWT_KEY_LEFT
#define KEY_RIGHT NEWT_KEY_RIGHT
#endif #endif
#endif /* __PERF_HIST_H */ #endif /* __PERF_HIST_H */
...@@ -235,6 +235,15 @@ static bool dialog_yesno(const char *msg) ...@@ -235,6 +235,15 @@ static bool dialog_yesno(const char *msg)
return newtWinChoice(NULL, yes, no, (char *)msg) == 1; return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
} }
static void ui__error_window(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
va_end(ap);
}
#define HE_COLORSET_TOP 50 #define HE_COLORSET_TOP 50
#define HE_COLORSET_MEDIUM 51 #define HE_COLORSET_MEDIUM 51
#define HE_COLORSET_NORMAL 52 #define HE_COLORSET_NORMAL 52
...@@ -386,6 +395,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, ...@@ -386,6 +395,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
newtFormAddHotKey(self->form, ' '); newtFormAddHotKey(self->form, ' ');
newtFormAddHotKey(self->form, NEWT_KEY_HOME); newtFormAddHotKey(self->form, NEWT_KEY_HOME);
newtFormAddHotKey(self->form, NEWT_KEY_END); newtFormAddHotKey(self->form, NEWT_KEY_END);
newtFormAddHotKey(self->form, NEWT_KEY_TAB);
newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
if (ui_browser__refresh_entries(self) < 0) if (ui_browser__refresh_entries(self) < 0)
return -1; return -1;
...@@ -398,6 +409,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, ...@@ -398,6 +409,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
if (es->reason != NEWT_EXIT_HOTKEY) if (es->reason != NEWT_EXIT_HOTKEY)
break; break;
if (is_exit_key(es->u.key))
return es->u.key;
switch (es->u.key) { switch (es->u.key) {
case NEWT_KEY_DOWN: case NEWT_KEY_DOWN:
if (self->index == self->nr_entries - 1) if (self->index == self->nr_entries - 1)
...@@ -471,12 +484,10 @@ static int ui_browser__run(struct ui_browser *self, const char *title, ...@@ -471,12 +484,10 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
} }
} }
break; break;
case NEWT_KEY_ESCAPE: case NEWT_KEY_RIGHT:
case NEWT_KEY_LEFT: case NEWT_KEY_LEFT:
case CTRL('c'): case NEWT_KEY_TAB:
case 'Q': return es->u.key;
case 'q':
return 0;
default: default:
continue; continue;
} }
...@@ -668,18 +679,24 @@ static size_t hist_entry__append_browser(struct hist_entry *self, ...@@ -668,18 +679,24 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
return ret; return ret;
} }
static void hist_entry__annotate_browser(struct hist_entry *self) int hist_entry__tui_annotate(struct hist_entry *self)
{ {
struct ui_browser browser; struct ui_browser browser;
struct newtExitStruct es; struct newtExitStruct es;
struct objdump_line *pos, *n; struct objdump_line *pos, *n;
LIST_HEAD(head); LIST_HEAD(head);
int ret;
if (self->ms.sym == NULL) if (self->ms.sym == NULL)
return; return -1;
if (hist_entry__annotate(self, &head) < 0) if (self->ms.map->dso->annotate_warned)
return; return -1;
if (hist_entry__annotate(self, &head) < 0) {
ui__error_window(browser__last_msg);
return -1;
}
ui_helpline__push("Press <- or ESC to exit"); ui_helpline__push("Press <- or ESC to exit");
...@@ -694,7 +711,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) ...@@ -694,7 +711,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self)
} }
browser.width += 18; /* Percentage */ browser.width += 18; /* Percentage */
ui_browser__run(&browser, self->ms.sym->name, &es); ret = ui_browser__run(&browser, self->ms.sym->name, &es);
newtFormDestroy(browser.form); newtFormDestroy(browser.form);
newtPopWindow(); newtPopWindow();
list_for_each_entry_safe(pos, n, &head, node) { list_for_each_entry_safe(pos, n, &head, node) {
...@@ -702,6 +719,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) ...@@ -702,6 +719,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self)
objdump_line__free(pos); objdump_line__free(pos);
} }
ui_helpline__pop(); ui_helpline__pop();
return ret;
} }
static const void *newt__symbol_tree_get_current(newtComponent self) static const void *newt__symbol_tree_get_current(newtComponent self)
...@@ -914,6 +932,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na ...@@ -914,6 +932,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
switch (toupper(es.u.key)) { switch (toupper(es.u.key)) {
case 'A': case 'A':
if (browser->selection->map == NULL &&
browser->selection->map->dso->annotate_warned)
continue;
goto do_annotate; goto do_annotate;
case 'D': case 'D':
goto zoom_dso; goto zoom_dso;
...@@ -932,14 +953,14 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na ...@@ -932,14 +953,14 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
continue; continue;
default:; default:;
} }
if (toupper(es.u.key) == 'Q' || if (is_exit_key(es.u.key)) {
es.u.key == CTRL('c'))
break;
if (es.u.key == NEWT_KEY_ESCAPE) { if (es.u.key == NEWT_KEY_ESCAPE) {
if (dialog_yesno("Do you really want to exit?")) if (dialog_yesno("Do you really want to exit?"))
break; break;
else else
continue; continue;
} else
break;
} }
if (es.u.key == NEWT_KEY_LEFT) { if (es.u.key == NEWT_KEY_LEFT) {
...@@ -957,6 +978,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na ...@@ -957,6 +978,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
} }
if (browser->selection->sym != NULL && if (browser->selection->sym != NULL &&
!browser->selection->map->dso->annotate_warned &&
asprintf(&options[nr_options], "Annotate %s", asprintf(&options[nr_options], "Annotate %s",
browser->selection->sym->name) > 0) browser->selection->sym->name) > 0)
annotate = nr_options++; annotate = nr_options++;
...@@ -991,6 +1013,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na ...@@ -991,6 +1013,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
struct hist_entry *he; struct hist_entry *he;
do_annotate: do_annotate:
if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
browser->selection->map->dso->annotate_warned = 1;
ui_helpline__puts("No vmlinux file found, can't " ui_helpline__puts("No vmlinux file found, can't "
"annotate with just a " "annotate with just a "
"kallsyms file"); "kallsyms file");
...@@ -1001,7 +1024,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na ...@@ -1001,7 +1024,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
if (he == NULL) if (he == NULL)
continue; continue;
hist_entry__annotate_browser(he); hist_entry__tui_annotate(he);
} else if (choice == zoom_dso) { } else if (choice == zoom_dso) {
zoom_dso: zoom_dso:
if (dso_filter) { if (dso_filter) {
...@@ -1069,7 +1092,7 @@ void setup_browser(void) ...@@ -1069,7 +1092,7 @@ void setup_browser(void)
{ {
struct newtPercentTreeColors *c = &defaultPercentTreeColors; struct newtPercentTreeColors *c = &defaultPercentTreeColors;
if (!isatty(1) || !use_browser) { if (!isatty(1) || !use_browser || dump_trace) {
setup_pager(); setup_pager();
return; return;
} }
......
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "../../../include/linux/magic.h" #include "../../../include/linux/magic.h"
#include "types.h" #include "types.h"
#include <sys/ttydefaults.h>
#ifndef NO_ICONV #ifndef NO_ICONV
#include <iconv.h> #include <iconv.h>
...@@ -263,6 +263,19 @@ bool strglobmatch(const char *str, const char *pat); ...@@ -263,6 +263,19 @@ bool strglobmatch(const char *str, const char *pat);
bool strlazymatch(const char *str, const char *pat); bool strlazymatch(const char *str, const char *pat);
unsigned long convert_unit(unsigned long value, char *unit); unsigned long convert_unit(unsigned long value, char *unit);
#ifndef ESC
#define ESC 27
#endif
static inline bool is_exit_key(int key)
{
char up;
if (key == CTRL('c') || key == ESC)
return true;
up = toupper(key);
return up == 'Q';
}
#define _STR(x) #x #define _STR(x) #x
#define STR(x) _STR(x) #define STR(x) _STR(x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment