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

Configure Feed

Select the types of activity you want to include in your feed.

perf pmu: Parse sysfs events directly from a file

Rather than read a sysfs events file into a 256 byte char buffer, pass
the FILE* directly to the lex/yacc parser.

This avoids there being a maximum events file size.

While changing the API, constify some arguments to remove unnecessary
casts.

Allocating the read buffer decreases the performance of pmu-scan by
around 3%.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
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: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230824041330.266337-10-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
edb217ff 3d504549

+33 -40
+1 -1
tools/perf/arch/x86/util/intel-pt.c
··· 74 74 75 75 INIT_LIST_HEAD(terms); 76 76 77 - err = parse_events_terms(terms, str); 77 + err = parse_events_terms(terms, str, /*input=*/ NULL); 78 78 if (err) 79 79 goto out_free; 80 80
+1 -1
tools/perf/tests/parse-events.c
··· 2472 2472 2473 2473 INIT_LIST_HEAD(&terms); 2474 2474 2475 - ret = parse_events_terms(&terms, t->str); 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", 2478 2478 t->str , ret);
+12 -6
tools/perf/util/parse-events.c
··· 1715 1715 } 1716 1716 1717 1717 static int parse_events__scanner(const char *str, 1718 + FILE *input, 1718 1719 struct parse_events_state *parse_state) 1719 1720 { 1720 1721 YY_BUFFER_STATE buffer; ··· 1726 1725 if (ret) 1727 1726 return ret; 1728 1727 1729 - buffer = parse_events__scan_string(str, scanner); 1728 + if (str) 1729 + buffer = parse_events__scan_string(str, scanner); 1730 + else 1731 + parse_events_set_in(input, scanner); 1730 1732 1731 1733 #ifdef PARSER_DEBUG 1732 1734 parse_events_debug = 1; ··· 1737 1733 #endif 1738 1734 ret = parse_events_parse(parse_state, scanner); 1739 1735 1740 - parse_events__flush_buffer(buffer, scanner); 1741 - parse_events__delete_buffer(buffer, scanner); 1736 + if (str) { 1737 + parse_events__flush_buffer(buffer, scanner); 1738 + parse_events__delete_buffer(buffer, scanner); 1739 + } 1742 1740 parse_events_lex_destroy(scanner); 1743 1741 return ret; 1744 1742 } ··· 1748 1742 /* 1749 1743 * parse event config string, return a list of event terms. 1750 1744 */ 1751 - int parse_events_terms(struct list_head *terms, const char *str) 1745 + int parse_events_terms(struct list_head *terms, const char *str, FILE *input) 1752 1746 { 1753 1747 struct parse_events_state parse_state = { 1754 1748 .terms = NULL, ··· 1756 1750 }; 1757 1751 int ret; 1758 1752 1759 - ret = parse_events__scanner(str, &parse_state); 1753 + ret = parse_events__scanner(str, input, &parse_state); 1760 1754 1761 1755 if (!ret) { 1762 1756 list_splice(parse_state.terms, terms); ··· 2007 2001 }; 2008 2002 int ret, ret2; 2009 2003 2010 - ret = parse_events__scanner(str, &parse_state); 2004 + ret = parse_events__scanner(str, /*input=*/ NULL, &parse_state); 2011 2005 2012 2006 if (!ret && list_empty(&parse_state.list)) { 2013 2007 WARN_ONCE(true, "WARNING: event parser found nothing\n");
+2 -1
tools/perf/util/parse-events.h
··· 9 9 #include <stdbool.h> 10 10 #include <linux/types.h> 11 11 #include <linux/perf_event.h> 12 + #include <stdio.h> 12 13 #include <string.h> 13 14 14 15 struct evsel; ··· 43 42 44 43 int parse_event(struct evlist *evlist, const char *str); 45 44 46 - int parse_events_terms(struct list_head *terms, const char *str); 45 + int parse_events_terms(struct list_head *terms, const char *str, FILE *input); 47 46 int parse_filter(const struct option *opt, const char *str, int unset); 48 47 int exclude_perf(const struct option *opt, const char *arg, int unset); 49 48
+17 -31
tools/perf/util/pmu.c
··· 280 280 return ret; 281 281 } 282 282 283 - static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name) 283 + static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const char *name) 284 284 { 285 285 struct stat st; 286 286 ssize_t sret; ··· 312 312 return ret; 313 313 } 314 314 315 - static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name) 315 + static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const char *name) 316 316 { 317 317 char path[PATH_MAX]; 318 318 ssize_t sret; ··· 343 343 } 344 344 345 345 static int 346 - perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name) 346 + perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *name) 347 347 { 348 348 char path[PATH_MAX]; 349 349 int fd; ··· 361 361 } 362 362 363 363 static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 364 - int dirfd, char *name) 364 + int dirfd, const char *name) 365 365 { 366 366 char path[PATH_MAX]; 367 367 int fd; ··· 454 454 return false; 455 455 } 456 456 457 - static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, 458 - char *desc, char *val, const struct pmu_event *pe) 457 + static int perf_pmu__new_alias(struct list_head *list, int dirfd, const char *name, 458 + const char *desc, const char *val, FILE *val_fd, 459 + const struct pmu_event *pe) 459 460 { 460 461 struct parse_events_term *term; 461 462 struct perf_pmu_alias *alias; ··· 485 484 alias->snapshot = false; 486 485 alias->deprecated = deprecated; 487 486 488 - ret = parse_events_terms(&alias->terms, val); 487 + ret = parse_events_terms(&alias->terms, val, val_fd); 489 488 if (ret) { 490 489 pr_err("Cannot parse alias %s: %d\n", val, ret); 491 490 free(alias); ··· 540 539 list_add_tail(&alias->list, list); 541 540 542 541 return 0; 543 - } 544 - 545 - static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file) 546 - { 547 - char buf[256]; 548 - int ret; 549 - 550 - ret = fread(buf, 1, sizeof(buf), file); 551 - if (ret == 0) 552 - return -EINVAL; 553 - 554 - buf[ret] = 0; 555 - 556 - /* Remove trailing newline from sysfs file */ 557 - strim(buf); 558 - 559 - return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL); 560 542 } 561 543 562 544 static inline bool pmu_alias_info_file(char *name) ··· 597 613 continue; 598 614 } 599 615 600 - if (perf_pmu__new_alias(head, dirfd, name, file) < 0) 616 + if (perf_pmu__new_alias(head, dirfd, name, /*desc=*/ NULL, 617 + /*val=*/ NULL, file, /*pe=*/ NULL) < 0) 601 618 pr_debug("Cannot set up %s\n", name); 602 619 fclose(file); 603 620 } ··· 851 866 struct list_head *head = vdata; 852 867 853 868 /* need type casts to override 'const' */ 854 - __perf_pmu__new_alias(head, -1, (char *)pe->name, (char *)pe->desc, (char *)pe->event, pe); 869 + perf_pmu__new_alias(head, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); 855 870 return 0; 856 871 } 857 872 ··· 892 907 893 908 if (!strcmp(pmu->id, pe->compat) && 894 909 pmu_uncore_alias_match(pe->pmu, pmu->name)) { 895 - __perf_pmu__new_alias(idata->head, -1, 896 - (char *)pe->name, 897 - (char *)pe->desc, 898 - (char *)pe->event, 899 - pe); 910 + perf_pmu__new_alias(idata->head, -1, 911 + pe->name, 912 + pe->desc, 913 + pe->event, 914 + /*val_fd=*/ NULL, 915 + pe); 900 916 } 901 917 902 918 return 0;