在 2023/7/31 下午6:59, Jing Zhang 写道: > > 在 2023/7/28 下午4:11, John Garry 写道: >> On 28/07/2023 07:17, Jing Zhang wrote: >>> The jevent "Compat" is used for uncore PMU alias or metric definitions. >>> >>> The same PMU driver has different PMU identifiers due to different hardware >>> versions and types, but they may have some common PMU event/metric. Since a >>> Compat value can only match one identifier, when adding the same event >>> alias and metric to PMUs with different identifiers, each identifier needs >>> to be defined once, which is not streamlined enough. >>> >>> So let "Compat" value supports matching multiple identifiers. For example, >>> the Compat value {abcde;123*} >> why not use a comma-separated list? that is more common >> > > Hi John, > > I use a semicolon instead of a comma because I want to distinguish it from the function > of the comma in "Unit" and avoid confusion between the use of commas in "Unit" and "Compat". > Because in “Compat”, the semicolon means "or". So I think semicolons are more appropriate, > what do you think? > >>> can match the PMU identifier "abcde" and the >>> the PMU identifier with the prefix "123", >> >> I have to admit that this is not a great example as it does not match an expected real-life scenario. I mean, I would not expect a PMU identifier for the same PMU to be in either format "abcde" or "123*". I would expect to be in only ever one format. >> > > Get, I'll pick a more appropriate example {43401;436*}(CMN600 r0p0 and all CMN650). > >>> where "*" is a wildcard. >>> Tokens in Unit field are delimited by ';' with no spaces. >>> >>> Signed-off-by: Jing Zhang <renyu.zj@xxxxxxxxxxxxxxxxx> >>> --- >>> tools/perf/util/metricgroup.c | 2 +- >>> tools/perf/util/pmu.c | 27 ++++++++++++++++++++++++++- >>> tools/perf/util/pmu.h | 1 + >>> 3 files changed, 28 insertions(+), 2 deletions(-) >>> >>> diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c >>> index 5e9c657..ff81bc5 100644 >>> --- a/tools/perf/util/metricgroup.c >>> +++ b/tools/perf/util/metricgroup.c >>> @@ -477,7 +477,7 @@ static int metricgroup__sys_event_iter(const struct pmu_metric *pm, >>> while ((pmu = perf_pmu__scan(pmu))) { >>> - if (!pmu->id || strcmp(pmu->id, pm->compat)) >>> + if (!pmu->id || !pmu_uncore_identifier_match(pmu->id, pm->compat)) >>> continue; >>> return d->fn(pm, table, d->data); >>> diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c >>> index ad209c8..3ae249b 100644 >>> --- a/tools/perf/util/pmu.c >>> +++ b/tools/perf/util/pmu.c >>> @@ -776,6 +776,31 @@ static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) >>> return res; >>> } >>> +bool pmu_uncore_identifier_match(const char *id, const char *compat) >>> +{ >>> + char *tmp = NULL, *tok, *str; >>> + bool res; >>> + int n; >>> + >>> + str = strdup(compat); >> >> why duplicate this? are you modifying something? >> > > This is really a redundant step, I will remove it. > Hi John, I reviewed this code again and found that it still needs to duplicate "compat" because "compat" is a const str* type and cannot be used as a parameter for the strtok_r function. If it is cast to char*, using "compat" as a parameter for strtok_r is also unsafe and can cause a "Segmentation fault" error. Therefore, let's keep the step of duplicating "compat". Thanks, Jing >>> + if (!str) >>> + return false; >>> + >>> + tok = strtok_r(str, ";", &tmp); >>> + for (; tok; tok = strtok_r(NULL, ";", &tmp)) { >>> + n = strlen(tok); >>> + if ((tok[n - 1] == '*' && !strncmp(id, tok, n - 1)) || >>> + !strcmp(id, tok)) { >>> + res = true; >>> + goto out; >>> + } >>> + } >>> + res = false; >>> +out: >>> + free(str); >>> + return res; >>> +} >>> + >>> struct pmu_add_cpu_aliases_map_data { >>> struct list_head *head; >>> const char *name; >>> @@ -847,7 +872,7 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, >> >> This is not for metrics specifically. You are really doing 2x things here. I suggest that you split the patch out into 1st pmu.c change and 2nd metricgroup.c change >> > > Ok, will do. > >>> if (!pe->compat || !pe->pmu) >>> return 0; >>> - if (!strcmp(pmu->id, pe->compat) && >>> + if (pmu_uncore_identifier_match(pmu->id, pe->compat) && >>> pmu_uncore_alias_match(pe->pmu, pmu->name)) { >> >> nit: let's change order to check alias and then identifier >> > > Will do. > > > Thanks, > Jing > >>> __perf_pmu__new_alias(idata->head, -1, >>> (char *)pe->name, >>> diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h >>> index b9a02de..9d4385d 100644 >>> --- a/tools/perf/util/pmu.h >>> +++ b/tools/perf/util/pmu.h >>> @@ -241,6 +241,7 @@ void pmu_add_cpu_aliases_table(struct list_head *head, struct perf_pmu *pmu, >>> char *perf_pmu__getcpuid(struct perf_pmu *pmu); >>> const struct pmu_events_table *pmu_events_table__find(void); >>> const struct pmu_metrics_table *pmu_metrics_table__find(void); >>> +bool pmu_uncore_identifier_match(const char *id, const char *compat); >>> void perf_pmu_free_alias(struct perf_pmu_alias *alias); >>> int perf_pmu__convert_scale(const char *scale, char **end, double *sval); >> >> Thanks, >> John