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

perf pmu: Separate pmu and pmus

Separate and hide the pmus list in pmus.[ch]. Move pmus functionality
out of pmu.[ch] into pmus.[ch] renaming pmus functions which were
prefixed perf_pmu__ to perf_pmus__.

Reviewed-by: Kan Liang <kan.liang@linux.intel.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: Ali Saidi <alisaidi@amazon.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
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: Kang Minchul <tegongkang@gmail.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Ming Wang <wangming01@loongson.cn>
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: Sandipan Das <sandipan.das@amd.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230527072210.2900565-28-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
1eaf496e 875375ea

+533 -506
+4 -3
tools/perf/arch/arm/util/auxtrace.c
··· 14 14 #include "../../../util/debug.h" 15 15 #include "../../../util/evlist.h" 16 16 #include "../../../util/pmu.h" 17 + #include "../../../util/pmus.h" 17 18 #include "cs-etm.h" 18 19 #include "arm-spe.h" 19 20 #include "hisi-ptt.h" ··· 41 40 return NULL; 42 41 } 43 42 44 - arm_spe_pmus[*nr_spes] = perf_pmu__find(arm_spe_pmu_name); 43 + arm_spe_pmus[*nr_spes] = perf_pmus__find(arm_spe_pmu_name); 45 44 if (arm_spe_pmus[*nr_spes]) { 46 45 pr_debug2("%s %d: arm_spe_pmu %d type %d name %s\n", 47 46 __func__, __LINE__, *nr_spes, ··· 88 87 rewinddir(dir); 89 88 while ((dent = readdir(dir))) { 90 89 if (strstr(dent->d_name, HISI_PTT_PMU_NAME) && idx < *nr_ptts) { 91 - hisi_ptt_pmus[idx] = perf_pmu__find(dent->d_name); 90 + hisi_ptt_pmus[idx] = perf_pmus__find(dent->d_name); 92 91 if (hisi_ptt_pmus[idx]) 93 92 idx++; 94 93 } ··· 132 131 if (!evlist) 133 132 return NULL; 134 133 135 - cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); 134 + cs_etm_pmu = perf_pmus__find(CORESIGHT_ETM_PMU_NAME); 136 135 arm_spe_pmus = find_all_arm_spe_pmus(&nr_spes, err); 137 136 hisi_ptt_pmus = find_all_hisi_ptt_pmus(&nr_ptts, err); 138 137
+2 -2
tools/perf/arch/arm/util/cs-etm.c
··· 25 25 #include "../../../util/evsel.h" 26 26 #include "../../../util/perf_api_probe.h" 27 27 #include "../../../util/evsel_config.h" 28 - #include "../../../util/pmu.h" 28 + #include "../../../util/pmus.h" 29 29 #include "../../../util/cs-etm.h" 30 30 #include <internal/lib.h> // page_size 31 31 #include "../../../util/session.h" ··· 881 881 struct perf_pmu *cs_etm_pmu; 882 882 struct cs_etm_recording *ptr; 883 883 884 - cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); 884 + cs_etm_pmu = perf_pmus__find(CORESIGHT_ETM_PMU_NAME); 885 885 886 886 if (!cs_etm_pmu) { 887 887 *err = -EINVAL;
+2 -1
tools/perf/arch/arm64/util/pmu.c
··· 3 3 #include <internal/cpumap.h> 4 4 #include "../../../util/cpumap.h" 5 5 #include "../../../util/pmu.h" 6 + #include "../../../util/pmus.h" 6 7 #include <api/fs/fs.h> 7 8 #include <math.h> 8 9 ··· 11 10 { 12 11 struct perf_pmu *pmu = NULL; 13 12 14 - while ((pmu = perf_pmu__scan(pmu))) { 13 + while ((pmu = perf_pmus__scan(pmu))) { 15 14 if (!is_pmu_core(pmu->name)) 16 15 continue; 17 16
+3 -2
tools/perf/arch/x86/tests/hybrid.c
··· 4 4 #include "evlist.h" 5 5 #include "evsel.h" 6 6 #include "pmu.h" 7 + #include "pmus.h" 7 8 #include "tests/tests.h" 8 9 9 10 static bool test_config(const struct evsel *evsel, __u64 expected_config) ··· 114 113 struct perf_evsel *evsel; 115 114 116 115 perf_evlist__for_each_evsel(&evlist->core, evsel) { 117 - struct perf_pmu *pmu = perf_pmu__find_by_type(evsel->attr.type); 116 + struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->attr.type); 118 117 119 118 TEST_ASSERT_VAL("missing pmu", pmu); 120 119 TEST_ASSERT_VAL("unexpected pmu", !strncmp(pmu->name, "cpu_", 4)); ··· 281 280 282 281 int test__hybrid(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 283 282 { 284 - if (!perf_pmu__has_hybrid()) 283 + if (!perf_pmus__has_hybrid()) 285 284 return TEST_SKIP; 286 285 287 286 return test_events(test__hybrid_events, ARRAY_SIZE(test__hybrid_events));
+3 -2
tools/perf/arch/x86/util/auxtrace.c
··· 10 10 #include "../../../util/header.h" 11 11 #include "../../../util/debug.h" 12 12 #include "../../../util/pmu.h" 13 + #include "../../../util/pmus.h" 13 14 #include "../../../util/auxtrace.h" 14 15 #include "../../../util/intel-pt.h" 15 16 #include "../../../util/intel-bts.h" ··· 26 25 bool found_pt = false; 27 26 bool found_bts = false; 28 27 29 - intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); 30 - intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 28 + intel_pt_pmu = perf_pmus__find(INTEL_PT_PMU_NAME); 29 + intel_bts_pmu = perf_pmus__find(INTEL_BTS_PMU_NAME); 31 30 32 31 evlist__for_each_entry(evlist, evsel) { 33 32 if (intel_pt_pmu && evsel->core.attr.type == intel_pt_pmu->type)
+3 -2
tools/perf/arch/x86/util/evlist.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <stdio.h> 3 3 #include "util/pmu.h" 4 + #include "util/pmus.h" 4 5 #include "util/evlist.h" 5 6 #include "util/parse-events.h" 6 7 #include "util/event.h" ··· 18 17 for (i = 0; i < nr_attrs; i++) 19 18 event_attr_init(attrs + i); 20 19 21 - if (!perf_pmu__has_hybrid()) 20 + if (!perf_pmus__has_hybrid()) 22 21 return evlist__add_attrs(evlist, attrs, nr_attrs); 23 22 24 23 for (i = 0; i < nr_attrs; i++) { ··· 33 32 continue; 34 33 } 35 34 36 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 35 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 37 36 struct perf_cpu_map *cpus; 38 37 struct evsel *evsel; 39 38
+4 -3
tools/perf/arch/x86/util/evsel.c
··· 4 4 #include "util/evsel.h" 5 5 #include "util/env.h" 6 6 #include "util/pmu.h" 7 + #include "util/pmus.h" 7 8 #include "linux/string.h" 8 9 #include "evsel.h" 9 10 #include "util/debug.h" ··· 31 30 * should be good enough to detect the perf metrics feature. 32 31 */ 33 32 if ((evsel->core.attr.type == PERF_TYPE_RAW) && 34 - pmu_have_event(pmu_name, "slots")) 33 + perf_pmus__have_event(pmu_name, "slots")) 35 34 return true; 36 35 37 36 return false; ··· 99 98 if (!evsel_pmu) 100 99 return; 101 100 102 - ibs_fetch_pmu = perf_pmu__find("ibs_fetch"); 103 - ibs_op_pmu = perf_pmu__find("ibs_op"); 101 + ibs_fetch_pmu = perf_pmus__find("ibs_fetch"); 102 + ibs_op_pmu = perf_pmus__find("ibs_op"); 104 103 105 104 if (ibs_fetch_pmu && ibs_fetch_pmu->type == evsel_pmu->type) { 106 105 if (attr->config & IBS_FETCH_L3MISSONLY) {
+2 -2
tools/perf/arch/x86/util/intel-bts.c
··· 17 17 #include "../../../util/evlist.h" 18 18 #include "../../../util/mmap.h" 19 19 #include "../../../util/session.h" 20 - #include "../../../util/pmu.h" 20 + #include "../../../util/pmus.h" 21 21 #include "../../../util/debug.h" 22 22 #include "../../../util/record.h" 23 23 #include "../../../util/tsc.h" ··· 416 416 417 417 struct auxtrace_record *intel_bts_recording_init(int *err) 418 418 { 419 - struct perf_pmu *intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 419 + struct perf_pmu *intel_bts_pmu = perf_pmus__find(INTEL_BTS_PMU_NAME); 420 420 struct intel_bts_recording *btsr; 421 421 422 422 if (!intel_bts_pmu)
+2 -2
tools/perf/arch/x86/util/intel-pt.c
··· 23 23 #include "../../../util/mmap.h" 24 24 #include <subcmd/parse-options.h> 25 25 #include "../../../util/parse-events.h" 26 - #include "../../../util/pmu.h" 26 + #include "../../../util/pmus.h" 27 27 #include "../../../util/debug.h" 28 28 #include "../../../util/auxtrace.h" 29 29 #include "../../../util/perf_api_probe.h" ··· 1185 1185 1186 1186 struct auxtrace_record *intel_pt_recording_init(int *err) 1187 1187 { 1188 - struct perf_pmu *intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); 1188 + struct perf_pmu *intel_pt_pmu = perf_pmus__find(INTEL_PT_PMU_NAME); 1189 1189 struct intel_pt_recording *ptr; 1190 1190 1191 1191 if (!intel_pt_pmu)
+5 -4
tools/perf/arch/x86/util/mem-events.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "util/pmu.h" 3 + #include "util/pmus.h" 3 4 #include "util/env.h" 4 5 #include "map_symbol.h" 5 6 #include "mem-events.h" ··· 56 55 57 56 bool is_mem_loads_aux_event(struct evsel *leader) 58 57 { 59 - struct perf_pmu *pmu = perf_pmu__find("cpu"); 58 + struct perf_pmu *pmu = perf_pmus__find("cpu"); 60 59 61 60 if (!pmu) 62 - pmu = perf_pmu__find("cpu_core"); 61 + pmu = perf_pmus__find("cpu_core"); 63 62 64 - if (pmu && !pmu_have_event(pmu->name, "mem-loads-aux")) 63 + if (pmu && !perf_pmu__have_event(pmu, "mem-loads-aux")) 65 64 return false; 66 65 67 66 return leader->core.attr.config == MEM_LOADS_AUX; ··· 83 82 pmu_name = (char *)"cpu"; 84 83 } 85 84 86 - if (pmu_have_event(pmu_name, "mem-loads-aux")) { 85 + if (perf_pmus__have_event(pmu_name, "mem-loads-aux")) { 87 86 scnprintf(mem_loads_name, sizeof(mem_loads_name), 88 87 MEM_LOADS_AUX_NAME, pmu_name, pmu_name, 89 88 perf_mem_events__loads_ldlat);
+3 -2
tools/perf/arch/x86/util/perf_regs.c
··· 10 10 #include "../../../util/debug.h" 11 11 #include "../../../util/event.h" 12 12 #include "../../../util/pmu.h" 13 + #include "../../../util/pmus.h" 13 14 14 15 const struct sample_reg sample_reg_masks[] = { 15 16 SMPL_REG(AX, PERF_REG_X86_AX), ··· 292 291 */ 293 292 attr.sample_period = 1; 294 293 295 - if (perf_pmu__has_hybrid()) { 294 + if (perf_pmus__has_hybrid()) { 296 295 struct perf_pmu *pmu = NULL; 297 296 __u64 type = PERF_TYPE_RAW; 298 297 ··· 300 299 * The same register set is supported among different hybrid PMUs. 301 300 * Only check the first available one. 302 301 */ 303 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 302 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 304 303 if (pmu->is_core) { 305 304 type = pmu->type; 306 305 break;
+3 -2
tools/perf/arch/x86/util/topdown.c
··· 2 2 #include "api/fs/fs.h" 3 3 #include "util/evsel.h" 4 4 #include "util/pmu.h" 5 + #include "util/pmus.h" 5 6 #include "util/topdown.h" 6 7 #include "topdown.h" 7 8 #include "evsel.h" ··· 23 22 * The slots event is only available when the core PMU 24 23 * supports the perf metrics feature. 25 24 */ 26 - pmu = perf_pmu__find_by_type(PERF_TYPE_RAW); 27 - if (pmu && pmu_have_event(pmu->name, "slots")) 25 + pmu = perf_pmus__find_by_type(PERF_TYPE_RAW); 26 + if (pmu && perf_pmu__have_event(pmu, "slots")) 28 27 has_perf_metrics = true; 29 28 30 29 cached = true;
+5 -5
tools/perf/bench/pmu-scan.c
··· 44 44 struct list_head *list; 45 45 struct pmu_scan_result *r; 46 46 47 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 47 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 48 48 r = realloc(results, (nr_pmus + 1) * sizeof(*r)); 49 49 if (r == NULL) 50 50 return -ENOMEM; ··· 68 68 nr_pmus++; 69 69 } 70 70 71 - perf_pmu__destroy(); 71 + perf_pmus__destroy(); 72 72 return 0; 73 73 } 74 74 ··· 81 81 82 82 for (int i = 0; i < nr_pmus; i++) { 83 83 r = &results[i]; 84 - pmu = perf_pmu__find(r->name); 84 + pmu = perf_pmus__find(r->name); 85 85 if (pmu == NULL) { 86 86 pr_err("Cannot find PMU %s\n", r->name); 87 87 return -1; ··· 144 144 145 145 for (i = 0; i < iterations; i++) { 146 146 gettimeofday(&start, NULL); 147 - perf_pmu__scan(NULL); 147 + perf_pmus__scan(NULL); 148 148 gettimeofday(&end, NULL); 149 149 150 150 timersub(&end, &start, &diff); ··· 152 152 update_stats(&stats, runtime_us); 153 153 154 154 ret = check_result(); 155 - perf_pmu__destroy(); 155 + perf_pmus__destroy(); 156 156 if (ret < 0) 157 157 break; 158 158 }
+2 -2
tools/perf/builtin-c2c.c
··· 41 41 #include "symbol.h" 42 42 #include "ui/ui.h" 43 43 #include "ui/progress.h" 44 - #include "pmu.h" 44 + #include "pmus.h" 45 45 #include "string2.h" 46 46 #include "util/util.h" 47 47 ··· 3259 3259 PARSE_OPT_KEEP_UNKNOWN); 3260 3260 3261 3261 /* Max number of arguments multiplied by number of PMUs that can support them. */ 3262 - rec_argc = argc + 11 * perf_pmu__num_mem_pmus(); 3262 + rec_argc = argc + 11 * perf_pmus__num_mem_pmus(); 3263 3263 3264 3264 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 3265 3265 if (!rec_argv)
+2 -2
tools/perf/builtin-list.c
··· 527 527 strcmp(argv[i], "hwcache") == 0) 528 528 print_hwcache_events(&print_cb, ps); 529 529 else if (strcmp(argv[i], "pmu") == 0) 530 - print_pmu_events(&print_cb, ps); 530 + perf_pmus__print_pmu_events(&print_cb, ps); 531 531 else if (strcmp(argv[i], "sdt") == 0) 532 532 print_sdt_events(&print_cb, ps); 533 533 else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { ··· 567 567 event_symbols_sw, PERF_COUNT_SW_MAX); 568 568 print_tool_events(&print_cb, ps); 569 569 print_hwcache_events(&print_cb, ps); 570 - print_pmu_events(&print_cb, ps); 570 + perf_pmus__print_pmu_events(&print_cb, ps); 571 571 print_tracepoint_events(&print_cb, ps); 572 572 print_sdt_events(&print_cb, ps); 573 573 default_ps.metrics = true;
+2 -2
tools/perf/builtin-mem.c
··· 17 17 #include "util/dso.h" 18 18 #include "util/map.h" 19 19 #include "util/symbol.h" 20 - #include "util/pmu.h" 20 + #include "util/pmus.h" 21 21 #include "util/sample.h" 22 22 #include "util/string2.h" 23 23 #include "util/util.h" ··· 93 93 PARSE_OPT_KEEP_UNKNOWN); 94 94 95 95 /* Max number of arguments multiplied by number of PMUs that can support them. */ 96 - rec_argc = argc + 9 * perf_pmu__num_mem_pmus(); 96 + rec_argc = argc + 9 * perf_pmus__num_mem_pmus(); 97 97 98 98 if (mem->cpu_list) 99 99 rec_argc += 2;
+4 -2
tools/perf/builtin-record.c
··· 48 48 #include "util/bpf-event.h" 49 49 #include "util/util.h" 50 50 #include "util/pfm.h" 51 + #include "util/pmu.h" 52 + #include "util/pmus.h" 51 53 #include "util/clockid.h" 52 54 #include "util/off_cpu.h" 53 55 #include "util/bpf-filter.h" ··· 1294 1292 * of waiting or event synthesis. 1295 1293 */ 1296 1294 if (opts->target.initial_delay || target__has_cpu(&opts->target) || 1297 - perf_pmu__has_hybrid()) { 1295 + perf_pmus__has_hybrid()) { 1298 1296 pos = evlist__get_tracking_event(evlist); 1299 1297 if (!evsel__is_dummy_event(pos)) { 1300 1298 /* Set up dummy event. */ ··· 2193 2191 char *new_name; 2194 2192 int ret; 2195 2193 2196 - if (!perf_pmu__has_hybrid()) 2194 + if (!perf_pmus__has_hybrid()) 2197 2195 return; 2198 2196 2199 2197 evlist__for_each_entry(evlist, pos) {
+2 -2
tools/perf/builtin-stat.c
··· 2140 2140 2141 2141 if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 2142 2142 return -1; 2143 - if (pmu_have_event("cpu", "stalled-cycles-frontend")) { 2143 + if (perf_pmus__have_event("cpu", "stalled-cycles-frontend")) { 2144 2144 if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) 2145 2145 return -1; 2146 2146 } 2147 - if (pmu_have_event("cpu", "stalled-cycles-backend")) { 2147 + if (perf_pmus__have_event("cpu", "stalled-cycles-backend")) { 2148 2148 if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) 2149 2149 return -1; 2150 2150 }
+2 -2
tools/perf/tests/attr.c
··· 34 34 #include "event.h" 35 35 #include "util.h" 36 36 #include "tests.h" 37 - #include "pmu.h" 37 + #include "pmus.h" 38 38 39 39 #define ENV "PERF_TEST_ATTR" 40 40 ··· 185 185 char path_dir[PATH_MAX]; 186 186 char *exec_path; 187 187 188 - if (perf_pmu__has_hybrid()) 188 + if (perf_pmus__has_hybrid()) 189 189 return TEST_SKIP; 190 190 191 191 /* First try development tree tests. */
+1 -1
tools/perf/tests/event_groups.c
··· 53 53 struct perf_pmu *pmu = NULL; 54 54 int i, fd; 55 55 56 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 56 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 57 57 for (i = 0; i < NR_UNCORE_PMUS; i++) { 58 58 if (!strcmp(uncore_pmus[i].name, pmu->name)) { 59 59 pr_debug("Using %s for uncore pmu event\n", pmu->name);
+4 -4
tools/perf/tests/parse-events.c
··· 112 112 bool type_matched = false; 113 113 114 114 TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 0x1a)); 115 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 115 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 116 116 if (pmu->type == evsel->attr.type) { 117 117 TEST_ASSERT_VAL("PMU type expected once", !type_matched); 118 118 type_matched = true; ··· 1443 1443 1444 1444 static bool test__pmu_cpu_valid(void) 1445 1445 { 1446 - return !!perf_pmu__find("cpu"); 1446 + return !!perf_pmus__find("cpu"); 1447 1447 } 1448 1448 1449 1449 static bool test__intel_pt_valid(void) 1450 1450 { 1451 - return !!perf_pmu__find("intel_pt"); 1451 + return !!perf_pmus__find("intel_pt"); 1452 1452 } 1453 1453 1454 1454 static int test__intel_pt(struct evlist *evlist) ··· 2246 2246 struct perf_pmu *pmu = NULL; 2247 2247 int ret = TEST_OK; 2248 2248 2249 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 2249 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 2250 2250 struct stat st; 2251 2251 char path[PATH_MAX]; 2252 2252 struct dirent *ent;
+2 -2
tools/perf/tests/parse-metric.c
··· 11 11 #include "debug.h" 12 12 #include "expr.h" 13 13 #include "stat.h" 14 - #include "pmu.h" 14 + #include "pmus.h" 15 15 16 16 struct value { 17 17 const char *event; ··· 303 303 TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0); 304 304 TEST_ASSERT_VAL("Memory bandwidth", test_memory_bandwidth() == 0); 305 305 306 - if (!perf_pmu__has_hybrid()) { 306 + if (!perf_pmus__has_hybrid()) { 307 307 TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); 308 308 TEST_ASSERT_VAL("test metric group", test_metric_group() == 0); 309 309 }
+2 -1
tools/perf/tests/pmu-events.c
··· 2 2 #include "math.h" 3 3 #include "parse-events.h" 4 4 #include "pmu.h" 5 + #include "pmus.h" 5 6 #include "tests.h" 6 7 #include <errno.h> 7 8 #include <stdio.h> ··· 709 708 struct perf_pmu *pmu = NULL; 710 709 unsigned long i; 711 710 712 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 711 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 713 712 int count = 0; 714 713 715 714 if (!is_pmu_core(pmu->name))
+2 -2
tools/perf/tests/switch-tracking.c
··· 20 20 #include "tests.h" 21 21 #include "util/mmap.h" 22 22 #include "util/sample.h" 23 - #include "pmu.h" 23 + #include "pmus.h" 24 24 25 25 static int spin_sleep(void) 26 26 { ··· 375 375 cpu_clocks_evsel = evlist__last(evlist); 376 376 377 377 /* Second event */ 378 - if (perf_pmu__has_hybrid()) { 378 + if (perf_pmus__has_hybrid()) { 379 379 cycles = "cpu_core/cycles/u"; 380 380 err = parse_event(evlist, cycles); 381 381 if (err) {
+2 -2
tools/perf/tests/topology.c
··· 8 8 #include "session.h" 9 9 #include "evlist.h" 10 10 #include "debug.h" 11 - #include "pmu.h" 11 + #include "pmus.h" 12 12 #include <linux/err.h> 13 13 14 14 #define TEMPL "/tmp/perf-test-XXXXXX" ··· 41 41 session = perf_session__new(&data, NULL); 42 42 TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); 43 43 44 - if (!perf_pmu__has_hybrid()) { 44 + if (!perf_pmus__has_hybrid()) { 45 45 session->evlist = evlist__new_default(); 46 46 TEST_ASSERT_VAL("can't get evlist", session->evlist); 47 47 } else {
+4 -3
tools/perf/util/cputopo.c
··· 13 13 #include "debug.h" 14 14 #include "env.h" 15 15 #include "pmu.h" 16 + #include "pmus.h" 16 17 17 18 #define PACKAGE_CPUS_FMT \ 18 19 "%s/devices/system/cpu/cpu%d/topology/package_cpus_list" ··· 474 473 struct hybrid_topology *tp = NULL; 475 474 u32 nr = 0, i = 0; 476 475 477 - if (!perf_pmu__has_hybrid()) 476 + if (!perf_pmus__has_hybrid()) 478 477 return NULL; 479 478 480 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 479 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 481 480 if (pmu->is_core) 482 481 nr++; 483 482 } ··· 489 488 return NULL; 490 489 491 490 tp->nr = nr; 492 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 491 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 493 492 if (!pmu->is_core) 494 493 continue; 495 494
+3 -2
tools/perf/util/env.c
··· 10 10 #include <sys/utsname.h> 11 11 #include <stdlib.h> 12 12 #include <string.h> 13 + #include "pmus.h" 13 14 #include "strbuf.h" 14 15 15 16 struct perf_env perf_env; ··· 324 323 u32 pmu_num = 0; 325 324 struct strbuf sb; 326 325 327 - while ((pmu = perf_pmu__scan(pmu))) { 326 + while ((pmu = perf_pmus__scan(pmu))) { 328 327 if (!pmu->name) 329 328 continue; 330 329 pmu_num++; ··· 338 337 if (strbuf_init(&sb, 128 * pmu_num) < 0) 339 338 return -ENOMEM; 340 339 341 - while ((pmu = perf_pmu__scan(pmu))) { 340 + while ((pmu = perf_pmus__scan(pmu))) { 342 341 if (!pmu->name) 343 342 continue; 344 343 if (strbuf_addf(&sb, "%u:%s", pmu->type, pmu->name) < 0)
+2 -1
tools/perf/util/evsel.c
··· 48 48 #include "util/hashmap.h" 49 49 #include "off_cpu.h" 50 50 #include "pmu.h" 51 + #include "pmus.h" 51 52 #include "../perf-sys.h" 52 53 #include "util/parse-branch-options.h" 53 54 #include "util/bpf-filter.h" ··· 3140 3139 */ 3141 3140 bool evsel__is_hybrid(const struct evsel *evsel) 3142 3141 { 3143 - if (!perf_pmu__has_hybrid()) 3142 + if (!perf_pmus__has_hybrid()) 3144 3143 return false; 3145 3144 3146 3145 return evsel->core.is_pmu_core;
+8 -7
tools/perf/util/header.c
··· 37 37 #include "debug.h" 38 38 #include "cpumap.h" 39 39 #include "pmu.h" 40 + #include "pmus.h" 40 41 #include "vdso.h" 41 42 #include "strbuf.h" 42 43 #include "build-id.h" ··· 745 744 * Do a first pass to count number of pmu to avoid lseek so this 746 745 * works in pipe mode as well. 747 746 */ 748 - while ((pmu = perf_pmu__scan(pmu))) { 747 + while ((pmu = perf_pmus__scan(pmu))) { 749 748 if (!pmu->name) 750 749 continue; 751 750 pmu_num++; ··· 755 754 if (ret < 0) 756 755 return ret; 757 756 758 - while ((pmu = perf_pmu__scan(pmu))) { 757 + while ((pmu = perf_pmus__scan(pmu))) { 759 758 if (!pmu->name) 760 759 continue; 761 760 ··· 1567 1566 static int write_cpu_pmu_caps(struct feat_fd *ff, 1568 1567 struct evlist *evlist __maybe_unused) 1569 1568 { 1570 - struct perf_pmu *cpu_pmu = perf_pmu__find("cpu"); 1569 + struct perf_pmu *cpu_pmu = perf_pmus__find("cpu"); 1571 1570 int ret; 1572 1571 1573 1572 if (!cpu_pmu) ··· 1587 1586 int nr_pmu = 0; 1588 1587 int ret; 1589 1588 1590 - while ((pmu = perf_pmu__scan(pmu))) { 1589 + while ((pmu = perf_pmus__scan(pmu))) { 1591 1590 if (!pmu->name || !strcmp(pmu->name, "cpu") || 1592 1591 perf_pmu__caps_parse(pmu) <= 0) 1593 1592 continue; ··· 1605 1604 * Write hybrid pmu caps first to maintain compatibility with 1606 1605 * older perf tool. 1607 1606 */ 1608 - if (perf_pmu__has_hybrid()) { 1607 + if (perf_pmus__has_hybrid()) { 1609 1608 pmu = NULL; 1610 - while ((pmu = perf_pmu__scan(pmu))) { 1609 + while ((pmu = perf_pmus__scan(pmu))) { 1611 1610 if (!pmu->is_core) 1612 1611 continue; 1613 1612 ··· 1618 1617 } 1619 1618 1620 1619 pmu = NULL; 1621 - while ((pmu = perf_pmu__scan(pmu))) { 1620 + while ((pmu = perf_pmus__scan(pmu))) { 1622 1621 if (pmu->is_core || !pmu->nr_caps) 1623 1622 continue; 1624 1623
+6 -5
tools/perf/util/mem-events.c
··· 13 13 #include "debug.h" 14 14 #include "symbol.h" 15 15 #include "pmu.h" 16 + #include "pmus.h" 16 17 17 18 unsigned int perf_mem_events__loads_ldlat = 30; 18 19 ··· 129 128 if (!e->tag) 130 129 continue; 131 130 132 - if (!perf_pmu__has_hybrid()) { 131 + if (!perf_pmus__has_hybrid()) { 133 132 scnprintf(sysfs_name, sizeof(sysfs_name), 134 133 e->sysfs_name, "cpu"); 135 134 e->supported = perf_mem_event__supported(mnt, sysfs_name); 136 135 } else { 137 136 struct perf_pmu *pmu = NULL; 138 137 139 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 138 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 140 139 if (!pmu->is_core) 141 140 continue; 142 141 ··· 176 175 char sysfs_name[100]; 177 176 struct perf_pmu *pmu = NULL; 178 177 179 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 178 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 180 179 if (!pmu->is_core) 181 180 continue; 182 181 ··· 202 201 if (!e->record) 203 202 continue; 204 203 205 - if (!perf_pmu__has_hybrid()) { 204 + if (!perf_pmus__has_hybrid()) { 206 205 if (!e->supported) { 207 206 pr_err("failed: event '%s' not supported\n", 208 207 perf_mem_events__name(j, NULL)); ··· 217 216 return -1; 218 217 } 219 218 220 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 219 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 221 220 if (!pmu->is_core) 222 221 continue; 223 222 rec_argv[i++] = "-e";
+3 -2
tools/perf/util/metricgroup.c
··· 11 11 #include "evsel.h" 12 12 #include "strbuf.h" 13 13 #include "pmu.h" 14 + #include "pmus.h" 14 15 #include "print-events.h" 15 16 #include "smt.h" 16 17 #include "expr.h" ··· 274 273 const char *metric_id; 275 274 struct evsel *ev; 276 275 size_t ids_size, matched_events, i; 277 - bool all_pmus = !strcmp(pmu, "all") || !perf_pmu__has_hybrid() || !is_pmu_hybrid(pmu); 276 + bool all_pmus = !strcmp(pmu, "all") || !perf_pmus__has_hybrid() || !is_pmu_hybrid(pmu); 278 277 279 278 *out_metric_events = NULL; 280 279 ids_size = hashmap__size(ids); ··· 489 488 if (!pm->metric_expr || !pm->compat) 490 489 return 0; 491 490 492 - while ((pmu = perf_pmu__scan(pmu))) { 491 + while ((pmu = perf_pmus__scan(pmu))) { 493 492 494 493 if (!pmu->id || strcmp(pmu->id, pm->compat)) 495 494 continue;
+8 -7
tools/perf/util/parse-events.c
··· 21 21 #include "parse-events-bison.h" 22 22 #include "parse-events-flex.h" 23 23 #include "pmu.h" 24 + #include "pmus.h" 24 25 #include "asm/bug.h" 25 26 #include "util/parse-branch-options.h" 26 27 #include "util/evsel_config.h" ··· 453 452 const char *config_name = get_config_name(head_config); 454 453 const char *metric_id = get_config_metric_id(head_config); 455 454 456 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 455 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 457 456 LIST_HEAD(config_terms); 458 457 struct perf_event_attr attr; 459 458 int ret; ··· 1194 1193 struct parse_events_error *err) 1195 1194 { 1196 1195 if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { 1197 - const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type); 1196 + const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 1198 1197 1199 1198 if (perf_pmu__supports_legacy_cache(pmu)) { 1200 1199 attr->type = PERF_TYPE_HW_CACHE; ··· 1204 1203 term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1205 1204 } 1206 1205 if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) { 1207 - const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type); 1206 + const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 1208 1207 1209 1208 if (!pmu) { 1210 1209 pr_debug("Failed to find PMU for type %d", attr->type); ··· 1481 1480 return __parse_events_add_numeric(parse_state, list, /*pmu=*/NULL, 1482 1481 type, config, head_config); 1483 1482 1484 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1483 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 1485 1484 int ret; 1486 1485 1487 1486 if (!perf_pmu__supports_wildcard_numeric(pmu)) ··· 1530 1529 struct parse_events_error *err = parse_state->error; 1531 1530 LIST_HEAD(config_terms); 1532 1531 1533 - pmu = parse_state->fake_pmu ?: perf_pmu__find(name); 1532 + pmu = parse_state->fake_pmu ?: perf_pmus__find(name); 1534 1533 1535 1534 if (verbose > 1 && !(pmu && pmu->selectable)) { 1536 1535 fprintf(stderr, "Attempting to add event pmu '%s' with '", ··· 1675 1674 1676 1675 INIT_LIST_HEAD(list); 1677 1676 1678 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1677 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 1679 1678 struct perf_pmu_alias *alias; 1680 1679 bool auto_merge_stats; 1681 1680 ··· 2411 2410 return 0; 2412 2411 } 2413 2412 2414 - while ((pmu = perf_pmu__scan(pmu)) != NULL) 2413 + while ((pmu = perf_pmus__scan(pmu)) != NULL) 2415 2414 if (pmu->type == evsel->core.attr.type) { 2416 2415 found = true; 2417 2416 break;
+2 -1
tools/perf/util/parse-events.y
··· 15 15 #include <linux/types.h> 16 16 #include <linux/zalloc.h> 17 17 #include "pmu.h" 18 + #include "pmus.h" 18 19 #include "evsel.h" 19 20 #include "parse-events.h" 20 21 #include "parse-events-bison.h" ··· 317 316 if (asprintf(&pattern, "%s*", $1) < 0) 318 317 CLEANUP_YYABORT; 319 318 320 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 319 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 321 320 char *name = pmu->name; 322 321 323 322 if (parse_events__filter_pmu(parse_state, pmu))
+3 -3
tools/perf/util/pfm.c
··· 10 10 #include "util/evlist.h" 11 11 #include "util/evsel.h" 12 12 #include "util/parse-events.h" 13 - #include "util/pmu.h" 13 + #include "util/pmus.h" 14 14 #include "util/pfm.h" 15 15 #include "util/strbuf.h" 16 16 ··· 49 49 /* 50 50 * force loading of the PMU list 51 51 */ 52 - perf_pmu__scan(NULL); 52 + perf_pmus__scan(NULL); 53 53 54 54 for (q = p; strsep(&p, ",{}"); q = p) { 55 55 sep = p ? str + (p - p_orig - 1) : ""; ··· 86 86 goto error; 87 87 } 88 88 89 - pmu = perf_pmu__find_by_type((unsigned int)attr.type); 89 + pmu = perf_pmus__find_by_type((unsigned int)attr.type); 90 90 evsel = parse_events__add_event(evlist->core.nr_entries, 91 91 &attr, q, /*metric_id=*/NULL, 92 92 pmu);
+8 -403
tools/perf/util/pmu.c
··· 4 4 #include <linux/string.h> 5 5 #include <linux/zalloc.h> 6 6 #include <linux/ctype.h> 7 - #include <subcmd/pager.h> 8 7 #include <sys/types.h> 9 - #include <errno.h> 10 8 #include <fcntl.h> 11 9 #include <sys/stat.h> 12 10 #include <unistd.h> 13 11 #include <stdio.h> 14 12 #include <stdbool.h> 15 - #include <stdarg.h> 16 13 #include <dirent.h> 17 14 #include <api/fs/fs.h> 18 15 #include <locale.h> 19 - #include <regex.h> 20 - #include <perf/cpumap.h> 21 16 #include <fnmatch.h> 22 17 #include <math.h> 23 18 #include "debug.h" ··· 53 58 /** @list: Element on list within struct perf_pmu. */ 54 59 struct list_head list; 55 60 }; 56 - 57 - static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name); 58 61 59 62 /* 60 63 * Parse & process all the sysfs attributes located under ··· 547 554 return 0; 548 555 } 549 556 550 - /* Add all pmus in sysfs to pmu list: */ 551 - static void pmu_read_sysfs(void) 552 - { 553 - int fd; 554 - DIR *dir; 555 - struct dirent *dent; 556 - 557 - fd = perf_pmu__event_source_devices_fd(); 558 - if (fd < 0) 559 - return; 560 - 561 - dir = fdopendir(fd); 562 - if (!dir) 563 - return; 564 - 565 - while ((dent = readdir(dir))) { 566 - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 567 - continue; 568 - /* add to static LIST_HEAD(pmus): */ 569 - perf_pmu__find2(fd, dent->d_name); 570 - } 571 - 572 - closedir(dir); 573 - } 574 - 575 557 /* 576 558 * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 577 559 * may have a "cpus" file. ··· 862 894 return max_precise; 863 895 } 864 896 865 - static struct perf_pmu *pmu_lookup(int dirfd, const char *lookup_name) 897 + struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 866 898 { 867 899 struct perf_pmu *pmu; 868 900 LIST_HEAD(format); ··· 919 951 INIT_LIST_HEAD(&pmu->caps); 920 952 list_splice(&format, &pmu->format); 921 953 list_splice(&aliases, &pmu->aliases); 922 - list_add_tail(&pmu->list, &pmus); 954 + list_add_tail(&pmu->list, pmus); 923 955 924 956 pmu->default_config = perf_pmu__get_default_config(pmu); 925 957 ··· 945 977 pmu->name, format->name, format->value); 946 978 return; 947 979 } 948 - } 949 - 950 - static struct perf_pmu *pmu_find(const char *name) 951 - { 952 - struct perf_pmu *pmu; 953 - 954 - list_for_each_entry(pmu, &pmus, list) { 955 - if (!strcmp(pmu->name, name) || 956 - (pmu->alias_name && !strcmp(pmu->alias_name, name))) 957 - return pmu; 958 - } 959 - 960 - return NULL; 961 - } 962 - 963 - struct perf_pmu *perf_pmu__find_by_type(unsigned int type) 964 - { 965 - struct perf_pmu *pmu; 966 - 967 - list_for_each_entry(pmu, &pmus, list) 968 - if (pmu->type == type) 969 - return pmu; 970 - 971 - return NULL; 972 - } 973 - 974 - struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 975 - { 976 - /* 977 - * pmu iterator: If pmu is NULL, we start at the begin, 978 - * otherwise return the next pmu. Returns NULL on end. 979 - */ 980 - if (!pmu) { 981 - pmu_read_sysfs(); 982 - pmu = list_prepare_entry(pmu, &pmus, list); 983 - } 984 - list_for_each_entry_continue(pmu, &pmus, list) 985 - return pmu; 986 - return NULL; 987 - } 988 - 989 - struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) 990 - { 991 - struct perf_pmu *pmu = NULL; 992 - 993 - if (evsel->pmu) 994 - return evsel->pmu; 995 - 996 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 997 - if (pmu->type == evsel->core.attr.type) 998 - break; 999 - } 1000 - 1001 - ((struct evsel *)evsel)->pmu = pmu; 1002 - return pmu; 1003 980 } 1004 981 1005 982 bool evsel__is_aux_event(const struct evsel *evsel) ··· 981 1068 /* Otherwise replace it */ 982 1069 evsel->core.attr.config &= ~bits; 983 1070 evsel->core.attr.config |= field_prep(bits, val); 984 - } 985 - 986 - struct perf_pmu *perf_pmu__find(const char *name) 987 - { 988 - struct perf_pmu *pmu; 989 - int dirfd; 990 - 991 - /* 992 - * Once PMU is loaded it stays in the list, 993 - * so we keep us from multiple reading/parsing 994 - * the pmu format definitions. 995 - */ 996 - pmu = pmu_find(name); 997 - if (pmu) 998 - return pmu; 999 - 1000 - dirfd = perf_pmu__event_source_devices_fd(); 1001 - pmu = pmu_lookup(dirfd, name); 1002 - close(dirfd); 1003 - 1004 - return pmu; 1005 - } 1006 - 1007 - static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) 1008 - { 1009 - struct perf_pmu *pmu; 1010 - 1011 - /* 1012 - * Once PMU is loaded it stays in the list, 1013 - * so we keep us from multiple reading/parsing 1014 - * the pmu format definitions. 1015 - */ 1016 - pmu = pmu_find(name); 1017 - if (pmu) 1018 - return pmu; 1019 - 1020 - return pmu_lookup(dirfd, name); 1021 1071 } 1022 1072 1023 1073 static struct perf_pmu_format * ··· 1412 1536 } 1413 1537 } 1414 1538 1415 - static int sub_non_neg(int a, int b) 1416 - { 1417 - if (b > a) 1418 - return 0; 1419 - return a - b; 1420 - } 1421 - 1422 - static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 1423 - const struct perf_pmu_alias *alias) 1424 - { 1425 - struct parse_events_term *term; 1426 - int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 1427 - 1428 - list_for_each_entry(term, &alias->terms, list) { 1429 - if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1430 - used += snprintf(buf + used, sub_non_neg(len, used), 1431 - ",%s=%s", term->config, 1432 - term->val.str); 1433 - } 1434 - 1435 - if (sub_non_neg(len, used) > 0) { 1436 - buf[used] = '/'; 1437 - used++; 1438 - } 1439 - if (sub_non_neg(len, used) > 0) { 1440 - buf[used] = '\0'; 1441 - used++; 1442 - } else 1443 - buf[len - 1] = '\0'; 1444 - 1445 - return buf; 1446 - } 1447 - 1448 - /** Struct for ordering events as output in perf list. */ 1449 - struct sevent { 1450 - /** PMU for event. */ 1451 - const struct perf_pmu *pmu; 1452 - /** 1453 - * Optional event for name, desc, etc. If not present then this is a 1454 - * selectable PMU and the event name is shown as "//". 1455 - */ 1456 - const struct perf_pmu_alias *event; 1457 - /** Is the PMU for the CPU? */ 1458 - bool is_cpu; 1459 - }; 1460 - 1461 - static int cmp_sevent(const void *a, const void *b) 1462 - { 1463 - const struct sevent *as = a; 1464 - const struct sevent *bs = b; 1465 - const char *a_pmu_name = NULL, *b_pmu_name = NULL; 1466 - const char *a_name = "//", *a_desc = NULL, *a_topic = ""; 1467 - const char *b_name = "//", *b_desc = NULL, *b_topic = ""; 1468 - int ret; 1469 - 1470 - if (as->event) { 1471 - a_name = as->event->name; 1472 - a_desc = as->event->desc; 1473 - a_topic = as->event->topic ?: ""; 1474 - a_pmu_name = as->event->pmu_name; 1475 - } 1476 - if (bs->event) { 1477 - b_name = bs->event->name; 1478 - b_desc = bs->event->desc; 1479 - b_topic = bs->event->topic ?: ""; 1480 - b_pmu_name = bs->event->pmu_name; 1481 - } 1482 - /* Put extra events last. */ 1483 - if (!!a_desc != !!b_desc) 1484 - return !!a_desc - !!b_desc; 1485 - 1486 - /* Order by topics. */ 1487 - ret = strcmp(a_topic, b_topic); 1488 - if (ret) 1489 - return ret; 1490 - 1491 - /* Order CPU core events to be first */ 1492 - if (as->is_cpu != bs->is_cpu) 1493 - return as->is_cpu ? -1 : 1; 1494 - 1495 - /* Order by PMU name. */ 1496 - if (as->pmu != bs->pmu) { 1497 - a_pmu_name = a_pmu_name ?: (as->pmu->name ?: ""); 1498 - b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: ""); 1499 - ret = strcmp(a_pmu_name, b_pmu_name); 1500 - if (ret) 1501 - return ret; 1502 - } 1503 - 1504 - /* Order by event name. */ 1505 - return strcmp(a_name, b_name); 1506 - } 1507 - 1508 1539 bool is_pmu_core(const char *name) 1509 1540 { 1510 1541 return !strcmp(name, "cpu") || is_sysfs_pmu_core(name); ··· 1437 1654 return !is_pmu_hybrid(pmu->name); 1438 1655 } 1439 1656 1440 - static bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu) 1657 + bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu) 1441 1658 { 1442 1659 return pmu->is_core; 1443 1660 } 1444 1661 1445 - int perf_pmu__num_mem_pmus(void) 1662 + bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1446 1663 { 1447 - struct perf_pmu *pmu = NULL; 1448 - int count = 0; 1449 - 1450 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1451 - if (perf_pmu__is_mem_pmu(pmu)) 1452 - count++; 1453 - } 1454 - return count; 1455 - } 1456 - 1457 - static bool pmu_alias_is_duplicate(struct sevent *alias_a, 1458 - struct sevent *alias_b) 1459 - { 1460 - const char *a_pmu_name = NULL, *b_pmu_name = NULL; 1461 - const char *a_name = "//", *b_name = "//"; 1462 - 1463 - 1464 - if (alias_a->event) { 1465 - a_name = alias_a->event->name; 1466 - a_pmu_name = alias_a->event->pmu_name; 1467 - } 1468 - if (alias_b->event) { 1469 - b_name = alias_b->event->name; 1470 - b_pmu_name = alias_b->event->pmu_name; 1471 - } 1472 - 1473 - /* Different names -> never duplicates */ 1474 - if (strcmp(a_name, b_name)) 1475 - return false; 1476 - 1477 - /* Don't remove duplicates for different PMUs */ 1478 - a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: ""); 1479 - b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: ""); 1480 - return strcmp(a_pmu_name, b_pmu_name) == 0; 1481 - } 1482 - 1483 - void print_pmu_events(const struct print_callbacks *print_cb, void *print_state) 1484 - { 1485 - struct perf_pmu *pmu; 1486 - struct perf_pmu_alias *event; 1487 - char buf[1024]; 1488 - int printed = 0; 1489 - int len, j; 1490 - struct sevent *aliases; 1491 - 1492 - pmu = NULL; 1493 - len = 0; 1494 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1495 - list_for_each_entry(event, &pmu->aliases, list) 1496 - len++; 1497 - if (pmu->selectable) 1498 - len++; 1499 - } 1500 - aliases = zalloc(sizeof(struct sevent) * len); 1501 - if (!aliases) { 1502 - pr_err("FATAL: not enough memory to print PMU events\n"); 1503 - return; 1504 - } 1505 - pmu = NULL; 1506 - j = 0; 1507 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1508 - bool is_cpu = pmu->is_core; 1509 - 1510 - list_for_each_entry(event, &pmu->aliases, list) { 1511 - aliases[j].event = event; 1512 - aliases[j].pmu = pmu; 1513 - aliases[j].is_cpu = is_cpu; 1514 - j++; 1515 - } 1516 - if (pmu->selectable) { 1517 - aliases[j].event = NULL; 1518 - aliases[j].pmu = pmu; 1519 - aliases[j].is_cpu = is_cpu; 1520 - j++; 1521 - } 1522 - } 1523 - len = j; 1524 - qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 1525 - for (j = 0; j < len; j++) { 1526 - const char *name, *alias = NULL, *scale_unit = NULL, 1527 - *desc = NULL, *long_desc = NULL, 1528 - *encoding_desc = NULL, *topic = NULL, 1529 - *pmu_name = NULL; 1530 - bool deprecated = false; 1531 - size_t buf_used; 1532 - 1533 - /* Skip duplicates */ 1534 - if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) 1535 - continue; 1536 - 1537 - if (!aliases[j].event) { 1538 - /* A selectable event. */ 1539 - pmu_name = aliases[j].pmu->name; 1540 - buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1; 1541 - name = buf; 1542 - } else { 1543 - if (aliases[j].event->desc) { 1544 - name = aliases[j].event->name; 1545 - buf_used = 0; 1546 - } else { 1547 - name = format_alias(buf, sizeof(buf), aliases[j].pmu, 1548 - aliases[j].event); 1549 - if (aliases[j].is_cpu) { 1550 - alias = name; 1551 - name = aliases[j].event->name; 1552 - } 1553 - buf_used = strlen(buf) + 1; 1554 - } 1555 - pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: ""); 1556 - if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) { 1557 - scale_unit = buf + buf_used; 1558 - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1559 - "%G%s", aliases[j].event->scale, 1560 - aliases[j].event->unit) + 1; 1561 - } 1562 - desc = aliases[j].event->desc; 1563 - long_desc = aliases[j].event->long_desc; 1564 - topic = aliases[j].event->topic; 1565 - encoding_desc = buf + buf_used; 1566 - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1567 - "%s/%s/", pmu_name, aliases[j].event->str) + 1; 1568 - deprecated = aliases[j].event->deprecated; 1569 - } 1570 - print_cb->print_event(print_state, 1571 - pmu_name, 1572 - topic, 1573 - name, 1574 - alias, 1575 - scale_unit, 1576 - deprecated, 1577 - "Kernel PMU event", 1578 - desc, 1579 - long_desc, 1580 - encoding_desc); 1581 - } 1582 - if (printed && pager_in_use()) 1583 - printf("\n"); 1584 - 1585 - zfree(&aliases); 1586 - return; 1587 - } 1588 - 1589 - bool pmu_have_event(const char *pname, const char *name) 1590 - { 1591 - struct perf_pmu *pmu; 1592 1664 struct perf_pmu_alias *alias; 1593 1665 1594 - pmu = NULL; 1595 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1596 - if (strcmp(pname, pmu->name)) 1597 - continue; 1598 - list_for_each_entry(alias, &pmu->aliases, list) 1599 - if (!strcmp(alias->name, name)) 1600 - return true; 1666 + list_for_each_entry(alias, &pmu->aliases, list) { 1667 + if (!strcmp(alias->name, name)) 1668 + return true; 1601 1669 } 1602 1670 return false; 1603 1671 } ··· 1654 2020 name ?: "N/A", buf, config); 1655 2021 } 1656 2022 1657 - bool perf_pmu__has_hybrid(void) 1658 - { 1659 - static bool hybrid_scanned, has_hybrid; 1660 - 1661 - if (!hybrid_scanned) { 1662 - struct perf_pmu *pmu = NULL; 1663 - 1664 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1665 - if (pmu->is_core && is_pmu_hybrid(pmu->name)) { 1666 - has_hybrid = true; 1667 - break; 1668 - } 1669 - } 1670 - hybrid_scanned = true; 1671 - } 1672 - return has_hybrid; 1673 - } 1674 - 1675 2023 int perf_pmu__match(char *pattern, char *name, char *tok) 1676 2024 { 1677 2025 if (!name) ··· 1721 2105 return openat(dirfd, path, flags); 1722 2106 } 1723 2107 1724 - static void perf_pmu__delete(struct perf_pmu *pmu) 2108 + void perf_pmu__delete(struct perf_pmu *pmu) 1725 2109 { 1726 2110 perf_pmu__del_formats(&pmu->format); 1727 2111 perf_pmu__del_aliases(pmu); ··· 1733 2117 zfree(&pmu->name); 1734 2118 zfree(&pmu->alias_name); 1735 2119 free(pmu); 1736 - } 1737 - 1738 - void perf_pmu__destroy(void) 1739 - { 1740 - struct perf_pmu *pmu, *tmp; 1741 - 1742 - list_for_each_entry_safe(pmu, tmp, &pmus, list) { 1743 - list_del(&pmu->list); 1744 - 1745 - perf_pmu__delete(pmu); 1746 - } 1747 2120 }
+4 -9
tools/perf/util/pmu.h
··· 198 198 char *pmu_name; 199 199 }; 200 200 201 - struct perf_pmu *perf_pmu__find(const char *name); 202 - struct perf_pmu *perf_pmu__find_by_type(unsigned int type); 203 201 void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu); 204 202 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 205 203 struct list_head *head_terms, ··· 220 222 int perf_pmu__format_parse(int dirfd, struct list_head *head); 221 223 void perf_pmu__del_formats(struct list_head *formats); 222 224 223 - struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); 224 - 225 225 bool is_pmu_core(const char *name); 226 226 bool is_pmu_hybrid(const char *name); 227 227 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu); 228 228 bool perf_pmu__supports_wildcard_numeric(const struct perf_pmu *pmu); 229 229 bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu); 230 - int perf_pmu__num_mem_pmus(void); 231 - void print_pmu_events(const struct print_callbacks *print_cb, void *print_state); 232 - bool pmu_have_event(const char *pname, const char *name); 230 + bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu); 231 + bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name); 233 232 234 233 FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name); 235 234 FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name); ··· 256 261 const char *name); 257 262 void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu); 258 263 259 - bool perf_pmu__has_hybrid(void); 260 264 int perf_pmu__match(char *pattern, char *name, char *tok); 261 265 262 266 char *pmu_find_real_name(const char *name); ··· 267 273 int perf_pmu__event_source_devices_fd(void); 268 274 int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags); 269 275 270 - void perf_pmu__destroy(void); 276 + struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name); 277 + void perf_pmu__delete(struct perf_pmu *pmu); 271 278 272 279 #endif /* __PMU_H */
+394 -2
tools/perf/util/pmus.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <linux/list.h> 3 + #include <linux/zalloc.h> 4 + #include <subcmd/pager.h> 5 + #include <sys/types.h> 6 + #include <dirent.h> 3 7 #include <string.h> 8 + #include <unistd.h> 9 + #include "debug.h" 10 + #include "evsel.h" 4 11 #include "pmus.h" 5 12 #include "pmu.h" 13 + #include "print-events.h" 6 14 7 - LIST_HEAD(pmus); 15 + static LIST_HEAD(pmus); 16 + 17 + void perf_pmus__destroy(void) 18 + { 19 + struct perf_pmu *pmu, *tmp; 20 + 21 + list_for_each_entry_safe(pmu, tmp, &pmus, list) { 22 + list_del(&pmu->list); 23 + 24 + perf_pmu__delete(pmu); 25 + } 26 + } 27 + 28 + static struct perf_pmu *pmu_find(const char *name) 29 + { 30 + struct perf_pmu *pmu; 31 + 32 + list_for_each_entry(pmu, &pmus, list) { 33 + if (!strcmp(pmu->name, name) || 34 + (pmu->alias_name && !strcmp(pmu->alias_name, name))) 35 + return pmu; 36 + } 37 + 38 + return NULL; 39 + } 40 + 41 + struct perf_pmu *perf_pmus__find(const char *name) 42 + { 43 + struct perf_pmu *pmu; 44 + int dirfd; 45 + 46 + /* 47 + * Once PMU is loaded it stays in the list, 48 + * so we keep us from multiple reading/parsing 49 + * the pmu format definitions. 50 + */ 51 + pmu = pmu_find(name); 52 + if (pmu) 53 + return pmu; 54 + 55 + dirfd = perf_pmu__event_source_devices_fd(); 56 + pmu = perf_pmu__lookup(&pmus, dirfd, name); 57 + close(dirfd); 58 + 59 + return pmu; 60 + } 61 + 62 + static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) 63 + { 64 + struct perf_pmu *pmu; 65 + 66 + /* 67 + * Once PMU is loaded it stays in the list, 68 + * so we keep us from multiple reading/parsing 69 + * the pmu format definitions. 70 + */ 71 + pmu = pmu_find(name); 72 + if (pmu) 73 + return pmu; 74 + 75 + return perf_pmu__lookup(&pmus, dirfd, name); 76 + } 77 + 78 + /* Add all pmus in sysfs to pmu list: */ 79 + static void pmu_read_sysfs(void) 80 + { 81 + int fd; 82 + DIR *dir; 83 + struct dirent *dent; 84 + 85 + fd = perf_pmu__event_source_devices_fd(); 86 + if (fd < 0) 87 + return; 88 + 89 + dir = fdopendir(fd); 90 + if (!dir) 91 + return; 92 + 93 + while ((dent = readdir(dir))) { 94 + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 95 + continue; 96 + /* add to static LIST_HEAD(pmus): */ 97 + perf_pmu__find2(fd, dent->d_name); 98 + } 99 + 100 + closedir(dir); 101 + } 102 + 103 + struct perf_pmu *perf_pmus__find_by_type(unsigned int type) 104 + { 105 + struct perf_pmu *pmu; 106 + 107 + list_for_each_entry(pmu, &pmus, list) 108 + if (pmu->type == type) 109 + return pmu; 110 + 111 + return NULL; 112 + } 113 + 114 + struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu) 115 + { 116 + /* 117 + * pmu iterator: If pmu is NULL, we start at the begin, 118 + * otherwise return the next pmu. Returns NULL on end. 119 + */ 120 + if (!pmu) { 121 + pmu_read_sysfs(); 122 + pmu = list_prepare_entry(pmu, &pmus, list); 123 + } 124 + list_for_each_entry_continue(pmu, &pmus, list) 125 + return pmu; 126 + return NULL; 127 + } 8 128 9 129 const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str) 10 130 { 11 131 struct perf_pmu *pmu = NULL; 12 132 13 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 133 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 14 134 if (!strcmp(pmu->name, str)) 15 135 return pmu; 16 136 /* Ignore "uncore_" prefix. */ ··· 145 25 } 146 26 } 147 27 return NULL; 28 + } 29 + 30 + int perf_pmus__num_mem_pmus(void) 31 + { 32 + struct perf_pmu *pmu = NULL; 33 + int count = 0; 34 + 35 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 36 + if (perf_pmu__is_mem_pmu(pmu)) 37 + count++; 38 + } 39 + return count; 40 + } 41 + 42 + /** Struct for ordering events as output in perf list. */ 43 + struct sevent { 44 + /** PMU for event. */ 45 + const struct perf_pmu *pmu; 46 + /** 47 + * Optional event for name, desc, etc. If not present then this is a 48 + * selectable PMU and the event name is shown as "//". 49 + */ 50 + const struct perf_pmu_alias *event; 51 + /** Is the PMU for the CPU? */ 52 + bool is_cpu; 53 + }; 54 + 55 + static int cmp_sevent(const void *a, const void *b) 56 + { 57 + const struct sevent *as = a; 58 + const struct sevent *bs = b; 59 + const char *a_pmu_name = NULL, *b_pmu_name = NULL; 60 + const char *a_name = "//", *a_desc = NULL, *a_topic = ""; 61 + const char *b_name = "//", *b_desc = NULL, *b_topic = ""; 62 + int ret; 63 + 64 + if (as->event) { 65 + a_name = as->event->name; 66 + a_desc = as->event->desc; 67 + a_topic = as->event->topic ?: ""; 68 + a_pmu_name = as->event->pmu_name; 69 + } 70 + if (bs->event) { 71 + b_name = bs->event->name; 72 + b_desc = bs->event->desc; 73 + b_topic = bs->event->topic ?: ""; 74 + b_pmu_name = bs->event->pmu_name; 75 + } 76 + /* Put extra events last. */ 77 + if (!!a_desc != !!b_desc) 78 + return !!a_desc - !!b_desc; 79 + 80 + /* Order by topics. */ 81 + ret = strcmp(a_topic, b_topic); 82 + if (ret) 83 + return ret; 84 + 85 + /* Order CPU core events to be first */ 86 + if (as->is_cpu != bs->is_cpu) 87 + return as->is_cpu ? -1 : 1; 88 + 89 + /* Order by PMU name. */ 90 + if (as->pmu != bs->pmu) { 91 + a_pmu_name = a_pmu_name ?: (as->pmu->name ?: ""); 92 + b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: ""); 93 + ret = strcmp(a_pmu_name, b_pmu_name); 94 + if (ret) 95 + return ret; 96 + } 97 + 98 + /* Order by event name. */ 99 + return strcmp(a_name, b_name); 100 + } 101 + 102 + static bool pmu_alias_is_duplicate(struct sevent *alias_a, 103 + struct sevent *alias_b) 104 + { 105 + const char *a_pmu_name = NULL, *b_pmu_name = NULL; 106 + const char *a_name = "//", *b_name = "//"; 107 + 108 + 109 + if (alias_a->event) { 110 + a_name = alias_a->event->name; 111 + a_pmu_name = alias_a->event->pmu_name; 112 + } 113 + if (alias_b->event) { 114 + b_name = alias_b->event->name; 115 + b_pmu_name = alias_b->event->pmu_name; 116 + } 117 + 118 + /* Different names -> never duplicates */ 119 + if (strcmp(a_name, b_name)) 120 + return false; 121 + 122 + /* Don't remove duplicates for different PMUs */ 123 + a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: ""); 124 + b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: ""); 125 + return strcmp(a_pmu_name, b_pmu_name) == 0; 126 + } 127 + 128 + static int sub_non_neg(int a, int b) 129 + { 130 + if (b > a) 131 + return 0; 132 + return a - b; 133 + } 134 + 135 + static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 136 + const struct perf_pmu_alias *alias) 137 + { 138 + struct parse_events_term *term; 139 + int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 140 + 141 + list_for_each_entry(term, &alias->terms, list) { 142 + if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 143 + used += snprintf(buf + used, sub_non_neg(len, used), 144 + ",%s=%s", term->config, 145 + term->val.str); 146 + } 147 + 148 + if (sub_non_neg(len, used) > 0) { 149 + buf[used] = '/'; 150 + used++; 151 + } 152 + if (sub_non_neg(len, used) > 0) { 153 + buf[used] = '\0'; 154 + used++; 155 + } else 156 + buf[len - 1] = '\0'; 157 + 158 + return buf; 159 + } 160 + 161 + void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state) 162 + { 163 + struct perf_pmu *pmu; 164 + struct perf_pmu_alias *event; 165 + char buf[1024]; 166 + int printed = 0; 167 + int len, j; 168 + struct sevent *aliases; 169 + 170 + pmu = NULL; 171 + len = 0; 172 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 173 + list_for_each_entry(event, &pmu->aliases, list) 174 + len++; 175 + if (pmu->selectable) 176 + len++; 177 + } 178 + aliases = zalloc(sizeof(struct sevent) * len); 179 + if (!aliases) { 180 + pr_err("FATAL: not enough memory to print PMU events\n"); 181 + return; 182 + } 183 + pmu = NULL; 184 + j = 0; 185 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 186 + bool is_cpu = pmu->is_core; 187 + 188 + list_for_each_entry(event, &pmu->aliases, list) { 189 + aliases[j].event = event; 190 + aliases[j].pmu = pmu; 191 + aliases[j].is_cpu = is_cpu; 192 + j++; 193 + } 194 + if (pmu->selectable) { 195 + aliases[j].event = NULL; 196 + aliases[j].pmu = pmu; 197 + aliases[j].is_cpu = is_cpu; 198 + j++; 199 + } 200 + } 201 + len = j; 202 + qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 203 + for (j = 0; j < len; j++) { 204 + const char *name, *alias = NULL, *scale_unit = NULL, 205 + *desc = NULL, *long_desc = NULL, 206 + *encoding_desc = NULL, *topic = NULL, 207 + *pmu_name = NULL; 208 + bool deprecated = false; 209 + size_t buf_used; 210 + 211 + /* Skip duplicates */ 212 + if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) 213 + continue; 214 + 215 + if (!aliases[j].event) { 216 + /* A selectable event. */ 217 + pmu_name = aliases[j].pmu->name; 218 + buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1; 219 + name = buf; 220 + } else { 221 + if (aliases[j].event->desc) { 222 + name = aliases[j].event->name; 223 + buf_used = 0; 224 + } else { 225 + name = format_alias(buf, sizeof(buf), aliases[j].pmu, 226 + aliases[j].event); 227 + if (aliases[j].is_cpu) { 228 + alias = name; 229 + name = aliases[j].event->name; 230 + } 231 + buf_used = strlen(buf) + 1; 232 + } 233 + pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: ""); 234 + if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) { 235 + scale_unit = buf + buf_used; 236 + buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 237 + "%G%s", aliases[j].event->scale, 238 + aliases[j].event->unit) + 1; 239 + } 240 + desc = aliases[j].event->desc; 241 + long_desc = aliases[j].event->long_desc; 242 + topic = aliases[j].event->topic; 243 + encoding_desc = buf + buf_used; 244 + buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 245 + "%s/%s/", pmu_name, aliases[j].event->str) + 1; 246 + deprecated = aliases[j].event->deprecated; 247 + } 248 + print_cb->print_event(print_state, 249 + pmu_name, 250 + topic, 251 + name, 252 + alias, 253 + scale_unit, 254 + deprecated, 255 + "Kernel PMU event", 256 + desc, 257 + long_desc, 258 + encoding_desc); 259 + } 260 + if (printed && pager_in_use()) 261 + printf("\n"); 262 + 263 + zfree(&aliases); 264 + } 265 + 266 + bool perf_pmus__have_event(const char *pname, const char *name) 267 + { 268 + struct perf_pmu *pmu = perf_pmus__find(pname); 269 + 270 + return pmu && perf_pmu__have_event(pmu, name); 271 + } 272 + 273 + bool perf_pmus__has_hybrid(void) 274 + { 275 + static bool hybrid_scanned, has_hybrid; 276 + 277 + if (!hybrid_scanned) { 278 + struct perf_pmu *pmu = NULL; 279 + 280 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 281 + if (pmu->is_core && is_pmu_hybrid(pmu->name)) { 282 + has_hybrid = true; 283 + break; 284 + } 285 + } 286 + hybrid_scanned = true; 287 + } 288 + return has_hybrid; 289 + } 290 + 291 + struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) 292 + { 293 + struct perf_pmu *pmu = evsel->pmu; 294 + 295 + if (!pmu) { 296 + pmu = perf_pmus__find_by_type(evsel->core.attr.type); 297 + ((struct evsel *)evsel)->pmu = pmu; 298 + } 299 + return pmu; 148 300 }
+13 -1
tools/perf/util/pmus.h
··· 2 2 #ifndef __PMUS_H 3 3 #define __PMUS_H 4 4 5 - extern struct list_head pmus; 6 5 struct perf_pmu; 6 + struct print_callbacks; 7 + 8 + void perf_pmus__destroy(void); 9 + 10 + struct perf_pmu *perf_pmus__find(const char *name); 11 + struct perf_pmu *perf_pmus__find_by_type(unsigned int type); 12 + 13 + struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu); 7 14 8 15 const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str); 16 + 17 + int perf_pmus__num_mem_pmus(void); 18 + void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state); 19 + bool perf_pmus__have_event(const char *pname, const char *name); 20 + bool perf_pmus__has_hybrid(void); 9 21 10 22 #endif /* __PMUS_H */
+3 -2
tools/perf/util/print-events.c
··· 20 20 #include "metricgroup.h" 21 21 #include "parse-events.h" 22 22 #include "pmu.h" 23 + #include "pmus.h" 23 24 #include "print-events.h" 24 25 #include "probe-file.h" 25 26 #include "string2.h" ··· 272 271 struct perf_pmu *pmu = NULL; 273 272 const char *event_type_descriptor = event_type_descriptors[PERF_TYPE_HW_CACHE]; 274 273 275 - while ((pmu = perf_pmu__scan(pmu)) != NULL) { 274 + while ((pmu = perf_pmus__scan(pmu)) != NULL) { 276 275 /* 277 276 * Skip uncore PMUs for performance. PERF_TYPE_HW_CACHE type 278 277 * attributes can accept software PMUs in the extended type, so ··· 405 404 406 405 print_hwcache_events(print_cb, print_state); 407 406 408 - print_pmu_events(print_cb, print_state); 407 + perf_pmus__print_pmu_events(print_cb, print_state); 409 408 410 409 print_cb->print_event(print_state, 411 410 /*topic=*/NULL,
+2 -1
tools/perf/util/python.c
··· 22 22 #include "util/bpf-filter.h" 23 23 #include "util/env.h" 24 24 #include "util/pmu.h" 25 + #include "util/pmus.h" 25 26 #include <internal/lib.h> 26 27 #include "util.h" 27 28 ··· 103 102 return EOF; 104 103 } 105 104 106 - bool perf_pmu__has_hybrid(void) 105 + bool perf_pmus__has_hybrid(void) 107 106 { 108 107 return false; 109 108 }
+2 -1
tools/perf/util/stat-display.c
··· 20 20 #include "util.h" 21 21 #include "iostat.h" 22 22 #include "pmu.h" 23 + #include "pmus.h" 23 24 24 25 #define CNTR_NOT_SUPPORTED "<not supported>" 25 26 #define CNTR_NOT_COUNTED "<not counted>" ··· 696 695 { 697 696 struct evsel *evsel; 698 697 699 - if (!perf_pmu__has_hybrid()) 698 + if (!perf_pmus__has_hybrid()) 700 699 return false; 701 700 702 701 evlist__for_each_entry(evlist, evsel) {