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

perf parse-events: Introduce 'struct parse_events_terms'

parse_events_terms() existed in function names but was passed a
'struct list_head'.

As many parse_events functions take an evsel_config list as well as a
parse_event_term list, and the naming head_terms and head_config is
inconsistent, there's a potential to switch the lists and get errors.

Introduce a 'struct parse_events_terms', that just wraps a list_head, to
avoid this. Add the regular init/exit functions and transition the code
to use them.

Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230901233949.2930562-6-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
0d3f0e6f 727adeed

+160 -144
+5 -10
tools/perf/arch/x86/util/intel-pt.c
··· 64 64 const char *str, 65 65 u64 *config) 66 66 { 67 - struct list_head *terms; 67 + struct parse_events_terms terms; 68 68 struct perf_event_attr attr = { .size = 0, }; 69 69 int err; 70 70 71 - terms = malloc(sizeof(struct list_head)); 72 - if (!terms) 73 - return -ENOMEM; 74 - 75 - INIT_LIST_HEAD(terms); 76 - 77 - err = parse_events_terms(terms, str, /*input=*/ NULL); 71 + parse_events_terms__init(&terms); 72 + err = parse_events_terms(&terms, str, /*input=*/ NULL); 78 73 if (err) 79 74 goto out_free; 80 75 81 76 attr.config = *config; 82 - err = perf_pmu__config_terms(pmu, &attr, terms, /*zero=*/true, /*err=*/NULL); 77 + err = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/true, /*err=*/NULL); 83 78 if (err) 84 79 goto out_free; 85 80 86 81 *config = attr.config; 87 82 out_free: 88 - parse_events_terms__delete(terms); 83 + parse_events_terms__exit(&terms); 89 84 return err; 90 85 } 91 86
+6 -6
tools/perf/tests/parse-events.c
··· 771 771 return TEST_OK; 772 772 } 773 773 774 - static int test__checkterms_simple(struct list_head *terms) 774 + static int test__checkterms_simple(struct parse_events_terms *terms) 775 775 { 776 776 struct parse_events_term *term; 777 777 778 778 /* config=10 */ 779 - term = list_entry(terms->next, struct parse_events_term, list); 779 + term = list_entry(terms->terms.next, struct parse_events_term, list); 780 780 TEST_ASSERT_VAL("wrong type term", 781 781 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG); 782 782 TEST_ASSERT_VAL("wrong type val", ··· 2363 2363 2364 2364 struct terms_test { 2365 2365 const char *str; 2366 - int (*check)(struct list_head *terms); 2366 + int (*check)(struct parse_events_terms *terms); 2367 2367 }; 2368 2368 2369 2369 static const struct terms_test test__terms[] = { ··· 2467 2467 2468 2468 static int test_term(const struct terms_test *t) 2469 2469 { 2470 - struct list_head terms; 2470 + struct parse_events_terms terms; 2471 2471 int ret; 2472 2472 2473 - INIT_LIST_HEAD(&terms); 2474 2473 2474 + parse_events_terms__init(&terms); 2475 2475 ret = parse_events_terms(&terms, t->str, /*input=*/ NULL); 2476 2476 if (ret) { 2477 2477 pr_debug("failed to parse terms '%s', err %d\n", ··· 2480 2480 } 2481 2481 2482 2482 ret = t->check(&terms); 2483 - parse_events_terms__purge(&terms); 2483 + parse_events_terms__exit(&terms); 2484 2484 2485 2485 return ret; 2486 2486 }
+15 -8
tools/perf/tests/pmu.c
··· 128 128 return system(buf); 129 129 } 130 130 131 - static struct list_head *test_terms_list(void) 131 + static void add_test_terms(struct parse_events_terms *terms) 132 132 { 133 - static LIST_HEAD(terms); 134 133 unsigned int i; 135 134 136 - for (i = 0; i < ARRAY_SIZE(test_terms); i++) 137 - list_add_tail(&test_terms[i].list, &terms); 135 + for (i = 0; i < ARRAY_SIZE(test_terms); i++) { 136 + struct parse_events_term *clone; 138 137 139 - return &terms; 138 + parse_events_term__clone(&clone, &test_terms[i]); 139 + list_add_tail(&clone->list, &terms->terms); 140 + } 140 141 } 141 142 142 143 static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 143 144 { 144 145 char dir[PATH_MAX]; 145 146 char *format; 146 - struct list_head *terms = test_terms_list(); 147 + struct parse_events_terms terms; 147 148 struct perf_event_attr attr; 148 149 struct perf_pmu *pmu; 149 150 int fd; 150 151 int ret; 151 152 153 + parse_events_terms__init(&terms); 154 + add_test_terms(&terms); 152 155 pmu = zalloc(sizeof(*pmu)); 153 - if (!pmu) 156 + if (!pmu) { 157 + parse_events_terms__exit(&terms); 154 158 return -ENOMEM; 159 + } 155 160 156 161 INIT_LIST_HEAD(&pmu->format); 157 162 INIT_LIST_HEAD(&pmu->aliases); ··· 164 159 format = test_format_dir_get(dir, sizeof(dir)); 165 160 if (!format) { 166 161 free(pmu); 162 + parse_events_terms__exit(&terms); 167 163 return -EINVAL; 168 164 } 169 165 ··· 181 175 if (ret) 182 176 goto out; 183 177 184 - ret = perf_pmu__config_terms(pmu, &attr, terms, /*zero=*/false, /*err=*/NULL); 178 + ret = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/false, /*err=*/NULL); 185 179 if (ret) 186 180 goto out; 187 181 ··· 197 191 out: 198 192 test_format_dir_put(format); 199 193 perf_pmu__delete(pmu); 194 + parse_events_terms__exit(&terms); 200 195 return ret; 201 196 } 202 197
+82 -76
tools/perf/util/parse-events.c
··· 34 34 #ifdef PARSER_DEBUG 35 35 extern int parse_events_debug; 36 36 #endif 37 - static int get_config_terms(struct list_head *head_config, struct list_head *head_terms); 38 - static int parse_events_terms__copy(const struct list_head *src, struct list_head *dest); 37 + static int get_config_terms(struct parse_events_terms *head_config, struct list_head *head_terms); 38 + static int parse_events_terms__copy(const struct parse_events_terms *src, 39 + struct parse_events_terms *dest); 39 40 40 41 struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 41 42 [PERF_COUNT_HW_CPU_CYCLES] = { ··· 154 153 return "unknown"; 155 154 } 156 155 157 - static char *get_config_str(struct list_head *head_terms, enum parse_events__term_type type_term) 156 + static char *get_config_str(struct parse_events_terms *head_terms, 157 + enum parse_events__term_type type_term) 158 158 { 159 159 struct parse_events_term *term; 160 160 161 161 if (!head_terms) 162 162 return NULL; 163 163 164 - list_for_each_entry(term, head_terms, list) 164 + list_for_each_entry(term, &head_terms->terms, list) 165 165 if (term->type_term == type_term) 166 166 return term->val.str; 167 167 168 168 return NULL; 169 169 } 170 170 171 - static char *get_config_metric_id(struct list_head *head_terms) 171 + static char *get_config_metric_id(struct parse_events_terms *head_terms) 172 172 { 173 173 return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_METRIC_ID); 174 174 } 175 175 176 - static char *get_config_name(struct list_head *head_terms) 176 + static char *get_config_name(struct parse_events_terms *head_terms) 177 177 { 178 178 return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_NAME); 179 179 } ··· 190 188 * @config_terms: the list of terms that may contain a raw term. 191 189 * @pmu: the PMU to scan for events from. 192 190 */ 193 - static void fix_raw(struct list_head *config_terms, struct perf_pmu *pmu) 191 + static void fix_raw(struct parse_events_terms *config_terms, struct perf_pmu *pmu) 194 192 { 195 193 struct parse_events_term *term; 196 194 197 - list_for_each_entry(term, config_terms, list) { 195 + list_for_each_entry(term, &config_terms->terms, list) { 198 196 u64 num; 199 197 200 198 if (term->type_term != PARSE_EVENTS__TERM_TYPE_RAW) ··· 358 356 struct parse_events_term *term, 359 357 struct parse_events_error *err); 360 358 static int config_attr(struct perf_event_attr *attr, 361 - struct list_head *head, 359 + struct parse_events_terms *head, 362 360 struct parse_events_error *err, 363 361 config_term_func_t config_term); 364 362 ··· 444 442 445 443 int parse_events_add_cache(struct list_head *list, int *idx, const char *name, 446 444 struct parse_events_state *parse_state, 447 - struct list_head *head_config) 445 + struct parse_events_terms *head_config) 448 446 { 449 447 struct perf_pmu *pmu = NULL; 450 448 bool found_supported = false; ··· 522 520 static int add_tracepoint(struct list_head *list, int *idx, 523 521 const char *sys_name, const char *evt_name, 524 522 struct parse_events_error *err, 525 - struct list_head *head_config, void *loc_) 523 + struct parse_events_terms *head_config, void *loc_) 526 524 { 527 525 YYLTYPE *loc = loc_; 528 526 struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++); ··· 547 545 static int add_tracepoint_multi_event(struct list_head *list, int *idx, 548 546 const char *sys_name, const char *evt_name, 549 547 struct parse_events_error *err, 550 - struct list_head *head_config, YYLTYPE *loc) 548 + struct parse_events_terms *head_config, YYLTYPE *loc) 551 549 { 552 550 char *evt_path; 553 551 struct dirent *evt_ent; ··· 595 593 static int add_tracepoint_event(struct list_head *list, int *idx, 596 594 const char *sys_name, const char *evt_name, 597 595 struct parse_events_error *err, 598 - struct list_head *head_config, YYLTYPE *loc) 596 + struct parse_events_terms *head_config, YYLTYPE *loc) 599 597 { 600 598 return strpbrk(evt_name, "*?") ? 601 599 add_tracepoint_multi_event(list, idx, sys_name, evt_name, ··· 607 605 static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 608 606 const char *sys_name, const char *evt_name, 609 607 struct parse_events_error *err, 610 - struct list_head *head_config, YYLTYPE *loc) 608 + struct parse_events_terms *head_config, YYLTYPE *loc) 611 609 { 612 610 struct dirent *events_ent; 613 611 DIR *events_dir; ··· 682 680 int parse_events_add_breakpoint(struct parse_events_state *parse_state, 683 681 struct list_head *list, 684 682 u64 addr, char *type, u64 len, 685 - struct list_head *head_config __maybe_unused) 683 + struct parse_events_terms *head_config) 686 684 { 687 685 struct perf_event_attr attr; 688 686 LIST_HEAD(config_terms); ··· 1068 1066 #endif 1069 1067 1070 1068 static int config_attr(struct perf_event_attr *attr, 1071 - struct list_head *head, 1069 + struct parse_events_terms *head, 1072 1070 struct parse_events_error *err, 1073 1071 config_term_func_t config_term) 1074 1072 { 1075 1073 struct parse_events_term *term; 1076 1074 1077 - list_for_each_entry(term, head, list) 1075 + list_for_each_entry(term, &head->terms, list) 1078 1076 if (config_term(attr, term, err)) 1079 1077 return -EINVAL; 1080 1078 1081 1079 return 0; 1082 1080 } 1083 1081 1084 - static int get_config_terms(struct list_head *head_config, struct list_head *head_terms) 1082 + static int get_config_terms(struct parse_events_terms *head_config, struct list_head *head_terms) 1085 1083 { 1086 1084 #define ADD_CONFIG_TERM(__type, __weak) \ 1087 1085 struct evsel_config_term *__t; \ ··· 1114 1112 1115 1113 struct parse_events_term *term; 1116 1114 1117 - list_for_each_entry(term, head_config, list) { 1115 + list_for_each_entry(term, &head_config->terms, list) { 1118 1116 switch (term->type_term) { 1119 1117 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 1120 1118 ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); ··· 1195 1193 * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for 1196 1194 * each bit of attr->config that the user has changed. 1197 1195 */ 1198 - static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, 1196 + static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head_config, 1199 1197 struct list_head *head_terms) 1200 1198 { 1201 1199 struct parse_events_term *term; 1202 1200 u64 bits = 0; 1203 1201 int type; 1204 1202 1205 - list_for_each_entry(term, head_config, list) { 1203 + list_for_each_entry(term, &head_config->terms, list) { 1206 1204 switch (term->type_term) { 1207 1205 case PARSE_EVENTS__TERM_TYPE_USER: 1208 1206 type = perf_pmu__format_type(pmu, term->config); ··· 1252 1250 int parse_events_add_tracepoint(struct list_head *list, int *idx, 1253 1251 const char *sys, const char *event, 1254 1252 struct parse_events_error *err, 1255 - struct list_head *head_config, void *loc_) 1253 + struct parse_events_terms *head_config, void *loc_) 1256 1254 { 1257 1255 YYLTYPE *loc = loc_; 1258 1256 #ifdef HAVE_LIBTRACEEVENT ··· 1285 1283 static int __parse_events_add_numeric(struct parse_events_state *parse_state, 1286 1284 struct list_head *list, 1287 1285 struct perf_pmu *pmu, u32 type, u32 extended_type, 1288 - u64 config, struct list_head *head_config) 1286 + u64 config, struct parse_events_terms *head_config) 1289 1287 { 1290 1288 struct perf_event_attr attr; 1291 1289 LIST_HEAD(config_terms); ··· 1321 1319 int parse_events_add_numeric(struct parse_events_state *parse_state, 1322 1320 struct list_head *list, 1323 1321 u32 type, u64 config, 1324 - struct list_head *head_config, 1322 + struct parse_events_terms *head_config, 1325 1323 bool wildcard) 1326 1324 { 1327 1325 struct perf_pmu *pmu = NULL; ··· 1370 1368 1371 1369 int parse_events_add_pmu(struct parse_events_state *parse_state, 1372 1370 struct list_head *list, const char *name, 1373 - const struct list_head *const_head_terms, 1371 + const struct parse_events_terms *const_parsed_terms, 1374 1372 bool auto_merge_stats, void *loc_) 1375 1373 { 1376 1374 struct perf_event_attr attr; ··· 1380 1378 struct parse_events_error *err = parse_state->error; 1381 1379 YYLTYPE *loc = loc_; 1382 1380 LIST_HEAD(config_terms); 1383 - LIST_HEAD(head_terms); 1381 + struct parse_events_terms parsed_terms; 1384 1382 1385 1383 pmu = parse_state->fake_pmu ?: perf_pmus__find(name); 1386 1384 ··· 1394 1392 return -EINVAL; 1395 1393 } 1396 1394 1397 - if (const_head_terms) { 1398 - int ret = parse_events_terms__copy(const_head_terms, &head_terms); 1395 + parse_events_terms__init(&parsed_terms); 1396 + if (const_parsed_terms) { 1397 + int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); 1399 1398 1400 1399 if (ret) 1401 1400 return ret; ··· 1406 1403 struct strbuf sb; 1407 1404 1408 1405 strbuf_init(&sb, /*hint=*/ 0); 1409 - if (pmu->selectable && list_empty(&head_terms)) { 1406 + if (pmu->selectable && list_empty(&parsed_terms.terms)) { 1410 1407 strbuf_addf(&sb, "%s//", name); 1411 1408 } else { 1412 1409 strbuf_addf(&sb, "%s/", name); 1413 - parse_events_term__to_strbuf(&head_terms, &sb); 1410 + parse_events_terms__to_strbuf(&parsed_terms, &sb); 1414 1411 strbuf_addch(&sb, '/'); 1415 1412 } 1416 1413 fprintf(stderr, "Attempt to add: %s\n", sb.buf); 1417 1414 strbuf_release(&sb); 1418 1415 } 1419 - fix_raw(&head_terms, pmu); 1416 + fix_raw(&parsed_terms, pmu); 1420 1417 1421 1418 if (pmu->default_config) { 1422 1419 memcpy(&attr, pmu->default_config, sizeof(struct perf_event_attr)); ··· 1425 1422 } 1426 1423 attr.type = pmu->type; 1427 1424 1428 - if (list_empty(&head_terms)) { 1425 + if (list_empty(&parsed_terms.terms)) { 1429 1426 evsel = __add_event(list, &parse_state->idx, &attr, 1430 1427 /*init_attr=*/true, /*name=*/NULL, 1431 1428 /*metric_id=*/NULL, pmu, ··· 1434 1431 return evsel ? 0 : -ENOMEM; 1435 1432 } 1436 1433 1437 - if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &head_terms, &info, err)) { 1438 - parse_events_terms__purge(&head_terms); 1434 + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &parsed_terms, &info, err)) { 1435 + parse_events_terms__exit(&parsed_terms); 1439 1436 return -EINVAL; 1440 1437 } 1441 1438 ··· 1443 1440 struct strbuf sb; 1444 1441 1445 1442 strbuf_init(&sb, /*hint=*/ 0); 1446 - parse_events_term__to_strbuf(&head_terms, &sb); 1443 + parse_events_terms__to_strbuf(&parsed_terms, &sb); 1447 1444 fprintf(stderr, "..after resolving event: %s/%s/\n", name, sb.buf); 1448 1445 strbuf_release(&sb); 1449 1446 } ··· 1452 1449 * Configure hardcoded terms first, no need to check 1453 1450 * return value when called with fail == 0 ;) 1454 1451 */ 1455 - if (config_attr(&attr, &head_terms, parse_state->error, config_term_pmu)) { 1456 - parse_events_terms__purge(&head_terms); 1452 + if (config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 1453 + parse_events_terms__exit(&parsed_terms); 1457 1454 return -EINVAL; 1458 1455 } 1459 1456 1460 - if (get_config_terms(&head_terms, &config_terms)) { 1461 - parse_events_terms__purge(&head_terms); 1457 + if (get_config_terms(&parsed_terms, &config_terms)) { 1458 + parse_events_terms__exit(&parsed_terms); 1462 1459 return -ENOMEM; 1463 1460 } 1464 1461 ··· 1466 1463 * When using default config, record which bits of attr->config were 1467 1464 * changed by the user. 1468 1465 */ 1469 - if (pmu->default_config && get_config_chgs(pmu, &head_terms, &config_terms)) { 1470 - parse_events_terms__purge(&head_terms); 1466 + if (pmu->default_config && get_config_chgs(pmu, &parsed_terms, &config_terms)) { 1467 + parse_events_terms__exit(&parsed_terms); 1471 1468 return -ENOMEM; 1472 1469 } 1473 1470 1474 1471 if (!parse_state->fake_pmu && 1475 - perf_pmu__config(pmu, &attr, &head_terms, parse_state->error)) { 1472 + perf_pmu__config(pmu, &attr, &parsed_terms, parse_state->error)) { 1476 1473 free_config_terms(&config_terms); 1477 - parse_events_terms__purge(&head_terms); 1474 + parse_events_terms__exit(&parsed_terms); 1478 1475 return -EINVAL; 1479 1476 } 1480 1477 1481 1478 evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, 1482 - get_config_name(&head_terms), 1483 - get_config_metric_id(&head_terms), pmu, 1479 + get_config_name(&parsed_terms), 1480 + get_config_metric_id(&parsed_terms), pmu, 1484 1481 &config_terms, auto_merge_stats, /*cpu_list=*/NULL); 1485 1482 if (!evsel) { 1486 - parse_events_terms__purge(&head_terms); 1483 + parse_events_terms__exit(&parsed_terms); 1487 1484 return -ENOMEM; 1488 1485 } 1489 1486 ··· 1493 1490 evsel->percore = config_term_percore(&evsel->config_terms); 1494 1491 1495 1492 if (parse_state->fake_pmu) { 1496 - parse_events_terms__purge(&head_terms); 1493 + parse_events_terms__exit(&parsed_terms); 1497 1494 return 0; 1498 1495 } 1499 1496 1500 - parse_events_terms__purge(&head_terms); 1497 + parse_events_terms__exit(&parsed_terms); 1501 1498 free((char *)evsel->unit); 1502 1499 evsel->unit = strdup(info.unit); 1503 1500 evsel->scale = info.scale; ··· 1508 1505 1509 1506 int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1510 1507 const char *event_name, 1511 - const struct list_head *const_head_terms, 1508 + const struct parse_events_terms *const_parsed_terms, 1512 1509 struct list_head **listp, void *loc_) 1513 1510 { 1514 1511 struct parse_events_term *term; ··· 1517 1514 YYLTYPE *loc = loc_; 1518 1515 int ok = 0; 1519 1516 const char *config; 1520 - LIST_HEAD(head_terms); 1517 + struct parse_events_terms parsed_terms; 1521 1518 1522 1519 *listp = NULL; 1523 1520 1524 - if (const_head_terms) { 1525 - int ret = parse_events_terms__copy(const_head_terms, &head_terms); 1521 + parse_events_terms__init(&parsed_terms); 1522 + if (const_parsed_terms) { 1523 + int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); 1526 1524 1527 1525 if (ret) 1528 1526 return ret; ··· 1540 1536 zfree(&config); 1541 1537 goto out_err; 1542 1538 } 1543 - list_add_tail(&term->list, &head_terms); 1539 + list_add_tail(&term->list, &parsed_terms.terms); 1544 1540 1545 1541 /* Add it for all PMUs that support the alias */ 1546 1542 list = malloc(sizeof(struct list_head)); ··· 1560 1556 1561 1557 auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 1562 1558 if (!parse_events_add_pmu(parse_state, list, pmu->name, 1563 - &head_terms, auto_merge_stats, loc)) { 1559 + &parsed_terms, auto_merge_stats, loc)) { 1564 1560 struct strbuf sb; 1565 1561 1566 1562 strbuf_init(&sb, /*hint=*/ 0); 1567 - parse_events_term__to_strbuf(&head_terms, &sb); 1563 + parse_events_terms__to_strbuf(&parsed_terms, &sb); 1568 1564 pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf); 1569 1565 strbuf_release(&sb); 1570 1566 ok++; ··· 1572 1568 } 1573 1569 1574 1570 if (parse_state->fake_pmu) { 1575 - if (!parse_events_add_pmu(parse_state, list, event_name, &head_terms, 1571 + if (!parse_events_add_pmu(parse_state, list, event_name, &parsed_terms, 1576 1572 /*auto_merge_stats=*/true, loc)) { 1577 1573 struct strbuf sb; 1578 1574 1579 1575 strbuf_init(&sb, /*hint=*/ 0); 1580 - parse_events_term__to_strbuf(&head_terms, &sb); 1576 + parse_events_terms__to_strbuf(&parsed_terms, &sb); 1581 1577 pr_debug("%s -> %s/%s/\n", event_name, "fake_pmu", sb.buf); 1582 1578 strbuf_release(&sb); 1583 1579 ok++; ··· 1585 1581 } 1586 1582 1587 1583 out_err: 1588 - parse_events_terms__purge(&head_terms); 1584 + parse_events_terms__exit(&parsed_terms); 1589 1585 if (ok) 1590 1586 *listp = list; 1591 1587 else ··· 1855 1851 /* 1856 1852 * parse event config string, return a list of event terms. 1857 1853 */ 1858 - int parse_events_terms(struct list_head *terms, const char *str, FILE *input) 1854 + int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input) 1859 1855 { 1860 1856 struct parse_events_state parse_state = { 1861 1857 .terms = NULL, ··· 1864 1860 int ret; 1865 1861 1866 1862 ret = parse_events__scanner(str, input, &parse_state); 1863 + if (!ret) 1864 + list_splice(&parse_state.terms->terms, &terms->terms); 1867 1865 1868 - if (!ret) { 1869 - list_splice(parse_state.terms, terms); 1870 - zfree(&parse_state.terms); 1871 - return 0; 1872 - } 1873 - 1874 - parse_events_terms__delete(parse_state.terms); 1866 + zfree(&parse_state.terms); 1875 1867 return ret; 1876 1868 } 1877 1869 ··· 2563 2563 free(term); 2564 2564 } 2565 2565 2566 - static int parse_events_terms__copy(const struct list_head *src, struct list_head *dest) 2566 + static int parse_events_terms__copy(const struct parse_events_terms *src, 2567 + struct parse_events_terms *dest) 2567 2568 { 2568 2569 struct parse_events_term *term; 2569 2570 2570 - list_for_each_entry (term, src, list) { 2571 + list_for_each_entry (term, &src->terms, list) { 2571 2572 struct parse_events_term *n; 2572 2573 int ret; 2573 2574 ··· 2576 2575 if (ret) 2577 2576 return ret; 2578 2577 2579 - list_add_tail(&n->list, dest); 2578 + list_add_tail(&n->list, &dest->terms); 2580 2579 } 2581 2580 return 0; 2582 2581 } 2583 2582 2584 - void parse_events_terms__purge(struct list_head *terms) 2583 + void parse_events_terms__init(struct parse_events_terms *terms) 2584 + { 2585 + INIT_LIST_HEAD(&terms->terms); 2586 + } 2587 + 2588 + void parse_events_terms__exit(struct parse_events_terms *terms) 2585 2589 { 2586 2590 struct parse_events_term *term, *h; 2587 2591 2588 - list_for_each_entry_safe(term, h, terms, list) { 2592 + list_for_each_entry_safe(term, h, &terms->terms, list) { 2589 2593 list_del_init(&term->list); 2590 2594 parse_events_term__delete(term); 2591 2595 } 2592 2596 } 2593 2597 2594 - void parse_events_terms__delete(struct list_head *terms) 2598 + void parse_events_terms__delete(struct parse_events_terms *terms) 2595 2599 { 2596 2600 if (!terms) 2597 2601 return; 2598 - parse_events_terms__purge(terms); 2602 + parse_events_terms__exit(terms); 2599 2603 free(terms); 2600 2604 } 2601 2605 2602 - int parse_events_term__to_strbuf(struct list_head *term_list, struct strbuf *sb) 2606 + int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb) 2603 2607 { 2604 2608 struct parse_events_term *term; 2605 2609 bool first = true; 2606 2610 2607 - if (!term_list) 2611 + if (!terms) 2608 2612 return 0; 2609 2613 2610 - list_for_each_entry(term, term_list, list) { 2614 + list_for_each_entry(term, &terms->terms, list) { 2611 2615 int ret; 2612 2616 2613 2617 if (!first) {
+18 -11
tools/perf/util/parse-events.h
··· 44 44 45 45 int parse_event(struct evlist *evlist, const char *str); 46 46 47 - int parse_events_terms(struct list_head *terms, const char *str, FILE *input); 48 47 int parse_filter(const struct option *opt, const char *str, int unset); 49 48 int exclude_perf(const struct option *opt, const char *arg, int unset); 50 49 ··· 139 140 char *first_help; 140 141 }; 141 142 143 + /* A wrapper around a list of terms for the sake of better type safety. */ 144 + struct parse_events_terms { 145 + struct list_head terms; 146 + }; 147 + 142 148 struct parse_events_state { 143 149 /* The list parsed events are placed on. */ 144 150 struct list_head list; ··· 152 148 /* Error information. */ 153 149 struct parse_events_error *error; 154 150 /* Holds returned terms for term parsing. */ 155 - struct list_head *terms; 151 + struct parse_events_terms *terms; 156 152 /* Start token. */ 157 153 int stoken; 158 154 /* Special fake PMU marker for testing. */ ··· 185 181 int parse_events_term__clone(struct parse_events_term **new, 186 182 struct parse_events_term *term); 187 183 void parse_events_term__delete(struct parse_events_term *term); 188 - void parse_events_terms__delete(struct list_head *terms); 189 - void parse_events_terms__purge(struct list_head *terms); 190 - int parse_events_term__to_strbuf(struct list_head *term_list, struct strbuf *sb); 184 + 185 + void parse_events_terms__delete(struct parse_events_terms *terms); 186 + void parse_events_terms__init(struct parse_events_terms *terms); 187 + void parse_events_terms__exit(struct parse_events_terms *terms); 188 + int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input); 189 + int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); 191 190 int parse_events__modifier_event(struct list_head *list, char *str, bool add); 192 191 int parse_events__modifier_group(struct list_head *list, char *event_mod); 193 192 int parse_events_name(struct list_head *list, const char *name); 194 193 int parse_events_add_tracepoint(struct list_head *list, int *idx, 195 194 const char *sys, const char *event, 196 195 struct parse_events_error *error, 197 - struct list_head *head_config, void *loc); 196 + struct parse_events_terms *head_config, void *loc); 198 197 int parse_events_add_numeric(struct parse_events_state *parse_state, 199 198 struct list_head *list, 200 199 u32 type, u64 config, 201 - struct list_head *head_config, 200 + struct parse_events_terms *head_config, 202 201 bool wildcard); 203 202 int parse_events_add_tool(struct parse_events_state *parse_state, 204 203 struct list_head *list, 205 204 int tool_event); 206 205 int parse_events_add_cache(struct list_head *list, int *idx, const char *name, 207 206 struct parse_events_state *parse_state, 208 - struct list_head *head_config); 207 + struct parse_events_terms *head_config); 209 208 int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config); 210 209 int parse_events_add_breakpoint(struct parse_events_state *parse_state, 211 210 struct list_head *list, 212 211 u64 addr, char *type, u64 len, 213 - struct list_head *head_config); 212 + struct parse_events_terms *head_config); 214 213 int parse_events_add_pmu(struct parse_events_state *parse_state, 215 214 struct list_head *list, const char *name, 216 - const struct list_head *const_head_terms, 215 + const struct parse_events_terms *const_parsed_terms, 217 216 bool auto_merge_stats, void *loc); 218 217 219 218 struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, ··· 225 218 226 219 int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 227 220 const char *event_name, 228 - const struct list_head *head_terms, 221 + const struct parse_events_terms *const_parsed_terms, 229 222 struct list_head **listp, void *loc); 230 223 231 224 void parse_events__set_leader(char *name, struct list_head *list);
+6 -6
tools/perf/util/parse-events.y
··· 113 113 u64 num; 114 114 enum parse_events__term_type term_type; 115 115 struct list_head *list_evsel; 116 - struct list_head *list_terms; 116 + struct parse_events_terms *list_terms; 117 117 struct parse_events_term *term; 118 118 struct tracepoint_name { 119 119 char *sys; ··· 644 644 event_config: 645 645 event_config ',' event_term 646 646 { 647 - struct list_head *head = $1; 647 + struct parse_events_terms *head = $1; 648 648 struct parse_events_term *term = $3; 649 649 650 650 if (!head) { 651 651 parse_events_term__delete(term); 652 652 YYABORT; 653 653 } 654 - list_add_tail(&term->list, head); 654 + list_add_tail(&term->list, &head->terms); 655 655 $$ = $1; 656 656 } 657 657 | 658 658 event_term 659 659 { 660 - struct list_head *head = malloc(sizeof(*head)); 660 + struct parse_events_terms *head = malloc(sizeof(*head)); 661 661 struct parse_events_term *term = $1; 662 662 663 663 if (!head) 664 664 YYNOMEM; 665 - INIT_LIST_HEAD(head); 666 - list_add_tail(&term->list, head); 665 + parse_events_terms__init(head); 666 + list_add_tail(&term->list, &head->terms); 667 667 $$ = head; 668 668 } 669 669
+25 -24
tools/perf/util/pmu.c
··· 52 52 */ 53 53 char *topic; 54 54 /** @terms: Owned list of the original parsed parameters. */ 55 - struct list_head terms; 55 + struct parse_events_terms terms; 56 56 /** @list: List element of struct perf_pmu aliases. */ 57 57 struct list_head list; 58 58 /** ··· 404 404 zfree(&newalias->long_desc); 405 405 zfree(&newalias->topic); 406 406 zfree(&newalias->pmu_name); 407 - parse_events_terms__purge(&newalias->terms); 407 + parse_events_terms__exit(&newalias->terms); 408 408 free(newalias); 409 409 } 410 410 ··· 484 484 assign_str(pe->name, "topic", &data->alias->topic, pe->topic); 485 485 data->alias->per_pkg = pe->perpkg; 486 486 if (pe->event) { 487 - parse_events_terms__purge(&data->alias->terms); 487 + parse_events_terms__exit(&data->alias->terms); 488 488 ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); 489 489 } 490 490 if (!ret && pe->unit) { ··· 524 524 if (!alias) 525 525 return -ENOMEM; 526 526 527 - INIT_LIST_HEAD(&alias->terms); 527 + parse_events_terms__init(&alias->terms); 528 528 alias->scale = 1.0; 529 529 alias->unit[0] = '\0'; 530 530 alias->per_pkg = perpkg; ··· 656 656 return 0; 657 657 } 658 658 659 - static int pmu_alias_terms(struct perf_pmu_alias *alias, 660 - struct list_head *terms) 659 + static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms) 661 660 { 662 661 struct parse_events_term *term, *cloned; 663 - LIST_HEAD(list); 664 - int ret; 662 + struct parse_events_terms clone_terms; 665 663 666 - list_for_each_entry(term, &alias->terms, list) { 667 - ret = parse_events_term__clone(&cloned, term); 664 + parse_events_terms__init(&clone_terms); 665 + list_for_each_entry(term, &alias->terms.terms, list) { 666 + int ret = parse_events_term__clone(&cloned, term); 667 + 668 668 if (ret) { 669 - parse_events_terms__purge(&list); 669 + parse_events_terms__exit(&clone_terms); 670 670 return ret; 671 671 } 672 672 /* ··· 674 674 * which we don't want for implicit terms in aliases. 675 675 */ 676 676 cloned->weak = true; 677 - list_add_tail(&cloned->list, &list); 677 + list_add_tail(&cloned->list, &clone_terms.terms); 678 678 } 679 - list_splice(&list, terms); 679 + list_splice_init(&clone_terms.terms, terms); 680 + parse_events_terms__exit(&clone_terms); 680 681 return 0; 681 682 } 682 683 ··· 1189 1188 * in a config string) later on in the term list. 1190 1189 */ 1191 1190 static int pmu_resolve_param_term(struct parse_events_term *term, 1192 - struct list_head *head_terms, 1191 + struct parse_events_terms *head_terms, 1193 1192 __u64 *value) 1194 1193 { 1195 1194 struct parse_events_term *t; 1196 1195 1197 - list_for_each_entry(t, head_terms, list) { 1196 + list_for_each_entry(t, &head_terms->terms, list) { 1198 1197 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 1199 1198 t->config && !strcmp(t->config, term->config)) { 1200 1199 t->used = true; ··· 1238 1237 static int pmu_config_term(struct perf_pmu *pmu, 1239 1238 struct perf_event_attr *attr, 1240 1239 struct parse_events_term *term, 1241 - struct list_head *head_terms, 1240 + struct parse_events_terms *head_terms, 1242 1241 bool zero, struct parse_events_error *err) 1243 1242 { 1244 1243 struct perf_pmu_format *format; ··· 1360 1359 1361 1360 int perf_pmu__config_terms(struct perf_pmu *pmu, 1362 1361 struct perf_event_attr *attr, 1363 - struct list_head *head_terms, 1362 + struct parse_events_terms *terms, 1364 1363 bool zero, struct parse_events_error *err) 1365 1364 { 1366 1365 struct parse_events_term *term; 1367 1366 1368 - list_for_each_entry(term, head_terms, list) { 1369 - if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1367 + list_for_each_entry(term, &terms->terms, list) { 1368 + if (pmu_config_term(pmu, attr, term, terms, zero, err)) 1370 1369 return -EINVAL; 1371 1370 } 1372 1371 ··· 1379 1378 * 2) pmu format definitions - specified by pmu parameter 1380 1379 */ 1381 1380 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1382 - struct list_head *head_terms, 1381 + struct parse_events_terms *head_terms, 1383 1382 struct parse_events_error *err) 1384 1383 { 1385 1384 bool zero = !!pmu->default_config; ··· 1473 1472 * Find alias in the terms list and replace it with the terms 1474 1473 * defined for the alias 1475 1474 */ 1476 - int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 1475 + int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 1477 1476 struct perf_pmu_info *info, struct parse_events_error *err) 1478 1477 { 1479 1478 struct parse_events_term *term, *h; ··· 1490 1489 info->scale = 0.0; 1491 1490 info->snapshot = false; 1492 1491 1493 - list_for_each_entry_safe(term, h, head_terms, list) { 1492 + list_for_each_entry_safe(term, h, &head_terms->terms, list) { 1494 1493 alias = pmu_find_alias(pmu, term); 1495 1494 if (!alias) 1496 1495 continue; ··· 1635 1634 : (int)strlen(pmu->name); 1636 1635 int used = snprintf(buf, len, "%.*s/%s", pmu_name_len, pmu->name, alias->name); 1637 1636 1638 - list_for_each_entry(term, &alias->terms, list) { 1637 + list_for_each_entry(term, &alias->terms.terms, list) { 1639 1638 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1640 1639 used += snprintf(buf + used, sub_non_neg(len, used), 1641 1640 ",%s=%s", term->config, ··· 1694 1693 info.desc = event->desc; 1695 1694 info.long_desc = event->long_desc; 1696 1695 info.encoding_desc = buf + buf_used; 1697 - parse_events_term__to_strbuf(&event->terms, &sb); 1696 + parse_events_terms__to_strbuf(&event->terms, &sb); 1698 1697 buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1699 1698 "%s/%s/", info.pmu_name, sb.buf) + 1; 1700 1699 info.topic = event->topic;
+3 -3
tools/perf/util/pmu.h
··· 191 191 192 192 void pmu_add_sys_aliases(struct perf_pmu *pmu); 193 193 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 194 - struct list_head *head_terms, 194 + struct parse_events_terms *head_terms, 195 195 struct parse_events_error *error); 196 196 int perf_pmu__config_terms(struct perf_pmu *pmu, 197 197 struct perf_event_attr *attr, 198 - struct list_head *head_terms, 198 + struct parse_events_terms *terms, 199 199 bool zero, struct parse_events_error *error); 200 200 __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name); 201 201 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name); 202 - int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 202 + int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 203 203 struct perf_pmu_info *info, struct parse_events_error *err); 204 204 int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb); 205 205