Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf pmu: Expand PMU events by prefix match

When the user specifies a pmu directly, expand it automatically with a
prefix match for all available PMUs, similar as we do for the normal
aliases now.

This allows to specify attributes for duplicated boxes quickly. For
example uncore_cbox_{0,6}/.../ can be now specified as uncore_cbox/.../
and it gets automatically expanded for all boxes.

This generally makes it more concise to write uncore specifications, and
also avoids the need to know the exact topology of the system.

Before:

% perf stat -a -e uncore_cbox_0/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_1/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_2/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_3/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_4/event=0x35,umask=0x1,filter_opc=0x19C/,\
uncore_cbox_5/event=0x35,umask=0x1,filter_opc=0x19C/ sleep 1

After:

% perf stat -a -e uncore_cbox/event=0x35,umask=0x1,filter_opc=0x19C/ sleep 1

v2: Handle all bison rules. Move multi add code to separate function.
Handle uncore_ prefix correctly.
v3: Move parse_events_multi_pmu_add to separate patch. Move uncore
prefix check to separate patch.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: http://lkml.kernel.org/r/20170320201711.14142-6-andi@firstfloor.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Andi Kleen and committed by
Arnaldo Carvalho de Melo
8255718f 2073ad33

+54 -14
+25
tools/perf/util/parse-events.c
··· 2462 2462 return new_term(new, &temp, term->val.str, term->val.num); 2463 2463 } 2464 2464 2465 + int parse_events_copy_term_list(struct list_head *old, 2466 + struct list_head **new) 2467 + { 2468 + struct parse_events_term *term, *n; 2469 + int ret; 2470 + 2471 + if (!old) { 2472 + *new = NULL; 2473 + return 0; 2474 + } 2475 + 2476 + *new = malloc(sizeof(struct list_head)); 2477 + if (!*new) 2478 + return -ENOMEM; 2479 + INIT_LIST_HEAD(*new); 2480 + 2481 + list_for_each_entry (term, old, list) { 2482 + ret = parse_events_term__clone(&n, term); 2483 + if (ret) 2484 + return ret; 2485 + list_add_tail(&n->list, *new); 2486 + } 2487 + return 0; 2488 + } 2489 + 2465 2490 void parse_events_terms__purge(struct list_head *terms) 2466 2491 { 2467 2492 struct parse_events_term *term, *h;
+3
tools/perf/util/parse-events.h
··· 172 172 char *str, 173 173 struct list_head **listp); 174 174 175 + int parse_events_copy_term_list(struct list_head *old, 176 + struct list_head **new); 177 + 175 178 enum perf_pmu_event_symbol_type 176 179 perf_pmu__parse_check(const char *name); 177 180 void parse_events__set_leader(char *name, struct list_head *list);
+26 -14
tools/perf/util/parse-events.y
··· 226 226 PE_NAME opt_event_config 227 227 { 228 228 struct parse_events_evlist *data = _data; 229 - struct list_head *list; 229 + struct list_head *list, *orig_terms, *terms; 230 + 231 + if (parse_events_copy_term_list($2, &orig_terms)) 232 + YYABORT; 230 233 231 234 ALLOC_LIST(list); 232 - ABORT_ON(parse_events_add_pmu(data, list, $1, $2)); 235 + if (parse_events_add_pmu(data, list, $1, $2)) { 236 + struct perf_pmu *pmu = NULL; 237 + int ok = 0; 238 + 239 + while ((pmu = perf_pmu__scan(pmu)) != NULL) { 240 + char *name = pmu->name; 241 + 242 + if (!strncmp($1, name, strlen($1))) { 243 + if (parse_events_copy_term_list(orig_terms, &terms)) 244 + YYABORT; 245 + if (!parse_events_add_pmu(data, list, pmu->name, terms)) 246 + ok++; 247 + parse_events_terms__delete(terms); 248 + } 249 + } 250 + if (!ok) 251 + YYABORT; 252 + } 233 253 parse_events_terms__delete($2); 254 + parse_events_terms__delete(orig_terms); 234 255 $$ = list; 235 256 } 236 257 | ··· 266 245 | 267 246 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 268 247 { 269 - struct parse_events_evlist *data = _data; 270 - struct list_head *head; 271 - struct parse_events_term *term; 272 248 struct list_head *list; 273 249 char pmu_name[128]; 250 + 274 251 snprintf(&pmu_name, 128, "%s-%s", $1, $3); 275 - 276 - ALLOC_LIST(head); 277 - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 278 - &pmu_name, 1, false, &@1, NULL)); 279 - list_add_tail(&term->list, head); 280 - 281 - ALLOC_LIST(list); 282 - ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 283 - parse_events_terms__delete(head); 252 + if (parse_events_multi_pmu_add(_data, pmu_name, &list) < 0) 253 + YYABORT; 284 254 $$ = list; 285 255 } 286 256