diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 114 |
1 files changed, 87 insertions, 27 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5b3a0ef4e23..fac7d59309b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -23,8 +23,10 @@ struct event_symbol { const char *alias; }; -int parse_events_parse(struct list_head *list, struct list_head *list_tmp, - int *idx); +#ifdef PARSER_DEBUG +extern int parse_events_debug; +#endif +int parse_events_parse(struct list_head *list, int *idx); #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x @@ -355,20 +357,30 @@ const char *__event_name(int type, u64 config) return "unknown"; } -static int add_event(struct list_head *list, int *idx, +static int add_event(struct list_head **_list, int *idx, struct perf_event_attr *attr, char *name) { struct perf_evsel *evsel; + struct list_head *list = *_list; + + if (!list) { + list = malloc(sizeof(*list)); + if (!list) + return -ENOMEM; + INIT_LIST_HEAD(list); + } event_attr_init(attr); evsel = perf_evsel__new(attr, (*idx)++); - if (!evsel) + if (!evsel) { + free(list); return -ENOMEM; - - list_add_tail(&evsel->node, list); + } evsel->name = strdup(name); + list_add_tail(&evsel->node, list); + *_list = list; return 0; } @@ -390,7 +402,7 @@ static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) return -1; } -int parse_events_add_cache(struct list_head *list, int *idx, +int parse_events_add_cache(struct list_head **list, int *idx, char *type, char *op_result1, char *op_result2) { struct perf_event_attr attr; @@ -451,7 +463,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, return add_event(list, idx, &attr, name); } -static int add_tracepoint(struct list_head *list, int *idx, +static int add_tracepoint(struct list_head **list, int *idx, char *sys_name, char *evt_name) { struct perf_event_attr attr; @@ -488,7 +500,7 @@ static int add_tracepoint(struct list_head *list, int *idx, return add_event(list, idx, &attr, name); } -static int add_tracepoint_multi(struct list_head *list, int *idx, +static int add_tracepoint_multi(struct list_head **list, int *idx, char *sys_name, char *evt_name) { char evt_path[MAXPATHLEN]; @@ -519,7 +531,7 @@ static int add_tracepoint_multi(struct list_head *list, int *idx, return ret; } -int parse_events_add_tracepoint(struct list_head *list, int *idx, +int parse_events_add_tracepoint(struct list_head **list, int *idx, char *sys, char *event) { int ret; @@ -563,7 +575,7 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr) return 0; } -int parse_events_add_breakpoint(struct list_head *list, int *idx, +int parse_events_add_breakpoint(struct list_head **list, int *idx, void *ptr, char *type) { struct perf_event_attr attr; @@ -593,17 +605,27 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx, static int config_term(struct perf_event_attr *attr, struct parse_events__term *term) { - switch (term->type) { +#define CHECK_TYPE_VAL(type) \ +do { \ + if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val) \ + return -EINVAL; \ +} while (0) + + switch (term->type_term) { case PARSE_EVENTS__TERM_TYPE_CONFIG: + CHECK_TYPE_VAL(NUM); attr->config = term->val.num; break; case PARSE_EVENTS__TERM_TYPE_CONFIG1: + CHECK_TYPE_VAL(NUM); attr->config1 = term->val.num; break; case PARSE_EVENTS__TERM_TYPE_CONFIG2: + CHECK_TYPE_VAL(NUM); attr->config2 = term->val.num; break; case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: + CHECK_TYPE_VAL(NUM); attr->sample_period = term->val.num; break; case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: @@ -612,10 +634,15 @@ static int config_term(struct perf_event_attr *attr, * attr->branch_sample_type = term->val.num; */ break; + case PARSE_EVENTS__TERM_TYPE_NAME: + CHECK_TYPE_VAL(STR); + break; default: return -EINVAL; } + return 0; +#undef CHECK_TYPE_VAL } static int config_attr(struct perf_event_attr *attr, @@ -630,7 +657,7 @@ static int config_attr(struct perf_event_attr *attr, return 0; } -int parse_events_add_numeric(struct list_head *list, int *idx, +int parse_events_add_numeric(struct list_head **list, int *idx, unsigned long type, unsigned long config, struct list_head *head_config) { @@ -648,7 +675,24 @@ int parse_events_add_numeric(struct list_head *list, int *idx, (char *) __event_name(type, config)); } -int parse_events_add_pmu(struct list_head *list, int *idx, +static int parse_events__is_name_term(struct parse_events__term *term) +{ + return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; +} + +static char *pmu_event_name(struct perf_event_attr *attr, + struct list_head *head_terms) +{ + struct parse_events__term *term; + + list_for_each_entry(term, head_terms, list) + if (parse_events__is_name_term(term)) + return term->val.str; + + return (char *) __event_name(PERF_TYPE_RAW, attr->config); +} + +int parse_events_add_pmu(struct list_head **list, int *idx, char *name, struct list_head *head_config) { struct perf_event_attr attr; @@ -669,7 +713,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx, if (perf_pmu__config(pmu, &attr, head_config)) return -EINVAL; - return add_event(list, idx, &attr, (char *) "pmu"); + return add_event(list, idx, &attr, + pmu_event_name(&attr, head_config)); } void parse_events_update_lists(struct list_head *list_event, @@ -681,7 +726,7 @@ void parse_events_update_lists(struct list_head *list_event, * list, for next event definition. */ list_splice_tail(list_event, list_all); - INIT_LIST_HEAD(list_event); + free(list_event); } int parse_events_modifier(struct list_head *list, char *str) @@ -756,10 +801,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) buffer = parse_events__scan_string(str); - ret = parse_events_parse(&list, &list_tmp, &idx); +#ifdef PARSER_DEBUG + parse_events_debug = 1; +#endif + ret = parse_events_parse(&list, &idx); parse_events__flush_buffer(buffer); parse_events__delete_buffer(buffer); + parse_events_lex_destroy(); if (!ret) { int entries = idx - evlist->nr_entries; @@ -1015,11 +1064,12 @@ void print_events(const char *event_glob) int parse_events__is_hardcoded_term(struct parse_events__term *term) { - return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX; + return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; } -int parse_events__new_term(struct parse_events__term **_term, int type, - char *config, char *str, long num) +static int new_term(struct parse_events__term **_term, int type_val, + int type_term, char *config, + char *str, long num) { struct parse_events__term *term; @@ -1028,15 +1078,11 @@ int parse_events__new_term(struct parse_events__term **_term, int type, return -ENOMEM; INIT_LIST_HEAD(&term->list); - term->type = type; + term->type_val = type_val; + term->type_term = type_term; 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: + switch (type_val) { case PARSE_EVENTS__TERM_TYPE_NUM: term->val.num = num; break; @@ -1051,6 +1097,20 @@ int parse_events__new_term(struct parse_events__term **_term, int type, return 0; } +int parse_events__term_num(struct parse_events__term **term, + int type_term, char *config, long num) +{ + return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, + config, NULL, num); +} + +int parse_events__term_str(struct parse_events__term **term, + int type_term, char *config, char *str) +{ + return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, + config, str, 0); +} + void parse_events__free_terms(struct list_head *terms) { struct parse_events__term *term, *h; |