pmu.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  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. struct perf_pmu_format {
  15. char *name;
  16. int value;
  17. DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
  18. struct list_head list;
  19. };
  20. #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
  21. int perf_pmu_parse(struct list_head *list, char *name);
  22. extern FILE *perf_pmu_in;
  23. static LIST_HEAD(pmus);
  24. /*
  25. * Parse & process all the sysfs attributes located under
  26. * the directory specified in 'dir' parameter.
  27. */
  28. int perf_pmu__format_parse(char *dir, struct list_head *head)
  29. {
  30. struct dirent *evt_ent;
  31. DIR *format_dir;
  32. int ret = 0;
  33. format_dir = opendir(dir);
  34. if (!format_dir)
  35. return -EINVAL;
  36. while (!ret && (evt_ent = readdir(format_dir))) {
  37. char path[PATH_MAX];
  38. char *name = evt_ent->d_name;
  39. FILE *file;
  40. if (!strcmp(name, ".") || !strcmp(name, ".."))
  41. continue;
  42. snprintf(path, PATH_MAX, "%s/%s", dir, name);
  43. ret = -EINVAL;
  44. file = fopen(path, "r");
  45. if (!file)
  46. break;
  47. perf_pmu_in = file;
  48. ret = perf_pmu_parse(head, name);
  49. fclose(file);
  50. }
  51. closedir(format_dir);
  52. return ret;
  53. }
  54. /*
  55. * Reading/parsing the default pmu format definition, which should be
  56. * located at:
  57. * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
  58. */
  59. static int pmu_format(const char *name, struct list_head *format)
  60. {
  61. struct stat st;
  62. char path[PATH_MAX];
  63. const char *sysfs = sysfs__mountpoint();
  64. if (!sysfs)
  65. return -1;
  66. snprintf(path, PATH_MAX,
  67. "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
  68. if (stat(path, &st) < 0)
  69. return 0; /* no error if format does not exist */
  70. if (perf_pmu__format_parse(path, format))
  71. return -1;
  72. return 0;
  73. }
  74. static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
  75. {
  76. struct stat st;
  77. ssize_t sret;
  78. char scale[128];
  79. int fd, ret = -1;
  80. char path[PATH_MAX];
  81. const char *lc;
  82. snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
  83. fd = open(path, O_RDONLY);
  84. if (fd == -1)
  85. return -1;
  86. if (fstat(fd, &st) < 0)
  87. goto error;
  88. sret = read(fd, scale, sizeof(scale)-1);
  89. if (sret < 0)
  90. goto error;
  91. scale[sret] = '\0';
  92. /*
  93. * save current locale
  94. */
  95. lc = setlocale(LC_NUMERIC, NULL);
  96. /*
  97. * force to C locale to ensure kernel
  98. * scale string is converted correctly.
  99. * kernel uses default C locale.
  100. */
  101. setlocale(LC_NUMERIC, "C");
  102. alias->scale = strtod(scale, NULL);
  103. /* restore locale */
  104. setlocale(LC_NUMERIC, lc);
  105. ret = 0;
  106. error:
  107. close(fd);
  108. return ret;
  109. }
  110. static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
  111. {
  112. char path[PATH_MAX];
  113. ssize_t sret;
  114. int fd;
  115. snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
  116. fd = open(path, O_RDONLY);
  117. if (fd == -1)
  118. return -1;
  119. sret = read(fd, alias->unit, UNIT_MAX_LEN);
  120. if (sret < 0)
  121. goto error;
  122. close(fd);
  123. alias->unit[sret] = '\0';
  124. return 0;
  125. error:
  126. close(fd);
  127. alias->unit[0] = '\0';
  128. return -1;
  129. }
  130. static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
  131. {
  132. struct perf_pmu_alias *alias;
  133. char buf[256];
  134. int ret;
  135. ret = fread(buf, 1, sizeof(buf), file);
  136. if (ret == 0)
  137. return -EINVAL;
  138. buf[ret] = 0;
  139. alias = malloc(sizeof(*alias));
  140. if (!alias)
  141. return -ENOMEM;
  142. INIT_LIST_HEAD(&alias->terms);
  143. alias->scale = 1.0;
  144. alias->unit[0] = '\0';
  145. ret = parse_events_terms(&alias->terms, buf);
  146. if (ret) {
  147. free(alias);
  148. return ret;
  149. }
  150. alias->name = strdup(name);
  151. /*
  152. * load unit name and scale if available
  153. */
  154. perf_pmu__parse_unit(alias, dir, name);
  155. perf_pmu__parse_scale(alias, dir, name);
  156. list_add_tail(&alias->list, list);
  157. return 0;
  158. }
  159. static inline bool pmu_alias_info_file(char *name)
  160. {
  161. size_t len;
  162. len = strlen(name);
  163. if (len > 5 && !strcmp(name + len - 5, ".unit"))
  164. return true;
  165. if (len > 6 && !strcmp(name + len - 6, ".scale"))
  166. return true;
  167. return false;
  168. }
  169. /*
  170. * Process all the sysfs attributes located under the directory
  171. * specified in 'dir' parameter.
  172. */
  173. static int pmu_aliases_parse(char *dir, struct list_head *head)
  174. {
  175. struct dirent *evt_ent;
  176. DIR *event_dir;
  177. int ret = 0;
  178. event_dir = opendir(dir);
  179. if (!event_dir)
  180. return -EINVAL;
  181. while (!ret && (evt_ent = readdir(event_dir))) {
  182. char path[PATH_MAX];
  183. char *name = evt_ent->d_name;
  184. FILE *file;
  185. if (!strcmp(name, ".") || !strcmp(name, ".."))
  186. continue;
  187. /*
  188. * skip info files parsed in perf_pmu__new_alias()
  189. */
  190. if (pmu_alias_info_file(name))
  191. continue;
  192. snprintf(path, PATH_MAX, "%s/%s", dir, name);
  193. ret = -EINVAL;
  194. file = fopen(path, "r");
  195. if (!file)
  196. break;
  197. ret = perf_pmu__new_alias(head, dir, name, file);
  198. fclose(file);
  199. }
  200. closedir(event_dir);
  201. return ret;
  202. }
  203. /*
  204. * Reading the pmu event aliases definition, which should be located at:
  205. * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
  206. */
  207. static int pmu_aliases(const char *name, struct list_head *head)
  208. {
  209. struct stat st;
  210. char path[PATH_MAX];
  211. const char *sysfs = sysfs__mountpoint();
  212. if (!sysfs)
  213. return -1;
  214. snprintf(path, PATH_MAX,
  215. "%s/bus/event_source/devices/%s/events", sysfs, name);
  216. if (stat(path, &st) < 0)
  217. return 0; /* no error if 'events' does not exist */
  218. if (pmu_aliases_parse(path, head))
  219. return -1;
  220. return 0;
  221. }
  222. static int pmu_alias_terms(struct perf_pmu_alias *alias,
  223. struct list_head *terms)
  224. {
  225. struct parse_events_term *term, *cloned;
  226. LIST_HEAD(list);
  227. int ret;
  228. list_for_each_entry(term, &alias->terms, list) {
  229. ret = parse_events_term__clone(&cloned, term);
  230. if (ret) {
  231. parse_events__free_terms(&list);
  232. return ret;
  233. }
  234. list_add_tail(&cloned->list, &list);
  235. }
  236. list_splice(&list, terms);
  237. return 0;
  238. }
  239. /*
  240. * Reading/parsing the default pmu type value, which should be
  241. * located at:
  242. * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
  243. */
  244. static int pmu_type(const char *name, __u32 *type)
  245. {
  246. struct stat st;
  247. char path[PATH_MAX];
  248. FILE *file;
  249. int ret = 0;
  250. const char *sysfs = sysfs__mountpoint();
  251. if (!sysfs)
  252. return -1;
  253. snprintf(path, PATH_MAX,
  254. "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
  255. if (stat(path, &st) < 0)
  256. return -1;
  257. file = fopen(path, "r");
  258. if (!file)
  259. return -EINVAL;
  260. if (1 != fscanf(file, "%u", type))
  261. ret = -1;
  262. fclose(file);
  263. return ret;
  264. }
  265. /* Add all pmus in sysfs to pmu list: */
  266. static void pmu_read_sysfs(void)
  267. {
  268. char path[PATH_MAX];
  269. DIR *dir;
  270. struct dirent *dent;
  271. const char *sysfs = sysfs__mountpoint();
  272. if (!sysfs)
  273. return;
  274. snprintf(path, PATH_MAX,
  275. "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
  276. dir = opendir(path);
  277. if (!dir)
  278. return;
  279. while ((dent = readdir(dir))) {
  280. if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
  281. continue;
  282. /* add to static LIST_HEAD(pmus): */
  283. perf_pmu__find(dent->d_name);
  284. }
  285. closedir(dir);
  286. }
  287. static struct cpu_map *pmu_cpumask(const char *name)
  288. {
  289. struct stat st;
  290. char path[PATH_MAX];
  291. FILE *file;
  292. struct cpu_map *cpus;
  293. const char *sysfs = sysfs__mountpoint();
  294. if (!sysfs)
  295. return NULL;
  296. snprintf(path, PATH_MAX,
  297. "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
  298. if (stat(path, &st) < 0)
  299. return NULL;
  300. file = fopen(path, "r");
  301. if (!file)
  302. return NULL;
  303. cpus = cpu_map__read(file);
  304. fclose(file);
  305. return cpus;
  306. }
  307. struct perf_event_attr *__attribute__((weak))
  308. perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
  309. {
  310. return NULL;
  311. }
  312. static struct perf_pmu *pmu_lookup(const char *name)
  313. {
  314. struct perf_pmu *pmu;
  315. LIST_HEAD(format);
  316. LIST_HEAD(aliases);
  317. __u32 type;
  318. /*
  319. * The pmu data we store & need consists of the pmu
  320. * type value and format definitions. Load both right
  321. * now.
  322. */
  323. if (pmu_format(name, &format))
  324. return NULL;
  325. if (pmu_aliases(name, &aliases))
  326. return NULL;
  327. if (pmu_type(name, &type))
  328. return NULL;
  329. pmu = zalloc(sizeof(*pmu));
  330. if (!pmu)
  331. return NULL;
  332. pmu->cpus = pmu_cpumask(name);
  333. INIT_LIST_HEAD(&pmu->format);
  334. INIT_LIST_HEAD(&pmu->aliases);
  335. list_splice(&format, &pmu->format);
  336. list_splice(&aliases, &pmu->aliases);
  337. pmu->name = strdup(name);
  338. pmu->type = type;
  339. list_add_tail(&pmu->list, &pmus);
  340. pmu->default_config = perf_pmu__get_default_config(pmu);
  341. return pmu;
  342. }
  343. static struct perf_pmu *pmu_find(const char *name)
  344. {
  345. struct perf_pmu *pmu;
  346. list_for_each_entry(pmu, &pmus, list)
  347. if (!strcmp(pmu->name, name))
  348. return pmu;
  349. return NULL;
  350. }
  351. struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
  352. {
  353. /*
  354. * pmu iterator: If pmu is NULL, we start at the begin,
  355. * otherwise return the next pmu. Returns NULL on end.
  356. */
  357. if (!pmu) {
  358. pmu_read_sysfs();
  359. pmu = list_prepare_entry(pmu, &pmus, list);
  360. }
  361. list_for_each_entry_continue(pmu, &pmus, list)
  362. return pmu;
  363. return NULL;
  364. }
  365. struct perf_pmu *perf_pmu__find(const char *name)
  366. {
  367. struct perf_pmu *pmu;
  368. /*
  369. * Once PMU is loaded it stays in the list,
  370. * so we keep us from multiple reading/parsing
  371. * the pmu format definitions.
  372. */
  373. pmu = pmu_find(name);
  374. if (pmu)
  375. return pmu;
  376. return pmu_lookup(name);
  377. }
  378. static struct perf_pmu_format *
  379. pmu_find_format(struct list_head *formats, char *name)
  380. {
  381. struct perf_pmu_format *format;
  382. list_for_each_entry(format, formats, list)
  383. if (!strcmp(format->name, name))
  384. return format;
  385. return NULL;
  386. }
  387. /*
  388. * Sets value based on the format definition (format parameter)
  389. * and unformated value (value parameter).
  390. */
  391. static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
  392. bool zero)
  393. {
  394. unsigned long fbit, vbit;
  395. for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
  396. if (!test_bit(fbit, format))
  397. continue;
  398. if (value & (1llu << vbit++))
  399. *v |= (1llu << fbit);
  400. else if (zero)
  401. *v &= ~(1llu << fbit);
  402. }
  403. }
  404. /*
  405. * Setup one of config[12] attr members based on the
  406. * user input data - term parameter.
  407. */
  408. static int pmu_config_term(struct list_head *formats,
  409. struct perf_event_attr *attr,
  410. struct parse_events_term *term,
  411. bool zero)
  412. {
  413. struct perf_pmu_format *format;
  414. __u64 *vp;
  415. /*
  416. * Support only for hardcoded and numnerial terms.
  417. * Hardcoded terms should be already in, so nothing
  418. * to be done for them.
  419. */
  420. if (parse_events__is_hardcoded_term(term))
  421. return 0;
  422. if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
  423. return -EINVAL;
  424. format = pmu_find_format(formats, term->config);
  425. if (!format)
  426. return -EINVAL;
  427. switch (format->value) {
  428. case PERF_PMU_FORMAT_VALUE_CONFIG:
  429. vp = &attr->config;
  430. break;
  431. case PERF_PMU_FORMAT_VALUE_CONFIG1:
  432. vp = &attr->config1;
  433. break;
  434. case PERF_PMU_FORMAT_VALUE_CONFIG2:
  435. vp = &attr->config2;
  436. break;
  437. default:
  438. return -EINVAL;
  439. }
  440. /*
  441. * XXX If we ever decide to go with string values for
  442. * non-hardcoded terms, here's the place to translate
  443. * them into value.
  444. */
  445. pmu_format_value(format->bits, term->val.num, vp, zero);
  446. return 0;
  447. }
  448. int perf_pmu__config_terms(struct list_head *formats,
  449. struct perf_event_attr *attr,
  450. struct list_head *head_terms,
  451. bool zero)
  452. {
  453. struct parse_events_term *term;
  454. list_for_each_entry(term, head_terms, list)
  455. if (pmu_config_term(formats, attr, term, zero))
  456. return -EINVAL;
  457. return 0;
  458. }
  459. /*
  460. * Configures event's 'attr' parameter based on the:
  461. * 1) users input - specified in terms parameter
  462. * 2) pmu format definitions - specified by pmu parameter
  463. */
  464. int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
  465. struct list_head *head_terms)
  466. {
  467. bool zero = !!pmu->default_config;
  468. attr->type = pmu->type;
  469. return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
  470. }
  471. static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
  472. struct parse_events_term *term)
  473. {
  474. struct perf_pmu_alias *alias;
  475. char *name;
  476. if (parse_events__is_hardcoded_term(term))
  477. return NULL;
  478. if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
  479. if (term->val.num != 1)
  480. return NULL;
  481. if (pmu_find_format(&pmu->format, term->config))
  482. return NULL;
  483. name = term->config;
  484. } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
  485. if (strcasecmp(term->config, "event"))
  486. return NULL;
  487. name = term->val.str;
  488. } else {
  489. return NULL;
  490. }
  491. list_for_each_entry(alias, &pmu->aliases, list) {
  492. if (!strcasecmp(alias->name, name))
  493. return alias;
  494. }
  495. return NULL;
  496. }
  497. static int check_unit_scale(struct perf_pmu_alias *alias,
  498. const char **unit, double *scale)
  499. {
  500. /*
  501. * Only one term in event definition can
  502. * define unit and scale, fail if there's
  503. * more than one.
  504. */
  505. if ((*unit && alias->unit) ||
  506. (*scale && alias->scale))
  507. return -EINVAL;
  508. if (alias->unit)
  509. *unit = alias->unit;
  510. if (alias->scale)
  511. *scale = alias->scale;
  512. return 0;
  513. }
  514. /*
  515. * Find alias in the terms list and replace it with the terms
  516. * defined for the alias
  517. */
  518. int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
  519. struct perf_pmu_info *info)
  520. {
  521. struct parse_events_term *term, *h;
  522. struct perf_pmu_alias *alias;
  523. int ret;
  524. /*
  525. * Mark unit and scale as not set
  526. * (different from default values, see below)
  527. */
  528. info->unit = NULL;
  529. info->scale = 0.0;
  530. list_for_each_entry_safe(term, h, head_terms, list) {
  531. alias = pmu_find_alias(pmu, term);
  532. if (!alias)
  533. continue;
  534. ret = pmu_alias_terms(alias, &term->list);
  535. if (ret)
  536. return ret;
  537. ret = check_unit_scale(alias, &info->unit, &info->scale);
  538. if (ret)
  539. return ret;
  540. list_del(&term->list);
  541. free(term);
  542. }
  543. /*
  544. * if no unit or scale foundin aliases, then
  545. * set defaults as for evsel
  546. * unit cannot left to NULL
  547. */
  548. if (info->unit == NULL)
  549. info->unit = "";
  550. if (info->scale == 0.0)
  551. info->scale = 1.0;
  552. return 0;
  553. }
  554. int perf_pmu__new_format(struct list_head *list, char *name,
  555. int config, unsigned long *bits)
  556. {
  557. struct perf_pmu_format *format;
  558. format = zalloc(sizeof(*format));
  559. if (!format)
  560. return -ENOMEM;
  561. format->name = strdup(name);
  562. format->value = config;
  563. memcpy(format->bits, bits, sizeof(format->bits));
  564. list_add_tail(&format->list, list);
  565. return 0;
  566. }
  567. void perf_pmu__set_format(unsigned long *bits, long from, long to)
  568. {
  569. long b;
  570. if (!to)
  571. to = from;
  572. memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
  573. for (b = from; b <= to; b++)
  574. set_bit(b, bits);
  575. }
  576. static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
  577. struct perf_pmu_alias *alias)
  578. {
  579. snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
  580. return buf;
  581. }
  582. static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
  583. struct perf_pmu_alias *alias)
  584. {
  585. snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
  586. return buf;
  587. }
  588. static int cmp_string(const void *a, const void *b)
  589. {
  590. const char * const *as = a;
  591. const char * const *bs = b;
  592. return strcmp(*as, *bs);
  593. }
  594. void print_pmu_events(const char *event_glob, bool name_only)
  595. {
  596. struct perf_pmu *pmu;
  597. struct perf_pmu_alias *alias;
  598. char buf[1024];
  599. int printed = 0;
  600. int len, j;
  601. char **aliases;
  602. pmu = NULL;
  603. len = 0;
  604. while ((pmu = perf_pmu__scan(pmu)) != NULL)
  605. list_for_each_entry(alias, &pmu->aliases, list)
  606. len++;
  607. aliases = malloc(sizeof(char *) * len);
  608. if (!aliases)
  609. return;
  610. pmu = NULL;
  611. j = 0;
  612. while ((pmu = perf_pmu__scan(pmu)) != NULL)
  613. list_for_each_entry(alias, &pmu->aliases, list) {
  614. char *name = format_alias(buf, sizeof(buf), pmu, alias);
  615. bool is_cpu = !strcmp(pmu->name, "cpu");
  616. if (event_glob != NULL &&
  617. !(strglobmatch(name, event_glob) ||
  618. (!is_cpu && strglobmatch(alias->name,
  619. event_glob))))
  620. continue;
  621. aliases[j] = name;
  622. if (is_cpu && !name_only)
  623. aliases[j] = format_alias_or(buf, sizeof(buf),
  624. pmu, alias);
  625. aliases[j] = strdup(aliases[j]);
  626. j++;
  627. }
  628. len = j;
  629. qsort(aliases, len, sizeof(char *), cmp_string);
  630. for (j = 0; j < len; j++) {
  631. if (name_only) {
  632. printf("%s ", aliases[j]);
  633. continue;
  634. }
  635. printf(" %-50s [Kernel PMU event]\n", aliases[j]);
  636. zfree(&aliases[j]);
  637. printed++;
  638. }
  639. if (printed)
  640. printf("\n");
  641. free(aliases);
  642. }
  643. bool pmu_have_event(const char *pname, const char *name)
  644. {
  645. struct perf_pmu *pmu;
  646. struct perf_pmu_alias *alias;
  647. pmu = NULL;
  648. while ((pmu = perf_pmu__scan(pmu)) != NULL) {
  649. if (strcmp(pname, pmu->name))
  650. continue;
  651. list_for_each_entry(alias, &pmu->aliases, list)
  652. if (!strcmp(alias->name, name))
  653. return true;
  654. }
  655. return false;
  656. }
  657. static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
  658. {
  659. struct stat st;
  660. char path[PATH_MAX];
  661. const char *sysfs;
  662. sysfs = sysfs__mountpoint();
  663. if (!sysfs)
  664. return NULL;
  665. snprintf(path, PATH_MAX,
  666. "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
  667. if (stat(path, &st) < 0)
  668. return NULL;
  669. return fopen(path, "r");
  670. }
  671. int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
  672. ...)
  673. {
  674. va_list args;
  675. FILE *file;
  676. int ret = EOF;
  677. va_start(args, fmt);
  678. file = perf_pmu__open_file(pmu, name);
  679. if (file) {
  680. ret = vfscanf(file, fmt, args);
  681. fclose(file);
  682. }
  683. va_end(args);
  684. return ret;
  685. }