test-evlist.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
  3. #include <inttypes.h>
  4. #include <sched.h>
  5. #include <stdio.h>
  6. #include <stdarg.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <linux/perf_event.h>
  10. #include <linux/limits.h>
  11. #include <sys/types.h>
  12. #include <sys/wait.h>
  13. #include <sys/prctl.h>
  14. #include <perf/cpumap.h>
  15. #include <perf/threadmap.h>
  16. #include <perf/evlist.h>
  17. #include <perf/evsel.h>
  18. #include <perf/mmap.h>
  19. #include <perf/event.h>
  20. #include <internal/tests.h>
  21. #include <api/fs/fs.h>
  22. #include "tests.h"
  23. #include <internal/evsel.h>
  24. #define EVENT_NUM 15
  25. #define WAIT_COUNT 100000000UL
  26. static int libperf_print(enum libperf_print_level level,
  27. const char *fmt, va_list ap)
  28. {
  29. return vfprintf(stderr, fmt, ap);
  30. }
  31. static int test_stat_cpu(void)
  32. {
  33. struct perf_cpu_map *cpus;
  34. struct perf_evlist *evlist;
  35. struct perf_evsel *evsel, *leader;
  36. struct perf_event_attr attr1 = {
  37. .type = PERF_TYPE_SOFTWARE,
  38. .config = PERF_COUNT_SW_CPU_CLOCK,
  39. };
  40. struct perf_event_attr attr2 = {
  41. .type = PERF_TYPE_SOFTWARE,
  42. .config = PERF_COUNT_SW_TASK_CLOCK,
  43. };
  44. int err, idx;
  45. cpus = perf_cpu_map__new_online_cpus();
  46. __T("failed to create cpus", cpus);
  47. evlist = perf_evlist__new();
  48. __T("failed to create evlist", evlist);
  49. evsel = leader = perf_evsel__new(&attr1);
  50. __T("failed to create evsel1", evsel);
  51. perf_evlist__add(evlist, evsel);
  52. evsel = perf_evsel__new(&attr2);
  53. __T("failed to create evsel2", evsel);
  54. perf_evlist__add(evlist, evsel);
  55. perf_evlist__set_leader(evlist);
  56. __T("failed to set leader", leader->leader == leader);
  57. __T("failed to set leader", evsel->leader == leader);
  58. perf_evlist__set_maps(evlist, cpus, NULL);
  59. err = perf_evlist__open(evlist);
  60. __T("failed to open evlist", err == 0);
  61. perf_evlist__for_each_evsel(evlist, evsel) {
  62. cpus = perf_evsel__cpus(evsel);
  63. for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
  64. struct perf_counts_values counts = { .val = 0 };
  65. perf_evsel__read(evsel, idx, 0, &counts);
  66. __T("failed to read value for evsel", counts.val != 0);
  67. }
  68. }
  69. perf_evlist__close(evlist);
  70. perf_evlist__delete(evlist);
  71. perf_cpu_map__put(cpus);
  72. return 0;
  73. }
  74. static int test_stat_thread(void)
  75. {
  76. struct perf_counts_values counts = { .val = 0 };
  77. struct perf_thread_map *threads;
  78. struct perf_evlist *evlist;
  79. struct perf_evsel *evsel, *leader;
  80. struct perf_event_attr attr1 = {
  81. .type = PERF_TYPE_SOFTWARE,
  82. .config = PERF_COUNT_SW_CPU_CLOCK,
  83. };
  84. struct perf_event_attr attr2 = {
  85. .type = PERF_TYPE_SOFTWARE,
  86. .config = PERF_COUNT_SW_TASK_CLOCK,
  87. };
  88. int err;
  89. threads = perf_thread_map__new_dummy();
  90. __T("failed to create threads", threads);
  91. perf_thread_map__set_pid(threads, 0, 0);
  92. evlist = perf_evlist__new();
  93. __T("failed to create evlist", evlist);
  94. evsel = leader = perf_evsel__new(&attr1);
  95. __T("failed to create evsel1", evsel);
  96. perf_evlist__add(evlist, evsel);
  97. evsel = perf_evsel__new(&attr2);
  98. __T("failed to create evsel2", evsel);
  99. perf_evlist__add(evlist, evsel);
  100. perf_evlist__set_leader(evlist);
  101. __T("failed to set leader", leader->leader == leader);
  102. __T("failed to set leader", evsel->leader == leader);
  103. perf_evlist__set_maps(evlist, NULL, threads);
  104. err = perf_evlist__open(evlist);
  105. __T("failed to open evlist", err == 0);
  106. perf_evlist__for_each_evsel(evlist, evsel) {
  107. perf_evsel__read(evsel, 0, 0, &counts);
  108. __T("failed to read value for evsel", counts.val != 0);
  109. }
  110. perf_evlist__close(evlist);
  111. perf_evlist__delete(evlist);
  112. perf_thread_map__put(threads);
  113. return 0;
  114. }
  115. static int test_stat_thread_enable(void)
  116. {
  117. struct perf_counts_values counts = { .val = 0 };
  118. struct perf_thread_map *threads;
  119. struct perf_evlist *evlist;
  120. struct perf_evsel *evsel, *leader;
  121. struct perf_event_attr attr1 = {
  122. .type = PERF_TYPE_SOFTWARE,
  123. .config = PERF_COUNT_SW_CPU_CLOCK,
  124. .disabled = 1,
  125. };
  126. struct perf_event_attr attr2 = {
  127. .type = PERF_TYPE_SOFTWARE,
  128. .config = PERF_COUNT_SW_TASK_CLOCK,
  129. .disabled = 1,
  130. };
  131. int err;
  132. threads = perf_thread_map__new_dummy();
  133. __T("failed to create threads", threads);
  134. perf_thread_map__set_pid(threads, 0, 0);
  135. evlist = perf_evlist__new();
  136. __T("failed to create evlist", evlist);
  137. evsel = leader = perf_evsel__new(&attr1);
  138. __T("failed to create evsel1", evsel);
  139. perf_evlist__add(evlist, evsel);
  140. evsel = perf_evsel__new(&attr2);
  141. __T("failed to create evsel2", evsel);
  142. perf_evlist__add(evlist, evsel);
  143. perf_evlist__set_leader(evlist);
  144. __T("failed to set leader", leader->leader == leader);
  145. __T("failed to set leader", evsel->leader == leader);
  146. perf_evlist__set_maps(evlist, NULL, threads);
  147. err = perf_evlist__open(evlist);
  148. __T("failed to open evlist", err == 0);
  149. perf_evlist__for_each_evsel(evlist, evsel) {
  150. perf_evsel__read(evsel, 0, 0, &counts);
  151. __T("failed to read value for evsel", counts.val == 0);
  152. }
  153. perf_evlist__enable(evlist);
  154. perf_evlist__for_each_evsel(evlist, evsel) {
  155. perf_evsel__read(evsel, 0, 0, &counts);
  156. __T("failed to read value for evsel", counts.val != 0);
  157. }
  158. perf_evlist__disable(evlist);
  159. perf_evlist__close(evlist);
  160. perf_evlist__delete(evlist);
  161. perf_thread_map__put(threads);
  162. return 0;
  163. }
  164. static int test_mmap_thread(void)
  165. {
  166. struct perf_evlist *evlist;
  167. struct perf_evsel *evsel;
  168. struct perf_mmap *map;
  169. struct perf_cpu_map *cpus;
  170. struct perf_thread_map *threads;
  171. struct perf_event_attr attr = {
  172. .type = PERF_TYPE_TRACEPOINT,
  173. .sample_period = 1,
  174. .wakeup_watermark = 1,
  175. .disabled = 1,
  176. };
  177. char path[PATH_MAX];
  178. int id, err, pid, go_pipe[2];
  179. union perf_event *event;
  180. int count = 0;
  181. snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
  182. sysfs__mountpoint());
  183. if (filename__read_int(path, &id)) {
  184. tests_failed++;
  185. fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
  186. return -1;
  187. }
  188. attr.config = id;
  189. err = pipe(go_pipe);
  190. __T("failed to create pipe", err == 0);
  191. fflush(NULL);
  192. pid = fork();
  193. if (!pid) {
  194. int i;
  195. char bf;
  196. read(go_pipe[0], &bf, 1);
  197. /* Generate 100 prctl calls. */
  198. for (i = 0; i < 100; i++)
  199. prctl(0, 0, 0, 0, 0);
  200. exit(0);
  201. }
  202. threads = perf_thread_map__new_dummy();
  203. __T("failed to create threads", threads);
  204. cpus = perf_cpu_map__new_any_cpu();
  205. __T("failed to create cpus", cpus);
  206. perf_thread_map__set_pid(threads, 0, pid);
  207. evlist = perf_evlist__new();
  208. __T("failed to create evlist", evlist);
  209. evsel = perf_evsel__new(&attr);
  210. __T("failed to create evsel1", evsel);
  211. __T("failed to set leader", evsel->leader == evsel);
  212. perf_evlist__add(evlist, evsel);
  213. perf_evlist__set_maps(evlist, cpus, threads);
  214. err = perf_evlist__open(evlist);
  215. __T("failed to open evlist", err == 0);
  216. err = perf_evlist__mmap(evlist, 4);
  217. __T("failed to mmap evlist", err == 0);
  218. perf_evlist__enable(evlist);
  219. /* kick the child and wait for it to finish */
  220. write(go_pipe[1], "A", 1);
  221. waitpid(pid, NULL, 0);
  222. /*
  223. * There's no need to call perf_evlist__disable,
  224. * monitored process is dead now.
  225. */
  226. perf_evlist__for_each_mmap(evlist, map, false) {
  227. if (perf_mmap__read_init(map) < 0)
  228. continue;
  229. while ((event = perf_mmap__read_event(map)) != NULL) {
  230. count++;
  231. perf_mmap__consume(map);
  232. }
  233. perf_mmap__read_done(map);
  234. }
  235. /* calls perf_evlist__munmap/perf_evlist__close */
  236. perf_evlist__delete(evlist);
  237. perf_thread_map__put(threads);
  238. perf_cpu_map__put(cpus);
  239. /*
  240. * The generated prctl calls should match the
  241. * number of events in the buffer.
  242. */
  243. __T("failed count", count == 100);
  244. return 0;
  245. }
  246. static int test_mmap_cpus(void)
  247. {
  248. struct perf_evlist *evlist;
  249. struct perf_evsel *evsel;
  250. struct perf_mmap *map;
  251. struct perf_cpu_map *cpus;
  252. struct perf_event_attr attr = {
  253. .type = PERF_TYPE_TRACEPOINT,
  254. .sample_period = 1,
  255. .wakeup_watermark = 1,
  256. .disabled = 1,
  257. };
  258. cpu_set_t saved_mask;
  259. char path[PATH_MAX];
  260. int id, err, tmp;
  261. struct perf_cpu cpu;
  262. union perf_event *event;
  263. int count = 0;
  264. snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
  265. sysfs__mountpoint());
  266. if (filename__read_int(path, &id)) {
  267. fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
  268. return -1;
  269. }
  270. attr.config = id;
  271. cpus = perf_cpu_map__new_online_cpus();
  272. __T("failed to create cpus", cpus);
  273. evlist = perf_evlist__new();
  274. __T("failed to create evlist", evlist);
  275. evsel = perf_evsel__new(&attr);
  276. __T("failed to create evsel1", evsel);
  277. __T("failed to set leader", evsel->leader == evsel);
  278. perf_evlist__add(evlist, evsel);
  279. perf_evlist__set_maps(evlist, cpus, NULL);
  280. err = perf_evlist__open(evlist);
  281. __T("failed to open evlist", err == 0);
  282. err = perf_evlist__mmap(evlist, 4);
  283. __T("failed to mmap evlist", err == 0);
  284. perf_evlist__enable(evlist);
  285. err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
  286. __T("sched_getaffinity failed", err == 0);
  287. perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
  288. cpu_set_t mask;
  289. CPU_ZERO(&mask);
  290. CPU_SET(cpu.cpu, &mask);
  291. err = sched_setaffinity(0, sizeof(mask), &mask);
  292. __T("sched_setaffinity failed", err == 0);
  293. prctl(0, 0, 0, 0, 0);
  294. }
  295. err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
  296. __T("sched_setaffinity failed", err == 0);
  297. perf_evlist__disable(evlist);
  298. perf_evlist__for_each_mmap(evlist, map, false) {
  299. if (perf_mmap__read_init(map) < 0)
  300. continue;
  301. while ((event = perf_mmap__read_event(map)) != NULL) {
  302. count++;
  303. perf_mmap__consume(map);
  304. }
  305. perf_mmap__read_done(map);
  306. }
  307. /* calls perf_evlist__munmap/perf_evlist__close */
  308. perf_evlist__delete(evlist);
  309. /*
  310. * The generated prctl events should match the
  311. * number of cpus or be bigger (we are system-wide).
  312. */
  313. __T("failed count", count >= perf_cpu_map__nr(cpus));
  314. perf_cpu_map__put(cpus);
  315. return 0;
  316. }
  317. static double display_error(long long average,
  318. long long high,
  319. long long low,
  320. long long expected)
  321. {
  322. double error;
  323. error = (((double)average - expected) / expected) * 100.0;
  324. __T_VERBOSE(" Expected: %lld\n", expected);
  325. __T_VERBOSE(" High: %lld Low: %lld Average: %lld\n",
  326. high, low, average);
  327. __T_VERBOSE(" Average Error = %.2f%%\n", error);
  328. return error;
  329. }
  330. static int test_stat_multiplexing(void)
  331. {
  332. struct perf_counts_values expected_counts = { .val = 0 };
  333. struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },};
  334. struct perf_thread_map *threads;
  335. struct perf_evlist *evlist;
  336. struct perf_evsel *evsel;
  337. struct perf_event_attr attr = {
  338. .type = PERF_TYPE_HARDWARE,
  339. .config = PERF_COUNT_HW_INSTRUCTIONS,
  340. .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
  341. PERF_FORMAT_TOTAL_TIME_RUNNING,
  342. .disabled = 1,
  343. };
  344. int err, i, nonzero = 0;
  345. unsigned long count;
  346. long long max = 0, min = 0, avg = 0;
  347. double error = 0.0;
  348. s8 scaled = 0;
  349. /* read for non-multiplexing event count */
  350. threads = perf_thread_map__new_dummy();
  351. __T("failed to create threads", threads);
  352. perf_thread_map__set_pid(threads, 0, 0);
  353. evsel = perf_evsel__new(&attr);
  354. __T("failed to create evsel", evsel);
  355. err = perf_evsel__open(evsel, NULL, threads);
  356. __T("failed to open evsel", err == 0);
  357. err = perf_evsel__enable(evsel);
  358. __T("failed to enable evsel", err == 0);
  359. /* wait loop */
  360. count = WAIT_COUNT;
  361. while (count--)
  362. ;
  363. perf_evsel__read(evsel, 0, 0, &expected_counts);
  364. __T("failed to read value for evsel", expected_counts.val != 0);
  365. __T("failed to read non-multiplexing event count",
  366. expected_counts.ena == expected_counts.run);
  367. err = perf_evsel__disable(evsel);
  368. __T("failed to enable evsel", err == 0);
  369. perf_evsel__close(evsel);
  370. perf_evsel__delete(evsel);
  371. perf_thread_map__put(threads);
  372. /* read for multiplexing event count */
  373. threads = perf_thread_map__new_dummy();
  374. __T("failed to create threads", threads);
  375. perf_thread_map__set_pid(threads, 0, 0);
  376. evlist = perf_evlist__new();
  377. __T("failed to create evlist", evlist);
  378. for (i = 0; i < EVENT_NUM; i++) {
  379. evsel = perf_evsel__new(&attr);
  380. __T("failed to create evsel", evsel);
  381. perf_evlist__add(evlist, evsel);
  382. }
  383. perf_evlist__set_maps(evlist, NULL, threads);
  384. err = perf_evlist__open(evlist);
  385. __T("failed to open evlist", err == 0);
  386. perf_evlist__enable(evlist);
  387. /* wait loop */
  388. count = WAIT_COUNT;
  389. while (count--)
  390. ;
  391. i = 0;
  392. perf_evlist__for_each_evsel(evlist, evsel) {
  393. perf_evsel__read(evsel, 0, 0, &counts[i]);
  394. __T("failed to read value for evsel", counts[i].val != 0);
  395. i++;
  396. }
  397. perf_evlist__disable(evlist);
  398. min = counts[0].val;
  399. for (i = 0; i < EVENT_NUM; i++) {
  400. __T_VERBOSE("Event %2d -- Raw count = %" PRIu64 ", run = %" PRIu64 ", enable = %" PRIu64 "\n",
  401. i, counts[i].val, counts[i].run, counts[i].ena);
  402. perf_counts_values__scale(&counts[i], true, &scaled);
  403. if (scaled == 1) {
  404. __T_VERBOSE("\t Scaled count = %" PRIu64 " (%.2lf%%, %" PRIu64 "/%" PRIu64 ")\n",
  405. counts[i].val,
  406. (double)counts[i].run / (double)counts[i].ena * 100.0,
  407. counts[i].run, counts[i].ena);
  408. } else if (scaled == -1) {
  409. __T_VERBOSE("\t Not Running\n");
  410. } else {
  411. __T_VERBOSE("\t Not Scaling\n");
  412. }
  413. if (counts[i].val > max)
  414. max = counts[i].val;
  415. if (counts[i].val < min)
  416. min = counts[i].val;
  417. avg += counts[i].val;
  418. if (counts[i].val != 0)
  419. nonzero++;
  420. }
  421. if (nonzero != 0)
  422. avg = avg / nonzero;
  423. else
  424. avg = 0;
  425. error = display_error(avg, max, min, expected_counts.val);
  426. __T("Error out of range!", ((error <= 1.0) && (error >= -1.0)));
  427. perf_evlist__close(evlist);
  428. perf_evlist__delete(evlist);
  429. perf_thread_map__put(threads);
  430. return 0;
  431. }
  432. int test_evlist(int argc, char **argv)
  433. {
  434. __T_START;
  435. libperf_init(libperf_print);
  436. test_stat_cpu();
  437. test_stat_thread();
  438. test_stat_thread_enable();
  439. test_mmap_thread();
  440. test_mmap_cpus();
  441. test_stat_multiplexing();
  442. __T_END;
  443. return tests_failed == 0 ? 0 : -1;
  444. }