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

perf pmu: Make parser reentrant

By default bison uses global state for compatibility with yacc. Make
the parser reentrant so that it may be used in asynchronous and
multithreaded situations.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Leo Yan <leo.yan@linaro.org>
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>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230406065224.2553640-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
3d88aec0 e5116f46

+37 -13
+20 -6
tools/perf/util/pmu.c
··· 24 24 #include "evsel.h" 25 25 #include "pmu.h" 26 26 #include "pmus.h" 27 + #include "pmu-bison.h" 28 + #include "pmu-flex.h" 27 29 #include "parse-events.h" 28 30 #include "print-events.h" 29 31 #include "header.h" ··· 59 57 struct list_head list; 60 58 }; 61 59 62 - int perf_pmu_parse(struct list_head *list, char *name); 63 - extern FILE *perf_pmu_in; 64 - 65 60 static bool hybrid_scanned; 66 61 67 62 static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name); ··· 80 81 while (!ret && (evt_ent = readdir(format_dir))) { 81 82 char *name = evt_ent->d_name; 82 83 int fd; 84 + void *scanner; 85 + FILE *file; 83 86 84 87 if (!strcmp(name, ".") || !strcmp(name, "..")) 85 88 continue; ··· 92 91 if (fd < 0) 93 92 break; 94 93 95 - perf_pmu_in = fdopen(fd, "r"); 96 - ret = perf_pmu_parse(head, name); 97 - fclose(perf_pmu_in); 94 + file = fdopen(fd, "r"); 95 + if (!file) { 96 + close(fd); 97 + break; 98 + } 99 + 100 + ret = perf_pmu_lex_init(&scanner); 101 + if (ret) { 102 + fclose(file); 103 + break; 104 + } 105 + 106 + perf_pmu_set_in(file, scanner); 107 + ret = perf_pmu_parse(head, name, scanner); 108 + perf_pmu_lex_destroy(scanner); 109 + fclose(file); 98 110 } 99 111 100 112 closedir(format_dir);
+1 -1
tools/perf/util/pmu.h
··· 206 206 struct perf_pmu_info *info); 207 207 struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 208 208 struct list_head *head_terms); 209 - void perf_pmu_error(struct list_head *list, char *name, char const *msg); 209 + void perf_pmu_error(struct list_head *list, char *name, void *scanner, char const *msg); 210 210 211 211 int perf_pmu__new_format(struct list_head *list, char *name, 212 212 int config, unsigned long *bits);
+12 -5
tools/perf/util/pmu.l
··· 1 1 %option prefix="perf_pmu_" 2 + %option reentrant 3 + %option bison-bridge 2 4 3 5 %{ 4 6 #include <stdlib.h> ··· 8 6 #include "pmu.h" 9 7 #include "pmu-bison.h" 10 8 11 - static int value(int base) 9 + char *perf_pmu_get_text(yyscan_t yyscanner); 10 + YYSTYPE *perf_pmu_get_lval(yyscan_t yyscanner); 11 + 12 + static int value(yyscan_t scanner, int base) 12 13 { 14 + YYSTYPE *yylval = perf_pmu_get_lval(scanner); 15 + char *text = perf_pmu_get_text(scanner); 13 16 long num; 14 17 15 18 errno = 0; 16 - num = strtoul(perf_pmu_text, NULL, base); 19 + num = strtoul(text, NULL, base); 17 20 if (errno) 18 21 return PP_ERROR; 19 22 20 - perf_pmu_lval.num = num; 23 + yylval->num = num; 21 24 return PP_VALUE; 22 25 } 23 26 ··· 32 25 33 26 %% 34 27 35 - {num_dec} { return value(10); } 28 + {num_dec} { return value(yyscanner, 10); } 36 29 config { return PP_CONFIG; } 37 30 - { return '-'; } 38 31 : { return ':'; } ··· 42 35 43 36 %% 44 37 45 - int perf_pmu_wrap(void) 38 + int perf_pmu_wrap(void *scanner __maybe_unused) 46 39 { 47 40 return 1; 48 41 }
+4 -1
tools/perf/util/pmu.y
··· 1 - 1 + %define api.pure full 2 2 %parse-param {struct list_head *format} 3 3 %parse-param {char *name} 4 + %parse-param {void *scanner} 5 + %lex-param {void* scanner} 4 6 5 7 %{ 6 8 ··· 80 78 81 79 void perf_pmu_error(struct list_head *list __maybe_unused, 82 80 char *name __maybe_unused, 81 + void *scanner __maybe_unused, 83 82 char const *msg __maybe_unused) 84 83 { 85 84 }