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 2386470930SIngo Molnar #include "util/color.h" 24361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2569aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 26b3165f41SArnaldo Carvalho de Melo #include "util/session.h" 27b3165f41SArnaldo Carvalho de Melo #include "util/symbol.h" 28439d473bSArnaldo Carvalho de Melo #include "util/thread.h" 2986470930SIngo Molnar #include "util/util.h" 3043cbcd8aSArnaldo Carvalho de Melo #include <linux/rbtree.h> 3186470930SIngo Molnar #include "util/parse-options.h" 3286470930SIngo Molnar #include "util/parse-events.h" 33a12b51c4SPaul Mackerras #include "util/cpumap.h" 3469aad6f1SArnaldo Carvalho de Melo #include "util/xyarray.h" 3586470930SIngo Molnar 368f28827aSFrederic Weisbecker #include "util/debug.h" 378f28827aSFrederic Weisbecker 3886470930SIngo Molnar #include <assert.h> 3986470930SIngo Molnar #include <fcntl.h> 4086470930SIngo Molnar 4186470930SIngo Molnar #include <stdio.h> 42923c42c1SMike Galbraith #include <termios.h> 43923c42c1SMike Galbraith #include <unistd.h> 449486aa38SArnaldo Carvalho de Melo #include <inttypes.h> 4586470930SIngo Molnar 4686470930SIngo Molnar #include <errno.h> 4786470930SIngo Molnar #include <time.h> 4886470930SIngo Molnar #include <sched.h> 4986470930SIngo Molnar #include <pthread.h> 5086470930SIngo Molnar 5186470930SIngo Molnar #include <sys/syscall.h> 5286470930SIngo Molnar #include <sys/ioctl.h> 5386470930SIngo Molnar #include <sys/poll.h> 5486470930SIngo Molnar #include <sys/prctl.h> 5586470930SIngo Molnar #include <sys/wait.h> 5686470930SIngo Molnar #include <sys/uio.h> 5786470930SIngo Molnar #include <sys/mman.h> 5886470930SIngo Molnar 5986470930SIngo Molnar #include <linux/unistd.h> 6086470930SIngo Molnar #include <linux/types.h> 6186470930SIngo Molnar 6269aad6f1SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 6386470930SIngo Molnar 64361c99a6SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 65361c99a6SArnaldo Carvalho de Melo 66c0555642SIan Munsie static bool system_wide = false; 6786470930SIngo Molnar 687e4ff9e3SMike Galbraith static int default_interval = 0; 6986470930SIngo Molnar 70923c42c1SMike Galbraith static int count_filter = 5; 713b6ed988SArnaldo Carvalho de Melo static int print_entries; 7286470930SIngo Molnar 7386470930SIngo Molnar static int target_pid = -1; 74d6d901c2SZhang, Yanmin static int target_tid = -1; 755c98d466SArnaldo Carvalho de Melo static struct thread_map *threads; 76c0555642SIan Munsie static bool inherit = false; 7760d567e2SArnaldo Carvalho de Melo static struct cpu_map *cpus; 781967936dSArnaldo Carvalho de Melo static int realtime_prio = 0; 79c0555642SIan Munsie static bool group = false; 8086470930SIngo Molnar static unsigned int page_size; 8170db7533SArnaldo Carvalho de Melo static unsigned int mmap_pages = 128; 8242e59d7dSIngo Molnar static int freq = 1000; /* 1 KHz */ 8386470930SIngo Molnar 8486470930SIngo Molnar static int delay_secs = 2; 85c0555642SIan Munsie static bool zero = false; 86c0555642SIan Munsie static bool dump_symtab = false; 8786470930SIngo Molnar 888ffcda17SArnaldo Carvalho de Melo static bool hide_kernel_symbols = false; 898ffcda17SArnaldo Carvalho de Melo static bool hide_user_symbols = false; 9013cc5079SArnaldo Carvalho de Melo static struct winsize winsize; 918ffcda17SArnaldo Carvalho de Melo 9286470930SIngo Molnar /* 93923c42c1SMike Galbraith * Source 94923c42c1SMike Galbraith */ 95923c42c1SMike Galbraith 96923c42c1SMike Galbraith struct source_line { 97923c42c1SMike Galbraith u64 eip; 98923c42c1SMike Galbraith unsigned long count[MAX_COUNTERS]; 99923c42c1SMike Galbraith char *line; 100923c42c1SMike Galbraith struct source_line *next; 101923c42c1SMike Galbraith }; 102923c42c1SMike Galbraith 103edb7c60eSArnaldo Carvalho de Melo static const char *sym_filter = NULL; 104923c42c1SMike Galbraith struct sym_entry *sym_filter_entry = NULL; 1056cff0e8dSKirill Smelkov struct sym_entry *sym_filter_entry_sched = NULL; 106923c42c1SMike Galbraith static int sym_pcnt_filter = 5; 107923c42c1SMike Galbraith static int sym_counter = 0; 10869aad6f1SArnaldo Carvalho de Melo static struct perf_evsel *sym_evsel = NULL; 10946ab9764SMike Galbraith static int display_weighted = -1; 110c45c6ea2SStephane Eranian static const char *cpu_list; 111923c42c1SMike Galbraith 112923c42c1SMike Galbraith /* 11386470930SIngo Molnar * Symbols 11486470930SIngo Molnar */ 11586470930SIngo Molnar 116b269876cSArnaldo Carvalho de Melo struct sym_entry_source { 117b269876cSArnaldo Carvalho de Melo struct source_line *source; 118b269876cSArnaldo Carvalho de Melo struct source_line *lines; 119b269876cSArnaldo Carvalho de Melo struct source_line **lines_tail; 120b269876cSArnaldo Carvalho de Melo pthread_mutex_t lock; 121b269876cSArnaldo Carvalho de Melo }; 122b269876cSArnaldo Carvalho de Melo 12386470930SIngo Molnar struct sym_entry { 12486470930SIngo Molnar struct rb_node rb_node; 12586470930SIngo Molnar struct list_head node; 12686470930SIngo Molnar unsigned long snap_count; 12786470930SIngo Molnar double weight; 12886470930SIngo Molnar int skip; 12913cc5079SArnaldo Carvalho de Melo u16 name_len; 1308ffcda17SArnaldo Carvalho de Melo u8 origin; 131439d473bSArnaldo Carvalho de Melo struct map *map; 132b269876cSArnaldo Carvalho de Melo struct sym_entry_source *src; 1335a8e5a30SArnaldo Carvalho de Melo unsigned long count[0]; 13486470930SIngo Molnar }; 13586470930SIngo Molnar 136923c42c1SMike Galbraith /* 137923c42c1SMike Galbraith * Source functions 138923c42c1SMike Galbraith */ 139923c42c1SMike Galbraith 14051a472deSArnaldo Carvalho de Melo static inline struct symbol *sym_entry__symbol(struct sym_entry *self) 14151a472deSArnaldo Carvalho de Melo { 142b32d133aSArnaldo Carvalho de Melo return ((void *)self) + symbol_conf.priv_size; 14351a472deSArnaldo Carvalho de Melo } 14451a472deSArnaldo Carvalho de Melo 145895f0edcSArnaldo Carvalho de Melo void get_term_dimensions(struct winsize *ws) 1463b6ed988SArnaldo Carvalho de Melo { 14713cc5079SArnaldo Carvalho de Melo char *s = getenv("LINES"); 1483b6ed988SArnaldo Carvalho de Melo 14913cc5079SArnaldo Carvalho de Melo if (s != NULL) { 15013cc5079SArnaldo Carvalho de Melo ws->ws_row = atoi(s); 15113cc5079SArnaldo Carvalho de Melo s = getenv("COLUMNS"); 15213cc5079SArnaldo Carvalho de Melo if (s != NULL) { 15313cc5079SArnaldo Carvalho de Melo ws->ws_col = atoi(s); 15413cc5079SArnaldo Carvalho de Melo if (ws->ws_row && ws->ws_col) 15513cc5079SArnaldo Carvalho de Melo return; 15613cc5079SArnaldo Carvalho de Melo } 15713cc5079SArnaldo Carvalho de Melo } 1583b6ed988SArnaldo Carvalho de Melo #ifdef TIOCGWINSZ 15913cc5079SArnaldo Carvalho de Melo if (ioctl(1, TIOCGWINSZ, ws) == 0 && 16013cc5079SArnaldo Carvalho de Melo ws->ws_row && ws->ws_col) 16113cc5079SArnaldo Carvalho de Melo return; 1623b6ed988SArnaldo Carvalho de Melo #endif 16313cc5079SArnaldo Carvalho de Melo ws->ws_row = 25; 16413cc5079SArnaldo Carvalho de Melo ws->ws_col = 80; 1653b6ed988SArnaldo Carvalho de Melo } 1663b6ed988SArnaldo Carvalho de Melo 16713cc5079SArnaldo Carvalho de Melo static void update_print_entries(struct winsize *ws) 1683b6ed988SArnaldo Carvalho de Melo { 16913cc5079SArnaldo Carvalho de Melo print_entries = ws->ws_row; 17013cc5079SArnaldo Carvalho de Melo 1713b6ed988SArnaldo Carvalho de Melo if (print_entries > 9) 1723b6ed988SArnaldo Carvalho de Melo print_entries -= 9; 1733b6ed988SArnaldo Carvalho de Melo } 1743b6ed988SArnaldo Carvalho de Melo 1753b6ed988SArnaldo Carvalho de Melo static void sig_winch_handler(int sig __used) 1763b6ed988SArnaldo Carvalho de Melo { 17713cc5079SArnaldo Carvalho de Melo get_term_dimensions(&winsize); 17813cc5079SArnaldo Carvalho de Melo update_print_entries(&winsize); 1793b6ed988SArnaldo Carvalho de Melo } 1803b6ed988SArnaldo Carvalho de Melo 181b0a9ab62SArnaldo Carvalho de Melo static int parse_source(struct sym_entry *syme) 182923c42c1SMike Galbraith { 183923c42c1SMike Galbraith struct symbol *sym; 184b269876cSArnaldo Carvalho de Melo struct sym_entry_source *source; 185439d473bSArnaldo Carvalho de Melo struct map *map; 186923c42c1SMike Galbraith FILE *file; 18783a0944fSIngo Molnar char command[PATH_MAX*2]; 188439d473bSArnaldo Carvalho de Melo const char *path; 189439d473bSArnaldo Carvalho de Melo u64 len; 190923c42c1SMike Galbraith 191923c42c1SMike Galbraith if (!syme) 192b0a9ab62SArnaldo Carvalho de Melo return -1; 193b0a9ab62SArnaldo Carvalho de Melo 194b0a9ab62SArnaldo Carvalho de Melo sym = sym_entry__symbol(syme); 195b0a9ab62SArnaldo Carvalho de Melo map = syme->map; 196b0a9ab62SArnaldo Carvalho de Melo 197b0a9ab62SArnaldo Carvalho de Melo /* 198b0a9ab62SArnaldo Carvalho de Melo * We can't annotate with just /proc/kallsyms 199b0a9ab62SArnaldo Carvalho de Melo */ 200b0a9ab62SArnaldo Carvalho de Melo if (map->dso->origin == DSO__ORIG_KERNEL) 201b0a9ab62SArnaldo Carvalho de Melo return -1; 202923c42c1SMike Galbraith 203b269876cSArnaldo Carvalho de Melo if (syme->src == NULL) { 20436479484SArnaldo Carvalho de Melo syme->src = zalloc(sizeof(*source)); 205b269876cSArnaldo Carvalho de Melo if (syme->src == NULL) 206b0a9ab62SArnaldo Carvalho de Melo return -1; 207b269876cSArnaldo Carvalho de Melo pthread_mutex_init(&syme->src->lock, NULL); 208b269876cSArnaldo Carvalho de Melo } 209b269876cSArnaldo Carvalho de Melo 210b269876cSArnaldo Carvalho de Melo source = syme->src; 211b269876cSArnaldo Carvalho de Melo 212b269876cSArnaldo Carvalho de Melo if (source->lines) { 213b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&source->lock); 214923c42c1SMike Galbraith goto out_assign; 215923c42c1SMike Galbraith } 216439d473bSArnaldo Carvalho de Melo path = map->dso->long_name; 217923c42c1SMike Galbraith 218923c42c1SMike Galbraith len = sym->end - sym->start; 219923c42c1SMike Galbraith 220439d473bSArnaldo Carvalho de Melo sprintf(command, 2219486aa38SArnaldo Carvalho de Melo "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s", 2225f485364SArnaldo Carvalho de Melo BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start), 2235f485364SArnaldo Carvalho de Melo BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path); 224923c42c1SMike Galbraith 225923c42c1SMike Galbraith file = popen(command, "r"); 226923c42c1SMike Galbraith if (!file) 227b0a9ab62SArnaldo Carvalho de Melo return -1; 228923c42c1SMike Galbraith 229b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&source->lock); 230b269876cSArnaldo Carvalho de Melo source->lines_tail = &source->lines; 231923c42c1SMike Galbraith while (!feof(file)) { 232923c42c1SMike Galbraith struct source_line *src; 233923c42c1SMike Galbraith size_t dummy = 0; 234ee11b90bSKirill Smelkov char *c, *sep; 235923c42c1SMike Galbraith 236923c42c1SMike Galbraith src = malloc(sizeof(struct source_line)); 237923c42c1SMike Galbraith assert(src != NULL); 238923c42c1SMike Galbraith memset(src, 0, sizeof(struct source_line)); 239923c42c1SMike Galbraith 240923c42c1SMike Galbraith if (getline(&src->line, &dummy, file) < 0) 241923c42c1SMike Galbraith break; 242923c42c1SMike Galbraith if (!src->line) 243923c42c1SMike Galbraith break; 244923c42c1SMike Galbraith 245923c42c1SMike Galbraith c = strchr(src->line, '\n'); 246923c42c1SMike Galbraith if (c) 247923c42c1SMike Galbraith *c = 0; 248923c42c1SMike Galbraith 249923c42c1SMike Galbraith src->next = NULL; 250b269876cSArnaldo Carvalho de Melo *source->lines_tail = src; 251b269876cSArnaldo Carvalho de Melo source->lines_tail = &src->next; 252923c42c1SMike Galbraith 253ee11b90bSKirill Smelkov src->eip = strtoull(src->line, &sep, 16); 254ee11b90bSKirill Smelkov if (*sep == ':') 255ee11b90bSKirill Smelkov src->eip = map__objdump_2ip(map, src->eip); 256ee11b90bSKirill Smelkov else /* this line has no ip info (e.g. source line) */ 257ee11b90bSKirill Smelkov src->eip = 0; 258923c42c1SMike Galbraith } 259923c42c1SMike Galbraith pclose(file); 260923c42c1SMike Galbraith out_assign: 261923c42c1SMike Galbraith sym_filter_entry = syme; 262b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&source->lock); 263b0a9ab62SArnaldo Carvalho de Melo return 0; 264923c42c1SMike Galbraith } 265923c42c1SMike Galbraith 266923c42c1SMike Galbraith static void __zero_source_counters(struct sym_entry *syme) 267923c42c1SMike Galbraith { 268923c42c1SMike Galbraith int i; 269923c42c1SMike Galbraith struct source_line *line; 270923c42c1SMike Galbraith 271b269876cSArnaldo Carvalho de Melo line = syme->src->lines; 272923c42c1SMike Galbraith while (line) { 273361c99a6SArnaldo Carvalho de Melo for (i = 0; i < evsel_list->nr_entries; i++) 274923c42c1SMike Galbraith line->count[i] = 0; 275923c42c1SMike Galbraith line = line->next; 276923c42c1SMike Galbraith } 277923c42c1SMike Galbraith } 278923c42c1SMike Galbraith 279923c42c1SMike Galbraith static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 280923c42c1SMike Galbraith { 281923c42c1SMike Galbraith struct source_line *line; 282923c42c1SMike Galbraith 283923c42c1SMike Galbraith if (syme != sym_filter_entry) 284923c42c1SMike Galbraith return; 285923c42c1SMike Galbraith 286b269876cSArnaldo Carvalho de Melo if (pthread_mutex_trylock(&syme->src->lock)) 287923c42c1SMike Galbraith return; 288923c42c1SMike Galbraith 289b269876cSArnaldo Carvalho de Melo if (syme->src == NULL || syme->src->source == NULL) 290923c42c1SMike Galbraith goto out_unlock; 291923c42c1SMike Galbraith 292b269876cSArnaldo Carvalho de Melo for (line = syme->src->lines; line; line = line->next) { 293ee11b90bSKirill Smelkov /* skip lines without IP info */ 294ee11b90bSKirill Smelkov if (line->eip == 0) 295ee11b90bSKirill Smelkov continue; 296923c42c1SMike Galbraith if (line->eip == ip) { 297923c42c1SMike Galbraith line->count[counter]++; 298923c42c1SMike Galbraith break; 299923c42c1SMike Galbraith } 300923c42c1SMike Galbraith if (line->eip > ip) 301923c42c1SMike Galbraith break; 302923c42c1SMike Galbraith } 303923c42c1SMike Galbraith out_unlock: 304b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&syme->src->lock); 305923c42c1SMike Galbraith } 306923c42c1SMike Galbraith 307c7ad21afSArnaldo Carvalho de Melo #define PATTERN_LEN (BITS_PER_LONG / 4 + 2) 308c7ad21afSArnaldo Carvalho de Melo 309923c42c1SMike Galbraith static void lookup_sym_source(struct sym_entry *syme) 310923c42c1SMike Galbraith { 31151a472deSArnaldo Carvalho de Melo struct symbol *symbol = sym_entry__symbol(syme); 312923c42c1SMike Galbraith struct source_line *line; 313c7ad21afSArnaldo Carvalho de Melo char pattern[PATTERN_LEN + 1]; 314923c42c1SMike Galbraith 3159486aa38SArnaldo Carvalho de Melo sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4, 3165f485364SArnaldo Carvalho de Melo map__rip_2objdump(syme->map, symbol->start)); 317923c42c1SMike Galbraith 318b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&syme->src->lock); 319b269876cSArnaldo Carvalho de Melo for (line = syme->src->lines; line; line = line->next) { 320c7ad21afSArnaldo Carvalho de Melo if (memcmp(line->line, pattern, PATTERN_LEN) == 0) { 321b269876cSArnaldo Carvalho de Melo syme->src->source = line; 322923c42c1SMike Galbraith break; 323923c42c1SMike Galbraith } 324923c42c1SMike Galbraith } 325b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&syme->src->lock); 326923c42c1SMike Galbraith } 327923c42c1SMike Galbraith 328923c42c1SMike Galbraith static void show_lines(struct source_line *queue, int count, int total) 329923c42c1SMike Galbraith { 330923c42c1SMike Galbraith int i; 331923c42c1SMike Galbraith struct source_line *line; 332923c42c1SMike Galbraith 333923c42c1SMike Galbraith line = queue; 334923c42c1SMike Galbraith for (i = 0; i < count; i++) { 335923c42c1SMike Galbraith float pcnt = 100.0*(float)line->count[sym_counter]/(float)total; 336923c42c1SMike Galbraith 337923c42c1SMike Galbraith printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line); 338923c42c1SMike Galbraith line = line->next; 339923c42c1SMike Galbraith } 340923c42c1SMike Galbraith } 341923c42c1SMike Galbraith 342923c42c1SMike Galbraith #define TRACE_COUNT 3 343923c42c1SMike Galbraith 344923c42c1SMike Galbraith static void show_details(struct sym_entry *syme) 345923c42c1SMike Galbraith { 346923c42c1SMike Galbraith struct symbol *symbol; 347923c42c1SMike Galbraith struct source_line *line; 348923c42c1SMike Galbraith struct source_line *line_queue = NULL; 349923c42c1SMike Galbraith int displayed = 0; 350923c42c1SMike Galbraith int line_queue_count = 0, total = 0, more = 0; 351923c42c1SMike Galbraith 352923c42c1SMike Galbraith if (!syme) 353923c42c1SMike Galbraith return; 354923c42c1SMike Galbraith 355b269876cSArnaldo Carvalho de Melo if (!syme->src->source) 356923c42c1SMike Galbraith lookup_sym_source(syme); 357923c42c1SMike Galbraith 358b269876cSArnaldo Carvalho de Melo if (!syme->src->source) 359923c42c1SMike Galbraith return; 360923c42c1SMike Galbraith 36151a472deSArnaldo Carvalho de Melo symbol = sym_entry__symbol(syme); 36269aad6f1SArnaldo Carvalho de Melo printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name); 363923c42c1SMike Galbraith printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 364923c42c1SMike Galbraith 365b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&syme->src->lock); 366b269876cSArnaldo Carvalho de Melo line = syme->src->source; 367923c42c1SMike Galbraith while (line) { 368923c42c1SMike Galbraith total += line->count[sym_counter]; 369923c42c1SMike Galbraith line = line->next; 370923c42c1SMike Galbraith } 371923c42c1SMike Galbraith 372b269876cSArnaldo Carvalho de Melo line = syme->src->source; 373923c42c1SMike Galbraith while (line) { 374923c42c1SMike Galbraith float pcnt = 0.0; 375923c42c1SMike Galbraith 376923c42c1SMike Galbraith if (!line_queue_count) 377923c42c1SMike Galbraith line_queue = line; 378923c42c1SMike Galbraith line_queue_count++; 379923c42c1SMike Galbraith 380923c42c1SMike Galbraith if (line->count[sym_counter]) 381923c42c1SMike Galbraith pcnt = 100.0 * line->count[sym_counter] / (float)total; 382923c42c1SMike Galbraith if (pcnt >= (float)sym_pcnt_filter) { 383923c42c1SMike Galbraith if (displayed <= print_entries) 384923c42c1SMike Galbraith show_lines(line_queue, line_queue_count, total); 385923c42c1SMike Galbraith else more++; 386923c42c1SMike Galbraith displayed += line_queue_count; 387923c42c1SMike Galbraith line_queue_count = 0; 388923c42c1SMike Galbraith line_queue = NULL; 389923c42c1SMike Galbraith } else if (line_queue_count > TRACE_COUNT) { 390923c42c1SMike Galbraith line_queue = line_queue->next; 391923c42c1SMike Galbraith line_queue_count--; 392923c42c1SMike Galbraith } 393923c42c1SMike Galbraith 394923c42c1SMike Galbraith line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; 395923c42c1SMike Galbraith line = line->next; 396923c42c1SMike Galbraith } 397b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&syme->src->lock); 398923c42c1SMike Galbraith if (more) 399923c42c1SMike Galbraith printf("%d lines not displayed, maybe increase display entries [e]\n", more); 400923c42c1SMike Galbraith } 40186470930SIngo Molnar 40286470930SIngo Molnar /* 4035b2bb75aSArnaldo Carvalho de Melo * Symbols will be added here in event__process_sample and will get out 40486470930SIngo Molnar * after decayed. 40586470930SIngo Molnar */ 40686470930SIngo Molnar static LIST_HEAD(active_symbols); 40786470930SIngo Molnar static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER; 40886470930SIngo Molnar 40986470930SIngo Molnar /* 41086470930SIngo Molnar * Ordering weight: count-1 * count-2 * ... / count-n 41186470930SIngo Molnar */ 41286470930SIngo Molnar static double sym_weight(const struct sym_entry *sym) 41386470930SIngo Molnar { 41486470930SIngo Molnar double weight = sym->snap_count; 41586470930SIngo Molnar int counter; 41686470930SIngo Molnar 41746ab9764SMike Galbraith if (!display_weighted) 41846ab9764SMike Galbraith return weight; 41946ab9764SMike Galbraith 420361c99a6SArnaldo Carvalho de Melo for (counter = 1; counter < evsel_list->nr_entries - 1; counter++) 42186470930SIngo Molnar weight *= sym->count[counter]; 42286470930SIngo Molnar 42386470930SIngo Molnar weight /= (sym->count[counter] + 1); 42486470930SIngo Molnar 42586470930SIngo Molnar return weight; 42686470930SIngo Molnar } 42786470930SIngo Molnar 42886470930SIngo Molnar static long samples; 429a1645ce1SZhang, Yanmin static long kernel_samples, us_samples; 4301676b8a0SPeter Zijlstra static long exact_samples; 431a1645ce1SZhang, Yanmin static long guest_us_samples, guest_kernel_samples; 43286470930SIngo Molnar static const char CONSOLE_CLEAR[] = "[H[2J"; 43386470930SIngo Molnar 43486470930SIngo Molnar static void __list_insert_active_sym(struct sym_entry *syme) 43586470930SIngo Molnar { 43686470930SIngo Molnar list_add(&syme->node, &active_symbols); 43786470930SIngo Molnar } 43886470930SIngo Molnar 43986470930SIngo Molnar static void list_remove_active_sym(struct sym_entry *syme) 44086470930SIngo Molnar { 44186470930SIngo Molnar pthread_mutex_lock(&active_symbols_lock); 44286470930SIngo Molnar list_del_init(&syme->node); 44386470930SIngo Molnar pthread_mutex_unlock(&active_symbols_lock); 44486470930SIngo Molnar } 44586470930SIngo Molnar 44686470930SIngo Molnar static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se) 44786470930SIngo Molnar { 44886470930SIngo Molnar struct rb_node **p = &tree->rb_node; 44986470930SIngo Molnar struct rb_node *parent = NULL; 45086470930SIngo Molnar struct sym_entry *iter; 45186470930SIngo Molnar 45286470930SIngo Molnar while (*p != NULL) { 45386470930SIngo Molnar parent = *p; 45486470930SIngo Molnar iter = rb_entry(parent, struct sym_entry, rb_node); 45586470930SIngo Molnar 45686470930SIngo Molnar if (se->weight > iter->weight) 45786470930SIngo Molnar p = &(*p)->rb_left; 45886470930SIngo Molnar else 45986470930SIngo Molnar p = &(*p)->rb_right; 46086470930SIngo Molnar } 46186470930SIngo Molnar 46286470930SIngo Molnar rb_link_node(&se->rb_node, parent, p); 46386470930SIngo Molnar rb_insert_color(&se->rb_node, tree); 46486470930SIngo Molnar } 46586470930SIngo Molnar 46686470930SIngo Molnar static void print_sym_table(void) 46786470930SIngo Molnar { 46886470930SIngo Molnar int printed = 0, j; 46969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 47069aad6f1SArnaldo Carvalho de Melo int snap = !display_weighted ? sym_counter : 0; 47186470930SIngo Molnar float samples_per_sec = samples/delay_secs; 472a1645ce1SZhang, Yanmin float ksamples_per_sec = kernel_samples/delay_secs; 473a1645ce1SZhang, Yanmin float us_samples_per_sec = (us_samples)/delay_secs; 474a1645ce1SZhang, Yanmin float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs; 475a1645ce1SZhang, Yanmin float guest_us_samples_per_sec = (guest_us_samples)/delay_secs; 4761676b8a0SPeter Zijlstra float esamples_percent = (100.0*exact_samples)/samples; 47786470930SIngo Molnar float sum_ksamples = 0.0; 47886470930SIngo Molnar struct sym_entry *syme, *n; 47986470930SIngo Molnar struct rb_root tmp = RB_ROOT; 48086470930SIngo Molnar struct rb_node *nd; 48100909e95SArnaldo Carvalho de Melo int sym_width = 0, dso_width = 0, dso_short_width = 0; 48213cc5079SArnaldo Carvalho de Melo const int win_width = winsize.ws_col - 1; 48386470930SIngo Molnar 484a1645ce1SZhang, Yanmin samples = us_samples = kernel_samples = exact_samples = 0; 485a1645ce1SZhang, Yanmin guest_kernel_samples = guest_us_samples = 0; 48686470930SIngo Molnar 48786470930SIngo Molnar /* Sort the active symbols */ 48886470930SIngo Molnar pthread_mutex_lock(&active_symbols_lock); 48986470930SIngo Molnar syme = list_entry(active_symbols.next, struct sym_entry, node); 49086470930SIngo Molnar pthread_mutex_unlock(&active_symbols_lock); 49186470930SIngo Molnar 49286470930SIngo Molnar list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 49346ab9764SMike Galbraith syme->snap_count = syme->count[snap]; 49486470930SIngo Molnar if (syme->snap_count != 0) { 49513cc5079SArnaldo Carvalho de Melo 4968ffcda17SArnaldo Carvalho de Melo if ((hide_user_symbols && 4978ffcda17SArnaldo Carvalho de Melo syme->origin == PERF_RECORD_MISC_USER) || 4988ffcda17SArnaldo Carvalho de Melo (hide_kernel_symbols && 4998ffcda17SArnaldo Carvalho de Melo syme->origin == PERF_RECORD_MISC_KERNEL)) { 5008ffcda17SArnaldo Carvalho de Melo list_remove_active_sym(syme); 5018ffcda17SArnaldo Carvalho de Melo continue; 5028ffcda17SArnaldo Carvalho de Melo } 50386470930SIngo Molnar syme->weight = sym_weight(syme); 50486470930SIngo Molnar rb_insert_active_sym(&tmp, syme); 50586470930SIngo Molnar sum_ksamples += syme->snap_count; 50686470930SIngo Molnar 507361c99a6SArnaldo Carvalho de Melo for (j = 0; j < evsel_list->nr_entries; j++) 50886470930SIngo Molnar syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; 50986470930SIngo Molnar } else 51086470930SIngo Molnar list_remove_active_sym(syme); 51186470930SIngo Molnar } 51286470930SIngo Molnar 51386470930SIngo Molnar puts(CONSOLE_CLEAR); 51486470930SIngo Molnar 51513cc5079SArnaldo Carvalho de Melo printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 516a1645ce1SZhang, Yanmin if (!perf_guest) { 517a1645ce1SZhang, Yanmin printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%%" 518a1645ce1SZhang, Yanmin " exact: %4.1f%% [", 51986470930SIngo Molnar samples_per_sec, 520a1645ce1SZhang, Yanmin 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / 521a1645ce1SZhang, Yanmin samples_per_sec)), 5221676b8a0SPeter Zijlstra esamples_percent); 523a1645ce1SZhang, Yanmin } else { 524a1645ce1SZhang, Yanmin printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%" 525a1645ce1SZhang, Yanmin " guest kernel:%4.1f%% guest us:%4.1f%%" 526a1645ce1SZhang, Yanmin " exact: %4.1f%% [", 527a1645ce1SZhang, Yanmin samples_per_sec, 528a1645ce1SZhang, Yanmin 100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) / 529a1645ce1SZhang, Yanmin samples_per_sec)), 530a1645ce1SZhang, Yanmin 100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) / 531a1645ce1SZhang, Yanmin samples_per_sec)), 532a1645ce1SZhang, Yanmin 100.0 - (100.0 * ((samples_per_sec - 533a1645ce1SZhang, Yanmin guest_kernel_samples_per_sec) / 534a1645ce1SZhang, Yanmin samples_per_sec)), 535a1645ce1SZhang, Yanmin 100.0 - (100.0 * ((samples_per_sec - 536a1645ce1SZhang, Yanmin guest_us_samples_per_sec) / 537a1645ce1SZhang, Yanmin samples_per_sec)), 538a1645ce1SZhang, Yanmin esamples_percent); 539a1645ce1SZhang, Yanmin } 54086470930SIngo Molnar 541361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 1 || !display_weighted) { 54269aad6f1SArnaldo Carvalho de Melo struct perf_evsel *first; 543361c99a6SArnaldo Carvalho de Melo first = list_entry(evsel_list->entries.next, struct perf_evsel, node); 5449486aa38SArnaldo Carvalho de Melo printf("%" PRIu64, (uint64_t)first->attr.sample_period); 54586470930SIngo Molnar if (freq) 54686470930SIngo Molnar printf("Hz "); 54786470930SIngo Molnar else 54886470930SIngo Molnar printf(" "); 54986470930SIngo Molnar } 55086470930SIngo Molnar 55146ab9764SMike Galbraith if (!display_weighted) 55269aad6f1SArnaldo Carvalho de Melo printf("%s", event_name(sym_evsel)); 553361c99a6SArnaldo Carvalho de Melo else list_for_each_entry(counter, &evsel_list->entries, node) { 55469aad6f1SArnaldo Carvalho de Melo if (counter->idx) 55586470930SIngo Molnar printf("/"); 55686470930SIngo Molnar 55786470930SIngo Molnar printf("%s", event_name(counter)); 55886470930SIngo Molnar } 55986470930SIngo Molnar 56086470930SIngo Molnar printf( "], "); 56186470930SIngo Molnar 56286470930SIngo Molnar if (target_pid != -1) 56386470930SIngo Molnar printf(" (target_pid: %d", target_pid); 564d6d901c2SZhang, Yanmin else if (target_tid != -1) 565d6d901c2SZhang, Yanmin printf(" (target_tid: %d", target_tid); 56686470930SIngo Molnar else 56786470930SIngo Molnar printf(" (all"); 56886470930SIngo Molnar 56901797c59SCorey Ashford if (cpu_list) 57060d567e2SArnaldo Carvalho de Melo printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list); 57186470930SIngo Molnar else { 572d6d901c2SZhang, Yanmin if (target_tid != -1) 57386470930SIngo Molnar printf(")\n"); 57486470930SIngo Molnar else 57560d567e2SArnaldo Carvalho de Melo printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : ""); 57686470930SIngo Molnar } 57786470930SIngo Molnar 5781a105f74SArnaldo Carvalho de Melo printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 57986470930SIngo Molnar 580923c42c1SMike Galbraith if (sym_filter_entry) { 581923c42c1SMike Galbraith show_details(sym_filter_entry); 582923c42c1SMike Galbraith return; 583923c42c1SMike Galbraith } 584923c42c1SMike Galbraith 58513cc5079SArnaldo Carvalho de Melo /* 58613cc5079SArnaldo Carvalho de Melo * Find the longest symbol name that will be displayed 58713cc5079SArnaldo Carvalho de Melo */ 58813cc5079SArnaldo Carvalho de Melo for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 58913cc5079SArnaldo Carvalho de Melo syme = rb_entry(nd, struct sym_entry, rb_node); 59013cc5079SArnaldo Carvalho de Melo if (++printed > print_entries || 59113cc5079SArnaldo Carvalho de Melo (int)syme->snap_count < count_filter) 59213cc5079SArnaldo Carvalho de Melo continue; 59313cc5079SArnaldo Carvalho de Melo 5941a105f74SArnaldo Carvalho de Melo if (syme->map->dso->long_name_len > dso_width) 5951a105f74SArnaldo Carvalho de Melo dso_width = syme->map->dso->long_name_len; 5961a105f74SArnaldo Carvalho de Melo 597b63be8d7SArnaldo Carvalho de Melo if (syme->map->dso->short_name_len > dso_short_width) 598b63be8d7SArnaldo Carvalho de Melo dso_short_width = syme->map->dso->short_name_len; 599b63be8d7SArnaldo Carvalho de Melo 60013cc5079SArnaldo Carvalho de Melo if (syme->name_len > sym_width) 60113cc5079SArnaldo Carvalho de Melo sym_width = syme->name_len; 60213cc5079SArnaldo Carvalho de Melo } 60313cc5079SArnaldo Carvalho de Melo 60413cc5079SArnaldo Carvalho de Melo printed = 0; 60513cc5079SArnaldo Carvalho de Melo 606b63be8d7SArnaldo Carvalho de Melo if (sym_width + dso_width > winsize.ws_col - 29) { 607b63be8d7SArnaldo Carvalho de Melo dso_width = dso_short_width; 608b63be8d7SArnaldo Carvalho de Melo if (sym_width + dso_width > winsize.ws_col - 29) 609b63be8d7SArnaldo Carvalho de Melo sym_width = winsize.ws_col - dso_width - 29; 610b63be8d7SArnaldo Carvalho de Melo } 6111a105f74SArnaldo Carvalho de Melo putchar('\n'); 612361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 1) 61386470930SIngo Molnar printf(" samples pcnt"); 61486470930SIngo Molnar else 61586470930SIngo Molnar printf(" weight samples pcnt"); 61686470930SIngo Molnar 6177ced156bSArnaldo Carvalho de Melo if (verbose) 6187ced156bSArnaldo Carvalho de Melo printf(" RIP "); 6197cc017edSArnaldo Carvalho de Melo printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); 6207ced156bSArnaldo Carvalho de Melo printf(" %s _______ _____", 621361c99a6SArnaldo Carvalho de Melo evsel_list->nr_entries == 1 ? " " : "______"); 6227ced156bSArnaldo Carvalho de Melo if (verbose) 6237ced156bSArnaldo Carvalho de Melo printf(" ________________"); 6241a105f74SArnaldo Carvalho de Melo printf(" %-*.*s", sym_width, sym_width, graph_line); 6251a105f74SArnaldo Carvalho de Melo printf(" %-*.*s", dso_width, dso_width, graph_line); 6261a105f74SArnaldo Carvalho de Melo puts("\n"); 62786470930SIngo Molnar 62886470930SIngo Molnar for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 62983a0944fSIngo Molnar struct symbol *sym; 63086470930SIngo Molnar double pcnt; 63186470930SIngo Molnar 63283a0944fSIngo Molnar syme = rb_entry(nd, struct sym_entry, rb_node); 63351a472deSArnaldo Carvalho de Melo sym = sym_entry__symbol(syme); 634923c42c1SMike Galbraith if (++printed > print_entries || (int)syme->snap_count < count_filter) 63586470930SIngo Molnar continue; 63686470930SIngo Molnar 63786470930SIngo Molnar pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 63886470930SIngo Molnar sum_ksamples)); 63986470930SIngo Molnar 640361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 1 || !display_weighted) 6415b2bb75aSArnaldo Carvalho de Melo printf("%20.2f ", syme->weight); 64286470930SIngo Molnar else 6435b2bb75aSArnaldo Carvalho de Melo printf("%9.1f %10ld ", syme->weight, syme->snap_count); 64486470930SIngo Molnar 6451e11fd82SFrederic Weisbecker percent_color_fprintf(stdout, "%4.1f%%", pcnt); 6467ced156bSArnaldo Carvalho de Melo if (verbose) 6479486aa38SArnaldo Carvalho de Melo printf(" %016" PRIx64, sym->start); 64813cc5079SArnaldo Carvalho de Melo printf(" %-*.*s", sym_width, sym_width, sym->name); 6497cc017edSArnaldo Carvalho de Melo printf(" %-*.*s\n", dso_width, dso_width, 65013cc5079SArnaldo Carvalho de Melo dso_width >= syme->map->dso->long_name_len ? 65113cc5079SArnaldo Carvalho de Melo syme->map->dso->long_name : 65213cc5079SArnaldo Carvalho de Melo syme->map->dso->short_name); 65386470930SIngo Molnar } 65486470930SIngo Molnar } 65586470930SIngo Molnar 656923c42c1SMike Galbraith static void prompt_integer(int *target, const char *msg) 657923c42c1SMike Galbraith { 658923c42c1SMike Galbraith char *buf = malloc(0), *p; 659923c42c1SMike Galbraith size_t dummy = 0; 660923c42c1SMike Galbraith int tmp; 661923c42c1SMike Galbraith 662923c42c1SMike Galbraith fprintf(stdout, "\n%s: ", msg); 663923c42c1SMike Galbraith if (getline(&buf, &dummy, stdin) < 0) 664923c42c1SMike Galbraith return; 665923c42c1SMike Galbraith 666923c42c1SMike Galbraith p = strchr(buf, '\n'); 667923c42c1SMike Galbraith if (p) 668923c42c1SMike Galbraith *p = 0; 669923c42c1SMike Galbraith 670923c42c1SMike Galbraith p = buf; 671923c42c1SMike Galbraith while(*p) { 672923c42c1SMike Galbraith if (!isdigit(*p)) 673923c42c1SMike Galbraith goto out_free; 674923c42c1SMike Galbraith p++; 675923c42c1SMike Galbraith } 676923c42c1SMike Galbraith tmp = strtoul(buf, NULL, 10); 677923c42c1SMike Galbraith *target = tmp; 678923c42c1SMike Galbraith out_free: 679923c42c1SMike Galbraith free(buf); 680923c42c1SMike Galbraith } 681923c42c1SMike Galbraith 682923c42c1SMike Galbraith static void prompt_percent(int *target, const char *msg) 683923c42c1SMike Galbraith { 684923c42c1SMike Galbraith int tmp = 0; 685923c42c1SMike Galbraith 686923c42c1SMike Galbraith prompt_integer(&tmp, msg); 687923c42c1SMike Galbraith if (tmp >= 0 && tmp <= 100) 688923c42c1SMike Galbraith *target = tmp; 689923c42c1SMike Galbraith } 690923c42c1SMike Galbraith 691923c42c1SMike Galbraith static void prompt_symbol(struct sym_entry **target, const char *msg) 692923c42c1SMike Galbraith { 693923c42c1SMike Galbraith char *buf = malloc(0), *p; 694923c42c1SMike Galbraith struct sym_entry *syme = *target, *n, *found = NULL; 695923c42c1SMike Galbraith size_t dummy = 0; 696923c42c1SMike Galbraith 697923c42c1SMike Galbraith /* zero counters of active symbol */ 698923c42c1SMike Galbraith if (syme) { 699b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&syme->src->lock); 700923c42c1SMike Galbraith __zero_source_counters(syme); 701923c42c1SMike Galbraith *target = NULL; 702b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&syme->src->lock); 703923c42c1SMike Galbraith } 704923c42c1SMike Galbraith 705923c42c1SMike Galbraith fprintf(stdout, "\n%s: ", msg); 706923c42c1SMike Galbraith if (getline(&buf, &dummy, stdin) < 0) 707923c42c1SMike Galbraith goto out_free; 708923c42c1SMike Galbraith 709923c42c1SMike Galbraith p = strchr(buf, '\n'); 710923c42c1SMike Galbraith if (p) 711923c42c1SMike Galbraith *p = 0; 712923c42c1SMike Galbraith 713923c42c1SMike Galbraith pthread_mutex_lock(&active_symbols_lock); 714923c42c1SMike Galbraith syme = list_entry(active_symbols.next, struct sym_entry, node); 715923c42c1SMike Galbraith pthread_mutex_unlock(&active_symbols_lock); 716923c42c1SMike Galbraith 717923c42c1SMike Galbraith list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 71851a472deSArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(syme); 719923c42c1SMike Galbraith 720923c42c1SMike Galbraith if (!strcmp(buf, sym->name)) { 721923c42c1SMike Galbraith found = syme; 722923c42c1SMike Galbraith break; 723923c42c1SMike Galbraith } 724923c42c1SMike Galbraith } 725923c42c1SMike Galbraith 726923c42c1SMike Galbraith if (!found) { 72766aeb6d5SKirill Smelkov fprintf(stderr, "Sorry, %s is not active.\n", buf); 728923c42c1SMike Galbraith sleep(1); 729923c42c1SMike Galbraith return; 730923c42c1SMike Galbraith } else 731923c42c1SMike Galbraith parse_source(found); 732923c42c1SMike Galbraith 733923c42c1SMike Galbraith out_free: 734923c42c1SMike Galbraith free(buf); 735923c42c1SMike Galbraith } 736923c42c1SMike Galbraith 737091bd2e9SMike Galbraith static void print_mapped_keys(void) 738923c42c1SMike Galbraith { 739091bd2e9SMike Galbraith char *name = NULL; 740091bd2e9SMike Galbraith 741091bd2e9SMike Galbraith if (sym_filter_entry) { 74251a472deSArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(sym_filter_entry); 743091bd2e9SMike Galbraith name = sym->name; 744091bd2e9SMike Galbraith } 745091bd2e9SMike Galbraith 746091bd2e9SMike Galbraith fprintf(stdout, "\nMapped keys:\n"); 747091bd2e9SMike Galbraith fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); 748091bd2e9SMike Galbraith fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 749091bd2e9SMike Galbraith 750361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries > 1) 75169aad6f1SArnaldo Carvalho de Melo fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); 752091bd2e9SMike Galbraith 753091bd2e9SMike Galbraith fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 754091bd2e9SMike Galbraith 755091bd2e9SMike Galbraith fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 756091bd2e9SMike Galbraith fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 757091bd2e9SMike Galbraith fprintf(stdout, "\t[S] stop annotation.\n"); 758091bd2e9SMike Galbraith 759361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries > 1) 76046ab9764SMike Galbraith fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 761091bd2e9SMike Galbraith 7628ffcda17SArnaldo Carvalho de Melo fprintf(stdout, 7638ffcda17SArnaldo Carvalho de Melo "\t[K] hide kernel_symbols symbols. \t(%s)\n", 7648ffcda17SArnaldo Carvalho de Melo hide_kernel_symbols ? "yes" : "no"); 7658ffcda17SArnaldo Carvalho de Melo fprintf(stdout, 7668ffcda17SArnaldo Carvalho de Melo "\t[U] hide user symbols. \t(%s)\n", 7678ffcda17SArnaldo Carvalho de Melo hide_user_symbols ? "yes" : "no"); 76846ab9764SMike Galbraith fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); 769091bd2e9SMike Galbraith fprintf(stdout, "\t[qQ] quit.\n"); 770091bd2e9SMike Galbraith } 771091bd2e9SMike Galbraith 772091bd2e9SMike Galbraith static int key_mapped(int c) 773091bd2e9SMike Galbraith { 774091bd2e9SMike Galbraith switch (c) { 775091bd2e9SMike Galbraith case 'd': 776091bd2e9SMike Galbraith case 'e': 777091bd2e9SMike Galbraith case 'f': 778091bd2e9SMike Galbraith case 'z': 779091bd2e9SMike Galbraith case 'q': 780091bd2e9SMike Galbraith case 'Q': 7818ffcda17SArnaldo Carvalho de Melo case 'K': 7828ffcda17SArnaldo Carvalho de Melo case 'U': 7836cff0e8dSKirill Smelkov case 'F': 7846cff0e8dSKirill Smelkov case 's': 7856cff0e8dSKirill Smelkov case 'S': 786091bd2e9SMike Galbraith return 1; 787091bd2e9SMike Galbraith case 'E': 788091bd2e9SMike Galbraith case 'w': 789361c99a6SArnaldo Carvalho de Melo return evsel_list->nr_entries > 1 ? 1 : 0; 79083a0944fSIngo Molnar default: 79183a0944fSIngo Molnar break; 792091bd2e9SMike Galbraith } 793091bd2e9SMike Galbraith 794091bd2e9SMike Galbraith return 0; 795923c42c1SMike Galbraith } 796923c42c1SMike Galbraith 797a1645ce1SZhang, Yanmin static void handle_keypress(struct perf_session *session, int c) 798923c42c1SMike Galbraith { 799091bd2e9SMike Galbraith if (!key_mapped(c)) { 800091bd2e9SMike Galbraith struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 801091bd2e9SMike Galbraith struct termios tc, save; 802091bd2e9SMike Galbraith 803091bd2e9SMike Galbraith print_mapped_keys(); 804091bd2e9SMike Galbraith fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 805091bd2e9SMike Galbraith fflush(stdout); 806091bd2e9SMike Galbraith 807091bd2e9SMike Galbraith tcgetattr(0, &save); 808091bd2e9SMike Galbraith tc = save; 809091bd2e9SMike Galbraith tc.c_lflag &= ~(ICANON | ECHO); 810091bd2e9SMike Galbraith tc.c_cc[VMIN] = 0; 811091bd2e9SMike Galbraith tc.c_cc[VTIME] = 0; 812091bd2e9SMike Galbraith tcsetattr(0, TCSANOW, &tc); 813091bd2e9SMike Galbraith 814091bd2e9SMike Galbraith poll(&stdin_poll, 1, -1); 815091bd2e9SMike Galbraith c = getc(stdin); 816091bd2e9SMike Galbraith 817091bd2e9SMike Galbraith tcsetattr(0, TCSAFLUSH, &save); 818091bd2e9SMike Galbraith if (!key_mapped(c)) 819091bd2e9SMike Galbraith return; 820091bd2e9SMike Galbraith } 821091bd2e9SMike Galbraith 822923c42c1SMike Galbraith switch (c) { 823923c42c1SMike Galbraith case 'd': 824923c42c1SMike Galbraith prompt_integer(&delay_secs, "Enter display delay"); 825dc79959aSTim Blechmann if (delay_secs < 1) 826dc79959aSTim Blechmann delay_secs = 1; 827923c42c1SMike Galbraith break; 828923c42c1SMike Galbraith case 'e': 829923c42c1SMike Galbraith prompt_integer(&print_entries, "Enter display entries (lines)"); 8303b6ed988SArnaldo Carvalho de Melo if (print_entries == 0) { 83113cc5079SArnaldo Carvalho de Melo sig_winch_handler(SIGWINCH); 8323b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, sig_winch_handler); 8333b6ed988SArnaldo Carvalho de Melo } else 8343b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, SIG_DFL); 835923c42c1SMike Galbraith break; 836923c42c1SMike Galbraith case 'E': 837361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries > 1) { 838923c42c1SMike Galbraith fprintf(stderr, "\nAvailable events:"); 83969aad6f1SArnaldo Carvalho de Melo 840361c99a6SArnaldo Carvalho de Melo list_for_each_entry(sym_evsel, &evsel_list->entries, node) 84169aad6f1SArnaldo Carvalho de Melo fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); 842923c42c1SMike Galbraith 843923c42c1SMike Galbraith prompt_integer(&sym_counter, "Enter details event counter"); 844923c42c1SMike Galbraith 845361c99a6SArnaldo Carvalho de Melo if (sym_counter >= evsel_list->nr_entries) { 846361c99a6SArnaldo Carvalho de Melo sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node); 847923c42c1SMike Galbraith sym_counter = 0; 84869aad6f1SArnaldo Carvalho de Melo fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); 849923c42c1SMike Galbraith sleep(1); 85069aad6f1SArnaldo Carvalho de Melo break; 851923c42c1SMike Galbraith } 852361c99a6SArnaldo Carvalho de Melo list_for_each_entry(sym_evsel, &evsel_list->entries, node) 85369aad6f1SArnaldo Carvalho de Melo if (sym_evsel->idx == sym_counter) 85469aad6f1SArnaldo Carvalho de Melo break; 855923c42c1SMike Galbraith } else sym_counter = 0; 856923c42c1SMike Galbraith break; 857923c42c1SMike Galbraith case 'f': 858923c42c1SMike Galbraith prompt_integer(&count_filter, "Enter display event count filter"); 859923c42c1SMike Galbraith break; 860923c42c1SMike Galbraith case 'F': 861923c42c1SMike Galbraith prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 862923c42c1SMike Galbraith break; 8638ffcda17SArnaldo Carvalho de Melo case 'K': 8648ffcda17SArnaldo Carvalho de Melo hide_kernel_symbols = !hide_kernel_symbols; 8658ffcda17SArnaldo Carvalho de Melo break; 866923c42c1SMike Galbraith case 'q': 867923c42c1SMike Galbraith case 'Q': 868923c42c1SMike Galbraith printf("exiting.\n"); 869c338aee8SArnaldo Carvalho de Melo if (dump_symtab) 870cbf69680SArnaldo Carvalho de Melo perf_session__fprintf_dsos(session, stderr); 871923c42c1SMike Galbraith exit(0); 872923c42c1SMike Galbraith case 's': 873923c42c1SMike Galbraith prompt_symbol(&sym_filter_entry, "Enter details symbol"); 874923c42c1SMike Galbraith break; 875923c42c1SMike Galbraith case 'S': 876923c42c1SMike Galbraith if (!sym_filter_entry) 877923c42c1SMike Galbraith break; 878923c42c1SMike Galbraith else { 879923c42c1SMike Galbraith struct sym_entry *syme = sym_filter_entry; 880923c42c1SMike Galbraith 881b269876cSArnaldo Carvalho de Melo pthread_mutex_lock(&syme->src->lock); 882923c42c1SMike Galbraith sym_filter_entry = NULL; 883923c42c1SMike Galbraith __zero_source_counters(syme); 884b269876cSArnaldo Carvalho de Melo pthread_mutex_unlock(&syme->src->lock); 885923c42c1SMike Galbraith } 886923c42c1SMike Galbraith break; 8878ffcda17SArnaldo Carvalho de Melo case 'U': 8888ffcda17SArnaldo Carvalho de Melo hide_user_symbols = !hide_user_symbols; 8898ffcda17SArnaldo Carvalho de Melo break; 89046ab9764SMike Galbraith case 'w': 89146ab9764SMike Galbraith display_weighted = ~display_weighted; 89246ab9764SMike Galbraith break; 893923c42c1SMike Galbraith case 'z': 894c0555642SIan Munsie zero = !zero; 895923c42c1SMike Galbraith break; 89683a0944fSIngo Molnar default: 89783a0944fSIngo Molnar break; 898923c42c1SMike Galbraith } 899923c42c1SMike Galbraith } 900923c42c1SMike Galbraith 901f37a291cSIngo Molnar static void *display_thread(void *arg __used) 90286470930SIngo Molnar { 90386470930SIngo Molnar struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 904923c42c1SMike Galbraith struct termios tc, save; 905923c42c1SMike Galbraith int delay_msecs, c; 906a1645ce1SZhang, Yanmin struct perf_session *session = (struct perf_session *) arg; 90786470930SIngo Molnar 908923c42c1SMike Galbraith tcgetattr(0, &save); 909923c42c1SMike Galbraith tc = save; 910923c42c1SMike Galbraith tc.c_lflag &= ~(ICANON | ECHO); 911923c42c1SMike Galbraith tc.c_cc[VMIN] = 0; 912923c42c1SMike Galbraith tc.c_cc[VTIME] = 0; 913091bd2e9SMike Galbraith 914923c42c1SMike Galbraith repeat: 915923c42c1SMike Galbraith delay_msecs = delay_secs * 1000; 916923c42c1SMike Galbraith tcsetattr(0, TCSANOW, &tc); 917923c42c1SMike Galbraith /* trash return*/ 918923c42c1SMike Galbraith getc(stdin); 91986470930SIngo Molnar 92086470930SIngo Molnar do { 92186470930SIngo Molnar print_sym_table(); 92286470930SIngo Molnar } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 92386470930SIngo Molnar 924923c42c1SMike Galbraith c = getc(stdin); 925923c42c1SMike Galbraith tcsetattr(0, TCSAFLUSH, &save); 926923c42c1SMike Galbraith 927a1645ce1SZhang, Yanmin handle_keypress(session, c); 928923c42c1SMike Galbraith goto repeat; 92986470930SIngo Molnar 93086470930SIngo Molnar return NULL; 93186470930SIngo Molnar } 93286470930SIngo Molnar 9332ab52083SAnton Blanchard /* Tag samples to be skipped. */ 934f37a291cSIngo Molnar static const char *skip_symbols[] = { 9352ab52083SAnton Blanchard "default_idle", 936b0e8572fSArnaldo Carvalho de Melo "native_safe_halt", 9372ab52083SAnton Blanchard "cpu_idle", 9382ab52083SAnton Blanchard "enter_idle", 9392ab52083SAnton Blanchard "exit_idle", 9402ab52083SAnton Blanchard "mwait_idle", 94159b90056SArnaldo Carvalho de Melo "mwait_idle_with_hints", 9428357275bSArnaldo Carvalho de Melo "poll_idle", 9433a3393efSAnton Blanchard "ppc64_runlatch_off", 9443a3393efSAnton Blanchard "pseries_dedicated_idle_sleep", 9452ab52083SAnton Blanchard NULL 9462ab52083SAnton Blanchard }; 9472ab52083SAnton Blanchard 948439d473bSArnaldo Carvalho de Melo static int symbol_filter(struct map *map, struct symbol *sym) 94986470930SIngo Molnar { 95086470930SIngo Molnar struct sym_entry *syme; 95186470930SIngo Molnar const char *name = sym->name; 9522ab52083SAnton Blanchard int i; 95386470930SIngo Molnar 9543a3393efSAnton Blanchard /* 9553a3393efSAnton Blanchard * ppc64 uses function descriptors and appends a '.' to the 9563a3393efSAnton Blanchard * start of every instruction address. Remove it. 9573a3393efSAnton Blanchard */ 9583a3393efSAnton Blanchard if (name[0] == '.') 9593a3393efSAnton Blanchard name++; 9603a3393efSAnton Blanchard 96186470930SIngo Molnar if (!strcmp(name, "_text") || 96286470930SIngo Molnar !strcmp(name, "_etext") || 96386470930SIngo Molnar !strcmp(name, "_sinittext") || 96486470930SIngo Molnar !strncmp("init_module", name, 11) || 96586470930SIngo Molnar !strncmp("cleanup_module", name, 14) || 96686470930SIngo Molnar strstr(name, "_text_start") || 96786470930SIngo Molnar strstr(name, "_text_end")) 96886470930SIngo Molnar return 1; 96986470930SIngo Molnar 97000a192b3SArnaldo Carvalho de Melo syme = symbol__priv(sym); 971439d473bSArnaldo Carvalho de Melo syme->map = map; 972b269876cSArnaldo Carvalho de Melo syme->src = NULL; 9736cff0e8dSKirill Smelkov 9746cff0e8dSKirill Smelkov if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { 9756cff0e8dSKirill Smelkov /* schedule initial sym_filter_entry setup */ 9766cff0e8dSKirill Smelkov sym_filter_entry_sched = syme; 9776cff0e8dSKirill Smelkov sym_filter = NULL; 9786cff0e8dSKirill Smelkov } 979923c42c1SMike Galbraith 9802ab52083SAnton Blanchard for (i = 0; skip_symbols[i]; i++) { 9812ab52083SAnton Blanchard if (!strcmp(skip_symbols[i], name)) { 98286470930SIngo Molnar syme->skip = 1; 9832ab52083SAnton Blanchard break; 9842ab52083SAnton Blanchard } 9852ab52083SAnton Blanchard } 98686470930SIngo Molnar 98713cc5079SArnaldo Carvalho de Melo if (!syme->skip) 98813cc5079SArnaldo Carvalho de Melo syme->name_len = strlen(sym->name); 98913cc5079SArnaldo Carvalho de Melo 99086470930SIngo Molnar return 0; 99186470930SIngo Molnar } 99286470930SIngo Molnar 993b3165f41SArnaldo Carvalho de Melo static void event__process_sample(const event_t *self, 9949c90a61cSArnaldo Carvalho de Melo struct sample_data *sample, 99570db7533SArnaldo Carvalho de Melo struct perf_session *session) 99686470930SIngo Molnar { 9975b2bb75aSArnaldo Carvalho de Melo u64 ip = self->ip.ip; 9985b2bb75aSArnaldo Carvalho de Melo struct sym_entry *syme; 9991ed091c4SArnaldo Carvalho de Melo struct addr_location al; 100023346f21SArnaldo Carvalho de Melo struct machine *machine; 10018ffcda17SArnaldo Carvalho de Melo u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 100286470930SIngo Molnar 100324bfef0fSArnaldo Carvalho de Melo ++samples; 100424bfef0fSArnaldo Carvalho de Melo 10058ffcda17SArnaldo Carvalho de Melo switch (origin) { 10061ed091c4SArnaldo Carvalho de Melo case PERF_RECORD_MISC_USER: 1007a1645ce1SZhang, Yanmin ++us_samples; 10088ffcda17SArnaldo Carvalho de Melo if (hide_user_symbols) 10098ffcda17SArnaldo Carvalho de Melo return; 101023346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 10115b2bb75aSArnaldo Carvalho de Melo break; 10125b2bb75aSArnaldo Carvalho de Melo case PERF_RECORD_MISC_KERNEL: 1013a1645ce1SZhang, Yanmin ++kernel_samples; 10148ffcda17SArnaldo Carvalho de Melo if (hide_kernel_symbols) 10158ffcda17SArnaldo Carvalho de Melo return; 101623346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 10175b2bb75aSArnaldo Carvalho de Melo break; 1018a1645ce1SZhang, Yanmin case PERF_RECORD_MISC_GUEST_KERNEL: 1019a1645ce1SZhang, Yanmin ++guest_kernel_samples; 102023346f21SArnaldo Carvalho de Melo machine = perf_session__find_machine(session, self->ip.pid); 1021a1645ce1SZhang, Yanmin break; 1022a1645ce1SZhang, Yanmin case PERF_RECORD_MISC_GUEST_USER: 1023a1645ce1SZhang, Yanmin ++guest_us_samples; 1024a1645ce1SZhang, Yanmin /* 1025a1645ce1SZhang, Yanmin * TODO: we don't process guest user from host side 1026a1645ce1SZhang, Yanmin * except simple counting. 1027a1645ce1SZhang, Yanmin */ 1028a1645ce1SZhang, Yanmin return; 10295b2bb75aSArnaldo Carvalho de Melo default: 10305b2bb75aSArnaldo Carvalho de Melo return; 10315b2bb75aSArnaldo Carvalho de Melo } 10325b2bb75aSArnaldo Carvalho de Melo 103323346f21SArnaldo Carvalho de Melo if (!machine && perf_guest) { 1034a1645ce1SZhang, Yanmin pr_err("Can't find guest [%d]'s kernel information\n", 1035a1645ce1SZhang, Yanmin self->ip.pid); 1036a1645ce1SZhang, Yanmin return; 1037a1645ce1SZhang, Yanmin } 1038a1645ce1SZhang, Yanmin 1039ab608344SPeter Zijlstra if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 10401676b8a0SPeter Zijlstra exact_samples++; 10411676b8a0SPeter Zijlstra 10429c90a61cSArnaldo Carvalho de Melo if (event__preprocess_sample(self, session, &al, sample, 104341a37e20SArnaldo Carvalho de Melo symbol_filter) < 0 || 104472b8fa17SArnaldo Carvalho de Melo al.filtered) 10451ed091c4SArnaldo Carvalho de Melo return; 104686470930SIngo Molnar 104772b8fa17SArnaldo Carvalho de Melo if (al.sym == NULL) { 104872b8fa17SArnaldo Carvalho de Melo /* 104972b8fa17SArnaldo Carvalho de Melo * As we do lazy loading of symtabs we only will know if the 105072b8fa17SArnaldo Carvalho de Melo * specified vmlinux file is invalid when we actually have a 105172b8fa17SArnaldo Carvalho de Melo * hit in kernel space and then try to load it. So if we get 105272b8fa17SArnaldo Carvalho de Melo * here and there are _no_ symbols in the DSO backing the 105372b8fa17SArnaldo Carvalho de Melo * kernel map, bail out. 105472b8fa17SArnaldo Carvalho de Melo * 105572b8fa17SArnaldo Carvalho de Melo * We may never get here, for instance, if we use -K/ 105672b8fa17SArnaldo Carvalho de Melo * --hide-kernel-symbols, even if the user specifies an 105772b8fa17SArnaldo Carvalho de Melo * invalid --vmlinux ;-) 105872b8fa17SArnaldo Carvalho de Melo */ 105923346f21SArnaldo Carvalho de Melo if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && 106072b8fa17SArnaldo Carvalho de Melo RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 106172b8fa17SArnaldo Carvalho de Melo pr_err("The %s file can't be used\n", 106272b8fa17SArnaldo Carvalho de Melo symbol_conf.vmlinux_name); 106372b8fa17SArnaldo Carvalho de Melo exit(1); 106472b8fa17SArnaldo Carvalho de Melo } 106572b8fa17SArnaldo Carvalho de Melo 106672b8fa17SArnaldo Carvalho de Melo return; 106772b8fa17SArnaldo Carvalho de Melo } 106872b8fa17SArnaldo Carvalho de Melo 10696cff0e8dSKirill Smelkov /* let's see, whether we need to install initial sym_filter_entry */ 10706cff0e8dSKirill Smelkov if (sym_filter_entry_sched) { 10716cff0e8dSKirill Smelkov sym_filter_entry = sym_filter_entry_sched; 10726cff0e8dSKirill Smelkov sym_filter_entry_sched = NULL; 1073b0a9ab62SArnaldo Carvalho de Melo if (parse_source(sym_filter_entry) < 0) { 1074b0a9ab62SArnaldo Carvalho de Melo struct symbol *sym = sym_entry__symbol(sym_filter_entry); 1075b0a9ab62SArnaldo Carvalho de Melo 1076b0a9ab62SArnaldo Carvalho de Melo pr_err("Can't annotate %s", sym->name); 1077b0a9ab62SArnaldo Carvalho de Melo if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { 1078b0a9ab62SArnaldo Carvalho de Melo pr_err(": No vmlinux file was found in the path:\n"); 10795ad90e4eSArnaldo Carvalho de Melo machine__fprintf_vmlinux_path(machine, stderr); 1080b0a9ab62SArnaldo Carvalho de Melo } else 1081b0a9ab62SArnaldo Carvalho de Melo pr_err(".\n"); 1082b0a9ab62SArnaldo Carvalho de Melo exit(1); 1083b0a9ab62SArnaldo Carvalho de Melo } 10846cff0e8dSKirill Smelkov } 10856cff0e8dSKirill Smelkov 10861ed091c4SArnaldo Carvalho de Melo syme = symbol__priv(al.sym); 108786470930SIngo Molnar if (!syme->skip) { 108870db7533SArnaldo Carvalho de Melo struct perf_evsel *evsel; 108970db7533SArnaldo Carvalho de Melo 10908ffcda17SArnaldo Carvalho de Melo syme->origin = origin; 109170db7533SArnaldo Carvalho de Melo evsel = perf_evlist__id2evsel(evsel_list, sample->id); 109270db7533SArnaldo Carvalho de Melo assert(evsel != NULL); 109370db7533SArnaldo Carvalho de Melo syme->count[evsel->idx]++; 109469aad6f1SArnaldo Carvalho de Melo record_precise_ip(syme, evsel->idx, ip); 109586470930SIngo Molnar pthread_mutex_lock(&active_symbols_lock); 109686470930SIngo Molnar if (list_empty(&syme->node) || !syme->node.next) 109786470930SIngo Molnar __list_insert_active_sym(syme); 109886470930SIngo Molnar pthread_mutex_unlock(&active_symbols_lock); 109986470930SIngo Molnar } 110086470930SIngo Molnar } 110186470930SIngo Molnar 110270db7533SArnaldo Carvalho de Melo static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu) 110386470930SIngo Molnar { 11049c90a61cSArnaldo Carvalho de Melo struct sample_data sample; 110504391debSArnaldo Carvalho de Melo event_t *event; 110686470930SIngo Molnar 110704391debSArnaldo Carvalho de Melo while ((event = perf_evlist__read_on_cpu(evsel_list, cpu)) != NULL) { 11089c90a61cSArnaldo Carvalho de Melo event__parse_sample(event, self, &sample); 110904391debSArnaldo Carvalho de Melo 11105b2bb75aSArnaldo Carvalho de Melo if (event->header.type == PERF_RECORD_SAMPLE) 111170db7533SArnaldo Carvalho de Melo event__process_sample(event, &sample, self); 11125b2bb75aSArnaldo Carvalho de Melo else 11139c90a61cSArnaldo Carvalho de Melo event__process(event, &sample, self); 111486470930SIngo Molnar } 111586470930SIngo Molnar } 111686470930SIngo Molnar 1117d8f66248SArnaldo Carvalho de Melo static void perf_session__mmap_read(struct perf_session *self) 11182f01190aSFrederic Weisbecker { 111970db7533SArnaldo Carvalho de Melo int i; 11202f01190aSFrederic Weisbecker 112170db7533SArnaldo Carvalho de Melo for (i = 0; i < cpus->nr; i++) 112270db7533SArnaldo Carvalho de Melo perf_session__mmap_read_cpu(self, i); 11232f01190aSFrederic Weisbecker } 11242f01190aSFrederic Weisbecker 112572cb7013SArnaldo Carvalho de Melo static void start_counters(struct perf_evlist *evlist) 112672cb7013SArnaldo Carvalho de Melo { 112772cb7013SArnaldo Carvalho de Melo struct perf_evsel *counter; 112872cb7013SArnaldo Carvalho de Melo 112972cb7013SArnaldo Carvalho de Melo list_for_each_entry(counter, &evlist->entries, node) { 113072cb7013SArnaldo Carvalho de Melo struct perf_event_attr *attr = &counter->attr; 113172cb7013SArnaldo Carvalho de Melo 113272cb7013SArnaldo Carvalho de Melo attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 113372cb7013SArnaldo Carvalho de Melo 113472cb7013SArnaldo Carvalho de Melo if (freq) { 113572cb7013SArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_PERIOD; 113672cb7013SArnaldo Carvalho de Melo attr->freq = 1; 113772cb7013SArnaldo Carvalho de Melo attr->sample_freq = freq; 113872cb7013SArnaldo Carvalho de Melo } 113972cb7013SArnaldo Carvalho de Melo 114070db7533SArnaldo Carvalho de Melo if (evlist->nr_entries > 1) { 114170db7533SArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_ID; 114270db7533SArnaldo Carvalho de Melo attr->read_format |= PERF_FORMAT_ID; 114370db7533SArnaldo Carvalho de Melo } 114470db7533SArnaldo Carvalho de Melo 114572cb7013SArnaldo Carvalho de Melo attr->mmap = 1; 114672cb7013SArnaldo Carvalho de Melo try_again: 114772cb7013SArnaldo Carvalho de Melo if (perf_evsel__open(counter, cpus, threads, group, inherit) < 0) { 114872cb7013SArnaldo Carvalho de Melo int err = errno; 114972cb7013SArnaldo Carvalho de Melo 115072cb7013SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) 115172cb7013SArnaldo Carvalho de Melo die("Permission error - are you root?\n" 115272cb7013SArnaldo Carvalho de Melo "\t Consider tweaking" 115372cb7013SArnaldo Carvalho de Melo " /proc/sys/kernel/perf_event_paranoid.\n"); 115472cb7013SArnaldo Carvalho de Melo /* 115572cb7013SArnaldo Carvalho de Melo * If it's cycles then fall back to hrtimer 115672cb7013SArnaldo Carvalho de Melo * based cpu-clock-tick sw counter, which 115772cb7013SArnaldo Carvalho de Melo * is always available even if no PMU support: 115872cb7013SArnaldo Carvalho de Melo */ 115972cb7013SArnaldo Carvalho de Melo if (attr->type == PERF_TYPE_HARDWARE && 116072cb7013SArnaldo Carvalho de Melo attr->config == PERF_COUNT_HW_CPU_CYCLES) { 116172cb7013SArnaldo Carvalho de Melo 116272cb7013SArnaldo Carvalho de Melo if (verbose) 116372cb7013SArnaldo Carvalho de Melo warning(" ... trying to fall back to cpu-clock-ticks\n"); 116472cb7013SArnaldo Carvalho de Melo 116572cb7013SArnaldo Carvalho de Melo attr->type = PERF_TYPE_SOFTWARE; 116672cb7013SArnaldo Carvalho de Melo attr->config = PERF_COUNT_SW_CPU_CLOCK; 116772cb7013SArnaldo Carvalho de Melo goto try_again; 116872cb7013SArnaldo Carvalho de Melo } 116972cb7013SArnaldo Carvalho de Melo printf("\n"); 117072cb7013SArnaldo Carvalho de Melo error("sys_perf_event_open() syscall returned with %d " 117172cb7013SArnaldo Carvalho de Melo "(%s). /bin/dmesg may provide additional information.\n", 117272cb7013SArnaldo Carvalho de Melo err, strerror(err)); 117372cb7013SArnaldo Carvalho de Melo die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 117472cb7013SArnaldo Carvalho de Melo exit(-1); 117572cb7013SArnaldo Carvalho de Melo } 117672cb7013SArnaldo Carvalho de Melo } 117770db7533SArnaldo Carvalho de Melo 117870db7533SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, cpus, threads, mmap_pages, true) < 0) 117970db7533SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 118072cb7013SArnaldo Carvalho de Melo } 118172cb7013SArnaldo Carvalho de Melo 1182716c69feSIngo Molnar static int __cmd_top(void) 1183716c69feSIngo Molnar { 1184716c69feSIngo Molnar pthread_t thread; 118570db7533SArnaldo Carvalho de Melo struct perf_evsel *first; 118672cb7013SArnaldo Carvalho de Melo int ret; 1187d8f66248SArnaldo Carvalho de Melo /* 1188b3165f41SArnaldo Carvalho de Melo * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1189b3165f41SArnaldo Carvalho de Melo * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1190d8f66248SArnaldo Carvalho de Melo */ 119121ef97f0SIan Munsie struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL); 1192b3165f41SArnaldo Carvalho de Melo if (session == NULL) 1193b3165f41SArnaldo Carvalho de Melo return -ENOMEM; 1194716c69feSIngo Molnar 1195d6d901c2SZhang, Yanmin if (target_tid != -1) 1196d6d901c2SZhang, Yanmin event__synthesize_thread(target_tid, event__process, session); 11975b2bb75aSArnaldo Carvalho de Melo else 1198d8f66248SArnaldo Carvalho de Melo event__synthesize_threads(event__process, session); 11995b2bb75aSArnaldo Carvalho de Melo 120072cb7013SArnaldo Carvalho de Melo start_counters(evsel_list); 120170db7533SArnaldo Carvalho de Melo first = list_entry(evsel_list->entries.next, struct perf_evsel, node); 120270db7533SArnaldo Carvalho de Melo perf_session__set_sample_type(session, first->attr.sample_type); 120386470930SIngo Molnar 12042f01190aSFrederic Weisbecker /* Wait for a minimal set of events before starting the snapshot */ 12055c581041SArnaldo Carvalho de Melo poll(evsel_list->pollfd, evsel_list->nr_fds, 100); 12062f01190aSFrederic Weisbecker 1207d8f66248SArnaldo Carvalho de Melo perf_session__mmap_read(session); 12082f01190aSFrederic Weisbecker 1209a1645ce1SZhang, Yanmin if (pthread_create(&thread, NULL, display_thread, session)) { 121086470930SIngo Molnar printf("Could not create display thread.\n"); 121186470930SIngo Molnar exit(-1); 121286470930SIngo Molnar } 121386470930SIngo Molnar 121486470930SIngo Molnar if (realtime_prio) { 121586470930SIngo Molnar struct sched_param param; 121686470930SIngo Molnar 121786470930SIngo Molnar param.sched_priority = realtime_prio; 121886470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 121986470930SIngo Molnar printf("Could not set realtime priority.\n"); 122086470930SIngo Molnar exit(-1); 122186470930SIngo Molnar } 122286470930SIngo Molnar } 122386470930SIngo Molnar 122486470930SIngo Molnar while (1) { 122586470930SIngo Molnar int hits = samples; 122686470930SIngo Molnar 1227d8f66248SArnaldo Carvalho de Melo perf_session__mmap_read(session); 122886470930SIngo Molnar 122986470930SIngo Molnar if (hits == samples) 12305c581041SArnaldo Carvalho de Melo ret = poll(evsel_list->pollfd, evsel_list->nr_fds, 100); 123186470930SIngo Molnar } 123286470930SIngo Molnar 123386470930SIngo Molnar return 0; 123486470930SIngo Molnar } 123586470930SIngo Molnar 123686470930SIngo Molnar static const char * const top_usage[] = { 123786470930SIngo Molnar "perf top [<options>]", 123886470930SIngo Molnar NULL 123986470930SIngo Molnar }; 124086470930SIngo Molnar 124186470930SIngo Molnar static const struct option options[] = { 1242361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 124386470930SIngo Molnar "event selector. use 'perf list' to list available events", 124486470930SIngo Molnar parse_events), 124586470930SIngo Molnar OPT_INTEGER('c', "count", &default_interval, 124686470930SIngo Molnar "event period to sample"), 124786470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 1248d6d901c2SZhang, Yanmin "profile events on existing process id"), 1249d6d901c2SZhang, Yanmin OPT_INTEGER('t', "tid", &target_tid, 1250d6d901c2SZhang, Yanmin "profile events on existing thread id"), 125186470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 125286470930SIngo Molnar "system-wide collection from all CPUs"), 1253c45c6ea2SStephane Eranian OPT_STRING('C', "cpu", &cpu_list, "cpu", 1254c45c6ea2SStephane Eranian "list of cpus to monitor"), 1255b32d133aSArnaldo Carvalho de Melo OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1256b32d133aSArnaldo Carvalho de Melo "file", "vmlinux pathname"), 12578ffcda17SArnaldo Carvalho de Melo OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, 12588ffcda17SArnaldo Carvalho de Melo "hide kernel symbols"), 12591967936dSArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 126086470930SIngo Molnar OPT_INTEGER('r', "realtime", &realtime_prio, 126186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 126286470930SIngo Molnar OPT_INTEGER('d', "delay", &delay_secs, 126386470930SIngo Molnar "number of seconds to delay between refreshes"), 126486470930SIngo Molnar OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, 126586470930SIngo Molnar "dump the symbol table used for profiling"), 126686470930SIngo Molnar OPT_INTEGER('f', "count-filter", &count_filter, 126786470930SIngo Molnar "only display functions with more events than this"), 126886470930SIngo Molnar OPT_BOOLEAN('g', "group", &group, 126986470930SIngo Molnar "put the counters into a counter group"), 12700fdc7e67SMike Galbraith OPT_BOOLEAN('i', "inherit", &inherit, 12710fdc7e67SMike Galbraith "child tasks inherit counters"), 1272923c42c1SMike Galbraith OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", 12736cff0e8dSKirill Smelkov "symbol to annotate"), 12741f208ea6SAnton Blanchard OPT_BOOLEAN('z', "zero", &zero, 127586470930SIngo Molnar "zero history across updates"), 127686470930SIngo Molnar OPT_INTEGER('F', "freq", &freq, 127786470930SIngo Molnar "profile at this frequency"), 127886470930SIngo Molnar OPT_INTEGER('E', "entries", &print_entries, 127986470930SIngo Molnar "display this many functions"), 12808ffcda17SArnaldo Carvalho de Melo OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols, 12818ffcda17SArnaldo Carvalho de Melo "hide user symbols"), 1282c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 12833da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 128486470930SIngo Molnar OPT_END() 128586470930SIngo Molnar }; 128686470930SIngo Molnar 1287f37a291cSIngo Molnar int cmd_top(int argc, const char **argv, const char *prefix __used) 128886470930SIngo Molnar { 128969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 129069aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 129186470930SIngo Molnar 1292361c99a6SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(); 1293361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1294361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1295361c99a6SArnaldo Carvalho de Melo 129686470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 129786470930SIngo Molnar 129886470930SIngo Molnar argc = parse_options(argc, argv, options, top_usage, 0); 129986470930SIngo Molnar if (argc) 130086470930SIngo Molnar usage_with_options(top_usage, options); 130186470930SIngo Molnar 13025c98d466SArnaldo Carvalho de Melo if (target_pid != -1) 1303d6d901c2SZhang, Yanmin target_tid = target_pid; 13045c98d466SArnaldo Carvalho de Melo 13055c98d466SArnaldo Carvalho de Melo threads = thread_map__new(target_pid, target_tid); 13065c98d466SArnaldo Carvalho de Melo if (threads == NULL) { 13075c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 1308d6d901c2SZhang, Yanmin usage_with_options(top_usage, options); 1309d6d901c2SZhang, Yanmin } 1310d6d901c2SZhang, Yanmin 131186470930SIngo Molnar /* CPU and PID are mutually exclusive */ 1312c45c6ea2SStephane Eranian if (target_tid > 0 && cpu_list) { 131386470930SIngo Molnar printf("WARNING: PID switch overriding CPU\n"); 131486470930SIngo Molnar sleep(1); 1315c45c6ea2SStephane Eranian cpu_list = NULL; 131686470930SIngo Molnar } 131786470930SIngo Molnar 1318361c99a6SArnaldo Carvalho de Melo if (!evsel_list->nr_entries && 1319361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 132069aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 132169aad6f1SArnaldo Carvalho de Melo return -ENOMEM; 132269aad6f1SArnaldo Carvalho de Melo } 13235a8e5a30SArnaldo Carvalho de Melo 132486470930SIngo Molnar if (delay_secs < 1) 132586470930SIngo Molnar delay_secs = 1; 132686470930SIngo Molnar 13277e4ff9e3SMike Galbraith /* 13287e4ff9e3SMike Galbraith * User specified count overrides default frequency. 13297e4ff9e3SMike Galbraith */ 13307e4ff9e3SMike Galbraith if (default_interval) 13317e4ff9e3SMike Galbraith freq = 0; 13327e4ff9e3SMike Galbraith else if (freq) { 13337e4ff9e3SMike Galbraith default_interval = freq; 13347e4ff9e3SMike Galbraith } else { 13357e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 13367e4ff9e3SMike Galbraith exit(EXIT_FAILURE); 13377e4ff9e3SMike Galbraith } 13387e4ff9e3SMike Galbraith 1339c45c6ea2SStephane Eranian if (target_tid != -1) 134060d567e2SArnaldo Carvalho de Melo cpus = cpu_map__dummy_new(); 1341a12b51c4SPaul Mackerras else 134260d567e2SArnaldo Carvalho de Melo cpus = cpu_map__new(cpu_list); 1343c45c6ea2SStephane Eranian 134460d567e2SArnaldo Carvalho de Melo if (cpus == NULL) 1345c45c6ea2SStephane Eranian usage_with_options(top_usage, options); 134686470930SIngo Molnar 1347361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 134870db7533SArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) 134969aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 135069aad6f1SArnaldo Carvalho de Melo /* 135169aad6f1SArnaldo Carvalho de Melo * Fill in the ones not specifically initialized via -c: 135269aad6f1SArnaldo Carvalho de Melo */ 135369aad6f1SArnaldo Carvalho de Melo if (pos->attr.sample_period) 135469aad6f1SArnaldo Carvalho de Melo continue; 135569aad6f1SArnaldo Carvalho de Melo 135669aad6f1SArnaldo Carvalho de Melo pos->attr.sample_period = default_interval; 135769aad6f1SArnaldo Carvalho de Melo } 135869aad6f1SArnaldo Carvalho de Melo 135970db7533SArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(evsel_list, cpus->nr, threads->nr) < 0 || 136070db7533SArnaldo Carvalho de Melo perf_evlist__alloc_mmap(evsel_list, cpus->nr) < 0) 13615c581041SArnaldo Carvalho de Melo goto out_free_fd; 13625c581041SArnaldo Carvalho de Melo 1363361c99a6SArnaldo Carvalho de Melo sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node); 1364cc841580SArnaldo Carvalho de Melo 136569aad6f1SArnaldo Carvalho de Melo symbol_conf.priv_size = (sizeof(struct sym_entry) + 1366361c99a6SArnaldo Carvalho de Melo (evsel_list->nr_entries + 1) * sizeof(unsigned long)); 136769aad6f1SArnaldo Carvalho de Melo 136869aad6f1SArnaldo Carvalho de Melo symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 136969aad6f1SArnaldo Carvalho de Melo if (symbol__init() < 0) 137069aad6f1SArnaldo Carvalho de Melo return -1; 137169aad6f1SArnaldo Carvalho de Melo 137213cc5079SArnaldo Carvalho de Melo get_term_dimensions(&winsize); 13733b6ed988SArnaldo Carvalho de Melo if (print_entries == 0) { 137413cc5079SArnaldo Carvalho de Melo update_print_entries(&winsize); 13753b6ed988SArnaldo Carvalho de Melo signal(SIGWINCH, sig_winch_handler); 13763b6ed988SArnaldo Carvalho de Melo } 13773b6ed988SArnaldo Carvalho de Melo 137869aad6f1SArnaldo Carvalho de Melo status = __cmd_top(); 137969aad6f1SArnaldo Carvalho de Melo out_free_fd: 1380361c99a6SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 138169aad6f1SArnaldo Carvalho de Melo 138269aad6f1SArnaldo Carvalho de Melo return status; 138386470930SIngo Molnar } 1384