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 } 915