perf pmu: Use relative path in setup_pmu_alias_list()
[platform/kernel/linux-starfive.git] / tools / perf / arch / x86 / util / pmu.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <string.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <dirent.h>
6 #include <fcntl.h>
7 #include <linux/stddef.h>
8 #include <linux/perf_event.h>
9 #include <linux/zalloc.h>
10 #include <api/fs/fs.h>
11 #include <errno.h>
12
13 #include "../../../util/intel-pt.h"
14 #include "../../../util/intel-bts.h"
15 #include "../../../util/pmu.h"
16 #include "../../../util/fncache.h"
17
18 struct pmu_alias {
19         char *name;
20         char *alias;
21         struct list_head list;
22 };
23
24 static LIST_HEAD(pmu_alias_name_list);
25 static bool cached_list;
26
27 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
28 {
29 #ifdef HAVE_AUXTRACE_SUPPORT
30         if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) {
31                 pmu->auxtrace = true;
32                 return intel_pt_pmu_default_config(pmu);
33         }
34         if (!strcmp(pmu->name, INTEL_BTS_PMU_NAME)) {
35                 pmu->auxtrace = true;
36                 pmu->selectable = true;
37         }
38 #endif
39         return NULL;
40 }
41
42 static void pmu_alias__delete(struct pmu_alias *pmu_alias)
43 {
44         if (!pmu_alias)
45                 return;
46
47         zfree(&pmu_alias->name);
48         zfree(&pmu_alias->alias);
49         free(pmu_alias);
50 }
51
52 static struct pmu_alias *pmu_alias__new(char *name, char *alias)
53 {
54         struct pmu_alias *pmu_alias = zalloc(sizeof(*pmu_alias));
55
56         if (pmu_alias) {
57                 pmu_alias->name = strdup(name);
58                 if (!pmu_alias->name)
59                         goto out_delete;
60
61                 pmu_alias->alias = strdup(alias);
62                 if (!pmu_alias->alias)
63                         goto out_delete;
64         }
65         return pmu_alias;
66
67 out_delete:
68         pmu_alias__delete(pmu_alias);
69         return NULL;
70 }
71
72 static int setup_pmu_alias_list(void)
73 {
74         int fd, dirfd;
75         DIR *dir;
76         struct dirent *dent;
77         struct pmu_alias *pmu_alias;
78         char buf[MAX_PMU_NAME_LEN];
79         FILE *file;
80         int ret = -ENOMEM;
81
82         dirfd = perf_pmu__event_source_devices_fd();
83         if (dirfd < 0)
84                 return -1;
85
86         dir = fdopendir(dirfd);
87         if (!dir)
88                 return -errno;
89
90         while ((dent = readdir(dir))) {
91                 if (!strcmp(dent->d_name, ".") ||
92                     !strcmp(dent->d_name, ".."))
93                         continue;
94
95                 fd = perf_pmu__pathname_fd(dirfd, dent->d_name, "alias", O_RDONLY);
96                 if (fd < 0)
97                         continue;
98
99                 file = fdopen(fd, "r");
100                 if (!file)
101                         continue;
102
103                 if (!fgets(buf, sizeof(buf), file)) {
104                         fclose(file);
105                         continue;
106                 }
107
108                 fclose(file);
109
110                 /* Remove the last '\n' */
111                 buf[strlen(buf) - 1] = 0;
112
113                 pmu_alias = pmu_alias__new(dent->d_name, buf);
114                 if (!pmu_alias)
115                         goto close_dir;
116
117                 list_add_tail(&pmu_alias->list, &pmu_alias_name_list);
118         }
119
120         ret = 0;
121
122 close_dir:
123         closedir(dir);
124         return ret;
125 }
126
127 static char *__pmu_find_real_name(const char *name)
128 {
129         struct pmu_alias *pmu_alias;
130
131         list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
132                 if (!strcmp(name, pmu_alias->alias))
133                         return pmu_alias->name;
134         }
135
136         return (char *)name;
137 }
138
139 char *pmu_find_real_name(const char *name)
140 {
141         if (cached_list)
142                 return __pmu_find_real_name(name);
143
144         setup_pmu_alias_list();
145         cached_list = true;
146
147         return __pmu_find_real_name(name);
148 }
149
150 static char *__pmu_find_alias_name(const char *name)
151 {
152         struct pmu_alias *pmu_alias;
153
154         list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
155                 if (!strcmp(name, pmu_alias->name))
156                         return pmu_alias->alias;
157         }
158         return NULL;
159 }
160
161 char *pmu_find_alias_name(const char *name)
162 {
163         if (cached_list)
164                 return __pmu_find_alias_name(name);
165
166         setup_pmu_alias_list();
167         cached_list = true;
168
169         return __pmu_find_alias_name(name);
170 }