Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <string.h>
0003 #include <stdio.h>
0004 #include <sys/types.h>
0005 #include <dirent.h>
0006 #include <fcntl.h>
0007 #include <linux/stddef.h>
0008 #include <linux/perf_event.h>
0009 #include <linux/zalloc.h>
0010 #include <api/fs/fs.h>
0011 #include <errno.h>
0012 
0013 #include "../../../util/intel-pt.h"
0014 #include "../../../util/intel-bts.h"
0015 #include "../../../util/pmu.h"
0016 #include "../../../util/fncache.h"
0017 
0018 #define TEMPLATE_ALIAS  "%s/bus/event_source/devices/%s/alias"
0019 
0020 struct pmu_alias {
0021     char *name;
0022     char *alias;
0023     struct list_head list;
0024 };
0025 
0026 static LIST_HEAD(pmu_alias_name_list);
0027 static bool cached_list;
0028 
0029 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
0030 {
0031 #ifdef HAVE_AUXTRACE_SUPPORT
0032     if (!strcmp(pmu->name, INTEL_PT_PMU_NAME))
0033         return intel_pt_pmu_default_config(pmu);
0034     if (!strcmp(pmu->name, INTEL_BTS_PMU_NAME))
0035         pmu->selectable = true;
0036 #endif
0037     return NULL;
0038 }
0039 
0040 static void pmu_alias__delete(struct pmu_alias *pmu_alias)
0041 {
0042     if (!pmu_alias)
0043         return;
0044 
0045     zfree(&pmu_alias->name);
0046     zfree(&pmu_alias->alias);
0047     free(pmu_alias);
0048 }
0049 
0050 static struct pmu_alias *pmu_alias__new(char *name, char *alias)
0051 {
0052     struct pmu_alias *pmu_alias = zalloc(sizeof(*pmu_alias));
0053 
0054     if (pmu_alias) {
0055         pmu_alias->name = strdup(name);
0056         if (!pmu_alias->name)
0057             goto out_delete;
0058 
0059         pmu_alias->alias = strdup(alias);
0060         if (!pmu_alias->alias)
0061             goto out_delete;
0062     }
0063     return pmu_alias;
0064 
0065 out_delete:
0066     pmu_alias__delete(pmu_alias);
0067     return NULL;
0068 }
0069 
0070 static int setup_pmu_alias_list(void)
0071 {
0072     char path[PATH_MAX];
0073     DIR *dir;
0074     struct dirent *dent;
0075     const char *sysfs = sysfs__mountpoint();
0076     struct pmu_alias *pmu_alias;
0077     char buf[MAX_PMU_NAME_LEN];
0078     FILE *file;
0079     int ret = -ENOMEM;
0080 
0081     if (!sysfs)
0082         return -1;
0083 
0084     snprintf(path, PATH_MAX,
0085          "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
0086 
0087     dir = opendir(path);
0088     if (!dir)
0089         return -errno;
0090 
0091     while ((dent = readdir(dir))) {
0092         if (!strcmp(dent->d_name, ".") ||
0093             !strcmp(dent->d_name, ".."))
0094             continue;
0095 
0096         snprintf(path, PATH_MAX,
0097              TEMPLATE_ALIAS, sysfs, dent->d_name);
0098 
0099         if (!file_available(path))
0100             continue;
0101 
0102         file = fopen(path, "r");
0103         if (!file)
0104             continue;
0105 
0106         if (!fgets(buf, sizeof(buf), file)) {
0107             fclose(file);
0108             continue;
0109         }
0110 
0111         fclose(file);
0112 
0113         /* Remove the last '\n' */
0114         buf[strlen(buf) - 1] = 0;
0115 
0116         pmu_alias = pmu_alias__new(dent->d_name, buf);
0117         if (!pmu_alias)
0118             goto close_dir;
0119 
0120         list_add_tail(&pmu_alias->list, &pmu_alias_name_list);
0121     }
0122 
0123     ret = 0;
0124 
0125 close_dir:
0126     closedir(dir);
0127     return ret;
0128 }
0129 
0130 static char *__pmu_find_real_name(const char *name)
0131 {
0132     struct pmu_alias *pmu_alias;
0133 
0134     list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
0135         if (!strcmp(name, pmu_alias->alias))
0136             return pmu_alias->name;
0137     }
0138 
0139     return (char *)name;
0140 }
0141 
0142 char *pmu_find_real_name(const char *name)
0143 {
0144     if (cached_list)
0145         return __pmu_find_real_name(name);
0146 
0147     setup_pmu_alias_list();
0148     cached_list = true;
0149 
0150     return __pmu_find_real_name(name);
0151 }
0152 
0153 static char *__pmu_find_alias_name(const char *name)
0154 {
0155     struct pmu_alias *pmu_alias;
0156 
0157     list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
0158         if (!strcmp(name, pmu_alias->name))
0159             return pmu_alias->alias;
0160     }
0161     return NULL;
0162 }
0163 
0164 char *pmu_find_alias_name(const char *name)
0165 {
0166     if (cached_list)
0167         return __pmu_find_alias_name(name);
0168 
0169     setup_pmu_alias_list();
0170     cached_list = true;
0171 
0172     return __pmu_find_alias_name(name);
0173 }