186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-top.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin top command: Display a continuously updated profile of 586470930SIngo Molnar * any workload, CPU or specific PID. 686470930SIngo Molnar * 786470930SIngo Molnar * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 886470930SIngo Molnar * 986470930SIngo Molnar * Improvements and fixes by: 1086470930SIngo Molnar * 1186470930SIngo Molnar * Arjan van de Ven <arjan@linux.intel.com> 1286470930SIngo Molnar * Yanmin Zhang <yanmin.zhang@intel.com> 1386470930SIngo Molnar * Wu Fengguang <fengguang.wu@intel.com> 1486470930SIngo Molnar * Mike Galbraith <efault@gmx.de> 1586470930SIngo Molnar * Paul Mackerras <paulus@samba.org> 1686470930SIngo Molnar * 1786470930SIngo Molnar * Released under the GPL v2. (and only v2, not any later version) 1886470930SIngo Molnar */ 1986470930SIngo Molnar #include "builtin.h" 2086470930SIngo Molnar 2186470930SIngo Molnar #include "perf.h" 2286470930SIngo Molnar 2336532461SArnaldo Carvalho de Melo #include "util/annotate.h" 24c0443df1SArnaldo Carvalho de Melo #include "util/cache.h" 2586470930SIngo Molnar #include "util/color.h" 26361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2769aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 28b3165f41SArnaldo Carvalho de Melo #include "util/session.h" 29b3165f41SArnaldo Carvalho de Melo #include "util/symbol.h" 30439d473bSArnaldo Carvalho de Melo #include "util/thread.h" 31fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 328c3e10ebSArnaldo Carvalho de Melo #include "util/top.h" 3386470930SIngo Molnar #include "util/util.h" 3443cbcd8aSArnaldo Carvalho de Melo #include <linux/rbtree.h> 3586470930SIngo Molnar #include "util/parse-options.h" 3686470930SIngo Molnar #include "util/parse-events.h" 37a12b51c4SPaul Mackerras #include "util/cpumap.h" 3869aad6f1SArnaldo Carvalho de Melo #include "util/xyarray.h" 3986470930SIngo Molnar 408f28827aSFrederic Weisbecker #include "util/debug.h" 418f28827aSFrederic Weisbecker 4286470930SIngo Molnar #include <assert.h> 4386470930SIngo Molnar #include <fcntl.h> 4486470930SIngo Molnar 4586470930SIngo Molnar #include <stdio.h> 46923c42c1SMike Galbraith #include <termios.h> 47923c42c1SMike Galbraith #include <unistd.h> 489486aa38SArnaldo Carvalho de Melo #include <inttypes.h> 4986470930SIngo Molnar 5086470930SIngo Molnar #include <errno.h> 5186470930SIngo Molnar #include <time.h> 5286470930SIngo Molnar #include <sched.h> 5386470930SIngo Molnar 5486470930SIngo Molnar #include <sys/syscall.h> 5586470930SIngo Molnar #include <sys/ioctl.h> 5686470930SIngo Molnar #include <sys/poll.h> 5786470930SIngo Molnar #include <sys/prctl.h> 5886470930SIngo Molnar #include <sys/wait.h> 5986470930SIngo Molnar #include <sys/uio.h> 6086470930SIngo Molnar #include <sys/mman.h> 6186470930SIngo Molnar 6286470930SIngo Molnar #include <linux/unistd.h> 6386470930SIngo Molnar #include <linux/types.h> 6486470930SIngo Molnar 658c3e10ebSArnaldo Carvalho de Melo static struct perf_top top = { 668c3e10ebSArnaldo Carvalho de Melo .count_filter = 5, 678c3e10ebSArnaldo Carvalho de Melo .delay_secs = 2, 688c3e10ebSArnaldo Carvalho de Melo .display_weighted = -1, 698c3e10ebSArnaldo Carvalho de Melo .target_pid = -1, 708c3e10ebSArnaldo Carvalho de Melo .target_tid = -1, 718c3e10ebSArnaldo Carvalho de Melo .active_symbols = LIST_HEAD_INIT(top.active_symbols), 728c3e10ebSArnaldo Carvalho de Melo .active_symbols_lock = PTHREAD_MUTEX_INITIALIZER, 735807806aSArnaldo Carvalho de Melo .active_symbols_cond = PTHREAD_COND_INITIALIZER, 748c3e10ebSArnaldo Carvalho de Melo .freq = 1000, /* 1 KHz */ 758c3e10ebSArnaldo Carvalho de Melo }; 76361c99a6SArnaldo Carvalho de Melo 77c0555642SIan Munsie static bool system_wide = false; 7886470930SIngo Molnar 79c0443df1SArnaldo Carvalho de Melo static bool use_tui, use_stdio; 80c0443df1SArnaldo Carvalho de Melo 817e4ff9e3SMike Galbraith static int default_interval = 0; 8286470930SIngo Molnar 835f6f5580SArnaldo Carvalho de Melo static bool kptr_restrict_warned; 84e4a338d0SArnaldo Carvalho de Melo static bool vmlinux_warned; 85c0555642SIan Munsie static bool inherit = false; 861967936dSArnaldo Carvalho de Melo static int realtime_prio = 0; 87c0555642SIan Munsie static bool group = false; 8886470930SIngo Molnar static unsigned int page_size; 8970db7533SArnaldo Carvalho de Melo static unsigned int mmap_pages = 128; 9086470930SIngo Molnar 91c0555642SIan Munsie static bool dump_symtab = false; 9286470930SIngo Molnar 9313cc5079SArnaldo Carvalho de Melo static struct winsize winsize; 948ffcda17SArnaldo Carvalho de Melo 95edb7c60eSArnaldo Carvalho de Melo static const char *sym_filter = NULL; 966cff0e8dSKirill Smelkov struct sym_entry *sym_filter_entry_sched = NULL; 97923c42c1SMike Galbraith static int sym_pcnt_filter = 5; 9886470930SIngo Molnar 99923c42c1SMike Galbraith /* 100923c42c1SMike Galbraith * Source functions 101923c42c1SMike Galbraith */ 102923c42c1SMike Galbraith 103895f0edcSArnaldo Carvalho de Melo void get_term_dimensions(struct winsize *ws) 1043b6ed988SArnaldo Carvalho de Melo { 10513cc5079SArnaldo Carvalho de Melo char *s = getenv("LINES"); 1063b6ed988SArnaldo Carvalho de Melo 10713cc5079SArnaldo Carvalho de Melo if (s != NULL) { 10813cc5079SArnaldo Carvalho de Melo ws->ws_row = atoi(s); 10913cc5079SArnaldo Carvalho de Melo s = getenv("COLUMNS"); 11013cc5079SArnaldo Carvalho de Melo if (s != NULL) { 11113cc5079SArnaldo Carvalho de Melo ws->ws_col = atoi(s); 11213cc5079SArnaldo Carvalho de Melo if (ws->ws_row && ws->ws_col) 11313cc5079SArnaldo Carvalho de Melo return; 11413cc5079SArnaldo Carvalho de Melo } 11513cc5079SArnaldo Carvalho de Melo } 1163b6ed988SArnaldo Carvalho de Melo #ifdef TIOCGWINSZ 11713cc5079SArnaldo Carvalho de Melo if (ioctl(1, TIOCGWINSZ, ws) == 0 && 11813cc5079SArnaldo Carvalho de Melo ws->ws_row && ws->ws_col) 11913cc5079SArnaldo Carvalho de Melo return; 1203b6ed988SArnaldo Carvalho de Melo #endif 12113cc5079SArnaldo Carvalho de Melo ws->ws_row = 25; 12213cc5079SArnaldo Carvalho de Melo ws->ws_col = 80; 1233b6ed988SArnaldo Carvalho de Melo } 1243b6ed988SArnaldo Carvalho de Melo 12513cc5079SArnaldo Carvalho de Melo static void update_print_entries(struct winsize *ws) 1263b6ed988SArnaldo Carvalho de Melo { 1278c3e10ebSArnaldo Carvalho de Melo top.print_entries = ws->ws_row; 12813cc5079SArnaldo Carvalho de Melo 1298c3e10ebSArnaldo Carvalho de Melo if (top.print_entries > 9) 1308c3e10ebSArnaldo Carvalho de Melo top.print_entries -= 9; 1313b6ed988SArnaldo Carvalho de Melo } 1323b6ed988SArnaldo Carvalho de Melo 1333b6ed988SArnaldo Carvalho de Melo static void sig_winch_handler(int sig __used) 1343b6ed988SArnaldo Carvalho de Melo { 13513cc5079SArnaldo Carvalho de Melo get_term_dimensions(&winsize); 13613cc5079SArnaldo Carvalho de Melo update_print_entries(&winsize); 1373b6ed988SArnaldo Carvalho de Melo } 1383b6ed988SArnaldo Carvalho de Melo 139b0a9ab62SArnaldo Carvalho de Melo static int parse_source(struct sym_entry *syme) 140923c42c1SMike Galbraith { 141923c42c1SMike Galbraith struct symbol *sym; 142ce6f4fabSArnaldo Carvalho de Melo struct annotation *notes; 143439d473bSArnaldo Carvalho de Melo struct map *map; 14436532461SArnaldo Carvalho de Melo int err = -1; 145923c42c1SMike Galbraith 146923c42c1SMike Galbraith if (!syme) 147b0a9ab62SArnaldo Carvalho de Melo return -1; 148b0a9ab62SArnaldo Carvalho de Melo 149b0a9ab62SArnaldo Carvalho de Melo sym = sym_entry__symbol(syme); 150b0a9ab62SArnaldo Carvalho de Melo map = syme->map; 151b0a9ab62SArnaldo Carvalho de Melo 152b0a9ab62SArnaldo Carvalho de Melo /* 153b0a9ab62SArnaldo Carvalho de Melo * We can't annotate with just /proc/kallsyms 154b0a9ab62SArnaldo Carvalho de Melo */ 155878b439dSArnaldo Carvalho de Melo if (map->dso->symtab_type == SYMTAB__KALLSYMS) { 156ce6f4fabSArnaldo Carvalho de Melo pr_err("Can't annotate %s: No vmlinux file was found in the " 157ce6f4fabSArnaldo Carvalho de Melo "path\n", sym->name); 158ce6f4fabSArnaldo Carvalho de Melo sleep(1); 159b0a9ab62SArnaldo Carvalho de Melo return -1; 160b269876cSArnaldo Carvalho de Melo } 161b269876cSArnaldo Carvalho de Melo 162ce6f4fabSArnaldo Carvalho de Melo notes = symbol__annotation(sym); 163ce6f4fabSArnaldo Carvalho de Melo if (notes->src != NULL) { 164ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_lock(¬es->lock); 165923c42c1SMike Galbraith goto out_assign; 166923c42c1SMike Galbraith } 167923c42c1SMike Galbraith 168ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_lock(¬es->lock); 169923c42c1SMike Galbraith 17036532461SArnaldo Carvalho de Melo if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { 171c97cf422SArnaldo Carvalho de Melo pthread_mutex_unlock(¬es->lock); 17236532461SArnaldo Carvalho de Melo pr_err("Not enough memory for annotating '%s' symbol!\n", 17336532461SArnaldo Carvalho de Melo sym->name); 174ce6f4fabSArnaldo Carvalho de Melo sleep(1); 175c97cf422SArnaldo Carvalho de Melo return err; 176923c42c1SMike Galbraith } 17736532461SArnaldo Carvalho de Melo 178ce6f4fabSArnaldo Carvalho de Melo err = symbol__annotate(sym, syme->map, 0); 17936532461SArnaldo Carvalho de Melo if (err == 0) { 180923c42c1SMike Galbraith out_assign: 181c97cf422SArnaldo Carvalho de Melo top.sym_filter_entry = syme; 18236532461SArnaldo Carvalho de Melo } 183c97cf422SArnaldo Carvalho de Melo 184ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_unlock(¬es->lock); 18536532461SArnaldo Carvalho de Melo return err; 186923c42c1SMike Galbraith } 187923c42c1SMike Galbraith 188923c42c1SMike Galbraith static void __zero_source_counters(struct sym_entry *syme) 189923c42c1SMike Galbraith { 19036532461SArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(syme); 19136532461SArnaldo Carvalho de Melo symbol__annotate_zero_histograms(sym); 192923c42c1SMike Galbraith } 193923c42c1SMike Galbraith 194923c42c1SMike Galbraith static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 195923c42c1SMike Galbraith { 196ce6f4fabSArnaldo Carvalho de Melo struct annotation *notes; 197ce6f4fabSArnaldo Carvalho de Melo struct symbol *sym; 198ce6f4fabSArnaldo Carvalho de Melo 199c97cf422SArnaldo Carvalho de Melo if (syme != top.sym_filter_entry) 200923c42c1SMike Galbraith return; 201923c42c1SMike Galbraith 202ce6f4fabSArnaldo Carvalho de Melo sym = sym_entry__symbol(syme); 203ce6f4fabSArnaldo Carvalho de Melo notes = symbol__annotation(sym); 204ce6f4fabSArnaldo Carvalho de Melo 205ce6f4fabSArnaldo Carvalho de Melo if (pthread_mutex_trylock(¬es->lock)) 206923c42c1SMike Galbraith return; 207923c42c1SMike Galbraith 20836532461SArnaldo Carvalho de Melo ip = syme->map->map_ip(syme->map, ip); 209ce6f4fabSArnaldo Carvalho de Melo symbol__inc_addr_samples(sym, syme->map, counter, ip); 210923c42c1SMike Galbraith 211ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_unlock(¬es->lock); 212923c42c1SMike Galbraith } 213923c42c1SMike Galbraith 214923c42c1SMike Galbraith static void show_details(struct sym_entry *syme) 215923c42c1SMike Galbraith { 216ce6f4fabSArnaldo Carvalho de Melo struct annotation *notes; 217923c42c1SMike Galbraith struct symbol *symbol; 21836532461SArnaldo Carvalho de Melo int more; 219923c42c1SMike Galbraith 220923c42c1SMike Galbraith if (!syme) 221923c42c1SMike Galbraith return; 222923c42c1SMike Galbraith 22336532461SArnaldo Carvalho de Melo symbol = sym_entry__symbol(syme); 224ce6f4fabSArnaldo Carvalho de Melo notes = symbol__annotation(symbol); 225ce6f4fabSArnaldo Carvalho de Melo 226ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_lock(¬es->lock); 227ce6f4fabSArnaldo Carvalho de Melo 228ce6f4fabSArnaldo Carvalho de Melo if (notes->src == NULL) 229ce6f4fabSArnaldo Carvalho de Melo goto out_unlock; 230923c42c1SMike Galbraith 2318c3e10ebSArnaldo Carvalho de Melo printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); 232923c42c1SMike Galbraith printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 233923c42c1SMike Galbraith 234ce6f4fabSArnaldo Carvalho de Melo more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx, 235d5e3d747SArnaldo Carvalho de Melo 0, sym_pcnt_filter, top.print_entries, 4); 23636532461SArnaldo Carvalho de Melo if (top.zero) 23736532461SArnaldo Carvalho de Melo symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); 23836532461SArnaldo Carvalho de Melo else 239ce6f4fabSArnaldo Carvalho de Melo symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx); 24036532461SArnaldo Carvalho de Melo if (more != 0) 241923c42c1SMike Galbraith printf("%d lines not displayed, maybe increase display entries [e]\n", more); 242ce6f4fabSArnaldo Carvalho de Melo out_unlock: 243ce6f4fabSArnaldo Carvalho de Melo pthread_mutex_unlock(¬es->lock); 244923c42c1SMike Galbraith } 24586470930SIngo Molnar 24686470930SIngo Molnar static const char CONSOLE_CLEAR[] = "[H[2J"; 24786470930SIngo Molnar 24886470930SIngo Molnar static void __list_insert_active_sym(struct sym_entry *syme) 24986470930SIngo Molnar { 2508c3e10ebSArnaldo Carvalho de Melo list_add(&syme->node, &top.active_symbols); 25186470930SIngo Molnar } 25286470930SIngo Molnar 253*dcc101d1SArnaldo Carvalho de Melo static void print_sym_table(void) 25486470930SIngo Molnar { 2558c3e10ebSArnaldo Carvalho de Melo char bf[160]; 2568c3e10ebSArnaldo Carvalho de Melo int printed = 0; 25786470930SIngo Molnar struct rb_node *nd; 2588c3e10ebSArnaldo Carvalho de Melo struct sym_entry *syme; 2598c3e10ebSArnaldo Carvalho de Melo struct rb_root tmp = RB_ROOT; 26013cc5079SArnaldo Carvalho de Melo const int win_width = winsize.ws_col - 1; 2618c3e10ebSArnaldo Carvalho de Melo int sym_width, dso_width, dso_short_width; 2628c3e10ebSArnaldo Carvalho de Melo float sum_ksamples = perf_top__decay_samples(&top, &tmp); 26386470930SIngo Molnar 26486470930SIngo Molnar puts(CONSOLE_CLEAR); 26586470930SIngo Molnar 2668c3e10ebSArnaldo Carvalho de Melo perf_top__header_snprintf(&top, bf, sizeof(bf)); 2678c3e10ebSArnaldo Carvalho de Melo printf("%s\n", bf); 26886470930SIngo Molnar 2698c3e10ebSArnaldo Carvalho de Melo perf_top__reset_sample_counters(&top); 27086470930SIngo Molnar 2711a105f74SArnaldo Carvalho de Melo printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 27286470930SIngo Molnar 273*dcc101d1SArnaldo Carvalho de Melo if (top.total_lost_warned != top.session->hists.stats.total_lost) { 274*dcc101d1SArnaldo Carvalho de Melo top.total_lost_warned = top.session->hists.stats.total_lost; 27593fc64f1SArnaldo Carvalho de Melo color_fprintf(stdout, PERF_COLOR_RED, "WARNING:"); 27693fc64f1SArnaldo Carvalho de Melo printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n", 277*dcc101d1SArnaldo Carvalho de Melo top.total_lost_warned); 27893fc64f1SArnaldo Carvalho de Melo } 27993fc64f1SArnaldo Carvalho de Melo 280c97cf422SArnaldo Carvalho de Melo if (top.sym_filter_entry) { 281c97cf422SArnaldo Carvalho de Melo show_details(top.sym_filter_entry); 282923c42c1SMike Galbraith return; 283923c42c1SMike Galbraith } 284923c42c1SMike Galbraith 2858c3e10ebSArnaldo Carvalho de Melo perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width, 2868c3e10ebSArnaldo Carvalho de Melo &sym_width); 28713cc5079SArnaldo Carvalho de Melo 288b63be8d7SArnaldo Carvalho de Melo if (sym_width + dso_width > winsize.ws_col - 29) { 289b63be8d7SArnaldo Carvalho de Melo dso_width = dso_short_width; 290b63be8d7SArnaldo Carvalho de Melo if (sym_width + dso_width > winsize.ws_col - 29) 291b63be8d7SArnaldo Carvalho de Melo sym_width = winsize.ws_col - dso_width - 29; 292b63be8d7SArnaldo Carvalho de Melo } 2931a105f74SArnaldo Carvalho de Melo putchar('\n'); 2948c3e10ebSArnaldo Carvalho de Melo if (top.evlist->nr_entries == 1) 29586470930SIngo Molnar printf(" samples pcnt"); 29686470930SIngo Molnar else 29786470930SIngo Molnar printf(" weight samples pcnt"); 29886470930SIngo Molnar 2997ced156bSArnaldo Carvalho de Melo if (verbose) 3007ced156bSArnaldo Carvalho de Melo printf(" RIP "); 3017cc017edSArnaldo Carvalho de Melo printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); 3027ced156bSArnaldo Carvalho de Melo printf(" %s _______ _____", 3038c3e10ebSArnaldo Carvalho de Melo top.evlist->nr_entries == 1 ? " " : "______"); 3047ced156bSArnaldo Carvalho de Melo if (verbose) 3057ced156bSArnaldo Carvalho de Melo printf(" ________________"); 3061a105f74SArnaldo Carvalho de Melo printf(" %-*.*s", sym_width, sym_width, graph_line); 3071a105f74SArnaldo Carvalho de Melo printf(" %-*.*s", dso_width, dso_width, graph_line); 3081a105f74SArnaldo Carvalho de Melo puts("\n"); 30986470930SIngo Molnar 31086470930SIngo Molnar for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 31183a0944fSIngo Molnar struct symbol *sym; 31286470930SIngo Molnar double pcnt; 31386470930SIngo Molnar 31483a0944fSIngo Molnar syme = rb_entry(nd, struct sym_entry, rb_node); 31551a472deSArnaldo Carvalho de Melo sym = sym_entry__symbol(syme); 3168c3e10ebSArnaldo Carvalho de Melo if (++printed > top.print_entries || 3178c3e10ebSArnaldo Carvalho de Melo (int)syme->snap_count < top.count_filter) 31886470930SIngo Molnar continue; 31986470930SIngo Molnar 32086470930SIngo Molnar pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 32186470930SIngo Molnar sum_ksamples)); 32286470930SIngo Molnar 3238c3e10ebSArnaldo Carvalho de Melo if (top.evlist->nr_entries == 1 || !top.display_weighted) 3245b2bb75aSArnaldo Carvalho de Melo printf("%20.2f ", syme->weight); 32586470930SIngo Molnar else 3265b2bb75aSArnaldo Carvalho de Melo printf("%9.1f %10ld ", syme->weight, syme->snap_count); 32786470930SIngo Molnar 3281e11fd82SFrederic Weisbecker percent_color_fprintf(stdout, "%4.1f%%", pcnt); 3297ced156bSArnaldo Carvalho de Melo if (verbose) 3309486aa38SArnaldo Carvalho de Melo printf(" %016" PRIx64, sym->start); 33113cc5079SArnaldo Carvalho de Melo printf(" %-*.*s", sym_width, sym_width, sym->name); 3327cc017edSArnaldo Carvalho de Melo printf(" %-*.*s\n", dso_width, dso_width, 33313cc5079SArnaldo Carvalho de Melo dso_width >= syme->map->dso->long_name_len ? 33413cc5079SArnaldo Carvalho de Melo syme->map->dso->long_name : 33513cc5079SArnaldo Carvalho de Melo syme->map->dso->short_name); 33686470930SIngo Molnar } 33786470930SIngo Molnar } 33886470930SIngo Molnar 339923c42c1SMike Galbraith static void prompt_integer(int *target, const char *msg) 340923c42c1SMike Galbraith { 341923c42c1SMike Galbraith char *buf = malloc(0), *p; 342923c42c1SMike Galbraith size_t dummy = 0; 343923c42c1SMike Galbraith int tmp; 344923c42c1SMike Galbraith 345923c42c1SMike Galbraith fprintf(stdout, "\n%s: ", msg); 346923c42c1SMike Galbraith if (getline(&buf, &dummy, stdin) < 0) 347923c42c1SMike Galbraith return; 348923c42c1SMike Galbraith 349923c42c1SMike Galbraith p = strchr(buf, '\n'); 350923c42c1SMike Galbraith if (p) 351923c42c1SMike Galbraith *p = 0; 352923c42c1SMike Galbraith 353923c42c1SMike Galbraith p = buf; 354923c42c1SMike Galbraith while(*p) { 355923c42c1SMike Galbraith if (!isdigit(*p)) 356923c42c1SMike Galbraith goto out_free; 357923c42c1SMike Galbraith p++; 358923c42c1SMike Galbraith } 359923c42c1SMike Galbraith tmp = strtoul(buf, NULL, 10); 360923c42c1SMike Galbraith *target = tmp; 361923c42c1SMike Galbraith out_free: 362923c42c1SMike Galbraith free(buf); 363923c42c1SMike Galbraith } 364923c42c1SMike Galbraith 365923c42c1SMike Galbraith static void prompt_percent(int *target, const char *msg) 366923c42c1SMike Galbraith { 367923c42c1SMike Galbraith int tmp = 0; 368923c42c1SMike Galbraith 369923c42c1SMike Galbraith prompt_integer(&tmp, msg); 370923c42c1SMike Galbraith if (tmp >= 0 && tmp <= 100) 371923c42c1SMike Galbraith *target = tmp; 372923c42c1SMike Galbraith } 373923c42c1SMike Galbraith 374923c42c1SMike Galbraith static void prompt_symbol(struct sym_entry **target, const char *msg) 375923c42c1SMike Galbraith { 376923c42c1SMike Galbraith char *buf = malloc(0), *p; 377923c42c1SMike Galbraith struct sym_entry *syme = *target, *n, *found = NULL; 378923c42c1SMike Galbraith size_t dummy = 0; 379923c42c1SMike Galbraith 380923c42c1SMike Galbraith /* zero counters of active symbol */ 381923c42c1SMike Galbraith if (syme) { 382923c42c1SMike Galbraith __zero_source_counters(syme); 383923c42c1SMike Galbraith *target = NULL; 384923c42c1SMike Galbraith } 385923c42c1SMike Galbraith 386923c42c1SMike Galbraith fprintf(stdout, "\n%s: ", msg); 387923c42c1SMike Galbraith if (getline(&buf, &dummy, stdin) < 0) 388923c42c1SMike Galbraith goto out_free; 389923c42c1SMike Galbraith 390923c42c1SMike Galbraith p = strchr(buf, '\n'); 391923c42c1SMike Galbraith if (p) 392923c42c1SMike Galbraith *p = 0; 393923c42c1SMike Galbraith 3948c3e10ebSArnaldo Carvalho de Melo pthread_mutex_lock(&top.active_symbols_lock); 3958c3e10ebSArnaldo Carvalho de Melo syme = list_entry(top.active_symbols.next, struct sym_entry, node); 3968c3e10ebSArnaldo Carvalho de Melo pthread_mutex_unlock(&top.active_symbols_lock); 397923c42c1SMike Galbraith 3988c3e10ebSArnaldo Carvalho de Melo list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) { 39951a472deSArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(syme); 400923c42c1SMike Galbraith 401923c42c1SMike Galbraith if (!strcmp(buf, sym->name)) { 402923c42c1SMike Galbraith found = syme; 403923c42c1SMike Galbraith break; 404923c42c1SMike Galbraith } 405923c42c1SMike Galbraith } 406923c42c1SMike Galbraith 407923c42c1SMike Galbraith if (!found) { 40866aeb6d5SKirill Smelkov fprintf(stderr, "Sorry, %s is not active.\n", buf); 409923c42c1SMike Galbraith sleep(1); 410923c42c1SMike Galbraith return; 411923c42c1SMike Galbraith } else 412923c42c1SMike Galbraith parse_source(found); 413923c42c1SMike Galbraith 414923c42c1SMike Galbraith out_free: 415923c42c1SMike Galbraith free(buf); 416923c42c1SMike Galbraith } 417923c42c1SMike Galbraith 418091bd2e9SMike Galbraith static void print_mapped_keys(void) 419923c42c1SMike Galbraith { 420091bd2e9SMike Galbraith char *name = NULL; 421091bd2e9SMike Galbraith 422c97cf422SArnaldo Carvalho de Melo if (top.sym_filter_entry) { 423c97cf422SArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); 424091bd2e9SMike Galbraith name = sym->name; 425091bd2e9SMike Galbraith } 426091bd2e9SMike Galbraith 427091bd2e9SMike Galbraith fprintf(stdout, "\nMapped keys:\n"); 4288c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs); 4298c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries); 430091bd2e9SMike Galbraith 4318c3e10ebSArnaldo Carvalho de Melo if (top.evlist->nr_entries > 1) 4328c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel)); 433091bd2e9SMike Galbraith 4348c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter); 435091bd2e9SMike Galbraith 436091bd2e9SMike Galbraith fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 437091bd2e9SMike Galbraith fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 438091bd2e9SMike Galbraith fprintf(stdout, "\t[S] stop annotation.\n"); 439091bd2e9SMike Galbraith 4408c3e10ebSArnaldo Carvalho de Melo if (top.evlist->nr_entries > 1) 4418c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0); 442091bd2e9SMike Galbraith 4438ffcda17SArnaldo Carvalho de Melo fprintf(stdout, 4448ffcda17SArnaldo Carvalho de Melo "\t[K] hide kernel_symbols symbols. \t(%s)\n", 4458c3e10ebSArnaldo Carvalho de Melo top.hide_kernel_symbols ? "yes" : "no"); 4468ffcda17SArnaldo Carvalho de Melo fprintf(stdout, 4478ffcda17SArnaldo Carvalho de Melo "\t[U] hide user symbols. \t(%s)\n", 4488c3e10ebSArnaldo Carvalho de Melo top.hide_user_symbols ? "yes" : "no"); 4498c3e10ebSArnaldo Carvalho de Melo fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0); 450091bd2e9SMike Galbraith fprintf(stdout, "\t[qQ] quit.\n"); 451091bd2e9SMike Galbraith } 452091bd2e9SMike Galbraith 453091bd2e9SMike Galbraith static int key_mapped(int c) 454091bd2e9SMike Galbraith { 455091bd2e9SMike Galbraith switch (c) { 456091bd2e9SMike Galbraith case 'd': 457091bd2e9SMike Galbraith case 'e': 458091bd2e9SMike Galbraith case 'f': 459091bd2e9SMike Galbraith case 'z': 460091bd2e9SMike Galbraith case 'q': 461091bd2e9SMike Galbraith case 'Q': 4628ffcda17SArnaldo Carvalho de Melo case 'K': 4638ffcda17SArnaldo Carvalho de Melo case 'U': 4646cff0e8dSKirill Smelkov case 'F': 4656cff0e8dSKirill Smelkov case 's': 4666cff0e8dSKirill Smelkov case 'S': 467091bd2e9SMike Galbraith return 1; 468091bd2e9SMike Galbraith case 'E': 469091bd2e9SMike Galbraith case 'w': 4708c3e10ebSArnaldo Carvalho de Melo return top.evlist->nr_entries > 1 ? 1 : 0; 47183a0944fSIngo Molnar default: 47283a0944fSIngo Molnar break; 473091bd2e9SMike Galbraith } 474091bd2e9SMike Galbraith 475091bd2e9SMike Galbraith return 0; 476923c42c1SMike Galbraith } 477923c42c1SMike Galbraith 478*dcc101d1SArnaldo Carvalho de Melo static void handle_keypress(int c) 479923c42c1SMike Galbraith { 480091bd2e9SMike Galbraith if (!key_mapped(c)) { 481091bd2e9SMike Galbraith struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 482091bd2e9SMike Galbraith struct termios tc, save; 483091bd2e9SMike Galbraith 484091bd2e9SMike Galbraith print_mapped_keys(); 485091bd2e9SMike Galbraith fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 486091bd2e9SMike Galbraith fflush(stdout); 487091bd2e9SMike Galbraith 488091bd2e9SMike Galbraith tcgetattr(0, &save); 489091bd2e9SMike Galbraith tc = save; 490091bd2e9SMike Galbraith tc.c_lflag &= ~(ICANON | ECHO); 491091bd2e9SMike Galbraith tc.c_cc[VMIN] = 0; 492091bd2e9SMike Galbraith tc.c_cc[VTIME] = 0; 493091bd2e9SMike Galbraith tcsetattr(0, TCSANOW, &tc); 494091bd2e9SMike Galbraith 495091bd2e9SMike Galbraith poll(&stdin_poll, 1, -1); 496091bd2e9SMike Galbraith c = getc(stdin); 497091bd2e9SMike Galbraith 498091bd2e9SMike Galbraith tcsetattr(0, TCSAFLUSH, &save); 499091bd2e9SMike Galbraith if (!key_mapped(c)) 500091bd2e9SMike Galbraith return; 501091bd2e9SMike Galbraith } 502091bd2e9SMike Galbraith 503923c42c1SMike Galbraith switch (c) { 504923c42c1SMike Galbraith case 'd': 5058c3e10ebSArnaldo Carvalho de Melo prompt_integer(&top.delay_secs, "Enter display delay"); 5068c3e10ebSArnaldo Carvalho de Melo if (top.delay_secs < 1) 5078c3e10ebSArnaldo Carvalho de Melo top.delay_secs = 1; 508923c42c1SMike Galbraith break; 509923c42c1SMike Galbraith case 'e': 5108c3e10ebSArnaldo Carvalho de Melo prompt_integer(&top.print_entries, "Enter display entries (lines)"); 5118c3e10ebSArnaldo Carvalho de Melo if (top.print_entries == 0) { 51213cc5079SArnaldo Carvalho de Melo sig_winch_handler(SIGWINCH); 5133b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, sig_winch_handler); 5143b6ed988SArnaldo Carvalho de Melo } else 5153b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, SIG_DFL); 516923c42c1SMike Galbraith break; 517923c42c1SMike Galbraith case 'E': 5188c3e10ebSArnaldo Carvalho de Melo if (top.evlist->nr_entries > 1) { 519ce2d17caSAkihiro Nagai /* Select 0 as the default event: */ 520ce2d17caSAkihiro Nagai int counter = 0; 521ce2d17caSAkihiro Nagai 522923c42c1SMike Galbraith fprintf(stderr, "\nAvailable events:"); 52369aad6f1SArnaldo Carvalho de Melo 5248c3e10ebSArnaldo Carvalho de Melo list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 5258c3e10ebSArnaldo Carvalho de Melo fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel)); 526923c42c1SMike Galbraith 527ec52d976SArnaldo Carvalho de Melo prompt_integer(&counter, "Enter details event counter"); 528923c42c1SMike Galbraith 529ec52d976SArnaldo Carvalho de Melo if (counter >= top.evlist->nr_entries) { 5308c3e10ebSArnaldo Carvalho de Melo top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 5318c3e10ebSArnaldo Carvalho de Melo fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel)); 532923c42c1SMike Galbraith sleep(1); 53369aad6f1SArnaldo Carvalho de Melo break; 534923c42c1SMike Galbraith } 5358c3e10ebSArnaldo Carvalho de Melo list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 536ec52d976SArnaldo Carvalho de Melo if (top.sym_evsel->idx == counter) 53769aad6f1SArnaldo Carvalho de Melo break; 538ec52d976SArnaldo Carvalho de Melo } else 539ec52d976SArnaldo Carvalho de Melo top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 540923c42c1SMike Galbraith break; 541923c42c1SMike Galbraith case 'f': 5428c3e10ebSArnaldo Carvalho de Melo prompt_integer(&top.count_filter, "Enter display event count filter"); 543923c42c1SMike Galbraith break; 544923c42c1SMike Galbraith case 'F': 545923c42c1SMike Galbraith prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 546923c42c1SMike Galbraith break; 5478ffcda17SArnaldo Carvalho de Melo case 'K': 5488c3e10ebSArnaldo Carvalho de Melo top.hide_kernel_symbols = !top.hide_kernel_symbols; 5498ffcda17SArnaldo Carvalho de Melo break; 550923c42c1SMike Galbraith case 'q': 551923c42c1SMike Galbraith case 'Q': 552923c42c1SMike Galbraith printf("exiting.\n"); 553c338aee8SArnaldo Carvalho de Melo if (dump_symtab) 554*dcc101d1SArnaldo Carvalho de Melo perf_session__fprintf_dsos(top.session, stderr); 555923c42c1SMike Galbraith exit(0); 556923c42c1SMike Galbraith case 's': 557c97cf422SArnaldo Carvalho de Melo prompt_symbol(&top.sym_filter_entry, "Enter details symbol"); 558923c42c1SMike Galbraith break; 559923c42c1SMike Galbraith case 'S': 560c97cf422SArnaldo Carvalho de Melo if (!top.sym_filter_entry) 561923c42c1SMike Galbraith break; 562923c42c1SMike Galbraith else { 563c97cf422SArnaldo Carvalho de Melo struct sym_entry *syme = top.sym_filter_entry; 564923c42c1SMike Galbraith 565c97cf422SArnaldo Carvalho de Melo top.sym_filter_entry = NULL; 566923c42c1SMike Galbraith __zero_source_counters(syme); 567923c42c1SMike Galbraith } 568923c42c1SMike Galbraith break; 5698ffcda17SArnaldo Carvalho de Melo case 'U': 5708c3e10ebSArnaldo Carvalho de Melo top.hide_user_symbols = !top.hide_user_symbols; 5718ffcda17SArnaldo Carvalho de Melo break; 57246ab9764SMike Galbraith case 'w': 5738c3e10ebSArnaldo Carvalho de Melo top.display_weighted = ~top.display_weighted; 57446ab9764SMike Galbraith break; 575923c42c1SMike Galbraith case 'z': 5768c3e10ebSArnaldo Carvalho de Melo top.zero = !top.zero; 577923c42c1SMike Galbraith break; 57883a0944fSIngo Molnar default: 57983a0944fSIngo Molnar break; 580923c42c1SMike Galbraith } 581923c42c1SMike Galbraith } 582923c42c1SMike Galbraith 583c0443df1SArnaldo Carvalho de Melo static void *display_thread_tui(void *arg __used) 584c0443df1SArnaldo Carvalho de Melo { 5855807806aSArnaldo Carvalho de Melo int err = 0; 5865807806aSArnaldo Carvalho de Melo pthread_mutex_lock(&top.active_symbols_lock); 5875807806aSArnaldo Carvalho de Melo while (list_empty(&top.active_symbols)) { 5885807806aSArnaldo Carvalho de Melo err = pthread_cond_wait(&top.active_symbols_cond, 5895807806aSArnaldo Carvalho de Melo &top.active_symbols_lock); 5905807806aSArnaldo Carvalho de Melo if (err) 5915807806aSArnaldo Carvalho de Melo break; 5925807806aSArnaldo Carvalho de Melo } 5935807806aSArnaldo Carvalho de Melo pthread_mutex_unlock(&top.active_symbols_lock); 5945807806aSArnaldo Carvalho de Melo if (!err) 595c0443df1SArnaldo Carvalho de Melo perf_top__tui_browser(&top); 596c0443df1SArnaldo Carvalho de Melo exit_browser(0); 597c0443df1SArnaldo Carvalho de Melo exit(0); 598c0443df1SArnaldo Carvalho de Melo return NULL; 599c0443df1SArnaldo Carvalho de Melo } 600c0443df1SArnaldo Carvalho de Melo 601f37a291cSIngo Molnar static void *display_thread(void *arg __used) 60286470930SIngo Molnar { 60386470930SIngo Molnar struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 604923c42c1SMike Galbraith struct termios tc, save; 605923c42c1SMike Galbraith int delay_msecs, c; 60686470930SIngo Molnar 607923c42c1SMike Galbraith tcgetattr(0, &save); 608923c42c1SMike Galbraith tc = save; 609923c42c1SMike Galbraith tc.c_lflag &= ~(ICANON | ECHO); 610923c42c1SMike Galbraith tc.c_cc[VMIN] = 0; 611923c42c1SMike Galbraith tc.c_cc[VTIME] = 0; 612091bd2e9SMike Galbraith 613923c42c1SMike Galbraith repeat: 6148c3e10ebSArnaldo Carvalho de Melo delay_msecs = top.delay_secs * 1000; 615923c42c1SMike Galbraith tcsetattr(0, TCSANOW, &tc); 616923c42c1SMike Galbraith /* trash return*/ 617923c42c1SMike Galbraith getc(stdin); 61886470930SIngo Molnar 61986470930SIngo Molnar do { 620*dcc101d1SArnaldo Carvalho de Melo print_sym_table(); 62186470930SIngo Molnar } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 62286470930SIngo Molnar 623923c42c1SMike Galbraith c = getc(stdin); 624923c42c1SMike Galbraith tcsetattr(0, TCSAFLUSH, &save); 625923c42c1SMike Galbraith 626*dcc101d1SArnaldo Carvalho de Melo handle_keypress(c); 627923c42c1SMike Galbraith goto repeat; 62886470930SIngo Molnar 62986470930SIngo Molnar return NULL; 63086470930SIngo Molnar } 63186470930SIngo Molnar 6322ab52083SAnton Blanchard /* Tag samples to be skipped. */ 633f37a291cSIngo Molnar static const char *skip_symbols[] = { 6342ab52083SAnton Blanchard "default_idle", 635b0e8572fSArnaldo Carvalho de Melo "native_safe_halt", 6362ab52083SAnton Blanchard "cpu_idle", 6372ab52083SAnton Blanchard "enter_idle", 6382ab52083SAnton Blanchard "exit_idle", 6392ab52083SAnton Blanchard "mwait_idle", 64059b90056SArnaldo Carvalho de Melo "mwait_idle_with_hints", 6418357275bSArnaldo Carvalho de Melo "poll_idle", 6423a3393efSAnton Blanchard "ppc64_runlatch_off", 6433a3393efSAnton Blanchard "pseries_dedicated_idle_sleep", 6442ab52083SAnton Blanchard NULL 6452ab52083SAnton Blanchard }; 6462ab52083SAnton Blanchard 647439d473bSArnaldo Carvalho de Melo static int symbol_filter(struct map *map, struct symbol *sym) 64886470930SIngo Molnar { 64986470930SIngo Molnar struct sym_entry *syme; 65086470930SIngo Molnar const char *name = sym->name; 6512ab52083SAnton Blanchard int i; 65286470930SIngo Molnar 6533a3393efSAnton Blanchard /* 6543a3393efSAnton Blanchard * ppc64 uses function descriptors and appends a '.' to the 6553a3393efSAnton Blanchard * start of every instruction address. Remove it. 6563a3393efSAnton Blanchard */ 6573a3393efSAnton Blanchard if (name[0] == '.') 6583a3393efSAnton Blanchard name++; 6593a3393efSAnton Blanchard 66086470930SIngo Molnar if (!strcmp(name, "_text") || 66186470930SIngo Molnar !strcmp(name, "_etext") || 66286470930SIngo Molnar !strcmp(name, "_sinittext") || 66386470930SIngo Molnar !strncmp("init_module", name, 11) || 66486470930SIngo Molnar !strncmp("cleanup_module", name, 14) || 66586470930SIngo Molnar strstr(name, "_text_start") || 66686470930SIngo Molnar strstr(name, "_text_end")) 66786470930SIngo Molnar return 1; 66886470930SIngo Molnar 66900a192b3SArnaldo Carvalho de Melo syme = symbol__priv(sym); 670439d473bSArnaldo Carvalho de Melo syme->map = map; 671ce6f4fabSArnaldo Carvalho de Melo symbol__annotate_init(map, sym); 6726cff0e8dSKirill Smelkov 673c97cf422SArnaldo Carvalho de Melo if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { 6746cff0e8dSKirill Smelkov /* schedule initial sym_filter_entry setup */ 6756cff0e8dSKirill Smelkov sym_filter_entry_sched = syme; 6766cff0e8dSKirill Smelkov sym_filter = NULL; 6776cff0e8dSKirill Smelkov } 678923c42c1SMike Galbraith 6792ab52083SAnton Blanchard for (i = 0; skip_symbols[i]; i++) { 6802ab52083SAnton Blanchard if (!strcmp(skip_symbols[i], name)) { 681171b3be9SArnaldo Carvalho de Melo sym->ignore = true; 6822ab52083SAnton Blanchard break; 6832ab52083SAnton Blanchard } 6842ab52083SAnton Blanchard } 68586470930SIngo Molnar 68686470930SIngo Molnar return 0; 68786470930SIngo Molnar } 68886470930SIngo Molnar 6898115d60cSArnaldo Carvalho de Melo static void perf_event__process_sample(const union perf_event *event, 6908d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample, 69170db7533SArnaldo Carvalho de Melo struct perf_session *session) 69286470930SIngo Molnar { 6938115d60cSArnaldo Carvalho de Melo u64 ip = event->ip.ip; 6945b2bb75aSArnaldo Carvalho de Melo struct sym_entry *syme; 6951ed091c4SArnaldo Carvalho de Melo struct addr_location al; 69623346f21SArnaldo Carvalho de Melo struct machine *machine; 6978115d60cSArnaldo Carvalho de Melo u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 69886470930SIngo Molnar 6998c3e10ebSArnaldo Carvalho de Melo ++top.samples; 70024bfef0fSArnaldo Carvalho de Melo 7018ffcda17SArnaldo Carvalho de Melo switch (origin) { 7021ed091c4SArnaldo Carvalho de Melo case PERF_RECORD_MISC_USER: 7038c3e10ebSArnaldo Carvalho de Melo ++top.us_samples; 7048c3e10ebSArnaldo Carvalho de Melo if (top.hide_user_symbols) 7058ffcda17SArnaldo Carvalho de Melo return; 70623346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 7075b2bb75aSArnaldo Carvalho de Melo break; 7085b2bb75aSArnaldo Carvalho de Melo case PERF_RECORD_MISC_KERNEL: 7098c3e10ebSArnaldo Carvalho de Melo ++top.kernel_samples; 7108c3e10ebSArnaldo Carvalho de Melo if (top.hide_kernel_symbols) 7118ffcda17SArnaldo Carvalho de Melo return; 71223346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 7135b2bb75aSArnaldo Carvalho de Melo break; 714a1645ce1SZhang, Yanmin case PERF_RECORD_MISC_GUEST_KERNEL: 7158c3e10ebSArnaldo Carvalho de Melo ++top.guest_kernel_samples; 7168115d60cSArnaldo Carvalho de Melo machine = perf_session__find_machine(session, event->ip.pid); 717a1645ce1SZhang, Yanmin break; 718a1645ce1SZhang, Yanmin case PERF_RECORD_MISC_GUEST_USER: 7198c3e10ebSArnaldo Carvalho de Melo ++top.guest_us_samples; 720a1645ce1SZhang, Yanmin /* 721a1645ce1SZhang, Yanmin * TODO: we don't process guest user from host side 722a1645ce1SZhang, Yanmin * except simple counting. 723a1645ce1SZhang, Yanmin */ 724a1645ce1SZhang, Yanmin return; 7255b2bb75aSArnaldo Carvalho de Melo default: 7265b2bb75aSArnaldo Carvalho de Melo return; 7275b2bb75aSArnaldo Carvalho de Melo } 7285b2bb75aSArnaldo Carvalho de Melo 72923346f21SArnaldo Carvalho de Melo if (!machine && perf_guest) { 730a1645ce1SZhang, Yanmin pr_err("Can't find guest [%d]'s kernel information\n", 7318115d60cSArnaldo Carvalho de Melo event->ip.pid); 732a1645ce1SZhang, Yanmin return; 733a1645ce1SZhang, Yanmin } 734a1645ce1SZhang, Yanmin 7358115d60cSArnaldo Carvalho de Melo if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 7368c3e10ebSArnaldo Carvalho de Melo top.exact_samples++; 7371676b8a0SPeter Zijlstra 7388115d60cSArnaldo Carvalho de Melo if (perf_event__preprocess_sample(event, session, &al, sample, 73941a37e20SArnaldo Carvalho de Melo symbol_filter) < 0 || 74072b8fa17SArnaldo Carvalho de Melo al.filtered) 7411ed091c4SArnaldo Carvalho de Melo return; 74286470930SIngo Molnar 7435f6f5580SArnaldo Carvalho de Melo if (!kptr_restrict_warned && 7445f6f5580SArnaldo Carvalho de Melo symbol_conf.kptr_restrict && 7455f6f5580SArnaldo Carvalho de Melo al.cpumode == PERF_RECORD_MISC_KERNEL) { 7465f6f5580SArnaldo Carvalho de Melo ui__warning( 7475f6f5580SArnaldo Carvalho de Melo "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n" 7485f6f5580SArnaldo Carvalho de Melo "Check /proc/sys/kernel/kptr_restrict.\n\n" 7495f6f5580SArnaldo Carvalho de Melo "Kernel%s samples will not be resolved.\n", 7505f6f5580SArnaldo Carvalho de Melo !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ? 7515f6f5580SArnaldo Carvalho de Melo " modules" : ""); 7525f6f5580SArnaldo Carvalho de Melo if (use_browser <= 0) 7535f6f5580SArnaldo Carvalho de Melo sleep(5); 7545f6f5580SArnaldo Carvalho de Melo kptr_restrict_warned = true; 7555f6f5580SArnaldo Carvalho de Melo } 7565f6f5580SArnaldo Carvalho de Melo 75772b8fa17SArnaldo Carvalho de Melo if (al.sym == NULL) { 758e4a338d0SArnaldo Carvalho de Melo const char *msg = "Kernel samples will not be resolved.\n"; 75972b8fa17SArnaldo Carvalho de Melo /* 76072b8fa17SArnaldo Carvalho de Melo * As we do lazy loading of symtabs we only will know if the 76172b8fa17SArnaldo Carvalho de Melo * specified vmlinux file is invalid when we actually have a 76272b8fa17SArnaldo Carvalho de Melo * hit in kernel space and then try to load it. So if we get 76372b8fa17SArnaldo Carvalho de Melo * here and there are _no_ symbols in the DSO backing the 76472b8fa17SArnaldo Carvalho de Melo * kernel map, bail out. 76572b8fa17SArnaldo Carvalho de Melo * 76672b8fa17SArnaldo Carvalho de Melo * We may never get here, for instance, if we use -K/ 76772b8fa17SArnaldo Carvalho de Melo * --hide-kernel-symbols, even if the user specifies an 76872b8fa17SArnaldo Carvalho de Melo * invalid --vmlinux ;-) 76972b8fa17SArnaldo Carvalho de Melo */ 770e4a338d0SArnaldo Carvalho de Melo if (!kptr_restrict_warned && !vmlinux_warned && 771e4a338d0SArnaldo Carvalho de Melo al.map == machine->vmlinux_maps[MAP__FUNCTION] && 77272b8fa17SArnaldo Carvalho de Melo RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 773e4a338d0SArnaldo Carvalho de Melo if (symbol_conf.vmlinux_name) { 774e4a338d0SArnaldo Carvalho de Melo ui__warning("The %s file can't be used.\n%s", 775e4a338d0SArnaldo Carvalho de Melo symbol_conf.vmlinux_name, msg); 776e4a338d0SArnaldo Carvalho de Melo } else { 777e4a338d0SArnaldo Carvalho de Melo ui__warning("A vmlinux file was not found.\n%s", 778e4a338d0SArnaldo Carvalho de Melo msg); 779e4a338d0SArnaldo Carvalho de Melo } 780e4a338d0SArnaldo Carvalho de Melo 781e4a338d0SArnaldo Carvalho de Melo if (use_browser <= 0) 782e4a338d0SArnaldo Carvalho de Melo sleep(5); 783e4a338d0SArnaldo Carvalho de Melo vmlinux_warned = true; 78472b8fa17SArnaldo Carvalho de Melo } 78572b8fa17SArnaldo Carvalho de Melo 78672b8fa17SArnaldo Carvalho de Melo return; 78772b8fa17SArnaldo Carvalho de Melo } 78872b8fa17SArnaldo Carvalho de Melo 7896cff0e8dSKirill Smelkov /* let's see, whether we need to install initial sym_filter_entry */ 7906cff0e8dSKirill Smelkov if (sym_filter_entry_sched) { 791c97cf422SArnaldo Carvalho de Melo top.sym_filter_entry = sym_filter_entry_sched; 7926cff0e8dSKirill Smelkov sym_filter_entry_sched = NULL; 793c97cf422SArnaldo Carvalho de Melo if (parse_source(top.sym_filter_entry) < 0) { 794c97cf422SArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); 795b0a9ab62SArnaldo Carvalho de Melo 796b0a9ab62SArnaldo Carvalho de Melo pr_err("Can't annotate %s", sym->name); 797878b439dSArnaldo Carvalho de Melo if (top.sym_filter_entry->map->dso->symtab_type == SYMTAB__KALLSYMS) { 798b0a9ab62SArnaldo Carvalho de Melo pr_err(": No vmlinux file was found in the path:\n"); 7995ad90e4eSArnaldo Carvalho de Melo machine__fprintf_vmlinux_path(machine, stderr); 800b0a9ab62SArnaldo Carvalho de Melo } else 801b0a9ab62SArnaldo Carvalho de Melo pr_err(".\n"); 802b0a9ab62SArnaldo Carvalho de Melo exit(1); 803b0a9ab62SArnaldo Carvalho de Melo } 8046cff0e8dSKirill Smelkov } 8056cff0e8dSKirill Smelkov 8061ed091c4SArnaldo Carvalho de Melo syme = symbol__priv(al.sym); 807171b3be9SArnaldo Carvalho de Melo if (!al.sym->ignore) { 80870db7533SArnaldo Carvalho de Melo struct perf_evsel *evsel; 80970db7533SArnaldo Carvalho de Melo 8108c3e10ebSArnaldo Carvalho de Melo evsel = perf_evlist__id2evsel(top.evlist, sample->id); 81170db7533SArnaldo Carvalho de Melo assert(evsel != NULL); 81270db7533SArnaldo Carvalho de Melo syme->count[evsel->idx]++; 81369aad6f1SArnaldo Carvalho de Melo record_precise_ip(syme, evsel->idx, ip); 8148c3e10ebSArnaldo Carvalho de Melo pthread_mutex_lock(&top.active_symbols_lock); 8155807806aSArnaldo Carvalho de Melo if (list_empty(&syme->node) || !syme->node.next) { 8165807806aSArnaldo Carvalho de Melo static bool first = true; 81786470930SIngo Molnar __list_insert_active_sym(syme); 8185807806aSArnaldo Carvalho de Melo if (first) { 8195807806aSArnaldo Carvalho de Melo pthread_cond_broadcast(&top.active_symbols_cond); 8205807806aSArnaldo Carvalho de Melo first = false; 8215807806aSArnaldo Carvalho de Melo } 8225807806aSArnaldo Carvalho de Melo } 8238c3e10ebSArnaldo Carvalho de Melo pthread_mutex_unlock(&top.active_symbols_lock); 82486470930SIngo Molnar } 82586470930SIngo Molnar } 82686470930SIngo Molnar 827aece948fSArnaldo Carvalho de Melo static void perf_session__mmap_read_idx(struct perf_session *self, int idx) 82886470930SIngo Molnar { 8298d50e5b4SArnaldo Carvalho de Melo struct perf_sample sample; 8308115d60cSArnaldo Carvalho de Melo union perf_event *event; 8315538becaSFrederic Weisbecker int ret; 83286470930SIngo Molnar 833aece948fSArnaldo Carvalho de Melo while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) { 8345538becaSFrederic Weisbecker ret = perf_session__parse_sample(self, event, &sample); 8355538becaSFrederic Weisbecker if (ret) { 8365538becaSFrederic Weisbecker pr_err("Can't parse sample, err = %d\n", ret); 8375538becaSFrederic Weisbecker continue; 8385538becaSFrederic Weisbecker } 83904391debSArnaldo Carvalho de Melo 8405b2bb75aSArnaldo Carvalho de Melo if (event->header.type == PERF_RECORD_SAMPLE) 8418115d60cSArnaldo Carvalho de Melo perf_event__process_sample(event, &sample, self); 8425b2bb75aSArnaldo Carvalho de Melo else 8438115d60cSArnaldo Carvalho de Melo perf_event__process(event, &sample, self); 84486470930SIngo Molnar } 84586470930SIngo Molnar } 84686470930SIngo Molnar 847d8f66248SArnaldo Carvalho de Melo static void perf_session__mmap_read(struct perf_session *self) 8482f01190aSFrederic Weisbecker { 84970db7533SArnaldo Carvalho de Melo int i; 8502f01190aSFrederic Weisbecker 851aece948fSArnaldo Carvalho de Melo for (i = 0; i < top.evlist->nr_mmaps; i++) 852aece948fSArnaldo Carvalho de Melo perf_session__mmap_read_idx(self, i); 8532f01190aSFrederic Weisbecker } 8542f01190aSFrederic Weisbecker 85572cb7013SArnaldo Carvalho de Melo static void start_counters(struct perf_evlist *evlist) 85672cb7013SArnaldo Carvalho de Melo { 85772cb7013SArnaldo Carvalho de Melo struct perf_evsel *counter; 85872cb7013SArnaldo Carvalho de Melo 85972cb7013SArnaldo Carvalho de Melo list_for_each_entry(counter, &evlist->entries, node) { 86072cb7013SArnaldo Carvalho de Melo struct perf_event_attr *attr = &counter->attr; 86172cb7013SArnaldo Carvalho de Melo 86272cb7013SArnaldo Carvalho de Melo attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 86372cb7013SArnaldo Carvalho de Melo 8648c3e10ebSArnaldo Carvalho de Melo if (top.freq) { 86572cb7013SArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_PERIOD; 86672cb7013SArnaldo Carvalho de Melo attr->freq = 1; 8678c3e10ebSArnaldo Carvalho de Melo attr->sample_freq = top.freq; 86872cb7013SArnaldo Carvalho de Melo } 86972cb7013SArnaldo Carvalho de Melo 87070db7533SArnaldo Carvalho de Melo if (evlist->nr_entries > 1) { 87170db7533SArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_ID; 87270db7533SArnaldo Carvalho de Melo attr->read_format |= PERF_FORMAT_ID; 87370db7533SArnaldo Carvalho de Melo } 87470db7533SArnaldo Carvalho de Melo 87572cb7013SArnaldo Carvalho de Melo attr->mmap = 1; 8765d2cd909SArnaldo Carvalho de Melo attr->inherit = inherit; 87772cb7013SArnaldo Carvalho de Melo try_again: 8788c3e10ebSArnaldo Carvalho de Melo if (perf_evsel__open(counter, top.evlist->cpus, 8795d2cd909SArnaldo Carvalho de Melo top.evlist->threads, group) < 0) { 88072cb7013SArnaldo Carvalho de Melo int err = errno; 88172cb7013SArnaldo Carvalho de Melo 882c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 883c286c419SArnaldo Carvalho de Melo ui__warning_paranoid(); 884c286c419SArnaldo Carvalho de Melo goto out_err; 885c286c419SArnaldo Carvalho de Melo } 88672cb7013SArnaldo Carvalho de Melo /* 88772cb7013SArnaldo Carvalho de Melo * If it's cycles then fall back to hrtimer 88872cb7013SArnaldo Carvalho de Melo * based cpu-clock-tick sw counter, which 88972cb7013SArnaldo Carvalho de Melo * is always available even if no PMU support: 89072cb7013SArnaldo Carvalho de Melo */ 89172cb7013SArnaldo Carvalho de Melo if (attr->type == PERF_TYPE_HARDWARE && 89272cb7013SArnaldo Carvalho de Melo attr->config == PERF_COUNT_HW_CPU_CYCLES) { 89372cb7013SArnaldo Carvalho de Melo if (verbose) 894c286c419SArnaldo Carvalho de Melo ui__warning("Cycles event not supported,\n" 895c286c419SArnaldo Carvalho de Melo "trying to fall back to cpu-clock-ticks\n"); 89672cb7013SArnaldo Carvalho de Melo 89772cb7013SArnaldo Carvalho de Melo attr->type = PERF_TYPE_SOFTWARE; 89872cb7013SArnaldo Carvalho de Melo attr->config = PERF_COUNT_SW_CPU_CLOCK; 89972cb7013SArnaldo Carvalho de Melo goto try_again; 90072cb7013SArnaldo Carvalho de Melo } 901c286c419SArnaldo Carvalho de Melo 902ca6a4258SDavid Ahern if (err == ENOENT) { 903ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 904ca6a4258SDavid Ahern event_name(counter)); 905ca6a4258SDavid Ahern goto out_err; 906ca6a4258SDavid Ahern } 907ca6a4258SDavid Ahern 908c286c419SArnaldo Carvalho de Melo ui__warning("The sys_perf_event_open() syscall " 909c286c419SArnaldo Carvalho de Melo "returned with %d (%s). /bin/dmesg " 910c286c419SArnaldo Carvalho de Melo "may provide additional information.\n" 911c286c419SArnaldo Carvalho de Melo "No CONFIG_PERF_EVENTS=y kernel support " 912c286c419SArnaldo Carvalho de Melo "configured?\n", err, strerror(err)); 913c286c419SArnaldo Carvalho de Melo goto out_err; 91472cb7013SArnaldo Carvalho de Melo } 91572cb7013SArnaldo Carvalho de Melo } 91670db7533SArnaldo Carvalho de Melo 917c286c419SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) { 918c286c419SArnaldo Carvalho de Melo ui__warning("Failed to mmap with %d (%s)\n", 919c286c419SArnaldo Carvalho de Melo errno, strerror(errno)); 920c286c419SArnaldo Carvalho de Melo goto out_err; 921c286c419SArnaldo Carvalho de Melo } 922c286c419SArnaldo Carvalho de Melo 923c286c419SArnaldo Carvalho de Melo return; 924c286c419SArnaldo Carvalho de Melo 925c286c419SArnaldo Carvalho de Melo out_err: 926c286c419SArnaldo Carvalho de Melo exit_browser(0); 927c286c419SArnaldo Carvalho de Melo exit(0); 92872cb7013SArnaldo Carvalho de Melo } 92972cb7013SArnaldo Carvalho de Melo 930716c69feSIngo Molnar static int __cmd_top(void) 931716c69feSIngo Molnar { 932716c69feSIngo Molnar pthread_t thread; 933fb7d0b3cSKyle McMartin int ret __used; 934d8f66248SArnaldo Carvalho de Melo /* 935b3165f41SArnaldo Carvalho de Melo * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 936b3165f41SArnaldo Carvalho de Melo * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 937d8f66248SArnaldo Carvalho de Melo */ 938*dcc101d1SArnaldo Carvalho de Melo top.session = perf_session__new(NULL, O_WRONLY, false, false, NULL); 939*dcc101d1SArnaldo Carvalho de Melo if (top.session == NULL) 940b3165f41SArnaldo Carvalho de Melo return -ENOMEM; 941716c69feSIngo Molnar 9428c3e10ebSArnaldo Carvalho de Melo if (top.target_tid != -1) 9437c940c18SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(top.evlist->threads, 944*dcc101d1SArnaldo Carvalho de Melo perf_event__process, top.session); 9455b2bb75aSArnaldo Carvalho de Melo else 946*dcc101d1SArnaldo Carvalho de Melo perf_event__synthesize_threads(perf_event__process, top.session); 9475b2bb75aSArnaldo Carvalho de Melo 9488c3e10ebSArnaldo Carvalho de Melo start_counters(top.evlist); 949*dcc101d1SArnaldo Carvalho de Melo top.session->evlist = top.evlist; 950*dcc101d1SArnaldo Carvalho de Melo perf_session__update_sample_type(top.session); 95186470930SIngo Molnar 9522f01190aSFrederic Weisbecker /* Wait for a minimal set of events before starting the snapshot */ 9538c3e10ebSArnaldo Carvalho de Melo poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 9542f01190aSFrederic Weisbecker 955*dcc101d1SArnaldo Carvalho de Melo perf_session__mmap_read(top.session); 9562f01190aSFrederic Weisbecker 957c0443df1SArnaldo Carvalho de Melo if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 958*dcc101d1SArnaldo Carvalho de Melo display_thread), NULL)) { 95986470930SIngo Molnar printf("Could not create display thread.\n"); 96086470930SIngo Molnar exit(-1); 96186470930SIngo Molnar } 96286470930SIngo Molnar 96386470930SIngo Molnar if (realtime_prio) { 96486470930SIngo Molnar struct sched_param param; 96586470930SIngo Molnar 96686470930SIngo Molnar param.sched_priority = realtime_prio; 96786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 96886470930SIngo Molnar printf("Could not set realtime priority.\n"); 96986470930SIngo Molnar exit(-1); 97086470930SIngo Molnar } 97186470930SIngo Molnar } 97286470930SIngo Molnar 97386470930SIngo Molnar while (1) { 9748c3e10ebSArnaldo Carvalho de Melo u64 hits = top.samples; 97586470930SIngo Molnar 976*dcc101d1SArnaldo Carvalho de Melo perf_session__mmap_read(top.session); 97786470930SIngo Molnar 9788c3e10ebSArnaldo Carvalho de Melo if (hits == top.samples) 9798c3e10ebSArnaldo Carvalho de Melo ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 98086470930SIngo Molnar } 98186470930SIngo Molnar 98286470930SIngo Molnar return 0; 98386470930SIngo Molnar } 98486470930SIngo Molnar 98586470930SIngo Molnar static const char * const top_usage[] = { 98686470930SIngo Molnar "perf top [<options>]", 98786470930SIngo Molnar NULL 98886470930SIngo Molnar }; 98986470930SIngo Molnar 99086470930SIngo Molnar static const struct option options[] = { 9918c3e10ebSArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &top.evlist, "event", 99286470930SIngo Molnar "event selector. use 'perf list' to list available events", 993f120f9d5SJiri Olsa parse_events_option), 99486470930SIngo Molnar OPT_INTEGER('c', "count", &default_interval, 99586470930SIngo Molnar "event period to sample"), 9968c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &top.target_pid, 997d6d901c2SZhang, Yanmin "profile events on existing process id"), 9988c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &top.target_tid, 999d6d901c2SZhang, Yanmin "profile events on existing thread id"), 100086470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 100186470930SIngo Molnar "system-wide collection from all CPUs"), 10028c3e10ebSArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &top.cpu_list, "cpu", 1003c45c6ea2SStephane Eranian "list of cpus to monitor"), 1004b32d133aSArnaldo Carvalho de Melo OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1005b32d133aSArnaldo Carvalho de Melo "file", "vmlinux pathname"), 10068c3e10ebSArnaldo Carvalho de Melo OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 10078ffcda17SArnaldo Carvalho de Melo "hide kernel symbols"), 10081967936dSArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 100986470930SIngo Molnar OPT_INTEGER('r', "realtime", &realtime_prio, 101086470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 10118c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('d', "delay", &top.delay_secs, 101286470930SIngo Molnar "number of seconds to delay between refreshes"), 101386470930SIngo Molnar OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, 101486470930SIngo Molnar "dump the symbol table used for profiling"), 10158c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('f', "count-filter", &top.count_filter, 101686470930SIngo Molnar "only display functions with more events than this"), 101786470930SIngo Molnar OPT_BOOLEAN('g', "group", &group, 101886470930SIngo Molnar "put the counters into a counter group"), 10190fdc7e67SMike Galbraith OPT_BOOLEAN('i', "inherit", &inherit, 10200fdc7e67SMike Galbraith "child tasks inherit counters"), 1021923c42c1SMike Galbraith OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", 10226cff0e8dSKirill Smelkov "symbol to annotate"), 10238c3e10ebSArnaldo Carvalho de Melo OPT_BOOLEAN('z', "zero", &top.zero, 102486470930SIngo Molnar "zero history across updates"), 10258c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('F', "freq", &top.freq, 102686470930SIngo Molnar "profile at this frequency"), 10278c3e10ebSArnaldo Carvalho de Melo OPT_INTEGER('E', "entries", &top.print_entries, 102886470930SIngo Molnar "display this many functions"), 10298c3e10ebSArnaldo Carvalho de Melo OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 10308ffcda17SArnaldo Carvalho de Melo "hide user symbols"), 1031c0443df1SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 1032c0443df1SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 1033c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10343da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 103586470930SIngo Molnar OPT_END() 103686470930SIngo Molnar }; 103786470930SIngo Molnar 1038f37a291cSIngo Molnar int cmd_top(int argc, const char **argv, const char *prefix __used) 103986470930SIngo Molnar { 104069aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 104169aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 104286470930SIngo Molnar 10438c3e10ebSArnaldo Carvalho de Melo top.evlist = perf_evlist__new(NULL, NULL); 10448c3e10ebSArnaldo Carvalho de Melo if (top.evlist == NULL) 1045361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1046361c99a6SArnaldo Carvalho de Melo 104786470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 104886470930SIngo Molnar 104986470930SIngo Molnar argc = parse_options(argc, argv, options, top_usage, 0); 105086470930SIngo Molnar if (argc) 105186470930SIngo Molnar usage_with_options(top_usage, options); 105286470930SIngo Molnar 1053c0443df1SArnaldo Carvalho de Melo /* 1054c0443df1SArnaldo Carvalho de Melo * XXX For now start disabled, only using TUI if explicitely asked for. 1055c0443df1SArnaldo Carvalho de Melo * Change that when handle_keys equivalent gets written, live annotation 1056c0443df1SArnaldo Carvalho de Melo * done, etc. 1057c0443df1SArnaldo Carvalho de Melo */ 1058c0443df1SArnaldo Carvalho de Melo use_browser = 0; 1059c0443df1SArnaldo Carvalho de Melo 1060c0443df1SArnaldo Carvalho de Melo if (use_stdio) 1061c0443df1SArnaldo Carvalho de Melo use_browser = 0; 1062c0443df1SArnaldo Carvalho de Melo else if (use_tui) 1063c0443df1SArnaldo Carvalho de Melo use_browser = 1; 1064c0443df1SArnaldo Carvalho de Melo 1065c0443df1SArnaldo Carvalho de Melo setup_browser(false); 1066c0443df1SArnaldo Carvalho de Melo 106786470930SIngo Molnar /* CPU and PID are mutually exclusive */ 10688c3e10ebSArnaldo Carvalho de Melo if (top.target_tid > 0 && top.cpu_list) { 106986470930SIngo Molnar printf("WARNING: PID switch overriding CPU\n"); 107086470930SIngo Molnar sleep(1); 10718c3e10ebSArnaldo Carvalho de Melo top.cpu_list = NULL; 107286470930SIngo Molnar } 107386470930SIngo Molnar 10748c3e10ebSArnaldo Carvalho de Melo if (top.target_pid != -1) 10758c3e10ebSArnaldo Carvalho de Melo top.target_tid = top.target_pid; 10767e2ed097SArnaldo Carvalho de Melo 10778c3e10ebSArnaldo Carvalho de Melo if (perf_evlist__create_maps(top.evlist, top.target_pid, 10788c3e10ebSArnaldo Carvalho de Melo top.target_tid, top.cpu_list) < 0) 10797e2ed097SArnaldo Carvalho de Melo usage_with_options(top_usage, options); 10807e2ed097SArnaldo Carvalho de Melo 10818c3e10ebSArnaldo Carvalho de Melo if (!top.evlist->nr_entries && 10828c3e10ebSArnaldo Carvalho de Melo perf_evlist__add_default(top.evlist) < 0) { 108369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 108469aad6f1SArnaldo Carvalho de Melo return -ENOMEM; 108569aad6f1SArnaldo Carvalho de Melo } 10865a8e5a30SArnaldo Carvalho de Melo 10878c3e10ebSArnaldo Carvalho de Melo if (top.delay_secs < 1) 10888c3e10ebSArnaldo Carvalho de Melo top.delay_secs = 1; 108986470930SIngo Molnar 10907e4ff9e3SMike Galbraith /* 10917e4ff9e3SMike Galbraith * User specified count overrides default frequency. 10927e4ff9e3SMike Galbraith */ 10937e4ff9e3SMike Galbraith if (default_interval) 10948c3e10ebSArnaldo Carvalho de Melo top.freq = 0; 10958c3e10ebSArnaldo Carvalho de Melo else if (top.freq) { 10968c3e10ebSArnaldo Carvalho de Melo default_interval = top.freq; 10977e4ff9e3SMike Galbraith } else { 10987e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 10997e4ff9e3SMike Galbraith exit(EXIT_FAILURE); 11007e4ff9e3SMike Galbraith } 11017e4ff9e3SMike Galbraith 11028c3e10ebSArnaldo Carvalho de Melo list_for_each_entry(pos, &top.evlist->entries, node) { 11038c3e10ebSArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr, 11048c3e10ebSArnaldo Carvalho de Melo top.evlist->threads->nr) < 0) 110569aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 110669aad6f1SArnaldo Carvalho de Melo /* 110769aad6f1SArnaldo Carvalho de Melo * Fill in the ones not specifically initialized via -c: 110869aad6f1SArnaldo Carvalho de Melo */ 110969aad6f1SArnaldo Carvalho de Melo if (pos->attr.sample_period) 111069aad6f1SArnaldo Carvalho de Melo continue; 111169aad6f1SArnaldo Carvalho de Melo 111269aad6f1SArnaldo Carvalho de Melo pos->attr.sample_period = default_interval; 111369aad6f1SArnaldo Carvalho de Melo } 111469aad6f1SArnaldo Carvalho de Melo 11158c3e10ebSArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(top.evlist) < 0 || 11168c3e10ebSArnaldo Carvalho de Melo perf_evlist__alloc_mmap(top.evlist) < 0) 11175c581041SArnaldo Carvalho de Melo goto out_free_fd; 11185c581041SArnaldo Carvalho de Melo 11198c3e10ebSArnaldo Carvalho de Melo top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 1120cc841580SArnaldo Carvalho de Melo 112136532461SArnaldo Carvalho de Melo symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) + 11228c3e10ebSArnaldo Carvalho de Melo (top.evlist->nr_entries + 1) * sizeof(unsigned long)); 112369aad6f1SArnaldo Carvalho de Melo 112469aad6f1SArnaldo Carvalho de Melo symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 112569aad6f1SArnaldo Carvalho de Melo if (symbol__init() < 0) 112669aad6f1SArnaldo Carvalho de Melo return -1; 112769aad6f1SArnaldo Carvalho de Melo 112813cc5079SArnaldo Carvalho de Melo get_term_dimensions(&winsize); 11298c3e10ebSArnaldo Carvalho de Melo if (top.print_entries == 0) { 113013cc5079SArnaldo Carvalho de Melo update_print_entries(&winsize); 11313b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, sig_winch_handler); 11323b6ed988SArnaldo Carvalho de Melo } 11333b6ed988SArnaldo Carvalho de Melo 113469aad6f1SArnaldo Carvalho de Melo status = __cmd_top(); 113569aad6f1SArnaldo Carvalho de Melo out_free_fd: 11368c3e10ebSArnaldo Carvalho de Melo perf_evlist__delete(top.evlist); 113769aad6f1SArnaldo Carvalho de Melo 113869aad6f1SArnaldo Carvalho de Melo return status; 113986470930SIngo Molnar } 1140