#include "util/parse-options.h"
#include "util/parse-events.h"
+#include "util/debug.h"
+
#include <assert.h>
#include <fcntl.h>
static unsigned int page_size;
static unsigned int mmap_pages = 16;
static int freq = 0;
-static int verbose = 0;
-static char *vmlinux = NULL;
static int delay_secs = 2;
static int zero;
struct module *module;
struct section *section = NULL;
FILE *file;
- char command[PATH_MAX*2], *path = vmlinux;
+ char command[PATH_MAX*2];
+ const char *path = vmlinux_name;
u64 start, end, len;
if (!syme)
printf("%d lines not displayed, maybe increase display entries [e]\n", more);
}
-struct dso *kernel_dso;
-
/*
* Symbols will be added here in record_ip and will get out
* after decayed.
if (nr_counters == 1)
printf(" samples pcnt");
else
- printf(" weight samples pcnt");
+ printf(" weight samples pcnt");
- printf(" RIP kernel function\n"
- " ______ _______ _____ ________________ _______________\n\n"
- );
+ if (verbose)
+ printf(" RIP ");
+ printf(" kernel function\n");
+ printf(" %s _______ _____",
+ nr_counters == 1 ? " " : "______");
+ if (verbose)
+ printf(" ________________");
+ printf(" _______________\n\n");
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
- struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
- struct symbol *sym = (struct symbol *)(syme + 1);
+ struct symbol *sym;
double pcnt;
+ syme = rb_entry(nd, struct sym_entry, rb_node);
+ sym = (struct symbol *)(syme + 1);
+
if (++printed > print_entries || (int)syme->snap_count < count_filter)
continue;
printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
percent_color_fprintf(stdout, "%4.1f%%", pcnt);
- printf(" - %016llx : %s", sym->start, sym->name);
+ if (verbose)
+ printf(" - %016llx", sym->start);
+ printf(" : %s", sym->name);
if (sym->module)
printf("\t[%s]", sym->module->name);
printf("\n");
free(buf);
}
-static void print_known_keys(void)
+static void print_mapped_keys(void)
{
- fprintf(stdout, "\nknown keys:\n");
- fprintf(stdout, "\t[d] select display delay.\n");
- fprintf(stdout, "\t[e] select display entries (lines).\n");
- fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter));
- fprintf(stdout, "\t[f] select normal display count filter.\n");
- fprintf(stdout, "\t[F] select annotation display count filter (percentage).\n");
- fprintf(stdout, "\t[qQ] quit.\n");
- fprintf(stdout, "\t[s] select annotation symbol and start annotation.\n");
- fprintf(stdout, "\t[S] stop annotation, revert to normal display.\n");
- fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
+ char *name = NULL;
+
+ if (sym_filter_entry) {
+ struct symbol *sym = (struct symbol *)(sym_filter_entry+1);
+ name = sym->name;
+ }
+
+ fprintf(stdout, "\nMapped keys:\n");
+ fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
+ fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
+
+ if (nr_counters > 1)
+ fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter));
+
+ fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
+
+ if (vmlinux_name) {
+ fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
+ fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
+ fprintf(stdout, "\t[S] stop annotation.\n");
+ }
+
+ if (nr_counters > 1)
+ fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
+
fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0);
+ fprintf(stdout, "\t[qQ] quit.\n");
+}
+
+static int key_mapped(int c)
+{
+ switch (c) {
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'z':
+ case 'q':
+ case 'Q':
+ return 1;
+ case 'E':
+ case 'w':
+ return nr_counters > 1 ? 1 : 0;
+ case 'F':
+ case 's':
+ case 'S':
+ return vmlinux_name ? 1 : 0;
+ default:
+ break;
+ }
+
+ return 0;
}
static void handle_keypress(int c)
{
- int once = 0;
-repeat:
+ if (!key_mapped(c)) {
+ struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
+ struct termios tc, save;
+
+ print_mapped_keys();
+ fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
+ fflush(stdout);
+
+ tcgetattr(0, &save);
+ tc = save;
+ tc.c_lflag &= ~(ICANON | ECHO);
+ tc.c_cc[VMIN] = 0;
+ tc.c_cc[VTIME] = 0;
+ tcsetattr(0, TCSANOW, &tc);
+
+ poll(&stdin_poll, 1, -1);
+ c = getc(stdin);
+
+ tcsetattr(0, TCSAFLUSH, &save);
+ if (!key_mapped(c))
+ return;
+ }
+
switch (c) {
case 'd':
prompt_integer(&delay_secs, "Enter display delay");
case 'z':
zero = ~zero;
break;
- default: {
- struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
- struct termios tc, save;
-
- if (!once) {
- print_known_keys();
- once++;
- }
-
- tcgetattr(0, &save);
- tc = save;
- tc.c_lflag &= ~(ICANON | ECHO);
- tc.c_cc[VMIN] = 0;
- tc.c_cc[VTIME] = 0;
- tcsetattr(0, TCSANOW, &tc);
-
- poll(&stdin_poll, 1, -1);
- c = getc(stdin);
-
- tcsetattr(0, TCSAFLUSH, &save);
- goto repeat;
- }
+ default:
+ break;
}
}
tc.c_lflag &= ~(ICANON | ECHO);
tc.c_cc[VMIN] = 0;
tc.c_cc[VTIME] = 0;
+
repeat:
delay_msecs = delay_secs * 1000;
tcsetattr(0, TCSANOW, &tc);
"exit_idle",
"mwait_idle",
"mwait_idle_with_hints",
+ "poll_idle",
"ppc64_runlatch_off",
"pseries_dedicated_idle_sleep",
NULL
{
struct rb_node *node;
struct symbol *sym;
- int modules = vmlinux ? 1 : 0;
+ int use_modules = vmlinux_name ? 1 : 0;
kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
if (kernel_dso == NULL)
return -1;
- if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
+ if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
goto out_delete_dso;
node = rb_first(&kernel_dso->syms);
static unsigned int mmap_read_head(struct mmap_data *md)
{
- struct perf_counter_mmap_page *pc = md->base;
+ struct perf_event_mmap_page *pc = md->base;
int head;
head = pc->data_head;
last_read = this_read;
for (; old != head;) {
- struct ip_event {
- struct perf_event_header header;
- u64 ip;
- u32 pid, target_pid;
- };
- struct mmap_event {
- struct perf_event_header header;
- u32 pid, target_pid;
- u64 start;
- u64 len;
- u64 pgoff;
- char filename[PATH_MAX];
- };
-
- typedef union event_union {
- struct perf_event_header header;
- struct ip_event ip;
- struct mmap_event mmap;
- } event_t;
-
event_t *event = (event_t *)&data[old & md->mask];
event_t event_copy;
old += size;
- if (event->header.type == PERF_EVENT_SAMPLE) {
+ if (event->header.type == PERF_RECORD_SAMPLE) {
int user =
- (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
+ (event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_USER;
process_event(event->ip.ip, md->counter, user);
}
}
static void start_counter(int i, int counter)
{
- struct perf_counter_attr *attr;
+ struct perf_event_attr *attr;
int cpu;
cpu = profile_cpu;
attr->inherit = (cpu < 0) && inherit;
try_again:
- fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
+ fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0);
if (fd[i][counter] < 0) {
int err = errno;
printf("\n");
error("perfcounter syscall returned with %d (%s)\n",
fd[i][counter], strerror(err));
- die("No CONFIG_PERF_COUNTERS=y kernel support configured?\n");
+ die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
exit(-1);
}
assert(fd[i][counter] >= 0);
"system-wide collection from all CPUs"),
OPT_INTEGER('C', "CPU", &profile_cpu,
"CPU to profile on"),
- OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+ OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
OPT_INTEGER('m', "mmap-pages", &mmap_pages,
"number of mmap data pages"),
OPT_INTEGER('r', "realtime", &realtime_prio,