aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/pmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r--tools/perf/util/pmu.c80
1 files changed, 78 insertions, 2 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a42cd6d..8a2229da594f 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -9,6 +9,9 @@
9#include "util.h" 9#include "util.h"
10#include "pmu.h" 10#include "pmu.h"
11#include "parse-events.h" 11#include "parse-events.h"
12#include "cpumap.h"
13
14#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
12 15
13int perf_pmu_parse(struct list_head *list, char *name); 16int perf_pmu_parse(struct list_head *list, char *name);
14extern FILE *perf_pmu_in; 17extern FILE *perf_pmu_in;
@@ -69,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
69 return -1; 72 return -1;
70 73
71 snprintf(path, PATH_MAX, 74 snprintf(path, PATH_MAX,
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 75 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
73 76
74 if (stat(path, &st) < 0) 77 if (stat(path, &st) < 0)
75 return 0; /* no error if format does not exist */ 78 return 0; /* no error if format does not exist */
@@ -206,7 +209,7 @@ static int pmu_type(char *name, __u32 *type)
206 return -1; 209 return -1;
207 210
208 snprintf(path, PATH_MAX, 211 snprintf(path, PATH_MAX,
209 "%s/bus/event_source/devices/%s/type", sysfs, name); 212 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
210 213
211 if (stat(path, &st) < 0) 214 if (stat(path, &st) < 0)
212 return -1; 215 return -1;
@@ -222,6 +225,62 @@ static int pmu_type(char *name, __u32 *type)
222 return ret; 225 return ret;
223} 226}
224 227
228/* Add all pmus in sysfs to pmu list: */
229static void pmu_read_sysfs(void)
230{
231 char path[PATH_MAX];
232 const char *sysfs;
233 DIR *dir;
234 struct dirent *dent;
235
236 sysfs = sysfs_find_mountpoint();
237 if (!sysfs)
238 return;
239
240 snprintf(path, PATH_MAX,
241 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
242
243 dir = opendir(path);
244 if (!dir)
245 return;
246
247 while ((dent = readdir(dir))) {
248 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
249 continue;
250 /* add to static LIST_HEAD(pmus): */
251 perf_pmu__find(dent->d_name);
252 }
253
254 closedir(dir);
255}
256
257static struct cpu_map *pmu_cpumask(char *name)
258{
259 struct stat st;
260 char path[PATH_MAX];
261 const char *sysfs;
262 FILE *file;
263 struct cpu_map *cpus;
264
265 sysfs = sysfs_find_mountpoint();
266 if (!sysfs)
267 return NULL;
268
269 snprintf(path, PATH_MAX,
270 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
271
272 if (stat(path, &st) < 0)
273 return NULL;
274
275 file = fopen(path, "r");
276 if (!file)
277 return NULL;
278
279 cpus = cpu_map__read(file);
280 fclose(file);
281 return cpus;
282}
283
225static struct perf_pmu *pmu_lookup(char *name) 284static struct perf_pmu *pmu_lookup(char *name)
226{ 285{
227 struct perf_pmu *pmu; 286 struct perf_pmu *pmu;
@@ -244,6 +303,8 @@ static struct perf_pmu *pmu_lookup(char *name)
244 if (!pmu) 303 if (!pmu)
245 return NULL; 304 return NULL;
246 305
306 pmu->cpus = pmu_cpumask(name);
307
247 pmu_aliases(name, &aliases); 308 pmu_aliases(name, &aliases);
248 309
249 INIT_LIST_HEAD(&pmu->format); 310 INIT_LIST_HEAD(&pmu->format);
@@ -267,6 +328,21 @@ static struct perf_pmu *pmu_find(char *name)
267 return NULL; 328 return NULL;
268} 329}
269 330
331struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
332{
333 /*
334 * pmu iterator: If pmu is NULL, we start at the begin,
335 * otherwise return the next pmu. Returns NULL on end.
336 */
337 if (!pmu) {
338 pmu_read_sysfs();
339 pmu = list_prepare_entry(pmu, &pmus, list);
340 }
341 list_for_each_entry_continue(pmu, &pmus, list)
342 return pmu;
343 return NULL;
344}
345
270struct perf_pmu *perf_pmu__find(char *name) 346struct perf_pmu *perf_pmu__find(char *name)
271{ 347{
272 struct perf_pmu *pmu; 348 struct perf_pmu *pmu;