PageRenderTime 1162ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/perf/builtin-top.c

https://github.com/Mengqi/linux-2.6
C | 1139 lines | 886 code | 182 blank | 71 comment | 164 complexity | ada4d75eb053e3dc43ca820fb327d19a MD5 | raw file
  1. /*
  2. * builtin-top.c
  3. *
  4. * Builtin top command: Display a continuously updated profile of
  5. * any workload, CPU or specific PID.
  6. *
  7. * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
  8. *
  9. * Improvements and fixes by:
  10. *
  11. * Arjan van de Ven <arjan@linux.intel.com>
  12. * Yanmin Zhang <yanmin.zhang@intel.com>
  13. * Wu Fengguang <fengguang.wu@intel.com>
  14. * Mike Galbraith <efault@gmx.de>
  15. * Paul Mackerras <paulus@samba.org>
  16. *
  17. * Released under the GPL v2. (and only v2, not any later version)
  18. */
  19. #include "builtin.h"
  20. #include "perf.h"
  21. #include "util/annotate.h"
  22. #include "util/cache.h"
  23. #include "util/color.h"
  24. #include "util/evlist.h"
  25. #include "util/evsel.h"
  26. #include "util/session.h"
  27. #include "util/symbol.h"
  28. #include "util/thread.h"
  29. #include "util/thread_map.h"
  30. #include "util/top.h"
  31. #include "util/util.h"
  32. #include <linux/rbtree.h>
  33. #include "util/parse-options.h"
  34. #include "util/parse-events.h"
  35. #include "util/cpumap.h"
  36. #include "util/xyarray.h"
  37. #include "util/debug.h"
  38. #include <assert.h>
  39. #include <fcntl.h>
  40. #include <stdio.h>
  41. #include <termios.h>
  42. #include <unistd.h>
  43. #include <inttypes.h>
  44. #include <errno.h>
  45. #include <time.h>
  46. #include <sched.h>
  47. #include <sys/syscall.h>
  48. #include <sys/ioctl.h>
  49. #include <sys/poll.h>
  50. #include <sys/prctl.h>
  51. #include <sys/wait.h>
  52. #include <sys/uio.h>
  53. #include <sys/mman.h>
  54. #include <linux/unistd.h>
  55. #include <linux/types.h>
  56. static struct perf_top top = {
  57. .count_filter = 5,
  58. .delay_secs = 2,
  59. .display_weighted = -1,
  60. .target_pid = -1,
  61. .target_tid = -1,
  62. .active_symbols = LIST_HEAD_INIT(top.active_symbols),
  63. .active_symbols_lock = PTHREAD_MUTEX_INITIALIZER,
  64. .active_symbols_cond = PTHREAD_COND_INITIALIZER,
  65. .freq = 1000, /* 1 KHz */
  66. };
  67. static bool system_wide = false;
  68. static bool use_tui, use_stdio;
  69. static int default_interval = 0;
  70. static bool kptr_restrict_warned;
  71. static bool vmlinux_warned;
  72. static bool inherit = false;
  73. static int realtime_prio = 0;
  74. static bool group = false;
  75. static unsigned int page_size;
  76. static unsigned int mmap_pages = 128;
  77. static bool dump_symtab = false;
  78. static struct winsize winsize;
  79. static const char *sym_filter = NULL;
  80. struct sym_entry *sym_filter_entry_sched = NULL;
  81. static int sym_pcnt_filter = 5;
  82. /*
  83. * Source functions
  84. */
  85. void get_term_dimensions(struct winsize *ws)
  86. {
  87. char *s = getenv("LINES");
  88. if (s != NULL) {
  89. ws->ws_row = atoi(s);
  90. s = getenv("COLUMNS");
  91. if (s != NULL) {
  92. ws->ws_col = atoi(s);
  93. if (ws->ws_row && ws->ws_col)
  94. return;
  95. }
  96. }
  97. #ifdef TIOCGWINSZ
  98. if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
  99. ws->ws_row && ws->ws_col)
  100. return;
  101. #endif
  102. ws->ws_row = 25;
  103. ws->ws_col = 80;
  104. }
  105. static void update_print_entries(struct winsize *ws)
  106. {
  107. top.print_entries = ws->ws_row;
  108. if (top.print_entries > 9)
  109. top.print_entries -= 9;
  110. }
  111. static void sig_winch_handler(int sig __used)
  112. {
  113. get_term_dimensions(&winsize);
  114. update_print_entries(&winsize);
  115. }
  116. static int parse_source(struct sym_entry *syme)
  117. {
  118. struct symbol *sym;
  119. struct annotation *notes;
  120. struct map *map;
  121. int err = -1;
  122. if (!syme)
  123. return -1;
  124. sym = sym_entry__symbol(syme);
  125. map = syme->map;
  126. /*
  127. * We can't annotate with just /proc/kallsyms
  128. */
  129. if (map->dso->symtab_type == SYMTAB__KALLSYMS) {
  130. pr_err("Can't annotate %s: No vmlinux file was found in the "
  131. "path\n", sym->name);
  132. sleep(1);
  133. return -1;
  134. }
  135. notes = symbol__annotation(sym);
  136. if (notes->src != NULL) {
  137. pthread_mutex_lock(&notes->lock);
  138. goto out_assign;
  139. }
  140. pthread_mutex_lock(&notes->lock);
  141. if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
  142. pthread_mutex_unlock(&notes->lock);
  143. pr_err("Not enough memory for annotating '%s' symbol!\n",
  144. sym->name);
  145. sleep(1);
  146. return err;
  147. }
  148. err = symbol__annotate(sym, syme->map, 0);
  149. if (err == 0) {
  150. out_assign:
  151. top.sym_filter_entry = syme;
  152. }
  153. pthread_mutex_unlock(&notes->lock);
  154. return err;
  155. }
  156. static void __zero_source_counters(struct sym_entry *syme)
  157. {
  158. struct symbol *sym = sym_entry__symbol(syme);
  159. symbol__annotate_zero_histograms(sym);
  160. }
  161. static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
  162. {
  163. struct annotation *notes;
  164. struct symbol *sym;
  165. if (syme != top.sym_filter_entry)
  166. return;
  167. sym = sym_entry__symbol(syme);
  168. notes = symbol__annotation(sym);
  169. if (pthread_mutex_trylock(&notes->lock))
  170. return;
  171. ip = syme->map->map_ip(syme->map, ip);
  172. symbol__inc_addr_samples(sym, syme->map, counter, ip);
  173. pthread_mutex_unlock(&notes->lock);
  174. }
  175. static void show_details(struct sym_entry *syme)
  176. {
  177. struct annotation *notes;
  178. struct symbol *symbol;
  179. int more;
  180. if (!syme)
  181. return;
  182. symbol = sym_entry__symbol(syme);
  183. notes = symbol__annotation(symbol);
  184. pthread_mutex_lock(&notes->lock);
  185. if (notes->src == NULL)
  186. goto out_unlock;
  187. printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
  188. printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
  189. more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx,
  190. 0, sym_pcnt_filter, top.print_entries, 4);
  191. if (top.zero)
  192. symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
  193. else
  194. symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
  195. if (more != 0)
  196. printf("%d lines not displayed, maybe increase display entries [e]\n", more);
  197. out_unlock:
  198. pthread_mutex_unlock(&notes->lock);
  199. }
  200. static const char CONSOLE_CLEAR[] = "";
  201. static void __list_insert_active_sym(struct sym_entry *syme)
  202. {
  203. list_add(&syme->node, &top.active_symbols);
  204. }
  205. static void print_sym_table(struct perf_session *session)
  206. {
  207. char bf[160];
  208. int printed = 0;
  209. struct rb_node *nd;
  210. struct sym_entry *syme;
  211. struct rb_root tmp = RB_ROOT;
  212. const int win_width = winsize.ws_col - 1;
  213. int sym_width, dso_width, dso_short_width;
  214. float sum_ksamples = perf_top__decay_samples(&top, &tmp);
  215. puts(CONSOLE_CLEAR);
  216. perf_top__header_snprintf(&top, bf, sizeof(bf));
  217. printf("%s\n", bf);
  218. perf_top__reset_sample_counters(&top);
  219. printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
  220. if (session->hists.stats.total_lost != 0) {
  221. color_fprintf(stdout, PERF_COLOR_RED, "WARNING:");
  222. printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n",
  223. session->hists.stats.total_lost);
  224. }
  225. if (top.sym_filter_entry) {
  226. show_details(top.sym_filter_entry);
  227. return;
  228. }
  229. perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width,
  230. &sym_width);
  231. if (sym_width + dso_width > winsize.ws_col - 29) {
  232. dso_width = dso_short_width;
  233. if (sym_width + dso_width > winsize.ws_col - 29)
  234. sym_width = winsize.ws_col - dso_width - 29;
  235. }
  236. putchar('\n');
  237. if (top.evlist->nr_entries == 1)
  238. printf(" samples pcnt");
  239. else
  240. printf(" weight samples pcnt");
  241. if (verbose)
  242. printf(" RIP ");
  243. printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
  244. printf(" %s _______ _____",
  245. top.evlist->nr_entries == 1 ? " " : "______");
  246. if (verbose)
  247. printf(" ________________");
  248. printf(" %-*.*s", sym_width, sym_width, graph_line);
  249. printf(" %-*.*s", dso_width, dso_width, graph_line);
  250. puts("\n");
  251. for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
  252. struct symbol *sym;
  253. double pcnt;
  254. syme = rb_entry(nd, struct sym_entry, rb_node);
  255. sym = sym_entry__symbol(syme);
  256. if (++printed > top.print_entries ||
  257. (int)syme->snap_count < top.count_filter)
  258. continue;
  259. pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
  260. sum_ksamples));
  261. if (top.evlist->nr_entries == 1 || !top.display_weighted)
  262. printf("%20.2f ", syme->weight);
  263. else
  264. printf("%9.1f %10ld ", syme->weight, syme->snap_count);
  265. percent_color_fprintf(stdout, "%4.1f%%", pcnt);
  266. if (verbose)
  267. printf(" %016" PRIx64, sym->start);
  268. printf(" %-*.*s", sym_width, sym_width, sym->name);
  269. printf(" %-*.*s\n", dso_width, dso_width,
  270. dso_width >= syme->map->dso->long_name_len ?
  271. syme->map->dso->long_name :
  272. syme->map->dso->short_name);
  273. }
  274. }
  275. static void prompt_integer(int *target, const char *msg)
  276. {
  277. char *buf = malloc(0), *p;
  278. size_t dummy = 0;
  279. int tmp;
  280. fprintf(stdout, "\n%s: ", msg);
  281. if (getline(&buf, &dummy, stdin) < 0)
  282. return;
  283. p = strchr(buf, '\n');
  284. if (p)
  285. *p = 0;
  286. p = buf;
  287. while(*p) {
  288. if (!isdigit(*p))
  289. goto out_free;
  290. p++;
  291. }
  292. tmp = strtoul(buf, NULL, 10);
  293. *target = tmp;
  294. out_free:
  295. free(buf);
  296. }
  297. static void prompt_percent(int *target, const char *msg)
  298. {
  299. int tmp = 0;
  300. prompt_integer(&tmp, msg);
  301. if (tmp >= 0 && tmp <= 100)
  302. *target = tmp;
  303. }
  304. static void prompt_symbol(struct sym_entry **target, const char *msg)
  305. {
  306. char *buf = malloc(0), *p;
  307. struct sym_entry *syme = *target, *n, *found = NULL;
  308. size_t dummy = 0;
  309. /* zero counters of active symbol */
  310. if (syme) {
  311. __zero_source_counters(syme);
  312. *target = NULL;
  313. }
  314. fprintf(stdout, "\n%s: ", msg);
  315. if (getline(&buf, &dummy, stdin) < 0)
  316. goto out_free;
  317. p = strchr(buf, '\n');
  318. if (p)
  319. *p = 0;
  320. pthread_mutex_lock(&top.active_symbols_lock);
  321. syme = list_entry(top.active_symbols.next, struct sym_entry, node);
  322. pthread_mutex_unlock(&top.active_symbols_lock);
  323. list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) {
  324. struct symbol *sym = sym_entry__symbol(syme);
  325. if (!strcmp(buf, sym->name)) {
  326. found = syme;
  327. break;
  328. }
  329. }
  330. if (!found) {
  331. fprintf(stderr, "Sorry, %s is not active.\n", buf);
  332. sleep(1);
  333. return;
  334. } else
  335. parse_source(found);
  336. out_free:
  337. free(buf);
  338. }
  339. static void print_mapped_keys(void)
  340. {
  341. char *name = NULL;
  342. if (top.sym_filter_entry) {
  343. struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
  344. name = sym->name;
  345. }
  346. fprintf(stdout, "\nMapped keys:\n");
  347. fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs);
  348. fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries);
  349. if (top.evlist->nr_entries > 1)
  350. fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel));
  351. fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter);
  352. fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
  353. fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
  354. fprintf(stdout, "\t[S] stop annotation.\n");
  355. if (top.evlist->nr_entries > 1)
  356. fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0);
  357. fprintf(stdout,
  358. "\t[K] hide kernel_symbols symbols. \t(%s)\n",
  359. top.hide_kernel_symbols ? "yes" : "no");
  360. fprintf(stdout,
  361. "\t[U] hide user symbols. \t(%s)\n",
  362. top.hide_user_symbols ? "yes" : "no");
  363. fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0);
  364. fprintf(stdout, "\t[qQ] quit.\n");
  365. }
  366. static int key_mapped(int c)
  367. {
  368. switch (c) {
  369. case 'd':
  370. case 'e':
  371. case 'f':
  372. case 'z':
  373. case 'q':
  374. case 'Q':
  375. case 'K':
  376. case 'U':
  377. case 'F':
  378. case 's':
  379. case 'S':
  380. return 1;
  381. case 'E':
  382. case 'w':
  383. return top.evlist->nr_entries > 1 ? 1 : 0;
  384. default:
  385. break;
  386. }
  387. return 0;
  388. }
  389. static void handle_keypress(struct perf_session *session, int c)
  390. {
  391. if (!key_mapped(c)) {
  392. struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
  393. struct termios tc, save;
  394. print_mapped_keys();
  395. fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
  396. fflush(stdout);
  397. tcgetattr(0, &save);
  398. tc = save;
  399. tc.c_lflag &= ~(ICANON | ECHO);
  400. tc.c_cc[VMIN] = 0;
  401. tc.c_cc[VTIME] = 0;
  402. tcsetattr(0, TCSANOW, &tc);
  403. poll(&stdin_poll, 1, -1);
  404. c = getc(stdin);
  405. tcsetattr(0, TCSAFLUSH, &save);
  406. if (!key_mapped(c))
  407. return;
  408. }
  409. switch (c) {
  410. case 'd':
  411. prompt_integer(&top.delay_secs, "Enter display delay");
  412. if (top.delay_secs < 1)
  413. top.delay_secs = 1;
  414. break;
  415. case 'e':
  416. prompt_integer(&top.print_entries, "Enter display entries (lines)");
  417. if (top.print_entries == 0) {
  418. sig_winch_handler(SIGWINCH);
  419. signal(SIGWINCH, sig_winch_handler);
  420. } else
  421. signal(SIGWINCH, SIG_DFL);
  422. break;
  423. case 'E':
  424. if (top.evlist->nr_entries > 1) {
  425. /* Select 0 as the default event: */
  426. int counter = 0;
  427. fprintf(stderr, "\nAvailable events:");
  428. list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
  429. fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel));
  430. prompt_integer(&counter, "Enter details event counter");
  431. if (counter >= top.evlist->nr_entries) {
  432. top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
  433. fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel));
  434. sleep(1);
  435. break;
  436. }
  437. list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
  438. if (top.sym_evsel->idx == counter)
  439. break;
  440. } else
  441. top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
  442. break;
  443. case 'f':
  444. prompt_integer(&top.count_filter, "Enter display event count filter");
  445. break;
  446. case 'F':
  447. prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
  448. break;
  449. case 'K':
  450. top.hide_kernel_symbols = !top.hide_kernel_symbols;
  451. break;
  452. case 'q':
  453. case 'Q':
  454. printf("exiting.\n");
  455. if (dump_symtab)
  456. perf_session__fprintf_dsos(session, stderr);
  457. exit(0);
  458. case 's':
  459. prompt_symbol(&top.sym_filter_entry, "Enter details symbol");
  460. break;
  461. case 'S':
  462. if (!top.sym_filter_entry)
  463. break;
  464. else {
  465. struct sym_entry *syme = top.sym_filter_entry;
  466. top.sym_filter_entry = NULL;
  467. __zero_source_counters(syme);
  468. }
  469. break;
  470. case 'U':
  471. top.hide_user_symbols = !top.hide_user_symbols;
  472. break;
  473. case 'w':
  474. top.display_weighted = ~top.display_weighted;
  475. break;
  476. case 'z':
  477. top.zero = !top.zero;
  478. break;
  479. default:
  480. break;
  481. }
  482. }
  483. static void *display_thread_tui(void *arg __used)
  484. {
  485. int err = 0;
  486. pthread_mutex_lock(&top.active_symbols_lock);
  487. while (list_empty(&top.active_symbols)) {
  488. err = pthread_cond_wait(&top.active_symbols_cond,
  489. &top.active_symbols_lock);
  490. if (err)
  491. break;
  492. }
  493. pthread_mutex_unlock(&top.active_symbols_lock);
  494. if (!err)
  495. perf_top__tui_browser(&top);
  496. exit_browser(0);
  497. exit(0);
  498. return NULL;
  499. }
  500. static void *display_thread(void *arg __used)
  501. {
  502. struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
  503. struct termios tc, save;
  504. int delay_msecs, c;
  505. struct perf_session *session = (struct perf_session *) arg;
  506. tcgetattr(0, &save);
  507. tc = save;
  508. tc.c_lflag &= ~(ICANON | ECHO);
  509. tc.c_cc[VMIN] = 0;
  510. tc.c_cc[VTIME] = 0;
  511. repeat:
  512. delay_msecs = top.delay_secs * 1000;
  513. tcsetattr(0, TCSANOW, &tc);
  514. /* trash return*/
  515. getc(stdin);
  516. do {
  517. print_sym_table(session);
  518. } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
  519. c = getc(stdin);
  520. tcsetattr(0, TCSAFLUSH, &save);
  521. handle_keypress(session, c);
  522. goto repeat;
  523. return NULL;
  524. }
  525. /* Tag samples to be skipped. */
  526. static const char *skip_symbols[] = {
  527. "default_idle",
  528. "native_safe_halt",
  529. "cpu_idle",
  530. "enter_idle",
  531. "exit_idle",
  532. "mwait_idle",
  533. "mwait_idle_with_hints",
  534. "poll_idle",
  535. "ppc64_runlatch_off",
  536. "pseries_dedicated_idle_sleep",
  537. NULL
  538. };
  539. static int symbol_filter(struct map *map, struct symbol *sym)
  540. {
  541. struct sym_entry *syme;
  542. const char *name = sym->name;
  543. int i;
  544. /*
  545. * ppc64 uses function descriptors and appends a '.' to the
  546. * start of every instruction address. Remove it.
  547. */
  548. if (name[0] == '.')
  549. name++;
  550. if (!strcmp(name, "_text") ||
  551. !strcmp(name, "_etext") ||
  552. !strcmp(name, "_sinittext") ||
  553. !strncmp("init_module", name, 11) ||
  554. !strncmp("cleanup_module", name, 14) ||
  555. strstr(name, "_text_start") ||
  556. strstr(name, "_text_end"))
  557. return 1;
  558. syme = symbol__priv(sym);
  559. syme->map = map;
  560. symbol__annotate_init(map, sym);
  561. if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
  562. /* schedule initial sym_filter_entry setup */
  563. sym_filter_entry_sched = syme;
  564. sym_filter = NULL;
  565. }
  566. for (i = 0; skip_symbols[i]; i++) {
  567. if (!strcmp(skip_symbols[i], name)) {
  568. sym->ignore = true;
  569. break;
  570. }
  571. }
  572. return 0;
  573. }
  574. static void perf_event__process_sample(const union perf_event *event,
  575. struct perf_sample *sample,
  576. struct perf_session *session)
  577. {
  578. u64 ip = event->ip.ip;
  579. struct sym_entry *syme;
  580. struct addr_location al;
  581. struct machine *machine;
  582. u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
  583. ++top.samples;
  584. switch (origin) {
  585. case PERF_RECORD_MISC_USER:
  586. ++top.us_samples;
  587. if (top.hide_user_symbols)
  588. return;
  589. machine = perf_session__find_host_machine(session);
  590. break;
  591. case PERF_RECORD_MISC_KERNEL:
  592. ++top.kernel_samples;
  593. if (top.hide_kernel_symbols)
  594. return;
  595. machine = perf_session__find_host_machine(session);
  596. break;
  597. case PERF_RECORD_MISC_GUEST_KERNEL:
  598. ++top.guest_kernel_samples;
  599. machine = perf_session__find_machine(session, event->ip.pid);
  600. break;
  601. case PERF_RECORD_MISC_GUEST_USER:
  602. ++top.guest_us_samples;
  603. /*
  604. * TODO: we don't process guest user from host side
  605. * except simple counting.
  606. */
  607. return;
  608. default:
  609. return;
  610. }
  611. if (!machine && perf_guest) {
  612. pr_err("Can't find guest [%d]'s kernel information\n",
  613. event->ip.pid);
  614. return;
  615. }
  616. if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
  617. top.exact_samples++;
  618. if (perf_event__preprocess_sample(event, session, &al, sample,
  619. symbol_filter) < 0 ||
  620. al.filtered)
  621. return;
  622. if (!kptr_restrict_warned &&
  623. symbol_conf.kptr_restrict &&
  624. al.cpumode == PERF_RECORD_MISC_KERNEL) {
  625. ui__warning(
  626. "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
  627. "Check /proc/sys/kernel/kptr_restrict.\n\n"
  628. "Kernel%s samples will not be resolved.\n",
  629. !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
  630. " modules" : "");
  631. if (use_browser <= 0)
  632. sleep(5);
  633. kptr_restrict_warned = true;
  634. }
  635. if (al.sym == NULL) {
  636. const char *msg = "Kernel samples will not be resolved.\n";
  637. /*
  638. * As we do lazy loading of symtabs we only will know if the
  639. * specified vmlinux file is invalid when we actually have a
  640. * hit in kernel space and then try to load it. So if we get
  641. * here and there are _no_ symbols in the DSO backing the
  642. * kernel map, bail out.
  643. *
  644. * We may never get here, for instance, if we use -K/
  645. * --hide-kernel-symbols, even if the user specifies an
  646. * invalid --vmlinux ;-)
  647. */
  648. if (!kptr_restrict_warned && !vmlinux_warned &&
  649. al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
  650. RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
  651. if (symbol_conf.vmlinux_name) {
  652. ui__warning("The %s file can't be used.\n%s",
  653. symbol_conf.vmlinux_name, msg);
  654. } else {
  655. ui__warning("A vmlinux file was not found.\n%s",
  656. msg);
  657. }
  658. if (use_browser <= 0)
  659. sleep(5);
  660. vmlinux_warned = true;
  661. }
  662. return;
  663. }
  664. /* let's see, whether we need to install initial sym_filter_entry */
  665. if (sym_filter_entry_sched) {
  666. top.sym_filter_entry = sym_filter_entry_sched;
  667. sym_filter_entry_sched = NULL;
  668. if (parse_source(top.sym_filter_entry) < 0) {
  669. struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
  670. pr_err("Can't annotate %s", sym->name);
  671. if (top.sym_filter_entry->map->dso->symtab_type == SYMTAB__KALLSYMS) {
  672. pr_err(": No vmlinux file was found in the path:\n");
  673. machine__fprintf_vmlinux_path(machine, stderr);
  674. } else
  675. pr_err(".\n");
  676. exit(1);
  677. }
  678. }
  679. syme = symbol__priv(al.sym);
  680. if (!al.sym->ignore) {
  681. struct perf_evsel *evsel;
  682. evsel = perf_evlist__id2evsel(top.evlist, sample->id);
  683. assert(evsel != NULL);
  684. syme->count[evsel->idx]++;
  685. record_precise_ip(syme, evsel->idx, ip);
  686. pthread_mutex_lock(&top.active_symbols_lock);
  687. if (list_empty(&syme->node) || !syme->node.next) {
  688. static bool first = true;
  689. __list_insert_active_sym(syme);
  690. if (first) {
  691. pthread_cond_broadcast(&top.active_symbols_cond);
  692. first = false;
  693. }
  694. }
  695. pthread_mutex_unlock(&top.active_symbols_lock);
  696. }
  697. }
  698. static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
  699. {
  700. struct perf_sample sample;
  701. union perf_event *event;
  702. int ret;
  703. while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) {
  704. ret = perf_session__parse_sample(self, event, &sample);
  705. if (ret) {
  706. pr_err("Can't parse sample, err = %d\n", ret);
  707. continue;
  708. }
  709. if (event->header.type == PERF_RECORD_SAMPLE)
  710. perf_event__process_sample(event, &sample, self);
  711. else
  712. perf_event__process(event, &sample, self);
  713. }
  714. }
  715. static void perf_session__mmap_read(struct perf_session *self)
  716. {
  717. int i;
  718. for (i = 0; i < top.evlist->nr_mmaps; i++)
  719. perf_session__mmap_read_idx(self, i);
  720. }
  721. static void start_counters(struct perf_evlist *evlist)
  722. {
  723. struct perf_evsel *counter;
  724. list_for_each_entry(counter, &evlist->entries, node) {
  725. struct perf_event_attr *attr = &counter->attr;
  726. attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
  727. if (top.freq) {
  728. attr->sample_type |= PERF_SAMPLE_PERIOD;
  729. attr->freq = 1;
  730. attr->sample_freq = top.freq;
  731. }
  732. if (evlist->nr_entries > 1) {
  733. attr->sample_type |= PERF_SAMPLE_ID;
  734. attr->read_format |= PERF_FORMAT_ID;
  735. }
  736. attr->mmap = 1;
  737. attr->inherit = inherit;
  738. try_again:
  739. if (perf_evsel__open(counter, top.evlist->cpus,
  740. top.evlist->threads, group) < 0) {
  741. int err = errno;
  742. if (err == EPERM || err == EACCES) {
  743. ui__warning_paranoid();
  744. goto out_err;
  745. }
  746. /*
  747. * If it's cycles then fall back to hrtimer
  748. * based cpu-clock-tick sw counter, which
  749. * is always available even if no PMU support:
  750. */
  751. if (attr->type == PERF_TYPE_HARDWARE &&
  752. attr->config == PERF_COUNT_HW_CPU_CYCLES) {
  753. if (verbose)
  754. ui__warning("Cycles event not supported,\n"
  755. "trying to fall back to cpu-clock-ticks\n");
  756. attr->type = PERF_TYPE_SOFTWARE;
  757. attr->config = PERF_COUNT_SW_CPU_CLOCK;
  758. goto try_again;
  759. }
  760. if (err == ENOENT) {
  761. ui__warning("The %s event is not supported.\n",
  762. event_name(counter));
  763. goto out_err;
  764. }
  765. ui__warning("The sys_perf_event_open() syscall "
  766. "returned with %d (%s). /bin/dmesg "
  767. "may provide additional information.\n"
  768. "No CONFIG_PERF_EVENTS=y kernel support "
  769. "configured?\n", err, strerror(err));
  770. goto out_err;
  771. }
  772. }
  773. if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) {
  774. ui__warning("Failed to mmap with %d (%s)\n",
  775. errno, strerror(errno));
  776. goto out_err;
  777. }
  778. return;
  779. out_err:
  780. exit_browser(0);
  781. exit(0);
  782. }
  783. static int __cmd_top(void)
  784. {
  785. pthread_t thread;
  786. int ret __used;
  787. /*
  788. * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
  789. * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
  790. */
  791. struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
  792. if (session == NULL)
  793. return -ENOMEM;
  794. if (top.target_tid != -1)
  795. perf_event__synthesize_thread_map(top.evlist->threads,
  796. perf_event__process, session);
  797. else
  798. perf_event__synthesize_threads(perf_event__process, session);
  799. start_counters(top.evlist);
  800. session->evlist = top.evlist;
  801. perf_session__update_sample_type(session);
  802. /* Wait for a minimal set of events before starting the snapshot */
  803. poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
  804. perf_session__mmap_read(session);
  805. if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
  806. display_thread), session)) {
  807. printf("Could not create display thread.\n");
  808. exit(-1);
  809. }
  810. if (realtime_prio) {
  811. struct sched_param param;
  812. param.sched_priority = realtime_prio;
  813. if (sched_setscheduler(0, SCHED_FIFO, &param)) {
  814. printf("Could not set realtime priority.\n");
  815. exit(-1);
  816. }
  817. }
  818. while (1) {
  819. u64 hits = top.samples;
  820. perf_session__mmap_read(session);
  821. if (hits == top.samples)
  822. ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
  823. }
  824. return 0;
  825. }
  826. static const char * const top_usage[] = {
  827. "perf top [<options>]",
  828. NULL
  829. };
  830. static const struct option options[] = {
  831. OPT_CALLBACK('e', "event", &top.evlist, "event",
  832. "event selector. use 'perf list' to list available events",
  833. parse_events_option),
  834. OPT_INTEGER('c', "count", &default_interval,
  835. "event period to sample"),
  836. OPT_INTEGER('p', "pid", &top.target_pid,
  837. "profile events on existing process id"),
  838. OPT_INTEGER('t', "tid", &top.target_tid,
  839. "profile events on existing thread id"),
  840. OPT_BOOLEAN('a', "all-cpus", &system_wide,
  841. "system-wide collection from all CPUs"),
  842. OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
  843. "list of cpus to monitor"),
  844. OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
  845. "file", "vmlinux pathname"),
  846. OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
  847. "hide kernel symbols"),
  848. OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
  849. OPT_INTEGER('r', "realtime", &realtime_prio,
  850. "collect data with this RT SCHED_FIFO priority"),
  851. OPT_INTEGER('d', "delay", &top.delay_secs,
  852. "number of seconds to delay between refreshes"),
  853. OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
  854. "dump the symbol table used for profiling"),
  855. OPT_INTEGER('f', "count-filter", &top.count_filter,
  856. "only display functions with more events than this"),
  857. OPT_BOOLEAN('g', "group", &group,
  858. "put the counters into a counter group"),
  859. OPT_BOOLEAN('i', "inherit", &inherit,
  860. "child tasks inherit counters"),
  861. OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
  862. "symbol to annotate"),
  863. OPT_BOOLEAN('z', "zero", &top.zero,
  864. "zero history across updates"),
  865. OPT_INTEGER('F', "freq", &top.freq,
  866. "profile at this frequency"),
  867. OPT_INTEGER('E', "entries", &top.print_entries,
  868. "display this many functions"),
  869. OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
  870. "hide user symbols"),
  871. OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
  872. OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
  873. OPT_INCR('v', "verbose", &verbose,
  874. "be more verbose (show counter open errors, etc)"),
  875. OPT_END()
  876. };
  877. int cmd_top(int argc, const char **argv, const char *prefix __used)
  878. {
  879. struct perf_evsel *pos;
  880. int status = -ENOMEM;
  881. top.evlist = perf_evlist__new(NULL, NULL);
  882. if (top.evlist == NULL)
  883. return -ENOMEM;
  884. page_size = sysconf(_SC_PAGE_SIZE);
  885. argc = parse_options(argc, argv, options, top_usage, 0);
  886. if (argc)
  887. usage_with_options(top_usage, options);
  888. /*
  889. * XXX For now start disabled, only using TUI if explicitely asked for.
  890. * Change that when handle_keys equivalent gets written, live annotation
  891. * done, etc.
  892. */
  893. use_browser = 0;
  894. if (use_stdio)
  895. use_browser = 0;
  896. else if (use_tui)
  897. use_browser = 1;
  898. setup_browser(false);
  899. /* CPU and PID are mutually exclusive */
  900. if (top.target_tid > 0 && top.cpu_list) {
  901. printf("WARNING: PID switch overriding CPU\n");
  902. sleep(1);
  903. top.cpu_list = NULL;
  904. }
  905. if (top.target_pid != -1)
  906. top.target_tid = top.target_pid;
  907. if (perf_evlist__create_maps(top.evlist, top.target_pid,
  908. top.target_tid, top.cpu_list) < 0)
  909. usage_with_options(top_usage, options);
  910. if (!top.evlist->nr_entries &&
  911. perf_evlist__add_default(top.evlist) < 0) {
  912. pr_err("Not enough memory for event selector list\n");
  913. return -ENOMEM;
  914. }
  915. if (top.delay_secs < 1)
  916. top.delay_secs = 1;
  917. /*
  918. * User specified count overrides default frequency.
  919. */
  920. if (default_interval)
  921. top.freq = 0;
  922. else if (top.freq) {
  923. default_interval = top.freq;
  924. } else {
  925. fprintf(stderr, "frequency and count are zero, aborting\n");
  926. exit(EXIT_FAILURE);
  927. }
  928. list_for_each_entry(pos, &top.evlist->entries, node) {
  929. if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr,
  930. top.evlist->threads->nr) < 0)
  931. goto out_free_fd;
  932. /*
  933. * Fill in the ones not specifically initialized via -c:
  934. */
  935. if (pos->attr.sample_period)
  936. continue;
  937. pos->attr.sample_period = default_interval;
  938. }
  939. if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
  940. perf_evlist__alloc_mmap(top.evlist) < 0)
  941. goto out_free_fd;
  942. top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
  943. symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) +
  944. (top.evlist->nr_entries + 1) * sizeof(unsigned long));
  945. symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
  946. if (symbol__init() < 0)
  947. return -1;
  948. get_term_dimensions(&winsize);
  949. if (top.print_entries == 0) {
  950. update_print_entries(&winsize);
  951. signal(SIGWINCH, sig_winch_handler);
  952. }
  953. status = __cmd_top();
  954. out_free_fd:
  955. perf_evlist__delete(top.evlist);
  956. return status;
  957. }