perf record: Provide default branch stack sampling mode option

This patch chanegs the logic of the -b, --branch-stack options
of perf record.

Based on users' request, the patch provides a default filter
mode with the -b (or --branch-any) option.  With the option,
any type of taken branches is sampled.

With -j (or --branch-filter), the user can specify any
valid combination of branch types and privilege levels
if supported by the underlying hardware.

The -b (--branch any) is a shortcut for: --branch-filter any.

 $ perf record -b foo

or:

 $ perf record --branch-filter any foo

For more specific filtering:

 $ perf record --branch-filter ind_call,u foo

Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-2-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Stephane Eranian
2012-03-08 23:47:45 +01:00
committed by Ingo Molnar
parent 114382a0ae
commit a5aabdacde
2 changed files with 57 additions and 34 deletions

View File

@@ -660,7 +660,7 @@ static const struct branch_mode branch_modes[] = {
};
static int
parse_branch_stack(const struct option *opt, const char *str, int unset __used)
parse_branch_stack(const struct option *opt, const char *str, int unset)
{
#define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER |\
@@ -669,40 +669,53 @@ parse_branch_stack(const struct option *opt, const char *str, int unset __used)
uint64_t *mode = (uint64_t *)opt->value;
const struct branch_mode *br;
char *s, *os, *p;
char *s, *os = NULL, *p;
int ret = -1;
*mode = 0;
if (unset)
return 0;
/* because str is read-only */
s = os = strdup(str);
if (!s)
/*
* cannot set it twice, -b + --branch-filter for instance
*/
if (*mode)
return -1;
for (;;) {
p = strchr(s, ',');
if (p)
*p = '\0';
/* str may be NULL in case no arg is passed to -b */
if (str) {
/* because str is read-only */
s = os = strdup(str);
if (!s)
return -1;
for (br = branch_modes; br->name; br++) {
if (!strcasecmp(s, br->name))
for (;;) {
p = strchr(s, ',');
if (p)
*p = '\0';
for (br = branch_modes; br->name; br++) {
if (!strcasecmp(s, br->name))
break;
}
if (!br->name) {
ui__warning("unknown branch filter %s,"
" check man page\n", s);
goto error;
}
*mode |= br->mode;
if (!p)
break;
s = p + 1;
}
if (!br->name)
goto error;
*mode |= br->mode;
if (!p)
break;
s = p + 1;
}
ret = 0;
/* default to any branch */
if ((*mode & ~ONLY_PLM) == 0) {
error("need at least one branch type with -b\n");
ret = -1;
*mode = PERF_SAMPLE_BRANCH_ANY;
}
error:
free(os);
@@ -798,8 +811,13 @@ const struct option record_options[] = {
"monitor event in cgroup name only",
parse_cgroups),
OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
OPT_CALLBACK('b', "branch-stack", &record.opts.branch_stack,
"branch mode mask", "branch stack sampling modes",
OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
"branch any", "sample any taken branches",
parse_branch_stack),
OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
"branch filter mask", "branch stack filter modes",
parse_branch_stack),
OPT_END()
};