diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/evsel.c | 9 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-branch-options.c | 85 | ||||
-rw-r--r-- | tools/perf/util/parse-branch-options.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 15 |
5 files changed, 71 insertions, 43 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8bc271141d9d..e58a2fbf3b16 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -28,6 +28,7 @@ #include "debug.h" #include "trace-event.h" #include "stat.h" +#include "util/parse-branch-options.h" static struct { bool sample_id_all; @@ -708,6 +709,14 @@ static void apply_config_terms(struct perf_evsel *evsel, case PERF_EVSEL__CONFIG_TERM_CALLGRAPH: callgraph_buf = term->val.callgraph; break; + case PERF_EVSEL__CONFIG_TERM_BRANCH: + if (term->val.branch && strcmp(term->val.branch, "no")) { + perf_evsel__set_sample_bit(evsel, BRANCH_STACK); + parse_branch_str(term->val.branch, + &attr->branch_sample_type); + } else + perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); + break; case PERF_EVSEL__CONFIG_TERM_STACK_USER: dump_size = term->val.stack_user; break; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index b1503b0ecdff..8cd7cd227483 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -47,6 +47,7 @@ enum { PERF_EVSEL__CONFIG_TERM_MAX_STACK, PERF_EVSEL__CONFIG_TERM_OVERWRITE, PERF_EVSEL__CONFIG_TERM_DRV_CFG, + PERF_EVSEL__CONFIG_TERM_BRANCH, PERF_EVSEL__CONFIG_TERM_MAX, }; @@ -63,6 +64,7 @@ struct perf_evsel_config_term { int max_stack; bool inherit; bool overwrite; + char *branch; } val; }; diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c index afc088dd7d20..3634d6974300 100644 --- a/tools/perf/util/parse-branch-options.c +++ b/tools/perf/util/parse-branch-options.c @@ -31,59 +31,51 @@ static const struct branch_mode branch_modes[] = { BRANCH_END }; -int -parse_branch_stack(const struct option *opt, const char *str, int unset) +int parse_branch_str(const char *str, __u64 *mode) { #define ONLY_PLM \ (PERF_SAMPLE_BRANCH_USER |\ PERF_SAMPLE_BRANCH_KERNEL |\ PERF_SAMPLE_BRANCH_HV) - uint64_t *mode = (uint64_t *)opt->value; + int ret = 0; + char *p, *s; + char *os = NULL; const struct branch_mode *br; - char *s, *os = NULL, *p; - int ret = -1; - if (unset) + if (str == NULL) { + *mode = PERF_SAMPLE_BRANCH_ANY; return 0; + } - /* - * cannot set it twice, -b + --branch-filter for instance - */ - if (*mode) + /* because str is read-only */ + s = os = strdup(str); + if (!s) return -1; - /* 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 (;;) { - 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; + for (;;) { + p = strchr(s, ','); + if (p) + *p = '\0'; - s = p + 1; + for (br = branch_modes; br->name; br++) { + if (!strcasecmp(s, br->name)) + break; + } + if (!br->name) { + ret = -1; + ui__warning("unknown branch filter %s," + " check man page\n", s); + goto error; } + + *mode |= br->mode; + + if (!p) + break; + + s = p + 1; } - ret = 0; /* default to any branch */ if ((*mode & ~ONLY_PLM) == 0) { @@ -93,3 +85,20 @@ error: free(os); return ret; } + +int +parse_branch_stack(const struct option *opt, const char *str, int unset) +{ + __u64 *mode = (__u64 *)opt->value; + + if (unset) + return 0; + + /* + * cannot set it twice, -b + --branch-filter for instance + */ + if (*mode) + return -1; + + return parse_branch_str(str, mode); +} diff --git a/tools/perf/util/parse-branch-options.h b/tools/perf/util/parse-branch-options.h index b9d9470c2e82..6086fd90eb23 100644 --- a/tools/perf/util/parse-branch-options.h +++ b/tools/perf/util/parse-branch-options.h @@ -1,5 +1,6 @@ #ifndef _PERF_PARSE_BRANCH_OPTIONS_H #define _PERF_PARSE_BRANCH_OPTIONS_H 1 -struct option; +#include <stdint.h> int parse_branch_stack(const struct option *opt, const char *str, int unset); +int parse_branch_str(const char *str, __u64 *mode); #endif /* _PERF_PARSE_BRANCH_OPTIONS_H */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4e778eae1510..3c876b8ba4de 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -22,6 +22,7 @@ #include "cpumap.h" #include "probe-file.h" #include "asm/bug.h" +#include "util/parse-branch-options.h" #define MAX_NAME_LEN 100 @@ -973,10 +974,13 @@ do { \ CHECK_TYPE_VAL(NUM); break; case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: - /* - * TODO uncomment when the field is available - * attr->branch_sample_type = term->val.num; - */ + CHECK_TYPE_VAL(STR); + if (strcmp(term->val.str, "no") && + parse_branch_str(term->val.str, &attr->branch_sample_type)) { + err->str = strdup("invalid branch sample type"); + err->idx = term->err_val; + return -EINVAL; + } break; case PARSE_EVENTS__TERM_TYPE_TIME: CHECK_TYPE_VAL(NUM); @@ -1119,6 +1123,9 @@ do { \ case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str); break; + case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: + ADD_CONFIG_TERM(BRANCH, branch, term->val.str); + break; case PARSE_EVENTS__TERM_TYPE_STACKSIZE: ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); break; |