diff options
author | Jiri Olsa <jolsa@redhat.com> | 2012-03-15 23:09:16 +0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-03-16 21:26:06 +0400 |
commit | 8f707d843c2f4023490a873dbc182f632a3a5906 (patch) | |
tree | e4c6d509756aa869314888de0d5873c4a20a7e92 /tools/perf/util/parse-events.c | |
parent | 89812fc81f8d62d70433a8ff63d26819f372e8ec (diff) | |
download | linux-8f707d843c2f4023490a873dbc182f632a3a5906.tar.xz |
perf tools: Add config options support for event parsing
Adding a new rule to the event grammar to be able to specify
values of additional attributes of symbolic event.
The new syntax for event symbolic definition is:
event_legacy_symbol: PE_NAME_SYM '/' event_config '/' |
PE_NAME_SYM sep_slash_dc
event_config: event_config ',' event_term | event_term
event_term: PE_NAME '=' PE_NAME |
PE_NAME '=' PE_VALUE
PE_NAME
sep_slash_dc: '/' | ':' |
At the moment the config options are hardcoded to be used for legacy
symbol events to define several perf_event_attr fields. It is:
'config' to define perf_event_attr::config
'config1' to define perf_event_attr::config1
'config2' to define perf_event_attr::config2
'period' to define perf_event_attr::sample_period
Legacy events could be now specified as:
cycles/period=100000/
If term is specified without the value assignment, then 1 is
assigned by default.
Acked-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/n/tip-mgkavww9790jbt2jdkooyv4q@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 99 |
1 files changed, 96 insertions, 3 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6e50b914cad4..59f5cf64ef70 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -588,15 +588,60 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx, return add_event(list, idx, &attr, name); } -int -parse_events_add_numeric(struct list_head *list, int *idx, - unsigned long type, unsigned long config) +static int config_term(struct perf_event_attr *attr, + struct parse_events__term *term) +{ + switch (term->type) { + case PARSE_EVENTS__TERM_TYPE_CONFIG: + attr->config = term->val.num; + break; + case PARSE_EVENTS__TERM_TYPE_CONFIG1: + attr->config1 = term->val.num; + break; + case PARSE_EVENTS__TERM_TYPE_CONFIG2: + attr->config2 = term->val.num; + break; + case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: + attr->sample_period = term->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; + */ + break; + default: + return -EINVAL; + } + return 0; +} + +static int config_attr(struct perf_event_attr *attr, + struct list_head *head, int fail) +{ + struct parse_events__term *term; + + list_for_each_entry(term, head, list) + if (config_term(attr, term) && fail) + return -EINVAL; + + return 0; +} + +int parse_events_add_numeric(struct list_head *list, int *idx, + unsigned long type, unsigned long config, + struct list_head *head_config) { struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); attr.type = type; attr.config = config; + + if (head_config && + config_attr(&attr, head_config, 1)) + return -EINVAL; + return add_event(list, idx, &attr, (char *) __event_name(type, config)); } @@ -923,3 +968,51 @@ void print_events(const char *event_glob) print_tracepoint_events(NULL, NULL); } + +int parse_events__is_hardcoded_term(struct parse_events__term *term) +{ + return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX; +} + +int parse_events__new_term(struct parse_events__term **_term, int type, + char *config, char *str, long num) +{ + struct parse_events__term *term; + + term = zalloc(sizeof(*term)); + if (!term) + return -ENOMEM; + + INIT_LIST_HEAD(&term->list); + term->type = type; + term->config = config; + + switch (type) { + case PARSE_EVENTS__TERM_TYPE_CONFIG: + case PARSE_EVENTS__TERM_TYPE_CONFIG1: + case PARSE_EVENTS__TERM_TYPE_CONFIG2: + case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: + case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: + case PARSE_EVENTS__TERM_TYPE_NUM: + term->val.num = num; + break; + case PARSE_EVENTS__TERM_TYPE_STR: + term->val.str = str; + break; + default: + return -EINVAL; + } + + *_term = term; + return 0; +} + +void parse_events__free_terms(struct list_head *terms) +{ + struct parse_events__term *term, *h; + + list_for_each_entry_safe(term, h, terms, list) + free(term); + + free(terms); +} |