1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 20506aeccSNamhyung Kim #include "perf.h" 30506aeccSNamhyung Kim #include "util/debug.h" 45ab8c689SArnaldo Carvalho de Melo #include "util/event.h" 50506aeccSNamhyung Kim #include "util/symbol.h" 60506aeccSNamhyung Kim #include "util/sort.h" 70506aeccSNamhyung Kim #include "util/evsel.h" 80506aeccSNamhyung Kim #include "util/evlist.h" 90506aeccSNamhyung Kim #include "util/machine.h" 100506aeccSNamhyung Kim #include "util/thread.h" 110506aeccSNamhyung Kim #include "util/parse-events.h" 120506aeccSNamhyung Kim #include "tests/tests.h" 130506aeccSNamhyung Kim #include "tests/hists_common.h" 14877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 150506aeccSNamhyung Kim 160506aeccSNamhyung Kim struct sample { 170506aeccSNamhyung Kim u32 pid; 180506aeccSNamhyung Kim u64 ip; 190506aeccSNamhyung Kim struct thread *thread; 200506aeccSNamhyung Kim struct map *map; 210506aeccSNamhyung Kim struct symbol *sym; 220506aeccSNamhyung Kim }; 230506aeccSNamhyung Kim 240506aeccSNamhyung Kim /* For the numbers, see hists_common.c */ 250506aeccSNamhyung Kim static struct sample fake_samples[] = { 260506aeccSNamhyung Kim /* perf [kernel] schedule() */ 270506aeccSNamhyung Kim { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, }, 280506aeccSNamhyung Kim /* perf [perf] main() */ 290506aeccSNamhyung Kim { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, }, 300506aeccSNamhyung Kim /* perf [perf] cmd_record() */ 310506aeccSNamhyung Kim { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, }, 320506aeccSNamhyung Kim /* perf [libc] malloc() */ 330506aeccSNamhyung Kim { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, }, 340506aeccSNamhyung Kim /* perf [libc] free() */ 350506aeccSNamhyung Kim { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, }, 360506aeccSNamhyung Kim /* perf [perf] main() */ 370506aeccSNamhyung Kim { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, 380506aeccSNamhyung Kim /* perf [kernel] page_fault() */ 390506aeccSNamhyung Kim { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 400506aeccSNamhyung Kim /* bash [bash] main() */ 410506aeccSNamhyung Kim { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, }, 420506aeccSNamhyung Kim /* bash [bash] xmalloc() */ 430506aeccSNamhyung Kim { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, }, 440506aeccSNamhyung Kim /* bash [kernel] page_fault() */ 450506aeccSNamhyung Kim { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, 460506aeccSNamhyung Kim }; 470506aeccSNamhyung Kim 480506aeccSNamhyung Kim /* 490506aeccSNamhyung Kim * Will be casted to struct ip_callchain which has all 64 bit entries 500506aeccSNamhyung Kim * of nr and ips[]. 510506aeccSNamhyung Kim */ 520506aeccSNamhyung Kim static u64 fake_callchains[][10] = { 530506aeccSNamhyung Kim /* schedule => run_command => main */ 540506aeccSNamhyung Kim { 3, FAKE_IP_KERNEL_SCHEDULE, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, }, 550506aeccSNamhyung Kim /* main */ 560506aeccSNamhyung Kim { 1, FAKE_IP_PERF_MAIN, }, 570506aeccSNamhyung Kim /* cmd_record => run_command => main */ 580506aeccSNamhyung Kim { 3, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, }, 590506aeccSNamhyung Kim /* malloc => cmd_record => run_command => main */ 600506aeccSNamhyung Kim { 4, FAKE_IP_LIBC_MALLOC, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, 610506aeccSNamhyung Kim FAKE_IP_PERF_MAIN, }, 620506aeccSNamhyung Kim /* free => cmd_record => run_command => main */ 630506aeccSNamhyung Kim { 4, FAKE_IP_LIBC_FREE, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, 640506aeccSNamhyung Kim FAKE_IP_PERF_MAIN, }, 650506aeccSNamhyung Kim /* main */ 660506aeccSNamhyung Kim { 1, FAKE_IP_PERF_MAIN, }, 670506aeccSNamhyung Kim /* page_fault => sys_perf_event_open => run_command => main */ 680506aeccSNamhyung Kim { 4, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_KERNEL_SYS_PERF_EVENT_OPEN, 690506aeccSNamhyung Kim FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, }, 700506aeccSNamhyung Kim /* main */ 710506aeccSNamhyung Kim { 1, FAKE_IP_BASH_MAIN, }, 720506aeccSNamhyung Kim /* xmalloc => malloc => xmalloc => malloc => xmalloc => main */ 730506aeccSNamhyung Kim { 6, FAKE_IP_BASH_XMALLOC, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, 740506aeccSNamhyung Kim FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, FAKE_IP_BASH_MAIN, }, 750506aeccSNamhyung Kim /* page_fault => malloc => main */ 760506aeccSNamhyung Kim { 3, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_MAIN, }, 770506aeccSNamhyung Kim }; 780506aeccSNamhyung Kim 790506aeccSNamhyung Kim static int add_hist_entries(struct hists *hists, struct machine *machine) 800506aeccSNamhyung Kim { 810506aeccSNamhyung Kim struct addr_location al; 820506aeccSNamhyung Kim struct perf_evsel *evsel = hists_to_evsel(hists); 830506aeccSNamhyung Kim struct perf_sample sample = { .period = 1000, }; 840506aeccSNamhyung Kim size_t i; 850506aeccSNamhyung Kim 860506aeccSNamhyung Kim for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { 870506aeccSNamhyung Kim struct hist_entry_iter iter = { 88063bd936SNamhyung Kim .evsel = evsel, 89063bd936SNamhyung Kim .sample = &sample, 900506aeccSNamhyung Kim .hide_unresolved = false, 910506aeccSNamhyung Kim }; 920506aeccSNamhyung Kim 930506aeccSNamhyung Kim if (symbol_conf.cumulate_callchain) 940506aeccSNamhyung Kim iter.ops = &hist_iter_cumulative; 950506aeccSNamhyung Kim else 960506aeccSNamhyung Kim iter.ops = &hist_iter_normal; 970506aeccSNamhyung Kim 98473398a2SArnaldo Carvalho de Melo sample.cpumode = PERF_RECORD_MISC_USER; 990506aeccSNamhyung Kim sample.pid = fake_samples[i].pid; 1000506aeccSNamhyung Kim sample.tid = fake_samples[i].pid; 1010506aeccSNamhyung Kim sample.ip = fake_samples[i].ip; 1020506aeccSNamhyung Kim sample.callchain = (struct ip_callchain *)fake_callchains[i]; 1030506aeccSNamhyung Kim 104bb3eb566SArnaldo Carvalho de Melo if (machine__resolve(machine, &al, &sample) < 0) 1050506aeccSNamhyung Kim goto out; 1060506aeccSNamhyung Kim 1074cb93446SArnaldo Carvalho de Melo if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack, 108063bd936SNamhyung Kim NULL) < 0) { 109b91fc39fSArnaldo Carvalho de Melo addr_location__put(&al); 1100506aeccSNamhyung Kim goto out; 111b91fc39fSArnaldo Carvalho de Melo } 1120506aeccSNamhyung Kim 1130506aeccSNamhyung Kim fake_samples[i].thread = al.thread; 1140506aeccSNamhyung Kim fake_samples[i].map = al.map; 1150506aeccSNamhyung Kim fake_samples[i].sym = al.sym; 1160506aeccSNamhyung Kim } 1170506aeccSNamhyung Kim 1180506aeccSNamhyung Kim return TEST_OK; 1190506aeccSNamhyung Kim 1200506aeccSNamhyung Kim out: 1210506aeccSNamhyung Kim pr_debug("Not enough memory for adding a hist entry\n"); 1220506aeccSNamhyung Kim return TEST_FAIL; 1230506aeccSNamhyung Kim } 1240506aeccSNamhyung Kim 1250506aeccSNamhyung Kim static void del_hist_entries(struct hists *hists) 1260506aeccSNamhyung Kim { 1270506aeccSNamhyung Kim struct hist_entry *he; 128*2eb3d689SDavidlohr Bueso struct rb_root_cached *root_in; 129*2eb3d689SDavidlohr Bueso struct rb_root_cached *root_out; 1300506aeccSNamhyung Kim struct rb_node *node; 1310506aeccSNamhyung Kim 13252225036SJiri Olsa if (hists__has(hists, need_collapse)) 1330506aeccSNamhyung Kim root_in = &hists->entries_collapsed; 1340506aeccSNamhyung Kim else 1350506aeccSNamhyung Kim root_in = hists->entries_in; 1360506aeccSNamhyung Kim 1370506aeccSNamhyung Kim root_out = &hists->entries; 1380506aeccSNamhyung Kim 139*2eb3d689SDavidlohr Bueso while (!RB_EMPTY_ROOT(&root_out->rb_root)) { 140*2eb3d689SDavidlohr Bueso node = rb_first_cached(root_out); 1410506aeccSNamhyung Kim 1420506aeccSNamhyung Kim he = rb_entry(node, struct hist_entry, rb_node); 143*2eb3d689SDavidlohr Bueso rb_erase_cached(node, root_out); 144*2eb3d689SDavidlohr Bueso rb_erase_cached(&he->rb_node_in, root_in); 1456733d1bfSArnaldo Carvalho de Melo hist_entry__delete(he); 1460506aeccSNamhyung Kim } 1470506aeccSNamhyung Kim } 1480506aeccSNamhyung Kim 1490506aeccSNamhyung Kim typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); 1500506aeccSNamhyung Kim 1510506aeccSNamhyung Kim #define COMM(he) (thread__comm_str(he->thread)) 1520506aeccSNamhyung Kim #define DSO(he) (he->ms.map->dso->short_name) 1530506aeccSNamhyung Kim #define SYM(he) (he->ms.sym->name) 1540506aeccSNamhyung Kim #define CPU(he) (he->cpu) 1550506aeccSNamhyung Kim #define PID(he) (he->thread->tid) 1560506aeccSNamhyung Kim #define DEPTH(he) (he->callchain->max_depth) 1570506aeccSNamhyung Kim #define CDSO(cl) (cl->ms.map->dso->short_name) 1580506aeccSNamhyung Kim #define CSYM(cl) (cl->ms.sym->name) 1590506aeccSNamhyung Kim 1600506aeccSNamhyung Kim struct result { 1610506aeccSNamhyung Kim u64 children; 1620506aeccSNamhyung Kim u64 self; 1630506aeccSNamhyung Kim const char *comm; 1640506aeccSNamhyung Kim const char *dso; 1650506aeccSNamhyung Kim const char *sym; 1660506aeccSNamhyung Kim }; 1670506aeccSNamhyung Kim 1680506aeccSNamhyung Kim struct callchain_result { 1690506aeccSNamhyung Kim u64 nr; 1700506aeccSNamhyung Kim struct { 1710506aeccSNamhyung Kim const char *dso; 1720506aeccSNamhyung Kim const char *sym; 1730506aeccSNamhyung Kim } node[10]; 1740506aeccSNamhyung Kim }; 1750506aeccSNamhyung Kim 1760506aeccSNamhyung Kim static int do_test(struct hists *hists, struct result *expected, size_t nr_expected, 1770506aeccSNamhyung Kim struct callchain_result *expected_callchain, size_t nr_callchain) 1780506aeccSNamhyung Kim { 1790506aeccSNamhyung Kim char buf[32]; 1800506aeccSNamhyung Kim size_t i, c; 1810506aeccSNamhyung Kim struct hist_entry *he; 1820506aeccSNamhyung Kim struct rb_root *root; 1830506aeccSNamhyung Kim struct rb_node *node; 1840506aeccSNamhyung Kim struct callchain_node *cnode; 1850506aeccSNamhyung Kim struct callchain_list *clist; 1860506aeccSNamhyung Kim 1870506aeccSNamhyung Kim /* 1880506aeccSNamhyung Kim * adding and deleting hist entries must be done outside of this 1890506aeccSNamhyung Kim * function since TEST_ASSERT_VAL() returns in case of failure. 1900506aeccSNamhyung Kim */ 1910506aeccSNamhyung Kim hists__collapse_resort(hists, NULL); 192452ce03bSJiri Olsa perf_evsel__output_resort(hists_to_evsel(hists), NULL); 1930506aeccSNamhyung Kim 1940506aeccSNamhyung Kim if (verbose > 2) { 1950506aeccSNamhyung Kim pr_info("use callchain: %d, cumulate callchain: %d\n", 1960506aeccSNamhyung Kim symbol_conf.use_callchain, 1970506aeccSNamhyung Kim symbol_conf.cumulate_callchain); 1980506aeccSNamhyung Kim print_hists_out(hists); 1990506aeccSNamhyung Kim } 2000506aeccSNamhyung Kim 201*2eb3d689SDavidlohr Bueso root = &hists->entries.rb_root; 2020506aeccSNamhyung Kim for (node = rb_first(root), i = 0; 2030506aeccSNamhyung Kim node && (he = rb_entry(node, struct hist_entry, rb_node)); 2040506aeccSNamhyung Kim node = rb_next(node), i++) { 2050506aeccSNamhyung Kim scnprintf(buf, sizeof(buf), "Invalid hist entry #%zd", i); 2060506aeccSNamhyung Kim 2070506aeccSNamhyung Kim TEST_ASSERT_VAL("Incorrect number of hist entry", 2080506aeccSNamhyung Kim i < nr_expected); 2090506aeccSNamhyung Kim TEST_ASSERT_VAL(buf, he->stat.period == expected[i].self && 2100506aeccSNamhyung Kim !strcmp(COMM(he), expected[i].comm) && 2110506aeccSNamhyung Kim !strcmp(DSO(he), expected[i].dso) && 2120506aeccSNamhyung Kim !strcmp(SYM(he), expected[i].sym)); 2130506aeccSNamhyung Kim 2140506aeccSNamhyung Kim if (symbol_conf.cumulate_callchain) 2150506aeccSNamhyung Kim TEST_ASSERT_VAL(buf, he->stat_acc->period == expected[i].children); 2160506aeccSNamhyung Kim 2170506aeccSNamhyung Kim if (!symbol_conf.use_callchain) 2180506aeccSNamhyung Kim continue; 2190506aeccSNamhyung Kim 2200506aeccSNamhyung Kim /* check callchain entries */ 2210506aeccSNamhyung Kim root = &he->callchain->node.rb_root; 222347ca878SJiri Olsa 223347ca878SJiri Olsa TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root)); 2240506aeccSNamhyung Kim cnode = rb_entry(rb_first(root), struct callchain_node, rb_node); 2250506aeccSNamhyung Kim 2260506aeccSNamhyung Kim c = 0; 2270506aeccSNamhyung Kim list_for_each_entry(clist, &cnode->val, list) { 2280506aeccSNamhyung Kim scnprintf(buf, sizeof(buf), "Invalid callchain entry #%zd/%zd", i, c); 2290506aeccSNamhyung Kim 2300506aeccSNamhyung Kim TEST_ASSERT_VAL("Incorrect number of callchain entry", 2310506aeccSNamhyung Kim c < expected_callchain[i].nr); 2320506aeccSNamhyung Kim TEST_ASSERT_VAL(buf, 2330506aeccSNamhyung Kim !strcmp(CDSO(clist), expected_callchain[i].node[c].dso) && 2340506aeccSNamhyung Kim !strcmp(CSYM(clist), expected_callchain[i].node[c].sym)); 2350506aeccSNamhyung Kim c++; 2360506aeccSNamhyung Kim } 2370506aeccSNamhyung Kim /* TODO: handle multiple child nodes properly */ 2380506aeccSNamhyung Kim TEST_ASSERT_VAL("Incorrect number of callchain entry", 2390506aeccSNamhyung Kim c <= expected_callchain[i].nr); 2400506aeccSNamhyung Kim } 2410506aeccSNamhyung Kim TEST_ASSERT_VAL("Incorrect number of hist entry", 2420506aeccSNamhyung Kim i == nr_expected); 2430506aeccSNamhyung Kim TEST_ASSERT_VAL("Incorrect number of callchain entry", 2440506aeccSNamhyung Kim !symbol_conf.use_callchain || nr_expected == nr_callchain); 2450506aeccSNamhyung Kim return 0; 2460506aeccSNamhyung Kim } 2470506aeccSNamhyung Kim 2480506aeccSNamhyung Kim /* NO callchain + NO children */ 2490506aeccSNamhyung Kim static int test1(struct perf_evsel *evsel, struct machine *machine) 2500506aeccSNamhyung Kim { 2510506aeccSNamhyung Kim int err; 2524ea062edSArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 2530506aeccSNamhyung Kim /* 2540506aeccSNamhyung Kim * expected output: 2550506aeccSNamhyung Kim * 2560506aeccSNamhyung Kim * Overhead Command Shared Object Symbol 2570506aeccSNamhyung Kim * ======== ======= ============= ============== 2580506aeccSNamhyung Kim * 20.00% perf perf [.] main 2590506aeccSNamhyung Kim * 10.00% bash [kernel] [k] page_fault 2600506aeccSNamhyung Kim * 10.00% bash bash [.] main 2610506aeccSNamhyung Kim * 10.00% bash bash [.] xmalloc 2620506aeccSNamhyung Kim * 10.00% perf [kernel] [k] page_fault 2630506aeccSNamhyung Kim * 10.00% perf [kernel] [k] schedule 2640506aeccSNamhyung Kim * 10.00% perf libc [.] free 2650506aeccSNamhyung Kim * 10.00% perf libc [.] malloc 2660506aeccSNamhyung Kim * 10.00% perf perf [.] cmd_record 2670506aeccSNamhyung Kim */ 2680506aeccSNamhyung Kim struct result expected[] = { 2690506aeccSNamhyung Kim { 0, 2000, "perf", "perf", "main" }, 2700506aeccSNamhyung Kim { 0, 1000, "bash", "[kernel]", "page_fault" }, 2710506aeccSNamhyung Kim { 0, 1000, "bash", "bash", "main" }, 2720506aeccSNamhyung Kim { 0, 1000, "bash", "bash", "xmalloc" }, 2730506aeccSNamhyung Kim { 0, 1000, "perf", "[kernel]", "page_fault" }, 2740506aeccSNamhyung Kim { 0, 1000, "perf", "[kernel]", "schedule" }, 2750506aeccSNamhyung Kim { 0, 1000, "perf", "libc", "free" }, 2760506aeccSNamhyung Kim { 0, 1000, "perf", "libc", "malloc" }, 2770506aeccSNamhyung Kim { 0, 1000, "perf", "perf", "cmd_record" }, 2780506aeccSNamhyung Kim }; 2790506aeccSNamhyung Kim 2800506aeccSNamhyung Kim symbol_conf.use_callchain = false; 2810506aeccSNamhyung Kim symbol_conf.cumulate_callchain = false; 282f9db0d0fSKan Liang perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 2830506aeccSNamhyung Kim 28440184c46SNamhyung Kim setup_sorting(NULL); 2850506aeccSNamhyung Kim callchain_register_param(&callchain_param); 2860506aeccSNamhyung Kim 2870506aeccSNamhyung Kim err = add_hist_entries(hists, machine); 2880506aeccSNamhyung Kim if (err < 0) 2890506aeccSNamhyung Kim goto out; 2900506aeccSNamhyung Kim 2910506aeccSNamhyung Kim err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0); 2920506aeccSNamhyung Kim 2930506aeccSNamhyung Kim out: 2940506aeccSNamhyung Kim del_hist_entries(hists); 2950506aeccSNamhyung Kim reset_output_field(); 2960506aeccSNamhyung Kim return err; 2970506aeccSNamhyung Kim } 2980506aeccSNamhyung Kim 2990506aeccSNamhyung Kim /* callcain + NO children */ 3000506aeccSNamhyung Kim static int test2(struct perf_evsel *evsel, struct machine *machine) 3010506aeccSNamhyung Kim { 3020506aeccSNamhyung Kim int err; 3034ea062edSArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 3040506aeccSNamhyung Kim /* 3050506aeccSNamhyung Kim * expected output: 3060506aeccSNamhyung Kim * 3070506aeccSNamhyung Kim * Overhead Command Shared Object Symbol 3080506aeccSNamhyung Kim * ======== ======= ============= ============== 3090506aeccSNamhyung Kim * 20.00% perf perf [.] main 3100506aeccSNamhyung Kim * | 3110506aeccSNamhyung Kim * --- main 3120506aeccSNamhyung Kim * 3130506aeccSNamhyung Kim * 10.00% bash [kernel] [k] page_fault 3140506aeccSNamhyung Kim * | 3150506aeccSNamhyung Kim * --- page_fault 3160506aeccSNamhyung Kim * malloc 3170506aeccSNamhyung Kim * main 3180506aeccSNamhyung Kim * 3190506aeccSNamhyung Kim * 10.00% bash bash [.] main 3200506aeccSNamhyung Kim * | 3210506aeccSNamhyung Kim * --- main 3220506aeccSNamhyung Kim * 3230506aeccSNamhyung Kim * 10.00% bash bash [.] xmalloc 3240506aeccSNamhyung Kim * | 3250506aeccSNamhyung Kim * --- xmalloc 3260506aeccSNamhyung Kim * malloc 3270506aeccSNamhyung Kim * xmalloc <--- NOTE: there's a cycle 3280506aeccSNamhyung Kim * malloc 3290506aeccSNamhyung Kim * xmalloc 3300506aeccSNamhyung Kim * main 3310506aeccSNamhyung Kim * 3320506aeccSNamhyung Kim * 10.00% perf [kernel] [k] page_fault 3330506aeccSNamhyung Kim * | 3340506aeccSNamhyung Kim * --- page_fault 3350506aeccSNamhyung Kim * sys_perf_event_open 3360506aeccSNamhyung Kim * run_command 3370506aeccSNamhyung Kim * main 3380506aeccSNamhyung Kim * 3390506aeccSNamhyung Kim * 10.00% perf [kernel] [k] schedule 3400506aeccSNamhyung Kim * | 3410506aeccSNamhyung Kim * --- schedule 3420506aeccSNamhyung Kim * run_command 3430506aeccSNamhyung Kim * main 3440506aeccSNamhyung Kim * 3450506aeccSNamhyung Kim * 10.00% perf libc [.] free 3460506aeccSNamhyung Kim * | 3470506aeccSNamhyung Kim * --- free 3480506aeccSNamhyung Kim * cmd_record 3490506aeccSNamhyung Kim * run_command 3500506aeccSNamhyung Kim * main 3510506aeccSNamhyung Kim * 3520506aeccSNamhyung Kim * 10.00% perf libc [.] malloc 3530506aeccSNamhyung Kim * | 3540506aeccSNamhyung Kim * --- malloc 3550506aeccSNamhyung Kim * cmd_record 3560506aeccSNamhyung Kim * run_command 3570506aeccSNamhyung Kim * main 3580506aeccSNamhyung Kim * 3590506aeccSNamhyung Kim * 10.00% perf perf [.] cmd_record 3600506aeccSNamhyung Kim * | 3610506aeccSNamhyung Kim * --- cmd_record 3620506aeccSNamhyung Kim * run_command 3630506aeccSNamhyung Kim * main 3640506aeccSNamhyung Kim * 3650506aeccSNamhyung Kim */ 3660506aeccSNamhyung Kim struct result expected[] = { 3670506aeccSNamhyung Kim { 0, 2000, "perf", "perf", "main" }, 3680506aeccSNamhyung Kim { 0, 1000, "bash", "[kernel]", "page_fault" }, 3690506aeccSNamhyung Kim { 0, 1000, "bash", "bash", "main" }, 3700506aeccSNamhyung Kim { 0, 1000, "bash", "bash", "xmalloc" }, 3710506aeccSNamhyung Kim { 0, 1000, "perf", "[kernel]", "page_fault" }, 3720506aeccSNamhyung Kim { 0, 1000, "perf", "[kernel]", "schedule" }, 3730506aeccSNamhyung Kim { 0, 1000, "perf", "libc", "free" }, 3740506aeccSNamhyung Kim { 0, 1000, "perf", "libc", "malloc" }, 3750506aeccSNamhyung Kim { 0, 1000, "perf", "perf", "cmd_record" }, 3760506aeccSNamhyung Kim }; 3770506aeccSNamhyung Kim struct callchain_result expected_callchain[] = { 3780506aeccSNamhyung Kim { 3790506aeccSNamhyung Kim 1, { { "perf", "main" }, }, 3800506aeccSNamhyung Kim }, 3810506aeccSNamhyung Kim { 3820506aeccSNamhyung Kim 3, { { "[kernel]", "page_fault" }, 3830506aeccSNamhyung Kim { "libc", "malloc" }, 3840506aeccSNamhyung Kim { "bash", "main" }, }, 3850506aeccSNamhyung Kim }, 3860506aeccSNamhyung Kim { 3870506aeccSNamhyung Kim 1, { { "bash", "main" }, }, 3880506aeccSNamhyung Kim }, 3890506aeccSNamhyung Kim { 3900506aeccSNamhyung Kim 6, { { "bash", "xmalloc" }, 3910506aeccSNamhyung Kim { "libc", "malloc" }, 3920506aeccSNamhyung Kim { "bash", "xmalloc" }, 3930506aeccSNamhyung Kim { "libc", "malloc" }, 3940506aeccSNamhyung Kim { "bash", "xmalloc" }, 3950506aeccSNamhyung Kim { "bash", "main" }, }, 3960506aeccSNamhyung Kim }, 3970506aeccSNamhyung Kim { 3980506aeccSNamhyung Kim 4, { { "[kernel]", "page_fault" }, 3990506aeccSNamhyung Kim { "[kernel]", "sys_perf_event_open" }, 4000506aeccSNamhyung Kim { "perf", "run_command" }, 4010506aeccSNamhyung Kim { "perf", "main" }, }, 4020506aeccSNamhyung Kim }, 4030506aeccSNamhyung Kim { 4040506aeccSNamhyung Kim 3, { { "[kernel]", "schedule" }, 4050506aeccSNamhyung Kim { "perf", "run_command" }, 4060506aeccSNamhyung Kim { "perf", "main" }, }, 4070506aeccSNamhyung Kim }, 4080506aeccSNamhyung Kim { 4090506aeccSNamhyung Kim 4, { { "libc", "free" }, 4100506aeccSNamhyung Kim { "perf", "cmd_record" }, 4110506aeccSNamhyung Kim { "perf", "run_command" }, 4120506aeccSNamhyung Kim { "perf", "main" }, }, 4130506aeccSNamhyung Kim }, 4140506aeccSNamhyung Kim { 4150506aeccSNamhyung Kim 4, { { "libc", "malloc" }, 4160506aeccSNamhyung Kim { "perf", "cmd_record" }, 4170506aeccSNamhyung Kim { "perf", "run_command" }, 4180506aeccSNamhyung Kim { "perf", "main" }, }, 4190506aeccSNamhyung Kim }, 4200506aeccSNamhyung Kim { 4210506aeccSNamhyung Kim 3, { { "perf", "cmd_record" }, 4220506aeccSNamhyung Kim { "perf", "run_command" }, 4230506aeccSNamhyung Kim { "perf", "main" }, }, 4240506aeccSNamhyung Kim }, 4250506aeccSNamhyung Kim }; 4260506aeccSNamhyung Kim 4270506aeccSNamhyung Kim symbol_conf.use_callchain = true; 4280506aeccSNamhyung Kim symbol_conf.cumulate_callchain = false; 429f9db0d0fSKan Liang perf_evsel__set_sample_bit(evsel, CALLCHAIN); 4300506aeccSNamhyung Kim 43140184c46SNamhyung Kim setup_sorting(NULL); 4320506aeccSNamhyung Kim callchain_register_param(&callchain_param); 4330506aeccSNamhyung Kim 4340506aeccSNamhyung Kim err = add_hist_entries(hists, machine); 4350506aeccSNamhyung Kim if (err < 0) 4360506aeccSNamhyung Kim goto out; 4370506aeccSNamhyung Kim 4380506aeccSNamhyung Kim err = do_test(hists, expected, ARRAY_SIZE(expected), 4390506aeccSNamhyung Kim expected_callchain, ARRAY_SIZE(expected_callchain)); 4400506aeccSNamhyung Kim 4410506aeccSNamhyung Kim out: 4420506aeccSNamhyung Kim del_hist_entries(hists); 4430506aeccSNamhyung Kim reset_output_field(); 4440506aeccSNamhyung Kim return err; 4450506aeccSNamhyung Kim } 4460506aeccSNamhyung Kim 4470506aeccSNamhyung Kim /* NO callchain + children */ 4480506aeccSNamhyung Kim static int test3(struct perf_evsel *evsel, struct machine *machine) 4490506aeccSNamhyung Kim { 4500506aeccSNamhyung Kim int err; 4514ea062edSArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 4520506aeccSNamhyung Kim /* 4530506aeccSNamhyung Kim * expected output: 4540506aeccSNamhyung Kim * 4550506aeccSNamhyung Kim * Children Self Command Shared Object Symbol 4560506aeccSNamhyung Kim * ======== ======== ======= ============= ======================= 4570506aeccSNamhyung Kim * 70.00% 20.00% perf perf [.] main 4580506aeccSNamhyung Kim * 50.00% 0.00% perf perf [.] run_command 4590506aeccSNamhyung Kim * 30.00% 10.00% bash bash [.] main 4600506aeccSNamhyung Kim * 30.00% 10.00% perf perf [.] cmd_record 4610506aeccSNamhyung Kim * 20.00% 0.00% bash libc [.] malloc 4620506aeccSNamhyung Kim * 10.00% 10.00% bash [kernel] [k] page_fault 4630506aeccSNamhyung Kim * 10.00% 10.00% bash bash [.] xmalloc 4645ca82710SNamhyung Kim * 10.00% 10.00% perf [kernel] [k] page_fault 4655ca82710SNamhyung Kim * 10.00% 10.00% perf libc [.] malloc 4665ca82710SNamhyung Kim * 10.00% 10.00% perf [kernel] [k] schedule 4675ca82710SNamhyung Kim * 10.00% 10.00% perf libc [.] free 4685ca82710SNamhyung Kim * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open 4690506aeccSNamhyung Kim */ 4700506aeccSNamhyung Kim struct result expected[] = { 4710506aeccSNamhyung Kim { 7000, 2000, "perf", "perf", "main" }, 4720506aeccSNamhyung Kim { 5000, 0, "perf", "perf", "run_command" }, 4730506aeccSNamhyung Kim { 3000, 1000, "bash", "bash", "main" }, 4740506aeccSNamhyung Kim { 3000, 1000, "perf", "perf", "cmd_record" }, 4750506aeccSNamhyung Kim { 2000, 0, "bash", "libc", "malloc" }, 4760506aeccSNamhyung Kim { 1000, 1000, "bash", "[kernel]", "page_fault" }, 4775ca82710SNamhyung Kim { 1000, 1000, "bash", "bash", "xmalloc" }, 4780506aeccSNamhyung Kim { 1000, 1000, "perf", "[kernel]", "page_fault" }, 4795ca82710SNamhyung Kim { 1000, 1000, "perf", "[kernel]", "schedule" }, 4800506aeccSNamhyung Kim { 1000, 1000, "perf", "libc", "free" }, 4810506aeccSNamhyung Kim { 1000, 1000, "perf", "libc", "malloc" }, 4825ca82710SNamhyung Kim { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, 4830506aeccSNamhyung Kim }; 4840506aeccSNamhyung Kim 4850506aeccSNamhyung Kim symbol_conf.use_callchain = false; 4860506aeccSNamhyung Kim symbol_conf.cumulate_callchain = true; 487f9db0d0fSKan Liang perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 4880506aeccSNamhyung Kim 48940184c46SNamhyung Kim setup_sorting(NULL); 4900506aeccSNamhyung Kim callchain_register_param(&callchain_param); 4910506aeccSNamhyung Kim 4920506aeccSNamhyung Kim err = add_hist_entries(hists, machine); 4930506aeccSNamhyung Kim if (err < 0) 4940506aeccSNamhyung Kim goto out; 4950506aeccSNamhyung Kim 4960506aeccSNamhyung Kim err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0); 4970506aeccSNamhyung Kim 4980506aeccSNamhyung Kim out: 4990506aeccSNamhyung Kim del_hist_entries(hists); 5000506aeccSNamhyung Kim reset_output_field(); 5010506aeccSNamhyung Kim return err; 5020506aeccSNamhyung Kim } 5030506aeccSNamhyung Kim 5040506aeccSNamhyung Kim /* callchain + children */ 5050506aeccSNamhyung Kim static int test4(struct perf_evsel *evsel, struct machine *machine) 5060506aeccSNamhyung Kim { 5070506aeccSNamhyung Kim int err; 5084ea062edSArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 5090506aeccSNamhyung Kim /* 5100506aeccSNamhyung Kim * expected output: 5110506aeccSNamhyung Kim * 5120506aeccSNamhyung Kim * Children Self Command Shared Object Symbol 5130506aeccSNamhyung Kim * ======== ======== ======= ============= ======================= 5140506aeccSNamhyung Kim * 70.00% 20.00% perf perf [.] main 5150506aeccSNamhyung Kim * | 5160506aeccSNamhyung Kim * --- main 5170506aeccSNamhyung Kim * 5180506aeccSNamhyung Kim * 50.00% 0.00% perf perf [.] run_command 5190506aeccSNamhyung Kim * | 5200506aeccSNamhyung Kim * --- run_command 5210506aeccSNamhyung Kim * main 5220506aeccSNamhyung Kim * 5230506aeccSNamhyung Kim * 30.00% 10.00% bash bash [.] main 5240506aeccSNamhyung Kim * | 5250506aeccSNamhyung Kim * --- main 5260506aeccSNamhyung Kim * 5270506aeccSNamhyung Kim * 30.00% 10.00% perf perf [.] cmd_record 5280506aeccSNamhyung Kim * | 5290506aeccSNamhyung Kim * --- cmd_record 5300506aeccSNamhyung Kim * run_command 5310506aeccSNamhyung Kim * main 5320506aeccSNamhyung Kim * 5330506aeccSNamhyung Kim * 20.00% 0.00% bash libc [.] malloc 5340506aeccSNamhyung Kim * | 5350506aeccSNamhyung Kim * --- malloc 5360506aeccSNamhyung Kim * | 5370506aeccSNamhyung Kim * |--50.00%-- xmalloc 5380506aeccSNamhyung Kim * | main 5390506aeccSNamhyung Kim * --50.00%-- main 5400506aeccSNamhyung Kim * 5410506aeccSNamhyung Kim * 10.00% 10.00% bash [kernel] [k] page_fault 5420506aeccSNamhyung Kim * | 5430506aeccSNamhyung Kim * --- page_fault 5440506aeccSNamhyung Kim * malloc 5450506aeccSNamhyung Kim * main 5460506aeccSNamhyung Kim * 5475ca82710SNamhyung Kim * 10.00% 10.00% bash bash [.] xmalloc 5480506aeccSNamhyung Kim * | 5495ca82710SNamhyung Kim * --- xmalloc 5505ca82710SNamhyung Kim * malloc 5515ca82710SNamhyung Kim * xmalloc <--- NOTE: there's a cycle 5525ca82710SNamhyung Kim * malloc 5535ca82710SNamhyung Kim * xmalloc 5540506aeccSNamhyung Kim * main 5550506aeccSNamhyung Kim * 5560506aeccSNamhyung Kim * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open 5570506aeccSNamhyung Kim * | 5580506aeccSNamhyung Kim * --- sys_perf_event_open 5590506aeccSNamhyung Kim * run_command 5600506aeccSNamhyung Kim * main 5610506aeccSNamhyung Kim * 5620506aeccSNamhyung Kim * 10.00% 10.00% perf [kernel] [k] page_fault 5630506aeccSNamhyung Kim * | 5640506aeccSNamhyung Kim * --- page_fault 5650506aeccSNamhyung Kim * sys_perf_event_open 5660506aeccSNamhyung Kim * run_command 5670506aeccSNamhyung Kim * main 5680506aeccSNamhyung Kim * 5695ca82710SNamhyung Kim * 10.00% 10.00% perf [kernel] [k] schedule 5705ca82710SNamhyung Kim * | 5715ca82710SNamhyung Kim * --- schedule 5725ca82710SNamhyung Kim * run_command 5735ca82710SNamhyung Kim * main 5745ca82710SNamhyung Kim * 5750506aeccSNamhyung Kim * 10.00% 10.00% perf libc [.] free 5760506aeccSNamhyung Kim * | 5770506aeccSNamhyung Kim * --- free 5780506aeccSNamhyung Kim * cmd_record 5790506aeccSNamhyung Kim * run_command 5800506aeccSNamhyung Kim * main 5810506aeccSNamhyung Kim * 5820506aeccSNamhyung Kim * 10.00% 10.00% perf libc [.] malloc 5830506aeccSNamhyung Kim * | 5840506aeccSNamhyung Kim * --- malloc 5850506aeccSNamhyung Kim * cmd_record 5860506aeccSNamhyung Kim * run_command 5870506aeccSNamhyung Kim * main 5880506aeccSNamhyung Kim * 5890506aeccSNamhyung Kim */ 5900506aeccSNamhyung Kim struct result expected[] = { 5910506aeccSNamhyung Kim { 7000, 2000, "perf", "perf", "main" }, 5920506aeccSNamhyung Kim { 5000, 0, "perf", "perf", "run_command" }, 5930506aeccSNamhyung Kim { 3000, 1000, "bash", "bash", "main" }, 5940506aeccSNamhyung Kim { 3000, 1000, "perf", "perf", "cmd_record" }, 5950506aeccSNamhyung Kim { 2000, 0, "bash", "libc", "malloc" }, 5960506aeccSNamhyung Kim { 1000, 1000, "bash", "[kernel]", "page_fault" }, 5975ca82710SNamhyung Kim { 1000, 1000, "bash", "bash", "xmalloc" }, 5980506aeccSNamhyung Kim { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, 5990506aeccSNamhyung Kim { 1000, 1000, "perf", "[kernel]", "page_fault" }, 6005ca82710SNamhyung Kim { 1000, 1000, "perf", "[kernel]", "schedule" }, 6010506aeccSNamhyung Kim { 1000, 1000, "perf", "libc", "free" }, 6020506aeccSNamhyung Kim { 1000, 1000, "perf", "libc", "malloc" }, 6030506aeccSNamhyung Kim }; 6040506aeccSNamhyung Kim struct callchain_result expected_callchain[] = { 6050506aeccSNamhyung Kim { 6060506aeccSNamhyung Kim 1, { { "perf", "main" }, }, 6070506aeccSNamhyung Kim }, 6080506aeccSNamhyung Kim { 6090506aeccSNamhyung Kim 2, { { "perf", "run_command" }, 6100506aeccSNamhyung Kim { "perf", "main" }, }, 6110506aeccSNamhyung Kim }, 6120506aeccSNamhyung Kim { 6130506aeccSNamhyung Kim 1, { { "bash", "main" }, }, 6140506aeccSNamhyung Kim }, 6150506aeccSNamhyung Kim { 6160506aeccSNamhyung Kim 3, { { "perf", "cmd_record" }, 6170506aeccSNamhyung Kim { "perf", "run_command" }, 6180506aeccSNamhyung Kim { "perf", "main" }, }, 6190506aeccSNamhyung Kim }, 6200506aeccSNamhyung Kim { 6210506aeccSNamhyung Kim 4, { { "libc", "malloc" }, 6220506aeccSNamhyung Kim { "bash", "xmalloc" }, 6230506aeccSNamhyung Kim { "bash", "main" }, 6240506aeccSNamhyung Kim { "bash", "main" }, }, 6250506aeccSNamhyung Kim }, 6260506aeccSNamhyung Kim { 6270506aeccSNamhyung Kim 3, { { "[kernel]", "page_fault" }, 6280506aeccSNamhyung Kim { "libc", "malloc" }, 6290506aeccSNamhyung Kim { "bash", "main" }, }, 6300506aeccSNamhyung Kim }, 6310506aeccSNamhyung Kim { 6325ca82710SNamhyung Kim 6, { { "bash", "xmalloc" }, 6335ca82710SNamhyung Kim { "libc", "malloc" }, 6345ca82710SNamhyung Kim { "bash", "xmalloc" }, 6355ca82710SNamhyung Kim { "libc", "malloc" }, 6365ca82710SNamhyung Kim { "bash", "xmalloc" }, 6375ca82710SNamhyung Kim { "bash", "main" }, }, 6380506aeccSNamhyung Kim }, 6390506aeccSNamhyung Kim { 6400506aeccSNamhyung Kim 3, { { "[kernel]", "sys_perf_event_open" }, 6410506aeccSNamhyung Kim { "perf", "run_command" }, 6420506aeccSNamhyung Kim { "perf", "main" }, }, 6430506aeccSNamhyung Kim }, 6440506aeccSNamhyung Kim { 6450506aeccSNamhyung Kim 4, { { "[kernel]", "page_fault" }, 6460506aeccSNamhyung Kim { "[kernel]", "sys_perf_event_open" }, 6470506aeccSNamhyung Kim { "perf", "run_command" }, 6480506aeccSNamhyung Kim { "perf", "main" }, }, 6490506aeccSNamhyung Kim }, 6500506aeccSNamhyung Kim { 6515ca82710SNamhyung Kim 3, { { "[kernel]", "schedule" }, 6525ca82710SNamhyung Kim { "perf", "run_command" }, 6535ca82710SNamhyung Kim { "perf", "main" }, }, 6545ca82710SNamhyung Kim }, 6555ca82710SNamhyung Kim { 6560506aeccSNamhyung Kim 4, { { "libc", "free" }, 6570506aeccSNamhyung Kim { "perf", "cmd_record" }, 6580506aeccSNamhyung Kim { "perf", "run_command" }, 6590506aeccSNamhyung Kim { "perf", "main" }, }, 6600506aeccSNamhyung Kim }, 6610506aeccSNamhyung Kim { 6620506aeccSNamhyung Kim 4, { { "libc", "malloc" }, 6630506aeccSNamhyung Kim { "perf", "cmd_record" }, 6640506aeccSNamhyung Kim { "perf", "run_command" }, 6650506aeccSNamhyung Kim { "perf", "main" }, }, 6660506aeccSNamhyung Kim }, 6670506aeccSNamhyung Kim }; 6680506aeccSNamhyung Kim 6690506aeccSNamhyung Kim symbol_conf.use_callchain = true; 6700506aeccSNamhyung Kim symbol_conf.cumulate_callchain = true; 671f9db0d0fSKan Liang perf_evsel__set_sample_bit(evsel, CALLCHAIN); 6720506aeccSNamhyung Kim 67340184c46SNamhyung Kim setup_sorting(NULL); 674347ca878SJiri Olsa 675347ca878SJiri Olsa callchain_param = callchain_param_default; 6760506aeccSNamhyung Kim callchain_register_param(&callchain_param); 6770506aeccSNamhyung Kim 6780506aeccSNamhyung Kim err = add_hist_entries(hists, machine); 6790506aeccSNamhyung Kim if (err < 0) 6800506aeccSNamhyung Kim goto out; 6810506aeccSNamhyung Kim 6820506aeccSNamhyung Kim err = do_test(hists, expected, ARRAY_SIZE(expected), 6830506aeccSNamhyung Kim expected_callchain, ARRAY_SIZE(expected_callchain)); 6840506aeccSNamhyung Kim 6850506aeccSNamhyung Kim out: 6860506aeccSNamhyung Kim del_hist_entries(hists); 6870506aeccSNamhyung Kim reset_output_field(); 6880506aeccSNamhyung Kim return err; 6890506aeccSNamhyung Kim } 6900506aeccSNamhyung Kim 69181f17c90SArnaldo Carvalho de Melo int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_unused) 6920506aeccSNamhyung Kim { 6930506aeccSNamhyung Kim int err = TEST_FAIL; 6940506aeccSNamhyung Kim struct machines machines; 6950506aeccSNamhyung Kim struct machine *machine; 6960506aeccSNamhyung Kim struct perf_evsel *evsel; 6970506aeccSNamhyung Kim struct perf_evlist *evlist = perf_evlist__new(); 6980506aeccSNamhyung Kim size_t i; 6990506aeccSNamhyung Kim test_fn_t testcases[] = { 7000506aeccSNamhyung Kim test1, 7010506aeccSNamhyung Kim test2, 7020506aeccSNamhyung Kim test3, 7030506aeccSNamhyung Kim test4, 7040506aeccSNamhyung Kim }; 7050506aeccSNamhyung Kim 7060506aeccSNamhyung Kim TEST_ASSERT_VAL("No memory", evlist); 7070506aeccSNamhyung Kim 708b39b8393SJiri Olsa err = parse_events(evlist, "cpu-clock", NULL); 7090506aeccSNamhyung Kim if (err) 7100506aeccSNamhyung Kim goto out; 711b0500c16SWang Nan err = TEST_FAIL; 7120506aeccSNamhyung Kim 7130506aeccSNamhyung Kim machines__init(&machines); 7140506aeccSNamhyung Kim 7150506aeccSNamhyung Kim /* setup threads/dso/map/symbols also */ 7160506aeccSNamhyung Kim machine = setup_fake_machine(&machines); 7170506aeccSNamhyung Kim if (!machine) 7180506aeccSNamhyung Kim goto out; 7190506aeccSNamhyung Kim 7200506aeccSNamhyung Kim if (verbose > 1) 7210506aeccSNamhyung Kim machine__fprintf(machine, stderr); 7220506aeccSNamhyung Kim 7230506aeccSNamhyung Kim evsel = perf_evlist__first(evlist); 7240506aeccSNamhyung Kim 7250506aeccSNamhyung Kim for (i = 0; i < ARRAY_SIZE(testcases); i++) { 7260506aeccSNamhyung Kim err = testcases[i](evsel, machine); 7270506aeccSNamhyung Kim if (err < 0) 7280506aeccSNamhyung Kim break; 7290506aeccSNamhyung Kim } 7300506aeccSNamhyung Kim 7310506aeccSNamhyung Kim out: 7320506aeccSNamhyung Kim /* tear down everything */ 7330506aeccSNamhyung Kim perf_evlist__delete(evlist); 7340506aeccSNamhyung Kim machines__exit(&machines); 7350506aeccSNamhyung Kim 7360506aeccSNamhyung Kim return err; 7370506aeccSNamhyung Kim } 738