diff options
Diffstat (limited to 'Documentation/perf_counter/perf.c')
-rw-r--r-- | Documentation/perf_counter/perf.c | 428 |
1 files changed, 0 insertions, 428 deletions
diff --git a/Documentation/perf_counter/perf.c b/Documentation/perf_counter/perf.c deleted file mode 100644 index 4eb725933703..000000000000 --- a/Documentation/perf_counter/perf.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * perf.c - * - * Performance analysis utility. - * - * This is the main hub from which the sub-commands (perf stat, - * perf top, perf record, perf report, etc.) are started. - */ -#include "builtin.h" - -#include "util/exec_cmd.h" -#include "util/cache.h" -#include "util/quote.h" -#include "util/run-command.h" - -const char perf_usage_string[] = - "perf [--version] [--help] COMMAND [ARGS]"; - -const char perf_more_info_string[] = - "See 'perf help COMMAND' for more information on a specific command."; - -static int use_pager = -1; -struct pager_config { - const char *cmd; - int val; -}; - -static int pager_command_config(const char *var, const char *value, void *data) -{ - struct pager_config *c = data; - if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) - c->val = perf_config_bool(var, value); - return 0; -} - -/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ -int check_pager_config(const char *cmd) -{ - struct pager_config c; - c.cmd = cmd; - c.val = -1; - perf_config(pager_command_config, &c); - return c.val; -} - -static void commit_pager_choice(void) { - switch (use_pager) { - case 0: - setenv("PERF_PAGER", "cat", 1); - break; - case 1: - /* setup_pager(); */ - break; - default: - break; - } -} - -static int handle_options(const char*** argv, int* argc, int* envchanged) -{ - int handled = 0; - - while (*argc > 0) { - const char *cmd = (*argv)[0]; - if (cmd[0] != '-') - break; - - /* - * For legacy reasons, the "version" and "help" - * commands can be written with "--" prepended - * to make them look like flags. - */ - if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version")) - break; - - /* - * Check remaining flags. - */ - if (!prefixcmp(cmd, "--exec-path")) { - cmd += 11; - if (*cmd == '=') - perf_set_argv_exec_path(cmd + 1); - else { - puts(perf_exec_path()); - exit(0); - } - } else if (!strcmp(cmd, "--html-path")) { - puts(system_path(PERF_HTML_PATH)); - exit(0); - } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { - use_pager = 1; - } else if (!strcmp(cmd, "--no-pager")) { - use_pager = 0; - if (envchanged) - *envchanged = 1; - } else if (!strcmp(cmd, "--perf-dir")) { - if (*argc < 2) { - fprintf(stderr, "No directory given for --perf-dir.\n" ); - usage(perf_usage_string); - } - setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1); - if (envchanged) - *envchanged = 1; - (*argv)++; - (*argc)--; - handled++; - } else if (!prefixcmp(cmd, "--perf-dir=")) { - setenv(PERF_DIR_ENVIRONMENT, cmd + 10, 1); - if (envchanged) - *envchanged = 1; - } else if (!strcmp(cmd, "--work-tree")) { - if (*argc < 2) { - fprintf(stderr, "No directory given for --work-tree.\n" ); - usage(perf_usage_string); - } - setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1); - if (envchanged) - *envchanged = 1; - (*argv)++; - (*argc)--; - } else if (!prefixcmp(cmd, "--work-tree=")) { - setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); - if (envchanged) - *envchanged = 1; - } else { - fprintf(stderr, "Unknown option: %s\n", cmd); - usage(perf_usage_string); - } - - (*argv)++; - (*argc)--; - handled++; - } - return handled; -} - -static int handle_alias(int *argcp, const char ***argv) -{ - int envchanged = 0, ret = 0, saved_errno = errno; - int count, option_count; - const char** new_argv; - const char *alias_command; - char *alias_string; - - alias_command = (*argv)[0]; - alias_string = alias_lookup(alias_command); - if (alias_string) { - if (alias_string[0] == '!') { - if (*argcp > 1) { - struct strbuf buf; - - strbuf_init(&buf, PATH_MAX); - strbuf_addstr(&buf, alias_string); - sq_quote_argv(&buf, (*argv) + 1, PATH_MAX); - free(alias_string); - alias_string = buf.buf; - } - ret = system(alias_string + 1); - if (ret >= 0 && WIFEXITED(ret) && - WEXITSTATUS(ret) != 127) - exit(WEXITSTATUS(ret)); - die("Failed to run '%s' when expanding alias '%s'", - alias_string + 1, alias_command); - } - count = split_cmdline(alias_string, &new_argv); - if (count < 0) - die("Bad alias.%s string", alias_command); - option_count = handle_options(&new_argv, &count, &envchanged); - if (envchanged) - die("alias '%s' changes environment variables\n" - "You can use '!perf' in the alias to do this.", - alias_command); - memmove(new_argv - option_count, new_argv, - count * sizeof(char *)); - new_argv -= option_count; - - if (count < 1) - die("empty alias for %s", alias_command); - - if (!strcmp(alias_command, new_argv[0])) - die("recursive alias: %s", alias_command); - - new_argv = realloc(new_argv, sizeof(char*) * - (count + *argcp + 1)); - /* insert after command name */ - memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp); - new_argv[count+*argcp] = NULL; - - *argv = new_argv; - *argcp += count - 1; - - ret = 1; - } - - errno = saved_errno; - - return ret; -} - -const char perf_version_string[] = PERF_VERSION; - -#define RUN_SETUP (1<<0) -#define USE_PAGER (1<<1) -/* - * require working tree to be present -- anything uses this needs - * RUN_SETUP for reading from the configuration file. - */ -#define NEED_WORK_TREE (1<<2) - -struct cmd_struct { - const char *cmd; - int (*fn)(int, const char **, const char *); - int option; -}; - -static int run_builtin(struct cmd_struct *p, int argc, const char **argv) -{ - int status; - struct stat st; - const char *prefix; - - prefix = NULL; - if (p->option & RUN_SETUP) - prefix = NULL; /* setup_perf_directory(); */ - - if (use_pager == -1 && p->option & RUN_SETUP) - use_pager = check_pager_config(p->cmd); - if (use_pager == -1 && p->option & USE_PAGER) - use_pager = 1; - commit_pager_choice(); - - if (p->option & NEED_WORK_TREE) - /* setup_work_tree() */; - - status = p->fn(argc, argv, prefix); - if (status) - return status & 0xff; - - /* Somebody closed stdout? */ - if (fstat(fileno(stdout), &st)) - return 0; - /* Ignore write errors for pipes and sockets.. */ - if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) - return 0; - - /* Check for ENOSPC and EIO errors.. */ - if (fflush(stdout)) - die("write failure on standard output: %s", strerror(errno)); - if (ferror(stdout)) - die("unknown write failure on standard output"); - if (fclose(stdout)) - die("close failed on standard output: %s", strerror(errno)); - return 0; -} - -static void handle_internal_command(int argc, const char **argv) -{ - const char *cmd = argv[0]; - static struct cmd_struct commands[] = { - { "help", cmd_help, 0 }, - { "list", cmd_list, 0 }, - { "record", cmd_record, 0 }, - { "report", cmd_report, 0 }, - { "stat", cmd_stat, 0 }, - { "top", cmd_top, 0 }, - { "annotate", cmd_annotate, 0 }, - { "version", cmd_version, 0 }, - }; - int i; - static const char ext[] = STRIP_EXTENSION; - - if (sizeof(ext) > 1) { - i = strlen(argv[0]) - strlen(ext); - if (i > 0 && !strcmp(argv[0] + i, ext)) { - char *argv0 = strdup(argv[0]); - argv[0] = cmd = argv0; - argv0[i] = '\0'; - } - } - - /* Turn "perf cmd --help" into "perf help cmd" */ - if (argc > 1 && !strcmp(argv[1], "--help")) { - argv[1] = argv[0]; - argv[0] = cmd = "help"; - } - - for (i = 0; i < ARRAY_SIZE(commands); i++) { - struct cmd_struct *p = commands+i; - if (strcmp(p->cmd, cmd)) - continue; - exit(run_builtin(p, argc, argv)); - } -} - -static void execv_dashed_external(const char **argv) -{ - struct strbuf cmd = STRBUF_INIT; - const char *tmp; - int status; - - strbuf_addf(&cmd, "perf-%s", argv[0]); - - /* - * argv[0] must be the perf command, but the argv array - * belongs to the caller, and may be reused in - * subsequent loop iterations. Save argv[0] and - * restore it on error. - */ - tmp = argv[0]; - argv[0] = cmd.buf; - - /* - * if we fail because the command is not found, it is - * OK to return. Otherwise, we just pass along the status code. - */ - status = run_command_v_opt(argv, 0); - if (status != -ERR_RUN_COMMAND_EXEC) { - if (IS_RUN_COMMAND_ERR(status)) - die("unable to run '%s'", argv[0]); - exit(-status); - } - errno = ENOENT; /* as if we called execvp */ - - argv[0] = tmp; - - strbuf_release(&cmd); -} - -static int run_argv(int *argcp, const char ***argv) -{ - int done_alias = 0; - - while (1) { - /* See if it's an internal command */ - handle_internal_command(*argcp, *argv); - - /* .. then try the external ones */ - execv_dashed_external(*argv); - - /* It could be an alias -- this works around the insanity - * of overriding "perf log" with "perf show" by having - * alias.log = show - */ - if (done_alias || !handle_alias(argcp, argv)) - break; - done_alias = 1; - } - - return done_alias; -} - - -int main(int argc, const char **argv) -{ - const char *cmd; - - cmd = perf_extract_argv0_path(argv[0]); - if (!cmd) - cmd = "perf-help"; - - /* - * "perf-xxxx" is the same as "perf xxxx", but we obviously: - * - * - cannot take flags in between the "perf" and the "xxxx". - * - cannot execute it externally (since it would just do - * the same thing over again) - * - * So we just directly call the internal command handler, and - * die if that one cannot handle it. - */ - if (!prefixcmp(cmd, "perf-")) { - cmd += 5; - argv[0] = cmd; - handle_internal_command(argc, argv); - die("cannot handle %s internally", cmd); - } - - /* Look for flags.. */ - argv++; - argc--; - handle_options(&argv, &argc, NULL); - commit_pager_choice(); - if (argc > 0) { - if (!prefixcmp(argv[0], "--")) - argv[0] += 2; - } else { - /* The user didn't specify a command; give them help */ - printf("\n usage: %s\n\n", perf_usage_string); - list_common_cmds_help(); - printf("\n %s\n\n", perf_more_info_string); - exit(1); - } - cmd = argv[0]; - - /* - * We use PATH to find perf commands, but we prepend some higher - * precidence paths: the "--exec-path" option, the PERF_EXEC_PATH - * environment, and the $(perfexecdir) from the Makefile at build - * time. - */ - setup_path(); - - while (1) { - static int done_help = 0; - static int was_alias = 0; - - was_alias = run_argv(&argc, &argv); - if (errno != ENOENT) - break; - - if (was_alias) { - fprintf(stderr, "Expansion of alias '%s' failed; " - "'%s' is not a perf-command\n", - cmd, argv[0]); - exit(1); - } - if (!done_help) { - cmd = argv[0] = help_unknown_cmd(cmd); - done_help = 1; - } else - break; - } - - fprintf(stderr, "Failed to run command '%s': %s\n", - cmd, strerror(errno)); - - return 1; -} |