diff options
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r-- | tools/perf/util/pmu.c | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 67715a42cd6d..6631d828db3d 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -10,6 +10,8 @@ #include "pmu.h" #include "parse-events.h" +#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" + int perf_pmu_parse(struct list_head *list, char *name); extern FILE *perf_pmu_in; @@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format) return -1; snprintf(path, PATH_MAX, - "%s/bus/event_source/devices/%s/format", sysfs, name); + "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name); if (stat(path, &st) < 0) return 0; /* no error if format does not exist */ @@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type) return -1; snprintf(path, PATH_MAX, - "%s/bus/event_source/devices/%s/type", sysfs, name); + "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); if (stat(path, &st) < 0) return -1; @@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type) return ret; } +/* Add all pmus in sysfs to pmu list: */ +static void pmu_read_sysfs(void) +{ + char path[PATH_MAX]; + const char *sysfs; + DIR *dir; + struct dirent *dent; + + sysfs = sysfs_find_mountpoint(); + if (!sysfs) + return; + + snprintf(path, PATH_MAX, + "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); + + dir = opendir(path); + if (!dir) + return; + + while ((dent = readdir(dir))) { + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + /* add to static LIST_HEAD(pmus): */ + perf_pmu__find(dent->d_name); + } + + closedir(dir); +} + static struct perf_pmu *pmu_lookup(char *name) { struct perf_pmu *pmu; @@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name) return NULL; } +struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) +{ + /* + * pmu iterator: If pmu is NULL, we start at the begin, + * otherwise return the next pmu. Returns NULL on end. + */ + if (!pmu) { + pmu_read_sysfs(); + pmu = list_prepare_entry(pmu, &pmus, list); + } + list_for_each_entry_continue(pmu, &pmus, list) + return pmu; + return NULL; +} + struct perf_pmu *perf_pmu__find(char *name) { struct perf_pmu *pmu; |