hists_cumulate.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "util/debug.h"
  3. #include "util/dso.h"
  4. #include "util/event.h"
  5. #include "util/map.h"
  6. #include "util/symbol.h"
  7. #include "util/sort.h"
  8. #include "util/evsel.h"
  9. #include "util/evlist.h"
  10. #include "util/machine.h"
  11. #include "util/parse-events.h"
  12. #include "util/thread.h"
  13. #include "tests/tests.h"
  14. #include "tests/hists_common.h"
  15. #include <linux/kernel.h>
  16. struct sample {
  17. u32 pid;
  18. u64 ip;
  19. struct thread *thread;
  20. struct map *map;
  21. struct symbol *sym;
  22. };
  23. /* For the numbers, see hists_common.c */
  24. static struct sample fake_samples[] = {
  25. /* perf [kernel] schedule() */
  26. { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
  27. /* perf [perf] main() */
  28. { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
  29. /* perf [perf] cmd_record() */
  30. { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
  31. /* perf [libc] malloc() */
  32. { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
  33. /* perf [libc] free() */
  34. { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
  35. /* perf [perf] main() */
  36. { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
  37. /* perf [kernel] page_fault() */
  38. { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  39. /* bash [bash] main() */
  40. { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, },
  41. /* bash [bash] xmalloc() */
  42. { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, },
  43. /* bash [kernel] page_fault() */
  44. { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
  45. };
  46. /*
  47. * Will be cast to struct ip_callchain which has all 64 bit entries
  48. * of nr and ips[].
  49. */
  50. static u64 fake_callchains[][10] = {
  51. /* schedule => run_command => main */
  52. { 3, FAKE_IP_KERNEL_SCHEDULE, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  53. /* main */
  54. { 1, FAKE_IP_PERF_MAIN, },
  55. /* cmd_record => run_command => main */
  56. { 3, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  57. /* malloc => cmd_record => run_command => main */
  58. { 4, FAKE_IP_LIBC_MALLOC, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
  59. FAKE_IP_PERF_MAIN, },
  60. /* free => cmd_record => run_command => main */
  61. { 4, FAKE_IP_LIBC_FREE, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
  62. FAKE_IP_PERF_MAIN, },
  63. /* main */
  64. { 1, FAKE_IP_PERF_MAIN, },
  65. /* page_fault => sys_perf_event_open => run_command => main */
  66. { 4, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_KERNEL_SYS_PERF_EVENT_OPEN,
  67. FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
  68. /* main */
  69. { 1, FAKE_IP_BASH_MAIN, },
  70. /* xmalloc => malloc => xmalloc => malloc => xmalloc => main */
  71. { 6, FAKE_IP_BASH_XMALLOC, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC,
  72. FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, FAKE_IP_BASH_MAIN, },
  73. /* page_fault => malloc => main */
  74. { 3, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_MAIN, },
  75. };
  76. static int add_hist_entries(struct hists *hists, struct machine *machine)
  77. {
  78. struct addr_location al;
  79. struct evsel *evsel = hists_to_evsel(hists);
  80. struct perf_sample sample = { .period = 1000, };
  81. size_t i;
  82. addr_location__init(&al);
  83. for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
  84. struct hist_entry_iter iter = {
  85. .evsel = evsel,
  86. .sample = &sample,
  87. .hide_unresolved = false,
  88. };
  89. if (symbol_conf.cumulate_callchain)
  90. iter.ops = &hist_iter_cumulative;
  91. else
  92. iter.ops = &hist_iter_normal;
  93. sample.cpumode = PERF_RECORD_MISC_USER;
  94. sample.pid = fake_samples[i].pid;
  95. sample.tid = fake_samples[i].pid;
  96. sample.ip = fake_samples[i].ip;
  97. sample.callchain = (struct ip_callchain *)fake_callchains[i];
  98. if (machine__resolve(machine, &al, &sample) < 0)
  99. goto out;
  100. if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
  101. NULL) < 0) {
  102. goto out;
  103. }
  104. thread__put(fake_samples[i].thread);
  105. fake_samples[i].thread = thread__get(al.thread);
  106. map__put(fake_samples[i].map);
  107. fake_samples[i].map = map__get(al.map);
  108. fake_samples[i].sym = al.sym;
  109. }
  110. addr_location__exit(&al);
  111. return TEST_OK;
  112. out:
  113. pr_debug("Not enough memory for adding a hist entry\n");
  114. addr_location__exit(&al);
  115. return TEST_FAIL;
  116. }
  117. static void del_hist_entries(struct hists *hists)
  118. {
  119. struct hist_entry *he;
  120. struct rb_root_cached *root_in;
  121. struct rb_root_cached *root_out;
  122. struct rb_node *node;
  123. if (hists__has(hists, need_collapse))
  124. root_in = &hists->entries_collapsed;
  125. else
  126. root_in = hists->entries_in;
  127. root_out = &hists->entries;
  128. while (!RB_EMPTY_ROOT(&root_out->rb_root)) {
  129. node = rb_first_cached(root_out);
  130. he = rb_entry(node, struct hist_entry, rb_node);
  131. rb_erase_cached(node, root_out);
  132. rb_erase_cached(&he->rb_node_in, root_in);
  133. hist_entry__delete(he);
  134. }
  135. }
  136. static void put_fake_samples(void)
  137. {
  138. size_t i;
  139. for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
  140. map__zput(fake_samples[i].map);
  141. thread__zput(fake_samples[i].thread);
  142. }
  143. }
  144. typedef int (*test_fn_t)(struct evsel *, struct machine *);
  145. #define COMM(he) (thread__comm_str(he->thread))
  146. #define DSO(he) (dso__short_name(map__dso(he->ms.map)))
  147. #define SYM(he) (he->ms.sym->name)
  148. #define CPU(he) (he->cpu)
  149. #define DEPTH(he) (he->callchain->max_depth)
  150. #define CDSO(cl) (dso__short_name(map__dso(cl->ms.map)))
  151. #define CSYM(cl) (cl->ms.sym->name)
  152. struct result {
  153. u64 children;
  154. u64 self;
  155. const char *comm;
  156. const char *dso;
  157. const char *sym;
  158. };
  159. struct callchain_result {
  160. u64 nr;
  161. struct {
  162. const char *dso;
  163. const char *sym;
  164. } node[10];
  165. };
  166. static int do_test(struct hists *hists, struct result *expected, size_t nr_expected,
  167. struct callchain_result *expected_callchain, size_t nr_callchain)
  168. {
  169. char buf[32];
  170. size_t i, c;
  171. struct hist_entry *he;
  172. struct rb_root *root;
  173. struct rb_node *node;
  174. struct callchain_node *cnode;
  175. struct callchain_list *clist;
  176. /*
  177. * adding and deleting hist entries must be done outside of this
  178. * function since TEST_ASSERT_VAL() returns in case of failure.
  179. */
  180. hists__collapse_resort(hists, NULL);
  181. evsel__output_resort(hists_to_evsel(hists), NULL);
  182. if (verbose > 2) {
  183. pr_info("use callchain: %d, cumulate callchain: %d\n",
  184. symbol_conf.use_callchain,
  185. symbol_conf.cumulate_callchain);
  186. print_hists_out(hists);
  187. }
  188. root = &hists->entries.rb_root;
  189. for (node = rb_first(root), i = 0;
  190. node && (he = rb_entry(node, struct hist_entry, rb_node));
  191. node = rb_next(node), i++) {
  192. scnprintf(buf, sizeof(buf), "Invalid hist entry #%zd", i);
  193. TEST_ASSERT_VAL("Incorrect number of hist entry",
  194. i < nr_expected);
  195. TEST_ASSERT_VAL(buf, he->stat.period == expected[i].self &&
  196. !strcmp(COMM(he), expected[i].comm) &&
  197. !strcmp(DSO(he), expected[i].dso) &&
  198. !strcmp(SYM(he), expected[i].sym));
  199. if (symbol_conf.cumulate_callchain)
  200. TEST_ASSERT_VAL(buf, he->stat_acc->period == expected[i].children);
  201. if (!symbol_conf.use_callchain)
  202. continue;
  203. /* check callchain entries */
  204. root = &he->callchain->node.rb_root;
  205. TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root));
  206. cnode = rb_entry(rb_first(root), struct callchain_node, rb_node);
  207. c = 0;
  208. list_for_each_entry(clist, &cnode->val, list) {
  209. scnprintf(buf, sizeof(buf), "Invalid callchain entry #%zd/%zd", i, c);
  210. TEST_ASSERT_VAL("Incorrect number of callchain entry",
  211. c < expected_callchain[i].nr);
  212. TEST_ASSERT_VAL(buf,
  213. !strcmp(CDSO(clist), expected_callchain[i].node[c].dso) &&
  214. !strcmp(CSYM(clist), expected_callchain[i].node[c].sym));
  215. c++;
  216. }
  217. /* TODO: handle multiple child nodes properly */
  218. TEST_ASSERT_VAL("Incorrect number of callchain entry",
  219. c <= expected_callchain[i].nr);
  220. }
  221. TEST_ASSERT_VAL("Incorrect number of hist entry",
  222. i == nr_expected);
  223. TEST_ASSERT_VAL("Incorrect number of callchain entry",
  224. !symbol_conf.use_callchain || nr_expected == nr_callchain);
  225. return 0;
  226. }
  227. /* NO callchain + NO children */
  228. static int test1(struct evsel *evsel, struct machine *machine)
  229. {
  230. int err;
  231. struct hists *hists = evsel__hists(evsel);
  232. /*
  233. * expected output:
  234. *
  235. * Overhead Command Shared Object Symbol
  236. * ======== ======= ============= ==============
  237. * 20.00% perf perf [.] main
  238. * 10.00% bash [kernel] [k] page_fault
  239. * 10.00% bash bash [.] main
  240. * 10.00% bash bash [.] xmalloc
  241. * 10.00% perf [kernel] [k] page_fault
  242. * 10.00% perf [kernel] [k] schedule
  243. * 10.00% perf libc [.] free
  244. * 10.00% perf libc [.] malloc
  245. * 10.00% perf perf [.] cmd_record
  246. */
  247. struct result expected[] = {
  248. { 0, 2000, "perf", "perf", "main" },
  249. { 0, 1000, "bash", "[kernel]", "page_fault" },
  250. { 0, 1000, "bash", "bash", "main" },
  251. { 0, 1000, "bash", "bash", "xmalloc" },
  252. { 0, 1000, "perf", "[kernel]", "page_fault" },
  253. { 0, 1000, "perf", "[kernel]", "schedule" },
  254. { 0, 1000, "perf", "libc", "free" },
  255. { 0, 1000, "perf", "libc", "malloc" },
  256. { 0, 1000, "perf", "perf", "cmd_record" },
  257. };
  258. symbol_conf.use_callchain = false;
  259. symbol_conf.cumulate_callchain = false;
  260. evsel__reset_sample_bit(evsel, CALLCHAIN);
  261. setup_sorting(/*evlist=*/NULL, machine->env);
  262. callchain_register_param(&callchain_param);
  263. err = add_hist_entries(hists, machine);
  264. if (err < 0)
  265. goto out;
  266. err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
  267. out:
  268. del_hist_entries(hists);
  269. reset_output_field();
  270. return err;
  271. }
  272. /* callchain + NO children */
  273. static int test2(struct evsel *evsel, struct machine *machine)
  274. {
  275. int err;
  276. struct hists *hists = evsel__hists(evsel);
  277. /*
  278. * expected output:
  279. *
  280. * Overhead Command Shared Object Symbol
  281. * ======== ======= ============= ==============
  282. * 20.00% perf perf [.] main
  283. * |
  284. * --- main
  285. *
  286. * 10.00% bash [kernel] [k] page_fault
  287. * |
  288. * --- page_fault
  289. * malloc
  290. * main
  291. *
  292. * 10.00% bash bash [.] main
  293. * |
  294. * --- main
  295. *
  296. * 10.00% bash bash [.] xmalloc
  297. * |
  298. * --- xmalloc
  299. * malloc
  300. * xmalloc <--- NOTE: there's a cycle
  301. * malloc
  302. * xmalloc
  303. * main
  304. *
  305. * 10.00% perf [kernel] [k] page_fault
  306. * |
  307. * --- page_fault
  308. * sys_perf_event_open
  309. * run_command
  310. * main
  311. *
  312. * 10.00% perf [kernel] [k] schedule
  313. * |
  314. * --- schedule
  315. * run_command
  316. * main
  317. *
  318. * 10.00% perf libc [.] free
  319. * |
  320. * --- free
  321. * cmd_record
  322. * run_command
  323. * main
  324. *
  325. * 10.00% perf libc [.] malloc
  326. * |
  327. * --- malloc
  328. * cmd_record
  329. * run_command
  330. * main
  331. *
  332. * 10.00% perf perf [.] cmd_record
  333. * |
  334. * --- cmd_record
  335. * run_command
  336. * main
  337. *
  338. */
  339. struct result expected[] = {
  340. { 0, 2000, "perf", "perf", "main" },
  341. { 0, 1000, "bash", "[kernel]", "page_fault" },
  342. { 0, 1000, "bash", "bash", "main" },
  343. { 0, 1000, "bash", "bash", "xmalloc" },
  344. { 0, 1000, "perf", "[kernel]", "page_fault" },
  345. { 0, 1000, "perf", "[kernel]", "schedule" },
  346. { 0, 1000, "perf", "libc", "free" },
  347. { 0, 1000, "perf", "libc", "malloc" },
  348. { 0, 1000, "perf", "perf", "cmd_record" },
  349. };
  350. struct callchain_result expected_callchain[] = {
  351. {
  352. 1, { { "perf", "main" }, },
  353. },
  354. {
  355. 3, { { "[kernel]", "page_fault" },
  356. { "libc", "malloc" },
  357. { "bash", "main" }, },
  358. },
  359. {
  360. 1, { { "bash", "main" }, },
  361. },
  362. {
  363. 6, { { "bash", "xmalloc" },
  364. { "libc", "malloc" },
  365. { "bash", "xmalloc" },
  366. { "libc", "malloc" },
  367. { "bash", "xmalloc" },
  368. { "bash", "main" }, },
  369. },
  370. {
  371. 4, { { "[kernel]", "page_fault" },
  372. { "[kernel]", "sys_perf_event_open" },
  373. { "perf", "run_command" },
  374. { "perf", "main" }, },
  375. },
  376. {
  377. 3, { { "[kernel]", "schedule" },
  378. { "perf", "run_command" },
  379. { "perf", "main" }, },
  380. },
  381. {
  382. 4, { { "libc", "free" },
  383. { "perf", "cmd_record" },
  384. { "perf", "run_command" },
  385. { "perf", "main" }, },
  386. },
  387. {
  388. 4, { { "libc", "malloc" },
  389. { "perf", "cmd_record" },
  390. { "perf", "run_command" },
  391. { "perf", "main" }, },
  392. },
  393. {
  394. 3, { { "perf", "cmd_record" },
  395. { "perf", "run_command" },
  396. { "perf", "main" }, },
  397. },
  398. };
  399. symbol_conf.use_callchain = true;
  400. symbol_conf.cumulate_callchain = false;
  401. evsel__set_sample_bit(evsel, CALLCHAIN);
  402. setup_sorting(/*evlist=*/NULL, machine->env);
  403. callchain_register_param(&callchain_param);
  404. err = add_hist_entries(hists, machine);
  405. if (err < 0)
  406. goto out;
  407. err = do_test(hists, expected, ARRAY_SIZE(expected),
  408. expected_callchain, ARRAY_SIZE(expected_callchain));
  409. out:
  410. del_hist_entries(hists);
  411. reset_output_field();
  412. return err;
  413. }
  414. /* NO callchain + children */
  415. static int test3(struct evsel *evsel, struct machine *machine)
  416. {
  417. int err;
  418. struct hists *hists = evsel__hists(evsel);
  419. /*
  420. * expected output:
  421. *
  422. * Children Self Command Shared Object Symbol
  423. * ======== ======== ======= ============= =======================
  424. * 70.00% 20.00% perf perf [.] main
  425. * 50.00% 0.00% perf perf [.] run_command
  426. * 30.00% 10.00% bash bash [.] main
  427. * 30.00% 10.00% perf perf [.] cmd_record
  428. * 20.00% 0.00% bash libc [.] malloc
  429. * 10.00% 10.00% bash [kernel] [k] page_fault
  430. * 10.00% 10.00% bash bash [.] xmalloc
  431. * 10.00% 10.00% perf [kernel] [k] page_fault
  432. * 10.00% 10.00% perf libc [.] malloc
  433. * 10.00% 10.00% perf [kernel] [k] schedule
  434. * 10.00% 10.00% perf libc [.] free
  435. * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
  436. */
  437. struct result expected[] = {
  438. { 7000, 2000, "perf", "perf", "main" },
  439. { 5000, 0, "perf", "perf", "run_command" },
  440. { 3000, 1000, "bash", "bash", "main" },
  441. { 3000, 1000, "perf", "perf", "cmd_record" },
  442. { 2000, 0, "bash", "libc", "malloc" },
  443. { 1000, 1000, "bash", "[kernel]", "page_fault" },
  444. { 1000, 1000, "bash", "bash", "xmalloc" },
  445. { 1000, 1000, "perf", "[kernel]", "page_fault" },
  446. { 1000, 1000, "perf", "[kernel]", "schedule" },
  447. { 1000, 1000, "perf", "libc", "free" },
  448. { 1000, 1000, "perf", "libc", "malloc" },
  449. { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
  450. };
  451. symbol_conf.use_callchain = false;
  452. symbol_conf.cumulate_callchain = true;
  453. evsel__reset_sample_bit(evsel, CALLCHAIN);
  454. setup_sorting(/*evlist=*/NULL, machine->env);
  455. callchain_register_param(&callchain_param);
  456. err = add_hist_entries(hists, machine);
  457. if (err < 0)
  458. goto out;
  459. err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
  460. out:
  461. del_hist_entries(hists);
  462. reset_output_field();
  463. return err;
  464. }
  465. /* callchain + children */
  466. static int test4(struct evsel *evsel, struct machine *machine)
  467. {
  468. int err;
  469. struct hists *hists = evsel__hists(evsel);
  470. /*
  471. * expected output:
  472. *
  473. * Children Self Command Shared Object Symbol
  474. * ======== ======== ======= ============= =======================
  475. * 70.00% 20.00% perf perf [.] main
  476. * |
  477. * --- main
  478. *
  479. * 50.00% 0.00% perf perf [.] run_command
  480. * |
  481. * --- run_command
  482. * main
  483. *
  484. * 30.00% 10.00% bash bash [.] main
  485. * |
  486. * --- main
  487. *
  488. * 30.00% 10.00% perf perf [.] cmd_record
  489. * |
  490. * --- cmd_record
  491. * run_command
  492. * main
  493. *
  494. * 20.00% 0.00% bash libc [.] malloc
  495. * |
  496. * --- malloc
  497. * |
  498. * |--50.00%-- xmalloc
  499. * | main
  500. * --50.00%-- main
  501. *
  502. * 10.00% 10.00% bash [kernel] [k] page_fault
  503. * |
  504. * --- page_fault
  505. * malloc
  506. * main
  507. *
  508. * 10.00% 10.00% bash bash [.] xmalloc
  509. * |
  510. * --- xmalloc
  511. * malloc
  512. * xmalloc <--- NOTE: there's a cycle
  513. * malloc
  514. * xmalloc
  515. * main
  516. *
  517. * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
  518. * |
  519. * --- sys_perf_event_open
  520. * run_command
  521. * main
  522. *
  523. * 10.00% 10.00% perf [kernel] [k] page_fault
  524. * |
  525. * --- page_fault
  526. * sys_perf_event_open
  527. * run_command
  528. * main
  529. *
  530. * 10.00% 10.00% perf [kernel] [k] schedule
  531. * |
  532. * --- schedule
  533. * run_command
  534. * main
  535. *
  536. * 10.00% 10.00% perf libc [.] free
  537. * |
  538. * --- free
  539. * cmd_record
  540. * run_command
  541. * main
  542. *
  543. * 10.00% 10.00% perf libc [.] malloc
  544. * |
  545. * --- malloc
  546. * cmd_record
  547. * run_command
  548. * main
  549. *
  550. */
  551. struct result expected[] = {
  552. { 7000, 2000, "perf", "perf", "main" },
  553. { 5000, 0, "perf", "perf", "run_command" },
  554. { 3000, 1000, "bash", "bash", "main" },
  555. { 3000, 1000, "perf", "perf", "cmd_record" },
  556. { 2000, 0, "bash", "libc", "malloc" },
  557. { 1000, 1000, "bash", "[kernel]", "page_fault" },
  558. { 1000, 1000, "bash", "bash", "xmalloc" },
  559. { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
  560. { 1000, 1000, "perf", "[kernel]", "page_fault" },
  561. { 1000, 1000, "perf", "[kernel]", "schedule" },
  562. { 1000, 1000, "perf", "libc", "free" },
  563. { 1000, 1000, "perf", "libc", "malloc" },
  564. };
  565. struct callchain_result expected_callchain[] = {
  566. {
  567. 1, { { "perf", "main" }, },
  568. },
  569. {
  570. 2, { { "perf", "run_command" },
  571. { "perf", "main" }, },
  572. },
  573. {
  574. 1, { { "bash", "main" }, },
  575. },
  576. {
  577. 3, { { "perf", "cmd_record" },
  578. { "perf", "run_command" },
  579. { "perf", "main" }, },
  580. },
  581. {
  582. 4, { { "libc", "malloc" },
  583. { "bash", "xmalloc" },
  584. { "bash", "main" },
  585. { "bash", "main" }, },
  586. },
  587. {
  588. 3, { { "[kernel]", "page_fault" },
  589. { "libc", "malloc" },
  590. { "bash", "main" }, },
  591. },
  592. {
  593. 6, { { "bash", "xmalloc" },
  594. { "libc", "malloc" },
  595. { "bash", "xmalloc" },
  596. { "libc", "malloc" },
  597. { "bash", "xmalloc" },
  598. { "bash", "main" }, },
  599. },
  600. {
  601. 3, { { "[kernel]", "sys_perf_event_open" },
  602. { "perf", "run_command" },
  603. { "perf", "main" }, },
  604. },
  605. {
  606. 4, { { "[kernel]", "page_fault" },
  607. { "[kernel]", "sys_perf_event_open" },
  608. { "perf", "run_command" },
  609. { "perf", "main" }, },
  610. },
  611. {
  612. 3, { { "[kernel]", "schedule" },
  613. { "perf", "run_command" },
  614. { "perf", "main" }, },
  615. },
  616. {
  617. 4, { { "libc", "free" },
  618. { "perf", "cmd_record" },
  619. { "perf", "run_command" },
  620. { "perf", "main" }, },
  621. },
  622. {
  623. 4, { { "libc", "malloc" },
  624. { "perf", "cmd_record" },
  625. { "perf", "run_command" },
  626. { "perf", "main" }, },
  627. },
  628. };
  629. symbol_conf.use_callchain = true;
  630. symbol_conf.cumulate_callchain = true;
  631. evsel__set_sample_bit(evsel, CALLCHAIN);
  632. setup_sorting(/*evlist=*/NULL, machine->env);
  633. callchain_param = callchain_param_default;
  634. callchain_register_param(&callchain_param);
  635. err = add_hist_entries(hists, machine);
  636. if (err < 0)
  637. goto out;
  638. err = do_test(hists, expected, ARRAY_SIZE(expected),
  639. expected_callchain, ARRAY_SIZE(expected_callchain));
  640. out:
  641. del_hist_entries(hists);
  642. reset_output_field();
  643. return err;
  644. }
  645. static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
  646. {
  647. int err = TEST_FAIL;
  648. struct machines machines;
  649. struct machine *machine;
  650. struct evsel *evsel;
  651. struct evlist *evlist = evlist__new();
  652. size_t i;
  653. test_fn_t testcases[] = {
  654. test1,
  655. test2,
  656. test3,
  657. test4,
  658. };
  659. TEST_ASSERT_VAL("No memory", evlist);
  660. err = parse_event(evlist, "cpu-clock");
  661. if (err)
  662. goto out;
  663. err = TEST_FAIL;
  664. machines__init(&machines);
  665. /* setup threads/dso/map/symbols also */
  666. machine = setup_fake_machine(&machines);
  667. if (!machine)
  668. goto out;
  669. if (verbose > 1)
  670. machine__fprintf(machine, stderr);
  671. evsel = evlist__first(evlist);
  672. for (i = 0; i < ARRAY_SIZE(testcases); i++) {
  673. err = testcases[i](evsel, machine);
  674. if (err < 0)
  675. break;
  676. }
  677. out:
  678. /* tear down everything */
  679. evlist__delete(evlist);
  680. machines__exit(&machines);
  681. put_fake_samples();
  682. return err;
  683. }
  684. DEFINE_SUITE("Cumulate child hist entries", hists_cumulate);