diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 2e8f435384a62a2128ce16835464f9ec034c0d23..76b98e2a587d7c8a52a1264d88aad3bdb6839831 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -409,6 +409,27 @@ static int test__checkevent_list(struct perf_evlist *evlist) return 0; } +static int test__checkevent_pmu_name(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + /* cpu/config=1,name=krava1/u */ + evsel = list_entry(evlist->entries.next, struct perf_evsel, node); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava")); + + /* cpu/config=2/" */ + evsel = list_entry(evsel->node.next, struct perf_evsel, node); + TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); + TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2")); + + return 0; +} + struct test__event_st { const char *name; __u32 type; @@ -529,6 +550,10 @@ static struct test__event_st test__events_pmu[] = { .name = "cpu/config=10,config1,config2=3,period=1000/u", .check = test__checkevent_pmu, }, + [1] = { + .name = "cpu/config=1,name=krava/u,cpu/config=2/u", + .check = test__checkevent_pmu_name, + }, }; #define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 59324e7b3d8ebba63051817198b94646f8bc4685..fac7d59309b83698cf22829936e86e1c511eb31e 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -634,6 +634,9 @@ do { \ * attr->branch_sample_type = term->val.num; */ break; + case PARSE_EVENTS__TERM_TYPE_NAME: + CHECK_TYPE_VAL(STR); + break; default: return -EINVAL; } @@ -672,6 +675,23 @@ int parse_events_add_numeric(struct list_head **list, int *idx, (char *) __event_name(type, config)); } +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) { @@ -693,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, diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 25ae3732f5b0ee585a3b9df6e8a163712dfca968..8cac57ab4ee6b396549a4ee857486effedb9343b 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -47,6 +47,7 @@ enum { PARSE_EVENTS__TERM_TYPE_CONFIG, PARSE_EVENTS__TERM_TYPE_CONFIG1, PARSE_EVENTS__TERM_TYPE_CONFIG2, + PARSE_EVENTS__TERM_TYPE_NAME, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, }; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 331d28a08dcba2000bca7e3f1fa0f14f58ce1cdc..618a8e7883995bbee72f4b90c6d5e55a012f05f1 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -105,6 +105,7 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } +name { return term(PARSE_EVENTS__TERM_TYPE_NAME); } period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 126fad0a993634997e1d3c4dc2c0722c40d595a5..362cc59332ae78e0774fed92e3f20a2f751fa211 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -237,6 +237,14 @@ PE_NAME $$ = term; } | +PE_TERM '=' PE_NAME +{ + struct parse_events__term *term; + + ABORT_ON(parse_events__term_str(&term, $1, NULL, $3)); + $$ = term; +} +| PE_TERM '=' PE_VALUE { struct parse_events__term *term; diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 8ee219b7285b95e6d90c8eb1b5b7db9d8c9e72f1..a119a5371699bd1c89575ce02de0d47655548e52 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -258,9 +258,9 @@ static int pmu_config_term(struct list_head *formats, static int pmu_config(struct list_head *formats, struct perf_event_attr *attr, struct list_head *head_terms) { - struct parse_events__term *term, *h; + struct parse_events__term *term; - list_for_each_entry_safe(term, h, head_terms, list) + list_for_each_entry(term, head_terms, list) if (pmu_config_term(formats, attr, term)) return -EINVAL;