2009-06-03 05:37:05 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2009-04-20 21:00:56 +08:00
|
|
|
#include "builtin.h"
|
2009-06-03 05:37:05 +08:00
|
|
|
|
2015-09-09 21:37:01 +08:00
|
|
|
#include "util/env.h"
|
2009-04-27 14:02:14 +08:00
|
|
|
#include "util/exec_cmd.h"
|
|
|
|
#include "util/cache.h"
|
|
|
|
#include "util/quote.h"
|
|
|
|
#include "util/run-command.h"
|
2009-07-22 02:16:29 +08:00
|
|
|
#include "util/parse-events.h"
|
perf tools: Fix the bash completion problem of 'perf --*'
The perf-completion.sh uses a predefined string '--help --version
--exec-path --html-path --paginate --no-pager --perf-dir --work-tree
--debugfs-dir' for the bash completion of 'perf --*', which has two
problems:
Problem 1: If the options of perf are changed (see handle_options() in
perf.c), the perf-completion.sh has to be changed at the same time. If
not, the bash completion of 'perf --*' and the options which perf
really supports will be inconsistent.
Problem 2: When typing another single character after 'perf --', e.g.
'h', and hit TAB key to get the bash completion of 'perf --h', the
character 'h' disappears at once. This is not what we want, we wish the
bash completion can return '--help --html-path' and then we can
continue to choose one.
To solve this problem, we add '--list-opts' to perf, which now supports
'perf --list-opts' directly, and its result can be used in bash
completion now.
Example:
Before this patch:
$ perf --h <-- hit TAB key after character 'h'
$ perf -- <-- 'h' disappears and no required result
After this patch:
$ perf --h <-- hit TAB key after character 'h'
--help --html-path <-- the required result
Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1425032491-20224-8-git-send-email-yunlong.song@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-02-27 18:21:31 +08:00
|
|
|
#include "util/parse-options.h"
|
perf tools: Enable passing bpf object file to --event
By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by an
eBPF object file. It calls parse_events_load_bpf() to load that file,
which uses bpf__prepare_load() and finally calls bpf_object__open() for
the object files.
After applying this patch, commands like:
# perf record --event foo.o sleep
become possible.
However, at this point it is unable to link any useful things onto the
evsel list because the creating of probe points and BPF program
attaching have not been implemented. Before real events are possible to
be extracted, to avoid perf report error because of empty evsel list,
this patch link a dummy evsel. The dummy event related code will be
removed when probing and extracting code is ready.
Commiter notes:
Using it:
$ ls -la foo.o
ls: cannot access foo.o: No such file or directory
$ perf record --event foo.o sleep
libbpf: failed to open foo.o: No such file or directory
event syntax error: 'foo.o'
\___ BPF object file 'foo.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/build/perf/perf.o
/tmp/build/perf/perf.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ perf record --event /tmp/build/perf/perf.o sleep
libbpf: /tmp/build/perf/perf.o is not an eBPF object file
event syntax error: '/tmp/build/perf/perf.o'
\___ BPF object file '/tmp/build/perf/perf.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/foo.o
/tmp/foo.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
$ perf record --event /tmp/foo.o sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data ]
$ perf evlist
/tmp/foo.o
$ perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
$
So, type 1 is PERF_TYPE_SOFTWARE, config 0x9 is PERF_COUNT_SW_DUMMY, ok.
$ perf report --stdio
Error:
The perf.data file has no samples!
# To display the perf.data header info, please use --header/--header-only options.
#
$
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-10-14 20:41:14 +08:00
|
|
|
#include "util/bpf-loader.h"
|
2014-07-17 18:55:00 +08:00
|
|
|
#include "util/debug.h"
|
2015-09-02 15:56:34 +08:00
|
|
|
#include <api/fs/tracing_path.h>
|
2012-09-08 08:43:19 +08:00
|
|
|
#include <pthread.h>
|
2009-04-20 21:00:56 +08:00
|
|
|
|
|
|
|
const char perf_usage_string[] =
|
2014-07-18 15:11:30 +08:00
|
|
|
"perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
|
2009-04-20 21:00:56 +08:00
|
|
|
|
|
|
|
const char perf_more_info_string[] =
|
|
|
|
"See 'perf help COMMAND' for more information on a specific command.";
|
|
|
|
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
int use_browser = -1;
|
2009-04-20 21:00:56 +08:00
|
|
|
static int use_pager = -1;
|
2012-10-30 11:56:02 +08:00
|
|
|
const char *input_name;
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
|
2012-08-09 22:31:51 +08:00
|
|
|
struct cmd_struct {
|
|
|
|
const char *cmd;
|
|
|
|
int (*fn)(int, const char **, const char *);
|
|
|
|
int option;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct cmd_struct commands[] = {
|
|
|
|
{ "buildid-cache", cmd_buildid_cache, 0 },
|
|
|
|
{ "buildid-list", cmd_buildid_list, 0 },
|
|
|
|
{ "diff", cmd_diff, 0 },
|
|
|
|
{ "evlist", cmd_evlist, 0 },
|
|
|
|
{ "help", cmd_help, 0 },
|
|
|
|
{ "list", cmd_list, 0 },
|
|
|
|
{ "record", cmd_record, 0 },
|
|
|
|
{ "report", cmd_report, 0 },
|
|
|
|
{ "bench", cmd_bench, 0 },
|
|
|
|
{ "stat", cmd_stat, 0 },
|
|
|
|
{ "timechart", cmd_timechart, 0 },
|
|
|
|
{ "top", cmd_top, 0 },
|
|
|
|
{ "annotate", cmd_annotate, 0 },
|
|
|
|
{ "version", cmd_version, 0 },
|
|
|
|
{ "script", cmd_script, 0 },
|
|
|
|
{ "sched", cmd_sched, 0 },
|
2013-09-30 18:07:11 +08:00
|
|
|
#ifdef HAVE_LIBELF_SUPPORT
|
2012-08-09 22:31:51 +08:00
|
|
|
{ "probe", cmd_probe, 0 },
|
2012-08-06 12:41:21 +08:00
|
|
|
#endif
|
2012-08-09 22:31:51 +08:00
|
|
|
{ "kmem", cmd_kmem, 0 },
|
|
|
|
{ "lock", cmd_lock, 0 },
|
|
|
|
{ "kvm", cmd_kvm, 0 },
|
|
|
|
{ "test", cmd_test, 0 },
|
2013-09-30 18:07:11 +08:00
|
|
|
#ifdef HAVE_LIBAUDIT_SUPPORT
|
2012-09-27 07:05:56 +08:00
|
|
|
{ "trace", cmd_trace, 0 },
|
2012-09-27 19:23:38 +08:00
|
|
|
#endif
|
2012-08-09 22:31:51 +08:00
|
|
|
{ "inject", cmd_inject, 0 },
|
2013-01-24 23:10:38 +08:00
|
|
|
{ "mem", cmd_mem, 0 },
|
2015-02-21 06:16:59 +08:00
|
|
|
{ "data", cmd_data, 0 },
|
2012-08-09 22:31:51 +08:00
|
|
|
};
|
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-11-12 10:50:17 +08:00
|
|
|
static int browser_command_config(const char *var, const char *value, void *data)
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
{
|
|
|
|
struct pager_config *c = data;
|
|
|
|
if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd))
|
|
|
|
c->val = perf_config_bool(var, value);
|
2012-11-12 10:50:17 +08:00
|
|
|
if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd))
|
|
|
|
c->val = perf_config_bool(var, value) ? 2 : 0;
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-12 10:50:17 +08:00
|
|
|
/*
|
|
|
|
* returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
|
|
|
|
* and -1 for "not specified"
|
|
|
|
*/
|
|
|
|
static int check_browser_config(const char *cmd)
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
{
|
|
|
|
struct pager_config c;
|
|
|
|
c.cmd = cmd;
|
|
|
|
c.val = -1;
|
2012-11-12 10:50:17 +08:00
|
|
|
perf_config(browser_command_config, &c);
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
return c.val;
|
|
|
|
}
|
|
|
|
|
2010-01-28 07:05:55 +08:00
|
|
|
static void commit_pager_choice(void)
|
|
|
|
{
|
2009-04-20 21:00:56 +08:00
|
|
|
switch (use_pager) {
|
|
|
|
case 0:
|
|
|
|
setenv("PERF_PAGER", "cat", 1);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
/* setup_pager(); */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
perf tools: Fix the bash completion problem of 'perf --*'
The perf-completion.sh uses a predefined string '--help --version
--exec-path --html-path --paginate --no-pager --perf-dir --work-tree
--debugfs-dir' for the bash completion of 'perf --*', which has two
problems:
Problem 1: If the options of perf are changed (see handle_options() in
perf.c), the perf-completion.sh has to be changed at the same time. If
not, the bash completion of 'perf --*' and the options which perf
really supports will be inconsistent.
Problem 2: When typing another single character after 'perf --', e.g.
'h', and hit TAB key to get the bash completion of 'perf --h', the
character 'h' disappears at once. This is not what we want, we wish the
bash completion can return '--help --html-path' and then we can
continue to choose one.
To solve this problem, we add '--list-opts' to perf, which now supports
'perf --list-opts' directly, and its result can be used in bash
completion now.
Example:
Before this patch:
$ perf --h <-- hit TAB key after character 'h'
$ perf -- <-- 'h' disappears and no required result
After this patch:
$ perf --h <-- hit TAB key after character 'h'
--help --html-path <-- the required result
Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1425032491-20224-8-git-send-email-yunlong.song@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-02-27 18:21:31 +08:00
|
|
|
struct option options[] = {
|
|
|
|
OPT_ARGUMENT("help", "help"),
|
|
|
|
OPT_ARGUMENT("version", "version"),
|
|
|
|
OPT_ARGUMENT("exec-path", "exec-path"),
|
|
|
|
OPT_ARGUMENT("html-path", "html-path"),
|
|
|
|
OPT_ARGUMENT("paginate", "paginate"),
|
|
|
|
OPT_ARGUMENT("no-pager", "no-pager"),
|
|
|
|
OPT_ARGUMENT("perf-dir", "perf-dir"),
|
|
|
|
OPT_ARGUMENT("work-tree", "work-tree"),
|
|
|
|
OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
|
|
|
|
OPT_ARGUMENT("buildid-dir", "buildid-dir"),
|
|
|
|
OPT_ARGUMENT("list-cmds", "list-cmds"),
|
|
|
|
OPT_ARGUMENT("list-opts", "list-opts"),
|
|
|
|
OPT_ARGUMENT("debug", "debug"),
|
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
2010-01-28 07:05:55 +08:00
|
|
|
static int handle_options(const char ***argv, int *argc, int *envchanged)
|
2009-04-20 21:00:56 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2015-10-06 02:06:09 +08:00
|
|
|
/*
|
|
|
|
* Shortcut for '-h' and '-v' options to invoke help
|
|
|
|
* and version command.
|
|
|
|
*/
|
|
|
|
if (!strcmp(cmd, "-h")) {
|
|
|
|
(*argv)[0] = "--help";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(cmd, "-v")) {
|
|
|
|
(*argv)[0] = "--version";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
/*
|
|
|
|
* Check remaining flags.
|
|
|
|
*/
|
2009-10-13 16:18:16 +08:00
|
|
|
if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
|
|
|
|
cmd += strlen(CMD_EXEC_PATH);
|
2009-04-20 21:00:56 +08:00
|
|
|
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) {
|
2010-01-28 07:05:55 +08:00
|
|
|
fprintf(stderr, "No directory given for --perf-dir.\n");
|
2009-04-20 21:00:56 +08:00
|
|
|
usage(perf_usage_string);
|
|
|
|
}
|
|
|
|
setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
|
|
|
handled++;
|
2009-10-13 16:18:16 +08:00
|
|
|
} else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
|
|
|
|
setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
|
2009-04-20 21:00:56 +08:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
} else if (!strcmp(cmd, "--work-tree")) {
|
|
|
|
if (*argc < 2) {
|
2010-01-28 07:05:55 +08:00
|
|
|
fprintf(stderr, "No directory given for --work-tree.\n");
|
2009-04-20 21:00:56 +08:00
|
|
|
usage(perf_usage_string);
|
|
|
|
}
|
|
|
|
setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2009-10-13 16:18:16 +08:00
|
|
|
} else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
|
|
|
|
setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
|
2009-04-20 21:00:56 +08:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2009-07-22 02:16:29 +08:00
|
|
|
} else if (!strcmp(cmd, "--debugfs-dir")) {
|
|
|
|
if (*argc < 2) {
|
|
|
|
fprintf(stderr, "No directory given for --debugfs-dir.\n");
|
|
|
|
usage(perf_usage_string);
|
|
|
|
}
|
2015-09-02 15:56:33 +08:00
|
|
|
tracing_path_set((*argv)[1]);
|
2009-07-22 02:16:29 +08:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2014-12-02 03:06:24 +08:00
|
|
|
} else if (!strcmp(cmd, "--buildid-dir")) {
|
|
|
|
if (*argc < 2) {
|
|
|
|
fprintf(stderr, "No directory given for --buildid-dir.\n");
|
|
|
|
usage(perf_usage_string);
|
|
|
|
}
|
|
|
|
set_buildid_dir((*argv)[1]);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2009-10-13 16:18:16 +08:00
|
|
|
} else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
|
2015-09-02 15:56:33 +08:00
|
|
|
tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
|
2015-08-26 21:46:45 +08:00
|
|
|
fprintf(stderr, "dir: %s\n", tracing_path);
|
2009-07-22 02:16:29 +08:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2012-08-09 22:31:51 +08:00
|
|
|
} else if (!strcmp(cmd, "--list-cmds")) {
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
|
|
|
struct cmd_struct *p = commands+i;
|
|
|
|
printf("%s ", p->cmd);
|
|
|
|
}
|
2015-02-27 18:21:29 +08:00
|
|
|
putchar('\n');
|
2012-08-09 22:31:51 +08:00
|
|
|
exit(0);
|
perf tools: Fix the bash completion problem of 'perf --*'
The perf-completion.sh uses a predefined string '--help --version
--exec-path --html-path --paginate --no-pager --perf-dir --work-tree
--debugfs-dir' for the bash completion of 'perf --*', which has two
problems:
Problem 1: If the options of perf are changed (see handle_options() in
perf.c), the perf-completion.sh has to be changed at the same time. If
not, the bash completion of 'perf --*' and the options which perf
really supports will be inconsistent.
Problem 2: When typing another single character after 'perf --', e.g.
'h', and hit TAB key to get the bash completion of 'perf --h', the
character 'h' disappears at once. This is not what we want, we wish the
bash completion can return '--help --html-path' and then we can
continue to choose one.
To solve this problem, we add '--list-opts' to perf, which now supports
'perf --list-opts' directly, and its result can be used in bash
completion now.
Example:
Before this patch:
$ perf --h <-- hit TAB key after character 'h'
$ perf -- <-- 'h' disappears and no required result
After this patch:
$ perf --h <-- hit TAB key after character 'h'
--help --html-path <-- the required result
Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1425032491-20224-8-git-send-email-yunlong.song@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-02-27 18:21:31 +08:00
|
|
|
} else if (!strcmp(cmd, "--list-opts")) {
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
|
|
|
|
struct option *p = options+i;
|
|
|
|
printf("--%s ", p->long_name);
|
|
|
|
}
|
|
|
|
putchar('\n');
|
|
|
|
exit(0);
|
2014-07-17 18:55:00 +08:00
|
|
|
} else if (!strcmp(cmd, "--debug")) {
|
|
|
|
if (*argc < 2) {
|
|
|
|
fprintf(stderr, "No variable specified for --debug.\n");
|
|
|
|
usage(perf_usage_string);
|
|
|
|
}
|
|
|
|
if (perf_debug_option((*argv)[1]))
|
|
|
|
usage(perf_usage_string);
|
|
|
|
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2009-04-20 21:00:56 +08:00
|
|
|
} 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;
|
2010-01-28 07:05:55 +08:00
|
|
|
const char **new_argv;
|
2009-04-20 21:00:56 +08:00
|
|
|
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);
|
|
|
|
|
2010-01-28 07:05:55 +08:00
|
|
|
new_argv = realloc(new_argv, sizeof(char *) *
|
2009-04-20 21:00:56 +08:00
|
|
|
(count + *argcp + 1));
|
|
|
|
/* insert after command name */
|
2010-01-28 07:05:55 +08:00
|
|
|
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
|
|
|
|
new_argv[count + *argcp] = NULL;
|
2009-04-20 21:00:56 +08:00
|
|
|
|
|
|
|
*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)
|
|
|
|
|
|
|
|
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
struct stat st;
|
|
|
|
const char *prefix;
|
2014-08-14 10:22:32 +08:00
|
|
|
char sbuf[STRERR_BUFSIZE];
|
2009-04-20 21:00:56 +08:00
|
|
|
|
|
|
|
prefix = NULL;
|
|
|
|
if (p->option & RUN_SETUP)
|
|
|
|
prefix = NULL; /* setup_perf_directory(); */
|
|
|
|
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
if (use_browser == -1)
|
2012-11-12 10:50:17 +08:00
|
|
|
use_browser = check_browser_config(p->cmd);
|
perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
Using the same scheme as for git's/perf's pager setup, i.e. if one
doesn't want to, on a newt enabled perf binary, to disable the TUI for
'perf report', its just a matter of doing:
[root@doppio linux-2.6-tip]# printf "[tui]\n\nreport = off\n" >
/root/.perfconfig
[root@doppio linux-2.6-tip]# cat /root/.perfconfig
[tui]
report = off
[root@doppio linux-2.6-tip]#
System wide settings are also possible, by editing /etc/perfconfig, etc,
i.e. the git machinery for config files applies to perf as well, so when
in doubt where to put your settings, consult the git documentation, if
it fails, please let us know.
Suggested-by: Ingo Molnar <mingo@elte.hu>
Discussed-with: Stephane Eranian <eranian@google.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-05-21 09:01:10 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
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();
|
|
|
|
|
|
|
|
status = p->fn(argc, argv, prefix);
|
2010-03-23 00:10:25 +08:00
|
|
|
exit_browser(status);
|
2015-09-09 21:37:01 +08:00
|
|
|
perf_env__exit(&perf_env);
|
perf tools: Enable passing bpf object file to --event
By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by an
eBPF object file. It calls parse_events_load_bpf() to load that file,
which uses bpf__prepare_load() and finally calls bpf_object__open() for
the object files.
After applying this patch, commands like:
# perf record --event foo.o sleep
become possible.
However, at this point it is unable to link any useful things onto the
evsel list because the creating of probe points and BPF program
attaching have not been implemented. Before real events are possible to
be extracted, to avoid perf report error because of empty evsel list,
this patch link a dummy evsel. The dummy event related code will be
removed when probing and extracting code is ready.
Commiter notes:
Using it:
$ ls -la foo.o
ls: cannot access foo.o: No such file or directory
$ perf record --event foo.o sleep
libbpf: failed to open foo.o: No such file or directory
event syntax error: 'foo.o'
\___ BPF object file 'foo.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/build/perf/perf.o
/tmp/build/perf/perf.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ perf record --event /tmp/build/perf/perf.o sleep
libbpf: /tmp/build/perf/perf.o is not an eBPF object file
event syntax error: '/tmp/build/perf/perf.o'
\___ BPF object file '/tmp/build/perf/perf.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/foo.o
/tmp/foo.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
$ perf record --event /tmp/foo.o sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data ]
$ perf evlist
/tmp/foo.o
$ perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
$
So, type 1 is PERF_TYPE_SOFTWARE, config 0x9 is PERF_COUNT_SW_DUMMY, ok.
$ perf report --stdio
Error:
The perf.data file has no samples!
# To display the perf.data header info, please use --header/--header-only options.
#
$
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-10-14 20:41:14 +08:00
|
|
|
bpf__clear();
|
2010-03-23 00:10:25 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
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;
|
|
|
|
|
2013-01-25 02:18:54 +08:00
|
|
|
status = 1;
|
2009-04-20 21:00:56 +08:00
|
|
|
/* Check for ENOSPC and EIO errors.. */
|
2013-01-25 02:18:54 +08:00
|
|
|
if (fflush(stdout)) {
|
2014-08-14 10:22:32 +08:00
|
|
|
fprintf(stderr, "write failure on standard output: %s",
|
|
|
|
strerror_r(errno, sbuf, sizeof(sbuf)));
|
2013-01-25 02:18:54 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (ferror(stdout)) {
|
|
|
|
fprintf(stderr, "unknown write failure on standard output");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (fclose(stdout)) {
|
2014-08-14 10:22:32 +08:00
|
|
|
fprintf(stderr, "close failed on standard output: %s",
|
|
|
|
strerror_r(errno, sbuf, sizeof(sbuf)));
|
2013-01-25 02:18:54 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
status = 0;
|
|
|
|
out:
|
|
|
|
return status;
|
2009-04-20 21:00:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_internal_command(int argc, const char **argv)
|
|
|
|
{
|
|
|
|
const char *cmd = argv[0];
|
2009-07-01 18:37:06 +08:00
|
|
|
unsigned int i;
|
2009-04-20 21:00:56 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-10-13 19:52:46 +08:00
|
|
|
static void pthread__block_sigwinch(void)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
sigaddset(&set, SIGWINCH);
|
|
|
|
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pthread__unblock_sigwinch(void)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
sigaddset(&set, SIGWINCH);
|
|
|
|
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
|
|
|
}
|
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
int main(int argc, const char **argv)
|
|
|
|
{
|
|
|
|
const char *cmd;
|
2014-08-14 10:22:32 +08:00
|
|
|
char sbuf[STRERR_BUFSIZE];
|
2009-04-20 21:00:56 +08:00
|
|
|
|
2013-09-13 00:39:35 +08:00
|
|
|
/* The page_size is placed in util object. */
|
2012-10-07 01:57:10 +08:00
|
|
|
page_size = sysconf(_SC_PAGE_SIZE);
|
2014-05-31 04:10:05 +08:00
|
|
|
cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
2012-10-07 01:57:10 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
cmd = perf_extract_argv0_path(argv[0]);
|
|
|
|
if (!cmd)
|
|
|
|
cmd = "perf-help";
|
2015-09-02 15:56:33 +08:00
|
|
|
|
|
|
|
/* get debugfs/tracefs mount point from /proc/mounts */
|
|
|
|
tracing_path_mount();
|
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
/*
|
|
|
|
* "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-")) {
|
2009-05-25 20:45:24 +08:00
|
|
|
cmd += 5;
|
2009-04-20 21:00:56 +08:00
|
|
|
argv[0] = cmd;
|
|
|
|
handle_internal_command(argc, argv);
|
2013-01-25 02:18:54 +08:00
|
|
|
fprintf(stderr, "cannot handle %s internally", cmd);
|
|
|
|
goto out;
|
2009-04-20 21:00:56 +08:00
|
|
|
}
|
perf trace: Add 'trace' alias to 'perf trace'
Make 'perf trace' more accessible by aliasing it to just 'trace':
[root@zoo linux]# trace --duration 15 -a -e futex sleep 1
110.092 (16.188 ms): libvirtd/1166 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174293 ) = 0
110.101 (15.903 ms): libvirtd/1171 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139265 ) = 0
111.594 (15.776 ms): libvirtd/1165 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174295 ) = 0
111.610 (15.969 ms): libvirtd/1169 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139267 ) = 0
113.556 (16.216 ms): libvirtd/1168 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139269 ) = 0
291.265 (199.508 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
360.354 (69.053 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
[root@zoo linux]#
I.e. looking for futex calls that take at least 15ms, system wide, during a one
second window. Now to get callchains into 'trace' to figure out what are those
locks :-)
Requested-by: Ingo Molnar <mingo@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ch4smqz8b5fmgrte7c5e4fuw@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-09-24 22:56:36 +08:00
|
|
|
if (!prefixcmp(cmd, "trace")) {
|
2014-05-27 03:02:29 +08:00
|
|
|
#ifdef HAVE_LIBAUDIT_SUPPORT
|
2014-12-02 03:06:24 +08:00
|
|
|
set_buildid_dir(NULL);
|
perf trace: Add 'trace' alias to 'perf trace'
Make 'perf trace' more accessible by aliasing it to just 'trace':
[root@zoo linux]# trace --duration 15 -a -e futex sleep 1
110.092 (16.188 ms): libvirtd/1166 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174293 ) = 0
110.101 (15.903 ms): libvirtd/1171 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139265 ) = 0
111.594 (15.776 ms): libvirtd/1165 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174295 ) = 0
111.610 (15.969 ms): libvirtd/1169 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139267 ) = 0
113.556 (16.216 ms): libvirtd/1168 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139269 ) = 0
291.265 (199.508 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
360.354 (69.053 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
[root@zoo linux]#
I.e. looking for futex calls that take at least 15ms, system wide, during a one
second window. Now to get callchains into 'trace' to figure out what are those
locks :-)
Requested-by: Ingo Molnar <mingo@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ch4smqz8b5fmgrte7c5e4fuw@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-09-24 22:56:36 +08:00
|
|
|
setup_path();
|
|
|
|
argv[0] = "trace";
|
|
|
|
return cmd_trace(argc, argv, NULL);
|
2014-05-27 03:02:29 +08:00
|
|
|
#else
|
|
|
|
fprintf(stderr,
|
|
|
|
"trace command not available: missing audit-libs devel package at build time.\n");
|
|
|
|
goto out;
|
perf trace: Add 'trace' alias to 'perf trace'
Make 'perf trace' more accessible by aliasing it to just 'trace':
[root@zoo linux]# trace --duration 15 -a -e futex sleep 1
110.092 (16.188 ms): libvirtd/1166 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174293 ) = 0
110.101 (15.903 ms): libvirtd/1171 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139265 ) = 0
111.594 (15.776 ms): libvirtd/1165 futex(uaddr: 0x185b344, op: WAIT|PRIV, val: 174295 ) = 0
111.610 (15.969 ms): libvirtd/1169 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139267 ) = 0
113.556 (16.216 ms): libvirtd/1168 futex(uaddr: 0x185b3dc, op: WAIT|PRIV, val: 139269 ) = 0
291.265 (199.508 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
360.354 (69.053 ms): chromium-brows/15830 futex(uaddr: 0x7fff2986bcb4, op: WAIT_BITSET|PRIV|CLKRT, val: 1, utime: 0x7fff2986bab0, val3: 4294967295) = -1 ETIMEDOUT Connection timed out
[root@zoo linux]#
I.e. looking for futex calls that take at least 15ms, system wide, during a one
second window. Now to get callchains into 'trace' to figure out what are those
locks :-)
Requested-by: Ingo Molnar <mingo@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ch4smqz8b5fmgrte7c5e4fuw@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-09-24 22:56:36 +08:00
|
|
|
#endif
|
2014-05-27 03:02:29 +08:00
|
|
|
}
|
2009-04-20 21:00:56 +08:00
|
|
|
/* Look for flags.. */
|
|
|
|
argv++;
|
|
|
|
argc--;
|
|
|
|
handle_options(&argv, &argc, NULL);
|
|
|
|
commit_pager_choice();
|
2014-12-02 03:06:24 +08:00
|
|
|
set_buildid_dir(NULL);
|
perf buildid: add perfconfig option to specify buildid cache dir
This patch adds the ability to specify an alternate directory to store the
buildid cache (buildids, copy of binaries). By default, it is hardcoded to
$HOME/.debug. This directory contains immutable data. The layout of the
directory is such that no conflicts in filenames are possible. A modification
in a file, yields a different buildid and thus a different location in the
subdir hierarchy.
You may want to put the buildid cache elsewhere because of disk space
limitation or simply to share the cache between users. It is also useful for
remote collect vs. local analysis of profiles.
This patch adds a new config option to the perfconfig file. Under the tag
'buildid', there is a dir option. For instance, if you have:
$ cat /etc/perfconfig
[buildid]
dir = /var/cache/perf-buildid
All buildids and binaries are be saved in the directory specified. The perf
record, buildid-list, buildid-cache, report, annotate, and archive commands
will it to pull information out.
The option can be set in the system-wide perfconfig file or in the
$HOME/.perfconfig file.
Cc: David S. Miller <davem@davemloft.net>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <4c055fb7.df0ce30a.5f0d.ffffae52@mx.google.com>
Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-06-02 03:25:01 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
if (argc > 0) {
|
|
|
|
if (!prefixcmp(argv[0], "--"))
|
|
|
|
argv[0] += 2;
|
|
|
|
} else {
|
|
|
|
/* The user didn't specify a command; give them help */
|
2009-03-13 10:20:49 +08:00
|
|
|
printf("\n usage: %s\n\n", perf_usage_string);
|
2009-04-20 21:00:56 +08:00
|
|
|
list_common_cmds_help();
|
2009-03-13 10:20:49 +08:00
|
|
|
printf("\n %s\n\n", perf_more_info_string);
|
2013-01-25 02:18:54 +08:00
|
|
|
goto out;
|
2009-04-20 21:00:56 +08:00
|
|
|
}
|
|
|
|
cmd = argv[0];
|
|
|
|
|
2012-10-31 22:52:47 +08:00
|
|
|
test_attr__init();
|
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
/*
|
|
|
|
* We use PATH to find perf commands, but we prepend some higher
|
2010-01-18 23:02:48 +08:00
|
|
|
* precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
|
2009-04-20 21:00:56 +08:00
|
|
|
* environment, and the $(perfexecdir) from the Makefile at build
|
|
|
|
* time.
|
|
|
|
*/
|
|
|
|
setup_path();
|
2011-10-13 19:52:46 +08:00
|
|
|
/*
|
|
|
|
* Block SIGWINCH notifications so that the thread that wants it can
|
|
|
|
* unblock and get syscalls like select interrupted instead of waiting
|
|
|
|
* forever while the signal goes to some other non interested thread.
|
|
|
|
*/
|
|
|
|
pthread__block_sigwinch();
|
2009-04-20 21:00:56 +08:00
|
|
|
|
|
|
|
while (1) {
|
2010-01-28 07:05:55 +08:00
|
|
|
static int done_help;
|
2013-03-27 22:00:07 +08:00
|
|
|
int was_alias = run_argv(&argc, &argv);
|
2009-06-06 21:19:13 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
if (errno != ENOENT)
|
|
|
|
break;
|
2009-06-06 21:19:13 +08:00
|
|
|
|
2009-04-20 21:00:56 +08:00
|
|
|
if (was_alias) {
|
|
|
|
fprintf(stderr, "Expansion of alias '%s' failed; "
|
|
|
|
"'%s' is not a perf-command\n",
|
|
|
|
cmd, argv[0]);
|
2013-01-25 02:18:54 +08:00
|
|
|
goto out;
|
2009-04-20 21:00:56 +08:00
|
|
|
}
|
|
|
|
if (!done_help) {
|
|
|
|
cmd = argv[0] = help_unknown_cmd(cmd);
|
|
|
|
done_help = 1;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Failed to run command '%s': %s\n",
|
2014-08-14 10:22:32 +08:00
|
|
|
cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
|
2013-01-25 02:18:54 +08:00
|
|
|
out:
|
2009-04-20 21:00:56 +08:00
|
|
|
return 1;
|
|
|
|
}
|