186470930SIngo Molnar /* 286470930SIngo Molnar * perf.c 386470930SIngo Molnar * 486470930SIngo Molnar * Performance analysis utility. 586470930SIngo Molnar * 686470930SIngo Molnar * This is the main hub from which the sub-commands (perf stat, 786470930SIngo Molnar * perf top, perf record, perf report, etc.) are started. 886470930SIngo Molnar */ 986470930SIngo Molnar #include "builtin.h" 1086470930SIngo Molnar 11aa36ddd7SArnaldo Carvalho de Melo #include "util/env.h" 124b6ab94eSJosh Poimboeuf #include <subcmd/exec-cmd.h> 1341840d21STaeung Song #include "util/config.h" 1486470930SIngo Molnar #include "util/quote.h" 154b6ab94eSJosh Poimboeuf #include <subcmd/run-command.h> 165beeded1SJason Baron #include "util/parse-events.h" 174b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1884c86ca1SWang Nan #include "util/bpf-loader.h" 19bbb2cea7SJiri Olsa #include "util/debug.h" 204cb93446SArnaldo Carvalho de Melo #include <api/fs/fs.h> 21592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 2227683dc5SIrina Tirdea #include <pthread.h> 2314cbfbebSNamhyung Kim #include <stdlib.h> 2414cbfbebSNamhyung Kim #include <time.h> 25*877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 2686470930SIngo Molnar 2786470930SIngo Molnar const char perf_usage_string[] = 2878a1b503SJiri Olsa "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]"; 2986470930SIngo Molnar 3086470930SIngo Molnar const char perf_more_info_string[] = 3186470930SIngo Molnar "See 'perf help COMMAND' for more information on a specific command."; 3286470930SIngo Molnar 3386470930SIngo Molnar static int use_pager = -1; 3470cb4e96SFeng Tang const char *input_name; 355d06e691SArnaldo Carvalho de Melo 3698a4179cSFrederic Weisbecker struct cmd_struct { 3798a4179cSFrederic Weisbecker const char *cmd; 38b0ad8ea6SArnaldo Carvalho de Melo int (*fn)(int, const char **); 3998a4179cSFrederic Weisbecker int option; 4098a4179cSFrederic Weisbecker }; 4198a4179cSFrederic Weisbecker 4298a4179cSFrederic Weisbecker static struct cmd_struct commands[] = { 4398a4179cSFrederic Weisbecker { "buildid-cache", cmd_buildid_cache, 0 }, 4498a4179cSFrederic Weisbecker { "buildid-list", cmd_buildid_list, 0 }, 4530862f2cSTaeung Song { "config", cmd_config, 0 }, 467aef3bf3SJiri Olsa { "c2c", cmd_c2c, 0 }, 4798a4179cSFrederic Weisbecker { "diff", cmd_diff, 0 }, 4898a4179cSFrederic Weisbecker { "evlist", cmd_evlist, 0 }, 4998a4179cSFrederic Weisbecker { "help", cmd_help, 0 }, 5035563771SArnaldo Carvalho de Melo { "kallsyms", cmd_kallsyms, 0 }, 5198a4179cSFrederic Weisbecker { "list", cmd_list, 0 }, 5298a4179cSFrederic Weisbecker { "record", cmd_record, 0 }, 5398a4179cSFrederic Weisbecker { "report", cmd_report, 0 }, 5498a4179cSFrederic Weisbecker { "bench", cmd_bench, 0 }, 5598a4179cSFrederic Weisbecker { "stat", cmd_stat, 0 }, 5698a4179cSFrederic Weisbecker { "timechart", cmd_timechart, 0 }, 5798a4179cSFrederic Weisbecker { "top", cmd_top, 0 }, 5898a4179cSFrederic Weisbecker { "annotate", cmd_annotate, 0 }, 5998a4179cSFrederic Weisbecker { "version", cmd_version, 0 }, 6098a4179cSFrederic Weisbecker { "script", cmd_script, 0 }, 6198a4179cSFrederic Weisbecker { "sched", cmd_sched, 0 }, 6289fe808aSIngo Molnar #ifdef HAVE_LIBELF_SUPPORT 6398a4179cSFrederic Weisbecker { "probe", cmd_probe, 0 }, 64393be2e3SNamhyung Kim #endif 6598a4179cSFrederic Weisbecker { "kmem", cmd_kmem, 0 }, 6698a4179cSFrederic Weisbecker { "lock", cmd_lock, 0 }, 6798a4179cSFrederic Weisbecker { "kvm", cmd_kvm, 0 }, 6898a4179cSFrederic Weisbecker { "test", cmd_test, 0 }, 6989fe808aSIngo Molnar #ifdef HAVE_LIBAUDIT_SUPPORT 70514f1c67SArnaldo Carvalho de Melo { "trace", cmd_trace, 0 }, 714d29089cSNamhyung Kim #endif 7298a4179cSFrederic Weisbecker { "inject", cmd_inject, 0 }, 73028f12eeSStephane Eranian { "mem", cmd_mem, 0 }, 742245bf14SJiri Olsa { "data", cmd_data, 0 }, 75d01f4e8dSNamhyung Kim { "ftrace", cmd_ftrace, 0 }, 7698a4179cSFrederic Weisbecker }; 7798a4179cSFrederic Weisbecker 7886470930SIngo Molnar struct pager_config { 7986470930SIngo Molnar const char *cmd; 8086470930SIngo Molnar int val; 8186470930SIngo Molnar }; 8286470930SIngo Molnar 8386470930SIngo Molnar static int pager_command_config(const char *var, const char *value, void *data) 8486470930SIngo Molnar { 8586470930SIngo Molnar struct pager_config *c = data; 8686470930SIngo Molnar if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) 8786470930SIngo Molnar c->val = perf_config_bool(var, value); 8886470930SIngo Molnar return 0; 8986470930SIngo Molnar } 9086470930SIngo Molnar 9186470930SIngo Molnar /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ 9286470930SIngo Molnar int check_pager_config(const char *cmd) 9386470930SIngo Molnar { 94ecc4c561SArnaldo Carvalho de Melo int err; 9586470930SIngo Molnar struct pager_config c; 9686470930SIngo Molnar c.cmd = cmd; 9786470930SIngo Molnar c.val = -1; 98ecc4c561SArnaldo Carvalho de Melo err = perf_config(pager_command_config, &c); 99ecc4c561SArnaldo Carvalho de Melo return err ?: c.val; 10086470930SIngo Molnar } 10186470930SIngo Molnar 1020020ce23SNamhyung Kim static int browser_command_config(const char *var, const char *value, void *data) 1035d06e691SArnaldo Carvalho de Melo { 1045d06e691SArnaldo Carvalho de Melo struct pager_config *c = data; 1055d06e691SArnaldo Carvalho de Melo if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) 1065d06e691SArnaldo Carvalho de Melo c->val = perf_config_bool(var, value); 1070020ce23SNamhyung Kim if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd)) 1080020ce23SNamhyung Kim c->val = perf_config_bool(var, value) ? 2 : 0; 1095d06e691SArnaldo Carvalho de Melo return 0; 1105d06e691SArnaldo Carvalho de Melo } 1115d06e691SArnaldo Carvalho de Melo 1120020ce23SNamhyung Kim /* 1130020ce23SNamhyung Kim * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk", 1140020ce23SNamhyung Kim * and -1 for "not specified" 1150020ce23SNamhyung Kim */ 1160020ce23SNamhyung Kim static int check_browser_config(const char *cmd) 1175d06e691SArnaldo Carvalho de Melo { 118ecc4c561SArnaldo Carvalho de Melo int err; 1195d06e691SArnaldo Carvalho de Melo struct pager_config c; 1205d06e691SArnaldo Carvalho de Melo c.cmd = cmd; 1215d06e691SArnaldo Carvalho de Melo c.val = -1; 122ecc4c561SArnaldo Carvalho de Melo err = perf_config(browser_command_config, &c); 123ecc4c561SArnaldo Carvalho de Melo return err ?: c.val; 1245d06e691SArnaldo Carvalho de Melo } 1255d06e691SArnaldo Carvalho de Melo 1264c574159SThiago Farina static void commit_pager_choice(void) 1274c574159SThiago Farina { 12886470930SIngo Molnar switch (use_pager) { 12986470930SIngo Molnar case 0: 130096d3558SJosh Poimboeuf setenv(PERF_PAGER_ENVIRONMENT, "cat", 1); 13186470930SIngo Molnar break; 13286470930SIngo Molnar case 1: 13386470930SIngo Molnar /* setup_pager(); */ 13486470930SIngo Molnar break; 13586470930SIngo Molnar default: 13686470930SIngo Molnar break; 13786470930SIngo Molnar } 13886470930SIngo Molnar } 13986470930SIngo Molnar 1407335399aSYunlong Song struct option options[] = { 1417335399aSYunlong Song OPT_ARGUMENT("help", "help"), 1427335399aSYunlong Song OPT_ARGUMENT("version", "version"), 1437335399aSYunlong Song OPT_ARGUMENT("exec-path", "exec-path"), 1447335399aSYunlong Song OPT_ARGUMENT("html-path", "html-path"), 1457335399aSYunlong Song OPT_ARGUMENT("paginate", "paginate"), 1467335399aSYunlong Song OPT_ARGUMENT("no-pager", "no-pager"), 1477335399aSYunlong Song OPT_ARGUMENT("debugfs-dir", "debugfs-dir"), 1487335399aSYunlong Song OPT_ARGUMENT("buildid-dir", "buildid-dir"), 1497335399aSYunlong Song OPT_ARGUMENT("list-cmds", "list-cmds"), 1507335399aSYunlong Song OPT_ARGUMENT("list-opts", "list-opts"), 1517335399aSYunlong Song OPT_ARGUMENT("debug", "debug"), 1527335399aSYunlong Song OPT_END() 1537335399aSYunlong Song }; 1547335399aSYunlong Song 15586470930SIngo Molnar static int handle_options(const char ***argv, int *argc, int *envchanged) 15686470930SIngo Molnar { 15786470930SIngo Molnar int handled = 0; 15886470930SIngo Molnar 15986470930SIngo Molnar while (*argc > 0) { 16086470930SIngo Molnar const char *cmd = (*argv)[0]; 16186470930SIngo Molnar if (cmd[0] != '-') 16286470930SIngo Molnar break; 16386470930SIngo Molnar 16486470930SIngo Molnar /* 16586470930SIngo Molnar * For legacy reasons, the "version" and "help" 16686470930SIngo Molnar * commands can be written with "--" prepended 16786470930SIngo Molnar * to make them look like flags. 16886470930SIngo Molnar */ 16986470930SIngo Molnar if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version")) 17086470930SIngo Molnar break; 17186470930SIngo Molnar 17286470930SIngo Molnar /* 173a1853e2cSJiri Olsa * Shortcut for '-h' and '-v' options to invoke help 174a1853e2cSJiri Olsa * and version command. 175a1853e2cSJiri Olsa */ 176a1853e2cSJiri Olsa if (!strcmp(cmd, "-h")) { 177a1853e2cSJiri Olsa (*argv)[0] = "--help"; 178a1853e2cSJiri Olsa break; 179a1853e2cSJiri Olsa } 180a1853e2cSJiri Olsa 181a1853e2cSJiri Olsa if (!strcmp(cmd, "-v")) { 182a1853e2cSJiri Olsa (*argv)[0] = "--version"; 183a1853e2cSJiri Olsa break; 184a1853e2cSJiri Olsa } 185a1853e2cSJiri Olsa 186a1853e2cSJiri Olsa /* 18786470930SIngo Molnar * Check remaining flags. 18886470930SIngo Molnar */ 189cfed95a6SVincent Legoll if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 190cfed95a6SVincent Legoll cmd += strlen(CMD_EXEC_PATH); 19186470930SIngo Molnar if (*cmd == '=') 19246113a54SJosh Poimboeuf set_argv_exec_path(cmd + 1); 19386470930SIngo Molnar else { 19446113a54SJosh Poimboeuf puts(get_argv_exec_path()); 19586470930SIngo Molnar exit(0); 19686470930SIngo Molnar } 19786470930SIngo Molnar } else if (!strcmp(cmd, "--html-path")) { 19886470930SIngo Molnar puts(system_path(PERF_HTML_PATH)); 19986470930SIngo Molnar exit(0); 20086470930SIngo Molnar } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { 20186470930SIngo Molnar use_pager = 1; 20286470930SIngo Molnar } else if (!strcmp(cmd, "--no-pager")) { 20386470930SIngo Molnar use_pager = 0; 20486470930SIngo Molnar if (envchanged) 20586470930SIngo Molnar *envchanged = 1; 2065beeded1SJason Baron } else if (!strcmp(cmd, "--debugfs-dir")) { 2075beeded1SJason Baron if (*argc < 2) { 2085beeded1SJason Baron fprintf(stderr, "No directory given for --debugfs-dir.\n"); 2095beeded1SJason Baron usage(perf_usage_string); 2105beeded1SJason Baron } 21165d4b265SJiri Olsa tracing_path_set((*argv)[1]); 2125beeded1SJason Baron if (envchanged) 2135beeded1SJason Baron *envchanged = 1; 2145beeded1SJason Baron (*argv)++; 2155beeded1SJason Baron (*argc)--; 21699ce8e9fSJiri Olsa } else if (!strcmp(cmd, "--buildid-dir")) { 21799ce8e9fSJiri Olsa if (*argc < 2) { 21899ce8e9fSJiri Olsa fprintf(stderr, "No directory given for --buildid-dir.\n"); 21999ce8e9fSJiri Olsa usage(perf_usage_string); 22099ce8e9fSJiri Olsa } 22199ce8e9fSJiri Olsa set_buildid_dir((*argv)[1]); 22299ce8e9fSJiri Olsa if (envchanged) 22399ce8e9fSJiri Olsa *envchanged = 1; 22499ce8e9fSJiri Olsa (*argv)++; 22599ce8e9fSJiri Olsa (*argc)--; 226cfed95a6SVincent Legoll } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 22765d4b265SJiri Olsa tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); 2289f30fffcSJiri Olsa fprintf(stderr, "dir: %s\n", tracing_path); 2295beeded1SJason Baron if (envchanged) 2305beeded1SJason Baron *envchanged = 1; 23198a4179cSFrederic Weisbecker } else if (!strcmp(cmd, "--list-cmds")) { 23298a4179cSFrederic Weisbecker unsigned int i; 23398a4179cSFrederic Weisbecker 23498a4179cSFrederic Weisbecker for (i = 0; i < ARRAY_SIZE(commands); i++) { 23598a4179cSFrederic Weisbecker struct cmd_struct *p = commands+i; 23698a4179cSFrederic Weisbecker printf("%s ", p->cmd); 23798a4179cSFrederic Weisbecker } 238ed457520SYunlong Song putchar('\n'); 23998a4179cSFrederic Weisbecker exit(0); 2407335399aSYunlong Song } else if (!strcmp(cmd, "--list-opts")) { 2417335399aSYunlong Song unsigned int i; 2427335399aSYunlong Song 2437335399aSYunlong Song for (i = 0; i < ARRAY_SIZE(options)-1; i++) { 2447335399aSYunlong Song struct option *p = options+i; 2457335399aSYunlong Song printf("--%s ", p->long_name); 2467335399aSYunlong Song } 2477335399aSYunlong Song putchar('\n'); 2487335399aSYunlong Song exit(0); 249bbb2cea7SJiri Olsa } else if (!strcmp(cmd, "--debug")) { 250bbb2cea7SJiri Olsa if (*argc < 2) { 251bbb2cea7SJiri Olsa fprintf(stderr, "No variable specified for --debug.\n"); 252bbb2cea7SJiri Olsa usage(perf_usage_string); 253bbb2cea7SJiri Olsa } 254bbb2cea7SJiri Olsa if (perf_debug_option((*argv)[1])) 255bbb2cea7SJiri Olsa usage(perf_usage_string); 256bbb2cea7SJiri Olsa 257bbb2cea7SJiri Olsa (*argv)++; 258bbb2cea7SJiri Olsa (*argc)--; 25986470930SIngo Molnar } else { 26086470930SIngo Molnar fprintf(stderr, "Unknown option: %s\n", cmd); 26186470930SIngo Molnar usage(perf_usage_string); 26286470930SIngo Molnar } 26386470930SIngo Molnar 26486470930SIngo Molnar (*argv)++; 26586470930SIngo Molnar (*argc)--; 26686470930SIngo Molnar handled++; 26786470930SIngo Molnar } 26886470930SIngo Molnar return handled; 26986470930SIngo Molnar } 27086470930SIngo Molnar 27186470930SIngo Molnar #define RUN_SETUP (1<<0) 27286470930SIngo Molnar #define USE_PAGER (1<<1) 27386470930SIngo Molnar 27486470930SIngo Molnar static int run_builtin(struct cmd_struct *p, int argc, const char **argv) 27586470930SIngo Molnar { 27686470930SIngo Molnar int status; 27786470930SIngo Molnar struct stat st; 278b2348e1dSMasami Hiramatsu char sbuf[STRERR_BUFSIZE]; 27986470930SIngo Molnar 2805d06e691SArnaldo Carvalho de Melo if (use_browser == -1) 2810020ce23SNamhyung Kim use_browser = check_browser_config(p->cmd); 2825d06e691SArnaldo Carvalho de Melo 28386470930SIngo Molnar if (use_pager == -1 && p->option & RUN_SETUP) 28486470930SIngo Molnar use_pager = check_pager_config(p->cmd); 28586470930SIngo Molnar if (use_pager == -1 && p->option & USE_PAGER) 28686470930SIngo Molnar use_pager = 1; 28786470930SIngo Molnar commit_pager_choice(); 28886470930SIngo Molnar 2892bdb2c27SJosh Poimboeuf perf_env__set_cmdline(&perf_env, argc, argv); 290b0ad8ea6SArnaldo Carvalho de Melo status = p->fn(argc, argv); 2918a0a9c7eSTaeung Song perf_config__exit(); 292f3a1f0eaSArnaldo Carvalho de Melo exit_browser(status); 293aa36ddd7SArnaldo Carvalho de Melo perf_env__exit(&perf_env); 29484c86ca1SWang Nan bpf__clear(); 295f3a1f0eaSArnaldo Carvalho de Melo 29686470930SIngo Molnar if (status) 29786470930SIngo Molnar return status & 0xff; 29886470930SIngo Molnar 29986470930SIngo Molnar /* Somebody closed stdout? */ 30086470930SIngo Molnar if (fstat(fileno(stdout), &st)) 30186470930SIngo Molnar return 0; 30286470930SIngo Molnar /* Ignore write errors for pipes and sockets.. */ 30386470930SIngo Molnar if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) 30486470930SIngo Molnar return 0; 30586470930SIngo Molnar 3062a16bf8cSArnaldo Carvalho de Melo status = 1; 30786470930SIngo Molnar /* Check for ENOSPC and EIO errors.. */ 3082a16bf8cSArnaldo Carvalho de Melo if (fflush(stdout)) { 309b2348e1dSMasami Hiramatsu fprintf(stderr, "write failure on standard output: %s", 310c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, sbuf, sizeof(sbuf))); 3112a16bf8cSArnaldo Carvalho de Melo goto out; 3122a16bf8cSArnaldo Carvalho de Melo } 3132a16bf8cSArnaldo Carvalho de Melo if (ferror(stdout)) { 3142a16bf8cSArnaldo Carvalho de Melo fprintf(stderr, "unknown write failure on standard output"); 3152a16bf8cSArnaldo Carvalho de Melo goto out; 3162a16bf8cSArnaldo Carvalho de Melo } 3172a16bf8cSArnaldo Carvalho de Melo if (fclose(stdout)) { 318b2348e1dSMasami Hiramatsu fprintf(stderr, "close failed on standard output: %s", 319c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, sbuf, sizeof(sbuf))); 3202a16bf8cSArnaldo Carvalho de Melo goto out; 3212a16bf8cSArnaldo Carvalho de Melo } 3222a16bf8cSArnaldo Carvalho de Melo status = 0; 3232a16bf8cSArnaldo Carvalho de Melo out: 3242a16bf8cSArnaldo Carvalho de Melo return status; 32586470930SIngo Molnar } 32686470930SIngo Molnar 32786470930SIngo Molnar static void handle_internal_command(int argc, const char **argv) 32886470930SIngo Molnar { 32986470930SIngo Molnar const char *cmd = argv[0]; 330f37a291cSIngo Molnar unsigned int i; 33186470930SIngo Molnar static const char ext[] = STRIP_EXTENSION; 33286470930SIngo Molnar 33386470930SIngo Molnar if (sizeof(ext) > 1) { 33486470930SIngo Molnar i = strlen(argv[0]) - strlen(ext); 33586470930SIngo Molnar if (i > 0 && !strcmp(argv[0] + i, ext)) { 33686470930SIngo Molnar char *argv0 = strdup(argv[0]); 33786470930SIngo Molnar argv[0] = cmd = argv0; 33886470930SIngo Molnar argv0[i] = '\0'; 33986470930SIngo Molnar } 34086470930SIngo Molnar } 34186470930SIngo Molnar 34286470930SIngo Molnar /* Turn "perf cmd --help" into "perf help cmd" */ 34386470930SIngo Molnar if (argc > 1 && !strcmp(argv[1], "--help")) { 34486470930SIngo Molnar argv[1] = argv[0]; 34586470930SIngo Molnar argv[0] = cmd = "help"; 34686470930SIngo Molnar } 34786470930SIngo Molnar 34886470930SIngo Molnar for (i = 0; i < ARRAY_SIZE(commands); i++) { 34986470930SIngo Molnar struct cmd_struct *p = commands+i; 35086470930SIngo Molnar if (strcmp(p->cmd, cmd)) 35186470930SIngo Molnar continue; 35286470930SIngo Molnar exit(run_builtin(p, argc, argv)); 35386470930SIngo Molnar } 35486470930SIngo Molnar } 35586470930SIngo Molnar 35686470930SIngo Molnar static void execv_dashed_external(const char **argv) 35786470930SIngo Molnar { 3585104ffb2SArnaldo Carvalho de Melo char *cmd; 35986470930SIngo Molnar const char *tmp; 36086470930SIngo Molnar int status; 36186470930SIngo Molnar 3625104ffb2SArnaldo Carvalho de Melo if (asprintf(&cmd, "perf-%s", argv[0]) < 0) 3635104ffb2SArnaldo Carvalho de Melo goto do_die; 36486470930SIngo Molnar 36586470930SIngo Molnar /* 36686470930SIngo Molnar * argv[0] must be the perf command, but the argv array 36786470930SIngo Molnar * belongs to the caller, and may be reused in 36886470930SIngo Molnar * subsequent loop iterations. Save argv[0] and 36986470930SIngo Molnar * restore it on error. 37086470930SIngo Molnar */ 37186470930SIngo Molnar tmp = argv[0]; 3725104ffb2SArnaldo Carvalho de Melo argv[0] = cmd; 37386470930SIngo Molnar 37486470930SIngo Molnar /* 37586470930SIngo Molnar * if we fail because the command is not found, it is 37686470930SIngo Molnar * OK to return. Otherwise, we just pass along the status code. 37786470930SIngo Molnar */ 37886470930SIngo Molnar status = run_command_v_opt(argv, 0); 37986470930SIngo Molnar if (status != -ERR_RUN_COMMAND_EXEC) { 3805104ffb2SArnaldo Carvalho de Melo if (IS_RUN_COMMAND_ERR(status)) { 3815104ffb2SArnaldo Carvalho de Melo do_die: 38242774806SArnaldo Carvalho de Melo pr_err("FATAL: unable to run '%s'", argv[0]); 38342774806SArnaldo Carvalho de Melo status = -128; 3845104ffb2SArnaldo Carvalho de Melo } 38586470930SIngo Molnar exit(-status); 38686470930SIngo Molnar } 38786470930SIngo Molnar errno = ENOENT; /* as if we called execvp */ 38886470930SIngo Molnar 38986470930SIngo Molnar argv[0] = tmp; 3905104ffb2SArnaldo Carvalho de Melo zfree(&cmd); 39186470930SIngo Molnar } 39286470930SIngo Molnar 39386470930SIngo Molnar static int run_argv(int *argcp, const char ***argv) 39486470930SIngo Molnar { 39586470930SIngo Molnar /* See if it's an internal command */ 39686470930SIngo Molnar handle_internal_command(*argcp, *argv); 39786470930SIngo Molnar 39886470930SIngo Molnar /* .. then try the external ones */ 39986470930SIngo Molnar execv_dashed_external(*argv); 400c6867701SArnaldo Carvalho de Melo return 0; 40186470930SIngo Molnar } 40286470930SIngo Molnar 4033af6e338SArnaldo Carvalho de Melo static void pthread__block_sigwinch(void) 4043af6e338SArnaldo Carvalho de Melo { 4053af6e338SArnaldo Carvalho de Melo sigset_t set; 4063af6e338SArnaldo Carvalho de Melo 4073af6e338SArnaldo Carvalho de Melo sigemptyset(&set); 4083af6e338SArnaldo Carvalho de Melo sigaddset(&set, SIGWINCH); 4093af6e338SArnaldo Carvalho de Melo pthread_sigmask(SIG_BLOCK, &set, NULL); 4103af6e338SArnaldo Carvalho de Melo } 4113af6e338SArnaldo Carvalho de Melo 4123af6e338SArnaldo Carvalho de Melo void pthread__unblock_sigwinch(void) 4133af6e338SArnaldo Carvalho de Melo { 4143af6e338SArnaldo Carvalho de Melo sigset_t set; 4153af6e338SArnaldo Carvalho de Melo 4163af6e338SArnaldo Carvalho de Melo sigemptyset(&set); 4173af6e338SArnaldo Carvalho de Melo sigaddset(&set, SIGWINCH); 4183af6e338SArnaldo Carvalho de Melo pthread_sigmask(SIG_UNBLOCK, &set, NULL); 4193af6e338SArnaldo Carvalho de Melo } 4203af6e338SArnaldo Carvalho de Melo 4219a3dc28bSArnaldo Carvalho de Melo #ifdef _SC_LEVEL1_DCACHE_LINESIZE 4229a3dc28bSArnaldo Carvalho de Melo #define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) 4239a3dc28bSArnaldo Carvalho de Melo #else 4249a3dc28bSArnaldo Carvalho de Melo static void cache_line_size(int *cacheline_sizep) 4259a3dc28bSArnaldo Carvalho de Melo { 4269a3dc28bSArnaldo Carvalho de Melo if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep)) 4278811e8eaSArnaldo Carvalho de Melo pr_debug("cannot determine cache line size"); 4289a3dc28bSArnaldo Carvalho de Melo } 4299a3dc28bSArnaldo Carvalho de Melo #endif 4309a3dc28bSArnaldo Carvalho de Melo 43186470930SIngo Molnar int main(int argc, const char **argv) 43286470930SIngo Molnar { 433ecc4c561SArnaldo Carvalho de Melo int err; 43486470930SIngo Molnar const char *cmd; 435b2348e1dSMasami Hiramatsu char sbuf[STRERR_BUFSIZE]; 4364cb93446SArnaldo Carvalho de Melo int value; 43786470930SIngo Molnar 438096d3558SJosh Poimboeuf /* libsubcmd init */ 439096d3558SJosh Poimboeuf exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); 440096d3558SJosh Poimboeuf pager_init(PERF_PAGER_ENVIRONMENT); 441096d3558SJosh Poimboeuf 442918512b4SJiri Olsa /* The page_size is placed in util object. */ 4430c1fe6b2SArnaldo Carvalho de Melo page_size = sysconf(_SC_PAGE_SIZE); 4449a3dc28bSArnaldo Carvalho de Melo cache_line_size(&cacheline_size); 4450c1fe6b2SArnaldo Carvalho de Melo 4464cb93446SArnaldo Carvalho de Melo if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 4474cb93446SArnaldo Carvalho de Melo sysctl_perf_event_max_stack = value; 4484cb93446SArnaldo Carvalho de Melo 449a29d5c9bSArnaldo Carvalho de Melo if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) 450a29d5c9bSArnaldo Carvalho de Melo sysctl_perf_event_max_contexts_per_stack = value; 451a29d5c9bSArnaldo Carvalho de Melo 45246113a54SJosh Poimboeuf cmd = extract_argv0_path(argv[0]); 45386470930SIngo Molnar if (!cmd) 45486470930SIngo Molnar cmd = "perf-help"; 45565d4b265SJiri Olsa 45614cbfbebSNamhyung Kim srandom(time(NULL)); 45714cbfbebSNamhyung Kim 4588a0a9c7eSTaeung Song perf_config__init(); 459ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_default_config, NULL); 460ecc4c561SArnaldo Carvalho de Melo if (err) 461ecc4c561SArnaldo Carvalho de Melo return err; 46258cb9d65STaeung Song set_buildid_dir(NULL); 463b8cbb349SWang Nan 46465d4b265SJiri Olsa /* get debugfs/tracefs mount point from /proc/mounts */ 46565d4b265SJiri Olsa tracing_path_mount(); 46665d4b265SJiri Olsa 46786470930SIngo Molnar /* 46886470930SIngo Molnar * "perf-xxxx" is the same as "perf xxxx", but we obviously: 46986470930SIngo Molnar * 47086470930SIngo Molnar * - cannot take flags in between the "perf" and the "xxxx". 47186470930SIngo Molnar * - cannot execute it externally (since it would just do 47286470930SIngo Molnar * the same thing over again) 47386470930SIngo Molnar * 47486470930SIngo Molnar * So we just directly call the internal command handler, and 47586470930SIngo Molnar * die if that one cannot handle it. 47686470930SIngo Molnar */ 47786470930SIngo Molnar if (!prefixcmp(cmd, "perf-")) { 47886470930SIngo Molnar cmd += 5; 47986470930SIngo Molnar argv[0] = cmd; 48086470930SIngo Molnar handle_internal_command(argc, argv); 4812a16bf8cSArnaldo Carvalho de Melo fprintf(stderr, "cannot handle %s internally", cmd); 4822a16bf8cSArnaldo Carvalho de Melo goto out; 48386470930SIngo Molnar } 484b52bc234SArnaldo Carvalho de Melo if (!prefixcmp(cmd, "trace")) { 4851b572622SArnaldo Carvalho de Melo #ifdef HAVE_LIBAUDIT_SUPPORT 486b52bc234SArnaldo Carvalho de Melo setup_path(); 487b52bc234SArnaldo Carvalho de Melo argv[0] = "trace"; 488b0ad8ea6SArnaldo Carvalho de Melo return cmd_trace(argc, argv); 4891b572622SArnaldo Carvalho de Melo #else 4901b572622SArnaldo Carvalho de Melo fprintf(stderr, 4911b572622SArnaldo Carvalho de Melo "trace command not available: missing audit-libs devel package at build time.\n"); 4921b572622SArnaldo Carvalho de Melo goto out; 493b52bc234SArnaldo Carvalho de Melo #endif 4941b572622SArnaldo Carvalho de Melo } 49586470930SIngo Molnar /* Look for flags.. */ 49686470930SIngo Molnar argv++; 49786470930SIngo Molnar argc--; 49886470930SIngo Molnar handle_options(&argv, &argc, NULL); 49986470930SIngo Molnar commit_pager_choice(); 50045de34bbSStephane Eranian 50186470930SIngo Molnar if (argc > 0) { 50286470930SIngo Molnar if (!prefixcmp(argv[0], "--")) 50386470930SIngo Molnar argv[0] += 2; 50486470930SIngo Molnar } else { 50586470930SIngo Molnar /* The user didn't specify a command; give them help */ 50686470930SIngo Molnar printf("\n usage: %s\n\n", perf_usage_string); 50786470930SIngo Molnar list_common_cmds_help(); 50886470930SIngo Molnar printf("\n %s\n\n", perf_more_info_string); 5092a16bf8cSArnaldo Carvalho de Melo goto out; 51086470930SIngo Molnar } 51186470930SIngo Molnar cmd = argv[0]; 51286470930SIngo Molnar 51352502bf2SJiri Olsa test_attr__init(); 51452502bf2SJiri Olsa 51586470930SIngo Molnar /* 51686470930SIngo Molnar * We use PATH to find perf commands, but we prepend some higher 517659431fcSUwe Kleine-König * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH 51886470930SIngo Molnar * environment, and the $(perfexecdir) from the Makefile at build 51986470930SIngo Molnar * time. 52086470930SIngo Molnar */ 52186470930SIngo Molnar setup_path(); 5223af6e338SArnaldo Carvalho de Melo /* 5233af6e338SArnaldo Carvalho de Melo * Block SIGWINCH notifications so that the thread that wants it can 5243af6e338SArnaldo Carvalho de Melo * unblock and get syscalls like select interrupted instead of waiting 5253af6e338SArnaldo Carvalho de Melo * forever while the signal goes to some other non interested thread. 5263af6e338SArnaldo Carvalho de Melo */ 5273af6e338SArnaldo Carvalho de Melo pthread__block_sigwinch(); 52886470930SIngo Molnar 529dd629cc0SJiri Olsa perf_debug_setup(); 530dd629cc0SJiri Olsa 53186470930SIngo Molnar while (1) { 5324c574159SThiago Farina static int done_help; 533c6867701SArnaldo Carvalho de Melo 534c6867701SArnaldo Carvalho de Melo run_argv(&argc, &argv); 53586470930SIngo Molnar 53686470930SIngo Molnar if (errno != ENOENT) 53786470930SIngo Molnar break; 53886470930SIngo Molnar 53986470930SIngo Molnar if (!done_help) { 54086470930SIngo Molnar cmd = argv[0] = help_unknown_cmd(cmd); 54186470930SIngo Molnar done_help = 1; 54286470930SIngo Molnar } else 54386470930SIngo Molnar break; 54486470930SIngo Molnar } 54586470930SIngo Molnar 54686470930SIngo Molnar fprintf(stderr, "Failed to run command '%s': %s\n", 547c8b5f2c9SArnaldo Carvalho de Melo cmd, str_error_r(errno, sbuf, sizeof(sbuf))); 5482a16bf8cSArnaldo Carvalho de Melo out: 54986470930SIngo Molnar return 1; 55086470930SIngo Molnar } 551