Merge branches 'x86-build-for-linus', 'x86-cleanups-for-linus' and 'x86-debug-for...
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / pmu.c
1 #include <linux/list.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdbool.h>
6 #include <stdarg.h>
7 #include <dirent.h>
8 #include <api/fs/fs.h>
9 #include <locale.h>
10 #include "util.h"
11 #include "pmu.h"
12 #include "parse-events.h"
13 #include "cpumap.h"
14
15 struct perf_pmu_format {
16         char *name;
17         int value;
18         DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
19         struct list_head list;
20 };
21
22 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
23
24 int perf_pmu_parse(struct list_head *list, char *name);
25 extern FILE *perf_pmu_in;
26
27 static LIST_HEAD(pmus);
28
29 /*
30  * Parse & process all the sysfs attributes located under
31  * the directory specified in 'dir' parameter.
32  */
33 int perf_pmu__format_parse(char *dir, struct list_head *head)
34 {
35         struct dirent *evt_ent;
36         DIR *format_dir;
37         int ret = 0;
38
39         format_dir = opendir(dir);
40         if (!format_dir)
41                 return -EINVAL;
42
43         while (!ret && (evt_ent = readdir(format_dir))) {
44                 char path[PATH_MAX];
45                 char *name = evt_ent->d_name;
46                 FILE *file;
47
48                 if (!strcmp(name, ".") || !strcmp(name, ".."))
49                         continue;
50
51                 snprintf(path, PATH_MAX, "%s/%s", dir, name);
52
53                 ret = -EINVAL;
54                 file = fopen(path, "r");
55                 if (!file)
56                         break;
57
58                 perf_pmu_in = file;
59                 ret = perf_pmu_parse(head, name);
60                 fclose(file);
61         }
62
63         closedir(format_dir);
64         return ret;
65 }
66
67 /*
68  * Reading/parsing the default pmu format definition, which should be
69  * located at:
70  * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
71  */
72 static int pmu_format(const char *name, struct list_head *format)
73 {
74         struct stat st;
75         char path[PATH_MAX];
76         const char *sysfs = sysfs__mountpoint();
77
78         if (!sysfs)
79                 return -1;
80
81         snprintf(path, PATH_MAX,
82                  "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
83
84         if (stat(path, &st) < 0)
85                 return 0;       /* no error if format does not exist */
86
87         if (perf_pmu__format_parse(path, format))
88                 return -1;
89
90         return 0;
91 }
92
93 static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
94 {
95         struct stat st;
96         ssize_t sret;
97         char scale[128];
98         int fd, ret = -1;
99         char path[PATH_MAX];
100         const char *lc;
101
102         snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
103
104         fd = open(path, O_RDONLY);
105         if (fd == -1)
106                 return -1;
107
108         if (fstat(fd, &st) < 0)
109                 goto error;
110
111         sret = read(fd, scale, sizeof(scale)-1);
112         if (sret < 0)
113                 goto error;
114
115         scale[sret] = '\0';
116         /*
117          * save current locale
118          */
119         lc = setlocale(LC_NUMERIC, NULL);
120
121         /*
122          * force to C locale to ensure kernel
123          * scale string is converted correctly.
124          * kernel uses default C locale.
125          */
126         setlocale(LC_NUMERIC, "C");
127
128         alias->scale = strtod(scale, NULL);
129
130         /* restore locale */
131         setlocale(LC_NUMERIC, lc);
132
133         ret = 0;
134 error:
135         close(fd);
136         return ret;
137 }
138
139 static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
140 {
141         char path[PATH_MAX];
142         ssize_t sret;
143         int fd;
144
145         snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
146
147         fd = open(path, O_RDONLY);
148         if (fd == -1)
149                 return -1;
150
151                 sret = read(fd, alias->unit, UNIT_MAX_LEN);
152         if (sret < 0)
153                 goto error;
154
155         close(fd);
156
157         alias->unit[sret] = '\0';
158
159         return 0;
160 error:
161         close(fd);
162         alias->unit[0] = '\0';
163         return -1;
164 }
165
166 static int
167 perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
168 {
169         char path[PATH_MAX];
170         int fd;
171
172         snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
173
174         fd = open(path, O_RDONLY);
175         if (fd == -1)
176                 return -1;
177
178         close(fd);
179
180         alias->per_pkg = true;
181         return 0;
182 }
183
184 static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
185                                     char *dir, char *name)
186 {
187         char path[PATH_MAX];
188         int fd;
189
190         snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
191
192         fd = open(path, O_RDONLY);
193         if (fd == -1)
194                 return -1;
195
196         alias->snapshot = true;
197         close(fd);
198         return 0;
199 }
200
201 static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
202 {
203         struct perf_pmu_alias *alias;
204         char buf[256];
205         int ret;
206
207         ret = fread(buf, 1, sizeof(buf), file);
208         if (ret == 0)
209                 return -EINVAL;
210         buf[ret] = 0;
211
212         alias = malloc(sizeof(*alias));
213         if (!alias)
214                 return -ENOMEM;
215
216         INIT_LIST_HEAD(&alias->terms);
217         alias->scale = 1.0;
218         alias->unit[0] = '\0';
219         alias->per_pkg = false;
220
221         ret = parse_events_terms(&alias->terms, buf);
222         if (ret) {
223                 free(alias);
224                 return ret;
225         }
226
227         alias->name = strdup(name);
228         /*
229          * load unit name and scale if available
230          */
231         perf_pmu__parse_unit(alias, dir, name);
232         perf_pmu__parse_scale(alias, dir, name);
233         perf_pmu__parse_per_pkg(alias, dir, name);
234         perf_pmu__parse_snapshot(alias, dir, name);
235
236         list_add_tail(&alias->list, list);
237
238         return 0;
239 }
240
241 static inline bool pmu_alias_info_file(char *name)
242 {
243         size_t len;
244
245         len = strlen(name);
246         if (len > 5 && !strcmp(name + len - 5, ".unit"))
247                 return true;
248         if (len > 6 && !strcmp(name + len - 6, ".scale"))
249                 return true;
250         if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
251                 return true;
252         if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
253                 return true;
254
255         return false;
256 }
257
258 /*
259  * Process all the sysfs attributes located under the directory
260  * specified in 'dir' parameter.
261  */
262 static int pmu_aliases_parse(char *dir, struct list_head *head)
263 {
264         struct dirent *evt_ent;
265         DIR *event_dir;
266         int ret = 0;
267
268         event_dir = opendir(dir);
269         if (!event_dir)
270                 return -EINVAL;
271
272         while (!ret && (evt_ent = readdir(event_dir))) {
273                 char path[PATH_MAX];
274                 char *name = evt_ent->d_name;
275                 FILE *file;
276
277                 if (!strcmp(name, ".") || !strcmp(name, ".."))
278                         continue;
279
280                 /*
281                  * skip info files parsed in perf_pmu__new_alias()
282                  */
283                 if (pmu_alias_info_file(name))
284                         continue;
285
286                 snprintf(path, PATH_MAX, "%s/%s", dir, name);
287
288                 ret = -EINVAL;
289                 file = fopen(path, "r");
290                 if (!file)
291                         break;
292
293                 ret = perf_pmu__new_alias(head, dir, name, file);
294                 fclose(file);
295         }
296
297         closedir(event_dir);
298         return ret;
299 }
300
301 /*
302  * Reading the pmu event aliases definition, which should be located at:
303  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
304  */
305 static int pmu_aliases(const char *name, struct list_head *head)
306 {
307         struct stat st;
308         char path[PATH_MAX];
309         const char *sysfs = sysfs__mountpoint();
310
311         if (!sysfs)
312                 return -1;
313
314         snprintf(path, PATH_MAX,
315                  "%s/bus/event_source/devices/%s/events", sysfs, name);
316
317         if (stat(path, &st) < 0)
318                 return 0;        /* no error if 'events' does not exist */
319
320         if (pmu_aliases_parse(path, head))
321                 return -1;
322
323         return 0;
324 }
325
326 static int pmu_alias_terms(struct perf_pmu_alias *alias,
327                            struct list_head *terms)
328 {
329         struct parse_events_term *term, *cloned;
330         LIST_HEAD(list);
331         int ret;
332
333         list_for_each_entry(term, &alias->terms, list) {
334                 ret = parse_events_term__clone(&cloned, term);
335                 if (ret) {
336                         parse_events__free_terms(&list);
337                         return ret;
338                 }
339                 list_add_tail(&cloned->list, &list);
340         }
341         list_splice(&list, terms);
342         return 0;
343 }
344
345 /*
346  * Reading/parsing the default pmu type value, which should be
347  * located at:
348  * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
349  */
350 static int pmu_type(const char *name, __u32 *type)
351 {
352         struct stat st;
353         char path[PATH_MAX];
354         FILE *file;
355         int ret = 0;
356         const char *sysfs = sysfs__mountpoint();
357
358         if (!sysfs)
359                 return -1;
360
361         snprintf(path, PATH_MAX,
362                  "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
363
364         if (stat(path, &st) < 0)
365                 return -1;
366
367         file = fopen(path, "r");
368         if (!file)
369                 return -EINVAL;
370
371         if (1 != fscanf(file, "%u", type))
372                 ret = -1;
373
374         fclose(file);
375         return ret;
376 }
377
378 /* Add all pmus in sysfs to pmu list: */
379 static void pmu_read_sysfs(void)
380 {
381         char path[PATH_MAX];
382         DIR *dir;
383         struct dirent *dent;
384         const char *sysfs = sysfs__mountpoint();
385
386         if (!sysfs)
387                 return;
388
389         snprintf(path, PATH_MAX,
390                  "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
391
392         dir = opendir(path);
393         if (!dir)
394                 return;
395
396         while ((dent = readdir(dir))) {
397                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
398                         continue;
399                 /* add to static LIST_HEAD(pmus): */
400                 perf_pmu__find(dent->d_name);
401         }
402
403         closedir(dir);
404 }
405
406 static struct cpu_map *pmu_cpumask(const char *name)
407 {
408         struct stat st;
409         char path[PATH_MAX];
410         FILE *file;
411         struct cpu_map *cpus;
412         const char *sysfs = sysfs__mountpoint();
413
414         if (!sysfs)
415                 return NULL;
416
417         snprintf(path, PATH_MAX,
418                  "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
419
420         if (stat(path, &st) < 0)
421                 return NULL;
422
423         file = fopen(path, "r");
424         if (!file)
425                 return NULL;
426
427         cpus = cpu_map__read(file);
428         fclose(file);
429         return cpus;
430 }
431
432 struct perf_event_attr *__attribute__((weak))
433 perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
434 {
435         return NULL;
436 }
437
438 static struct perf_pmu *pmu_lookup(const char *name)
439 {
440         struct perf_pmu *pmu;
441         LIST_HEAD(format);
442         LIST_HEAD(aliases);
443         __u32 type;
444
445         /*
446          * The pmu data we store & need consists of the pmu
447          * type value and format definitions. Load both right
448          * now.
449          */
450         if (pmu_format(name, &format))
451                 return NULL;
452
453         if (pmu_aliases(name, &aliases))
454                 return NULL;
455
456         if (pmu_type(name, &type))
457                 return NULL;
458
459         pmu = zalloc(sizeof(*pmu));
460         if (!pmu)
461                 return NULL;
462
463         pmu->cpus = pmu_cpumask(name);
464
465         INIT_LIST_HEAD(&pmu->format);
466         INIT_LIST_HEAD(&pmu->aliases);
467         list_splice(&format, &pmu->format);
468         list_splice(&aliases, &pmu->aliases);
469         pmu->name = strdup(name);
470         pmu->type = type;
471         list_add_tail(&pmu->list, &pmus);
472
473         pmu->default_config = perf_pmu__get_default_config(pmu);
474
475         return pmu;
476 }
477
478 static struct perf_pmu *pmu_find(const char *name)
479 {
480         struct perf_pmu *pmu;
481
482         list_for_each_entry(pmu, &pmus, list)
483                 if (!strcmp(pmu->name, name))
484                         return pmu;
485
486         return NULL;
487 }
488
489 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
490 {
491         /*
492          * pmu iterator: If pmu is NULL, we start at the begin,
493          * otherwise return the next pmu. Returns NULL on end.
494          */
495         if (!pmu) {
496                 pmu_read_sysfs();
497                 pmu = list_prepare_entry(pmu, &pmus, list);
498         }
499         list_for_each_entry_continue(pmu, &pmus, list)
500                 return pmu;
501         return NULL;
502 }
503
504 struct perf_pmu *perf_pmu__find(const char *name)
505 {
506         struct perf_pmu *pmu;
507
508         /*
509          * Once PMU is loaded it stays in the list,
510          * so we keep us from multiple reading/parsing
511          * the pmu format definitions.
512          */
513         pmu = pmu_find(name);
514         if (pmu)
515                 return pmu;
516
517         return pmu_lookup(name);
518 }
519
520 static struct perf_pmu_format *
521 pmu_find_format(struct list_head *formats, char *name)
522 {
523         struct perf_pmu_format *format;
524
525         list_for_each_entry(format, formats, list)
526                 if (!strcmp(format->name, name))
527                         return format;
528
529         return NULL;
530 }
531
532 /*
533  * Sets value based on the format definition (format parameter)
534  * and unformated value (value parameter).
535  */
536 static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
537                              bool zero)
538 {
539         unsigned long fbit, vbit;
540
541         for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
542
543                 if (!test_bit(fbit, format))
544                         continue;
545
546                 if (value & (1llu << vbit++))
547                         *v |= (1llu << fbit);
548                 else if (zero)
549                         *v &= ~(1llu << fbit);
550         }
551 }
552
553 /*
554  * Setup one of config[12] attr members based on the
555  * user input data - term parameter.
556  */
557 static int pmu_config_term(struct list_head *formats,
558                            struct perf_event_attr *attr,
559                            struct parse_events_term *term,
560                            bool zero)
561 {
562         struct perf_pmu_format *format;
563         __u64 *vp;
564
565         /*
566          * Support only for hardcoded and numnerial terms.
567          * Hardcoded terms should be already in, so nothing
568          * to be done for them.
569          */
570         if (parse_events__is_hardcoded_term(term))
571                 return 0;
572
573         if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
574                 return -EINVAL;
575
576         format = pmu_find_format(formats, term->config);
577         if (!format)
578                 return -EINVAL;
579
580         switch (format->value) {
581         case PERF_PMU_FORMAT_VALUE_CONFIG:
582                 vp = &attr->config;
583                 break;
584         case PERF_PMU_FORMAT_VALUE_CONFIG1:
585                 vp = &attr->config1;
586                 break;
587         case PERF_PMU_FORMAT_VALUE_CONFIG2:
588                 vp = &attr->config2;
589                 break;
590         default:
591                 return -EINVAL;
592         }
593
594         /*
595          * XXX If we ever decide to go with string values for
596          * non-hardcoded terms, here's the place to translate
597          * them into value.
598          */
599         pmu_format_value(format->bits, term->val.num, vp, zero);
600         return 0;
601 }
602
603 int perf_pmu__config_terms(struct list_head *formats,
604                            struct perf_event_attr *attr,
605                            struct list_head *head_terms,
606                            bool zero)
607 {
608         struct parse_events_term *term;
609
610         list_for_each_entry(term, head_terms, list)
611                 if (pmu_config_term(formats, attr, term, zero))
612                         return -EINVAL;
613
614         return 0;
615 }
616
617 /*
618  * Configures event's 'attr' parameter based on the:
619  * 1) users input - specified in terms parameter
620  * 2) pmu format definitions - specified by pmu parameter
621  */
622 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
623                      struct list_head *head_terms)
624 {
625         bool zero = !!pmu->default_config;
626
627         attr->type = pmu->type;
628         return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
629 }
630
631 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
632                                              struct parse_events_term *term)
633 {
634         struct perf_pmu_alias *alias;
635         char *name;
636
637         if (parse_events__is_hardcoded_term(term))
638                 return NULL;
639
640         if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
641                 if (term->val.num != 1)
642                         return NULL;
643                 if (pmu_find_format(&pmu->format, term->config))
644                         return NULL;
645                 name = term->config;
646         } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
647                 if (strcasecmp(term->config, "event"))
648                         return NULL;
649                 name = term->val.str;
650         } else {
651                 return NULL;
652         }
653
654         list_for_each_entry(alias, &pmu->aliases, list) {
655                 if (!strcasecmp(alias->name, name))
656                         return alias;
657         }
658         return NULL;
659 }
660
661
662 static int check_info_data(struct perf_pmu_alias *alias,
663                            struct perf_pmu_info *info)
664 {
665         /*
666          * Only one term in event definition can
667          * define unit, scale and snapshot, fail
668          * if there's more than one.
669          */
670         if ((info->unit && alias->unit) ||
671             (info->scale && alias->scale) ||
672             (info->snapshot && alias->snapshot))
673                 return -EINVAL;
674
675         if (alias->unit)
676                 info->unit = alias->unit;
677
678         if (alias->scale)
679                 info->scale = alias->scale;
680
681         if (alias->snapshot)
682                 info->snapshot = alias->snapshot;
683
684         return 0;
685 }
686
687 /*
688  * Find alias in the terms list and replace it with the terms
689  * defined for the alias
690  */
691 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
692                           struct perf_pmu_info *info)
693 {
694         struct parse_events_term *term, *h;
695         struct perf_pmu_alias *alias;
696         int ret;
697
698         info->per_pkg = false;
699
700         /*
701          * Mark unit and scale as not set
702          * (different from default values, see below)
703          */
704         info->unit     = NULL;
705         info->scale    = 0.0;
706         info->snapshot = false;
707
708         list_for_each_entry_safe(term, h, head_terms, list) {
709                 alias = pmu_find_alias(pmu, term);
710                 if (!alias)
711                         continue;
712                 ret = pmu_alias_terms(alias, &term->list);
713                 if (ret)
714                         return ret;
715
716                 ret = check_info_data(alias, info);
717                 if (ret)
718                         return ret;
719
720                 if (alias->per_pkg)
721                         info->per_pkg = true;
722
723                 list_del(&term->list);
724                 free(term);
725         }
726
727         /*
728          * if no unit or scale foundin aliases, then
729          * set defaults as for evsel
730          * unit cannot left to NULL
731          */
732         if (info->unit == NULL)
733                 info->unit   = "";
734
735         if (info->scale == 0.0)
736                 info->scale  = 1.0;
737
738         return 0;
739 }
740
741 int perf_pmu__new_format(struct list_head *list, char *name,
742                          int config, unsigned long *bits)
743 {
744         struct perf_pmu_format *format;
745
746         format = zalloc(sizeof(*format));
747         if (!format)
748                 return -ENOMEM;
749
750         format->name = strdup(name);
751         format->value = config;
752         memcpy(format->bits, bits, sizeof(format->bits));
753
754         list_add_tail(&format->list, list);
755         return 0;
756 }
757
758 void perf_pmu__set_format(unsigned long *bits, long from, long to)
759 {
760         long b;
761
762         if (!to)
763                 to = from;
764
765         memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
766         for (b = from; b <= to; b++)
767                 set_bit(b, bits);
768 }
769
770 static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
771                           struct perf_pmu_alias *alias)
772 {
773         snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
774         return buf;
775 }
776
777 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
778                              struct perf_pmu_alias *alias)
779 {
780         snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
781         return buf;
782 }
783
784 static int cmp_string(const void *a, const void *b)
785 {
786         const char * const *as = a;
787         const char * const *bs = b;
788         return strcmp(*as, *bs);
789 }
790
791 void print_pmu_events(const char *event_glob, bool name_only)
792 {
793         struct perf_pmu *pmu;
794         struct perf_pmu_alias *alias;
795         char buf[1024];
796         int printed = 0;
797         int len, j;
798         char **aliases;
799
800         pmu = NULL;
801         len = 0;
802         while ((pmu = perf_pmu__scan(pmu)) != NULL) {
803                 list_for_each_entry(alias, &pmu->aliases, list)
804                         len++;
805                 if (pmu->selectable)
806                         len++;
807         }
808         aliases = zalloc(sizeof(char *) * len);
809         if (!aliases)
810                 goto out_enomem;
811         pmu = NULL;
812         j = 0;
813         while ((pmu = perf_pmu__scan(pmu)) != NULL) {
814                 list_for_each_entry(alias, &pmu->aliases, list) {
815                         char *name = format_alias(buf, sizeof(buf), pmu, alias);
816                         bool is_cpu = !strcmp(pmu->name, "cpu");
817
818                         if (event_glob != NULL &&
819                             !(strglobmatch(name, event_glob) ||
820                               (!is_cpu && strglobmatch(alias->name,
821                                                        event_glob))))
822                                 continue;
823
824                         if (is_cpu && !name_only)
825                                 name = format_alias_or(buf, sizeof(buf), pmu, alias);
826
827                         aliases[j] = strdup(name);
828                         if (aliases[j] == NULL)
829                                 goto out_enomem;
830                         j++;
831                 }
832                 if (pmu->selectable) {
833                         char *s;
834                         if (asprintf(&s, "%s//", pmu->name) < 0)
835                                 goto out_enomem;
836                         aliases[j] = s;
837                         j++;
838                 }
839         }
840         len = j;
841         qsort(aliases, len, sizeof(char *), cmp_string);
842         for (j = 0; j < len; j++) {
843                 if (name_only) {
844                         printf("%s ", aliases[j]);
845                         continue;
846                 }
847                 printf("  %-50s [Kernel PMU event]\n", aliases[j]);
848                 printed++;
849         }
850         if (printed)
851                 printf("\n");
852 out_free:
853         for (j = 0; j < len; j++)
854                 zfree(&aliases[j]);
855         zfree(&aliases);
856         return;
857
858 out_enomem:
859         printf("FATAL: not enough memory to print PMU events\n");
860         if (aliases)
861                 goto out_free;
862 }
863
864 bool pmu_have_event(const char *pname, const char *name)
865 {
866         struct perf_pmu *pmu;
867         struct perf_pmu_alias *alias;
868
869         pmu = NULL;
870         while ((pmu = perf_pmu__scan(pmu)) != NULL) {
871                 if (strcmp(pname, pmu->name))
872                         continue;
873                 list_for_each_entry(alias, &pmu->aliases, list)
874                         if (!strcmp(alias->name, name))
875                                 return true;
876         }
877         return false;
878 }
879
880 static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
881 {
882         struct stat st;
883         char path[PATH_MAX];
884         const char *sysfs;
885
886         sysfs = sysfs__mountpoint();
887         if (!sysfs)
888                 return NULL;
889
890         snprintf(path, PATH_MAX,
891                  "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
892
893         if (stat(path, &st) < 0)
894                 return NULL;
895
896         return fopen(path, "r");
897 }
898
899 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
900                         ...)
901 {
902         va_list args;
903         FILE *file;
904         int ret = EOF;
905
906         va_start(args, fmt);
907         file = perf_pmu__open_file(pmu, name);
908         if (file) {
909                 ret = vfscanf(file, fmt, args);
910                 fclose(file);
911         }
912         va_end(args);
913         return ret;
914 }