1f8ebb0cdSNamhyung Kim #include "perf.h" 2f8ebb0cdSNamhyung Kim #include "tests.h" 3f8ebb0cdSNamhyung Kim #include "debug.h" 4f8ebb0cdSNamhyung Kim #include "symbol.h" 5f8ebb0cdSNamhyung Kim #include "sort.h" 6f8ebb0cdSNamhyung Kim #include "evsel.h" 7f8ebb0cdSNamhyung Kim #include "evlist.h" 8f8ebb0cdSNamhyung Kim #include "machine.h" 9f8ebb0cdSNamhyung Kim #include "thread.h" 10f8ebb0cdSNamhyung Kim #include "parse-events.h" 11f8ebb0cdSNamhyung Kim 12f8ebb0cdSNamhyung Kim static struct { 13f8ebb0cdSNamhyung Kim u32 pid; 14f8ebb0cdSNamhyung Kim const char *comm; 15f8ebb0cdSNamhyung Kim } fake_threads[] = { 16f8ebb0cdSNamhyung Kim { 100, "perf" }, 17f8ebb0cdSNamhyung Kim { 200, "perf" }, 18f8ebb0cdSNamhyung Kim { 300, "bash" }, 19f8ebb0cdSNamhyung Kim }; 20f8ebb0cdSNamhyung Kim 21f8ebb0cdSNamhyung Kim static struct { 22f8ebb0cdSNamhyung Kim u32 pid; 23f8ebb0cdSNamhyung Kim u64 start; 24f8ebb0cdSNamhyung Kim const char *filename; 25f8ebb0cdSNamhyung Kim } fake_mmap_info[] = { 26f8ebb0cdSNamhyung Kim { 100, 0x40000, "perf" }, 27f8ebb0cdSNamhyung Kim { 100, 0x50000, "libc" }, 28f8ebb0cdSNamhyung Kim { 100, 0xf0000, "[kernel]" }, 29f8ebb0cdSNamhyung Kim { 200, 0x40000, "perf" }, 30f8ebb0cdSNamhyung Kim { 200, 0x50000, "libc" }, 31f8ebb0cdSNamhyung Kim { 200, 0xf0000, "[kernel]" }, 32f8ebb0cdSNamhyung Kim { 300, 0x40000, "bash" }, 33f8ebb0cdSNamhyung Kim { 300, 0x50000, "libc" }, 34f8ebb0cdSNamhyung Kim { 300, 0xf0000, "[kernel]" }, 35f8ebb0cdSNamhyung Kim }; 36f8ebb0cdSNamhyung Kim 37f8ebb0cdSNamhyung Kim struct fake_sym { 38f8ebb0cdSNamhyung Kim u64 start; 39f8ebb0cdSNamhyung Kim u64 length; 40f8ebb0cdSNamhyung Kim const char *name; 41f8ebb0cdSNamhyung Kim }; 42f8ebb0cdSNamhyung Kim 43f8ebb0cdSNamhyung Kim static struct fake_sym perf_syms[] = { 44f8ebb0cdSNamhyung Kim { 700, 100, "main" }, 45f8ebb0cdSNamhyung Kim { 800, 100, "run_command" }, 46f8ebb0cdSNamhyung Kim { 900, 100, "cmd_record" }, 47f8ebb0cdSNamhyung Kim }; 48f8ebb0cdSNamhyung Kim 49f8ebb0cdSNamhyung Kim static struct fake_sym bash_syms[] = { 50f8ebb0cdSNamhyung Kim { 700, 100, "main" }, 51f8ebb0cdSNamhyung Kim { 800, 100, "xmalloc" }, 52f8ebb0cdSNamhyung Kim { 900, 100, "xfree" }, 53f8ebb0cdSNamhyung Kim }; 54f8ebb0cdSNamhyung Kim 55f8ebb0cdSNamhyung Kim static struct fake_sym libc_syms[] = { 56f8ebb0cdSNamhyung Kim { 700, 100, "malloc" }, 57f8ebb0cdSNamhyung Kim { 800, 100, "free" }, 58f8ebb0cdSNamhyung Kim { 900, 100, "realloc" }, 59f8ebb0cdSNamhyung Kim }; 60f8ebb0cdSNamhyung Kim 61f8ebb0cdSNamhyung Kim static struct fake_sym kernel_syms[] = { 62f8ebb0cdSNamhyung Kim { 700, 100, "schedule" }, 63f8ebb0cdSNamhyung Kim { 800, 100, "page_fault" }, 64f8ebb0cdSNamhyung Kim { 900, 100, "sys_perf_event_open" }, 65f8ebb0cdSNamhyung Kim }; 66f8ebb0cdSNamhyung Kim 67f8ebb0cdSNamhyung Kim static struct { 68f8ebb0cdSNamhyung Kim const char *dso_name; 69f8ebb0cdSNamhyung Kim struct fake_sym *syms; 70f8ebb0cdSNamhyung Kim size_t nr_syms; 71f8ebb0cdSNamhyung Kim } fake_symbols[] = { 72f8ebb0cdSNamhyung Kim { "perf", perf_syms, ARRAY_SIZE(perf_syms) }, 73f8ebb0cdSNamhyung Kim { "bash", bash_syms, ARRAY_SIZE(bash_syms) }, 74f8ebb0cdSNamhyung Kim { "libc", libc_syms, ARRAY_SIZE(libc_syms) }, 75f8ebb0cdSNamhyung Kim { "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) }, 76f8ebb0cdSNamhyung Kim }; 77f8ebb0cdSNamhyung Kim 78876650e6SArnaldo Carvalho de Melo static struct machine *setup_fake_machine(struct machines *machines) 79f8ebb0cdSNamhyung Kim { 80876650e6SArnaldo Carvalho de Melo struct machine *machine = machines__find(machines, HOST_KERNEL_ID); 81f8ebb0cdSNamhyung Kim size_t i; 82f8ebb0cdSNamhyung Kim 83f8ebb0cdSNamhyung Kim if (machine == NULL) { 84f8ebb0cdSNamhyung Kim pr_debug("Not enough memory for machine setup\n"); 85f8ebb0cdSNamhyung Kim return NULL; 86f8ebb0cdSNamhyung Kim } 87f8ebb0cdSNamhyung Kim 88f8ebb0cdSNamhyung Kim for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { 89f8ebb0cdSNamhyung Kim struct thread *thread; 90f8ebb0cdSNamhyung Kim 91314add6bSAdrian Hunter thread = machine__findnew_thread(machine, fake_threads[i].pid, 92314add6bSAdrian Hunter fake_threads[i].pid); 93f8ebb0cdSNamhyung Kim if (thread == NULL) 94f8ebb0cdSNamhyung Kim goto out; 95f8ebb0cdSNamhyung Kim 96f8ebb0cdSNamhyung Kim thread__set_comm(thread, fake_threads[i].comm); 97f8ebb0cdSNamhyung Kim } 98f8ebb0cdSNamhyung Kim 99f8ebb0cdSNamhyung Kim for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { 100f8ebb0cdSNamhyung Kim union perf_event fake_mmap_event = { 101f8ebb0cdSNamhyung Kim .mmap = { 102f8ebb0cdSNamhyung Kim .header = { .misc = PERF_RECORD_MISC_USER, }, 103f8ebb0cdSNamhyung Kim .pid = fake_mmap_info[i].pid, 104f8ebb0cdSNamhyung Kim .start = fake_mmap_info[i].start, 105f8ebb0cdSNamhyung Kim .len = 0x1000ULL, 106f8ebb0cdSNamhyung Kim .pgoff = 0ULL, 107f8ebb0cdSNamhyung Kim }, 108f8ebb0cdSNamhyung Kim }; 109f8ebb0cdSNamhyung Kim 110f8ebb0cdSNamhyung Kim strcpy(fake_mmap_event.mmap.filename, 111f8ebb0cdSNamhyung Kim fake_mmap_info[i].filename); 112f8ebb0cdSNamhyung Kim 113f8ebb0cdSNamhyung Kim machine__process_mmap_event(machine, &fake_mmap_event); 114f8ebb0cdSNamhyung Kim } 115f8ebb0cdSNamhyung Kim 116f8ebb0cdSNamhyung Kim for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { 117f8ebb0cdSNamhyung Kim size_t k; 118f8ebb0cdSNamhyung Kim struct dso *dso; 119f8ebb0cdSNamhyung Kim 120f8ebb0cdSNamhyung Kim dso = __dsos__findnew(&machine->user_dsos, 121f8ebb0cdSNamhyung Kim fake_symbols[i].dso_name); 122f8ebb0cdSNamhyung Kim if (dso == NULL) 123f8ebb0cdSNamhyung Kim goto out; 124f8ebb0cdSNamhyung Kim 125f8ebb0cdSNamhyung Kim /* emulate dso__load() */ 126f8ebb0cdSNamhyung Kim dso__set_loaded(dso, MAP__FUNCTION); 127f8ebb0cdSNamhyung Kim 128f8ebb0cdSNamhyung Kim for (k = 0; k < fake_symbols[i].nr_syms; k++) { 129f8ebb0cdSNamhyung Kim struct symbol *sym; 130f8ebb0cdSNamhyung Kim struct fake_sym *fsym = &fake_symbols[i].syms[k]; 131f8ebb0cdSNamhyung Kim 132f8ebb0cdSNamhyung Kim sym = symbol__new(fsym->start, fsym->length, 133f8ebb0cdSNamhyung Kim STB_GLOBAL, fsym->name); 134f8ebb0cdSNamhyung Kim if (sym == NULL) 135f8ebb0cdSNamhyung Kim goto out; 136f8ebb0cdSNamhyung Kim 137f8ebb0cdSNamhyung Kim symbols__insert(&dso->symbols[MAP__FUNCTION], sym); 138f8ebb0cdSNamhyung Kim } 139f8ebb0cdSNamhyung Kim } 140f8ebb0cdSNamhyung Kim 141f8ebb0cdSNamhyung Kim return machine; 142f8ebb0cdSNamhyung Kim 143f8ebb0cdSNamhyung Kim out: 144f8ebb0cdSNamhyung Kim pr_debug("Not enough memory for machine setup\n"); 145f8ebb0cdSNamhyung Kim machine__delete_threads(machine); 146f8ebb0cdSNamhyung Kim machine__delete(machine); 147f8ebb0cdSNamhyung Kim return NULL; 148f8ebb0cdSNamhyung Kim } 149f8ebb0cdSNamhyung Kim 150f8ebb0cdSNamhyung Kim struct sample { 151f8ebb0cdSNamhyung Kim u32 pid; 152f8ebb0cdSNamhyung Kim u64 ip; 153f8ebb0cdSNamhyung Kim struct thread *thread; 154f8ebb0cdSNamhyung Kim struct map *map; 155f8ebb0cdSNamhyung Kim struct symbol *sym; 156f8ebb0cdSNamhyung Kim }; 157f8ebb0cdSNamhyung Kim 158f8ebb0cdSNamhyung Kim static struct sample fake_common_samples[] = { 159f8ebb0cdSNamhyung Kim /* perf [kernel] schedule() */ 160f8ebb0cdSNamhyung Kim { .pid = 100, .ip = 0xf0000 + 700, }, 161f8ebb0cdSNamhyung Kim /* perf [perf] main() */ 162f8ebb0cdSNamhyung Kim { .pid = 200, .ip = 0x40000 + 700, }, 163f8ebb0cdSNamhyung Kim /* perf [perf] cmd_record() */ 164f8ebb0cdSNamhyung Kim { .pid = 200, .ip = 0x40000 + 900, }, 165f8ebb0cdSNamhyung Kim /* bash [bash] xmalloc() */ 166f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x40000 + 800, }, 167f8ebb0cdSNamhyung Kim /* bash [libc] malloc() */ 168f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x50000 + 700, }, 169f8ebb0cdSNamhyung Kim }; 170f8ebb0cdSNamhyung Kim 171f8ebb0cdSNamhyung Kim static struct sample fake_samples[][5] = { 172f8ebb0cdSNamhyung Kim { 173f8ebb0cdSNamhyung Kim /* perf [perf] run_command() */ 174f8ebb0cdSNamhyung Kim { .pid = 100, .ip = 0x40000 + 800, }, 175f8ebb0cdSNamhyung Kim /* perf [libc] malloc() */ 176f8ebb0cdSNamhyung Kim { .pid = 100, .ip = 0x50000 + 700, }, 177f8ebb0cdSNamhyung Kim /* perf [kernel] page_fault() */ 178f8ebb0cdSNamhyung Kim { .pid = 100, .ip = 0xf0000 + 800, }, 179f8ebb0cdSNamhyung Kim /* perf [kernel] sys_perf_event_open() */ 180f8ebb0cdSNamhyung Kim { .pid = 200, .ip = 0xf0000 + 900, }, 181f8ebb0cdSNamhyung Kim /* bash [libc] free() */ 182f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x50000 + 800, }, 183f8ebb0cdSNamhyung Kim }, 184f8ebb0cdSNamhyung Kim { 185f8ebb0cdSNamhyung Kim /* perf [libc] free() */ 186f8ebb0cdSNamhyung Kim { .pid = 200, .ip = 0x50000 + 800, }, 187f8ebb0cdSNamhyung Kim /* bash [libc] malloc() */ 188f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x50000 + 700, }, /* will be merged */ 189f8ebb0cdSNamhyung Kim /* bash [bash] xfee() */ 190f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x40000 + 900, }, 191f8ebb0cdSNamhyung Kim /* bash [libc] realloc() */ 192f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0x50000 + 900, }, 193f8ebb0cdSNamhyung Kim /* bash [kernel] page_fault() */ 194f8ebb0cdSNamhyung Kim { .pid = 300, .ip = 0xf0000 + 800, }, 195f8ebb0cdSNamhyung Kim }, 196f8ebb0cdSNamhyung Kim }; 197f8ebb0cdSNamhyung Kim 198f8ebb0cdSNamhyung Kim static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) 199f8ebb0cdSNamhyung Kim { 200f8ebb0cdSNamhyung Kim struct perf_evsel *evsel; 201f8ebb0cdSNamhyung Kim struct addr_location al; 202f8ebb0cdSNamhyung Kim struct hist_entry *he; 203f8ebb0cdSNamhyung Kim struct perf_sample sample = { .cpu = 0, }; 204f8ebb0cdSNamhyung Kim size_t i = 0, k; 205f8ebb0cdSNamhyung Kim 206f8ebb0cdSNamhyung Kim /* 207f8ebb0cdSNamhyung Kim * each evsel will have 10 samples - 5 common and 5 distinct. 208f8ebb0cdSNamhyung Kim * However the second evsel also has a collapsed entry for 209f8ebb0cdSNamhyung Kim * "bash [libc] malloc" so total 9 entries will be in the tree. 210f8ebb0cdSNamhyung Kim */ 211f8ebb0cdSNamhyung Kim list_for_each_entry(evsel, &evlist->entries, node) { 212f8ebb0cdSNamhyung Kim for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 213f8ebb0cdSNamhyung Kim const union perf_event event = { 214f8ebb0cdSNamhyung Kim .header = { 215f8ebb0cdSNamhyung Kim .misc = PERF_RECORD_MISC_USER, 216f8ebb0cdSNamhyung Kim }, 217f8ebb0cdSNamhyung Kim }; 218f8ebb0cdSNamhyung Kim 219*ef89325fSAdrian Hunter sample.pid = fake_common_samples[k].pid; 220*ef89325fSAdrian Hunter sample.ip = fake_common_samples[k].ip; 221f8ebb0cdSNamhyung Kim if (perf_event__preprocess_sample(&event, machine, &al, 222e44baa3eSAdrian Hunter &sample) < 0) 223f8ebb0cdSNamhyung Kim goto out; 224f8ebb0cdSNamhyung Kim 22505484298SAndi Kleen he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 226f8ebb0cdSNamhyung Kim if (he == NULL) 227f8ebb0cdSNamhyung Kim goto out; 228f8ebb0cdSNamhyung Kim 229f8ebb0cdSNamhyung Kim fake_common_samples[k].thread = al.thread; 230f8ebb0cdSNamhyung Kim fake_common_samples[k].map = al.map; 231f8ebb0cdSNamhyung Kim fake_common_samples[k].sym = al.sym; 232f8ebb0cdSNamhyung Kim } 233f8ebb0cdSNamhyung Kim 234f8ebb0cdSNamhyung Kim for (k = 0; k < ARRAY_SIZE(fake_samples[i]); k++) { 235f8ebb0cdSNamhyung Kim const union perf_event event = { 236f8ebb0cdSNamhyung Kim .header = { 237f8ebb0cdSNamhyung Kim .misc = PERF_RECORD_MISC_USER, 238f8ebb0cdSNamhyung Kim }, 239f8ebb0cdSNamhyung Kim }; 240f8ebb0cdSNamhyung Kim 241*ef89325fSAdrian Hunter sample.pid = fake_samples[i][k].pid; 242*ef89325fSAdrian Hunter sample.ip = fake_samples[i][k].ip; 243f8ebb0cdSNamhyung Kim if (perf_event__preprocess_sample(&event, machine, &al, 244e44baa3eSAdrian Hunter &sample) < 0) 245f8ebb0cdSNamhyung Kim goto out; 246f8ebb0cdSNamhyung Kim 24705484298SAndi Kleen he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 248f8ebb0cdSNamhyung Kim if (he == NULL) 249f8ebb0cdSNamhyung Kim goto out; 250f8ebb0cdSNamhyung Kim 251f8ebb0cdSNamhyung Kim fake_samples[i][k].thread = al.thread; 252f8ebb0cdSNamhyung Kim fake_samples[i][k].map = al.map; 253f8ebb0cdSNamhyung Kim fake_samples[i][k].sym = al.sym; 254f8ebb0cdSNamhyung Kim } 255f8ebb0cdSNamhyung Kim i++; 256f8ebb0cdSNamhyung Kim } 257f8ebb0cdSNamhyung Kim 258f8ebb0cdSNamhyung Kim return 0; 259f8ebb0cdSNamhyung Kim 260f8ebb0cdSNamhyung Kim out: 261f8ebb0cdSNamhyung Kim pr_debug("Not enough memory for adding a hist entry\n"); 262f8ebb0cdSNamhyung Kim return -1; 263f8ebb0cdSNamhyung Kim } 264f8ebb0cdSNamhyung Kim 265f8ebb0cdSNamhyung Kim static int find_sample(struct sample *samples, size_t nr_samples, 266f8ebb0cdSNamhyung Kim struct thread *t, struct map *m, struct symbol *s) 267f8ebb0cdSNamhyung Kim { 268f8ebb0cdSNamhyung Kim while (nr_samples--) { 269f8ebb0cdSNamhyung Kim if (samples->thread == t && samples->map == m && 270f8ebb0cdSNamhyung Kim samples->sym == s) 271f8ebb0cdSNamhyung Kim return 1; 272f8ebb0cdSNamhyung Kim samples++; 273f8ebb0cdSNamhyung Kim } 274f8ebb0cdSNamhyung Kim return 0; 275f8ebb0cdSNamhyung Kim } 276f8ebb0cdSNamhyung Kim 277f8ebb0cdSNamhyung Kim static int __validate_match(struct hists *hists) 278f8ebb0cdSNamhyung Kim { 279f8ebb0cdSNamhyung Kim size_t count = 0; 280f8ebb0cdSNamhyung Kim struct rb_root *root; 281f8ebb0cdSNamhyung Kim struct rb_node *node; 282f8ebb0cdSNamhyung Kim 283f8ebb0cdSNamhyung Kim /* 284f8ebb0cdSNamhyung Kim * Only entries from fake_common_samples should have a pair. 285f8ebb0cdSNamhyung Kim */ 286f8ebb0cdSNamhyung Kim if (sort__need_collapse) 287f8ebb0cdSNamhyung Kim root = &hists->entries_collapsed; 288f8ebb0cdSNamhyung Kim else 289f8ebb0cdSNamhyung Kim root = hists->entries_in; 290f8ebb0cdSNamhyung Kim 291f8ebb0cdSNamhyung Kim node = rb_first(root); 292f8ebb0cdSNamhyung Kim while (node) { 293f8ebb0cdSNamhyung Kim struct hist_entry *he; 294f8ebb0cdSNamhyung Kim 295f8ebb0cdSNamhyung Kim he = rb_entry(node, struct hist_entry, rb_node_in); 296f8ebb0cdSNamhyung Kim 297f8ebb0cdSNamhyung Kim if (hist_entry__has_pairs(he)) { 298f8ebb0cdSNamhyung Kim if (find_sample(fake_common_samples, 299f8ebb0cdSNamhyung Kim ARRAY_SIZE(fake_common_samples), 300f8ebb0cdSNamhyung Kim he->thread, he->ms.map, he->ms.sym)) { 301f8ebb0cdSNamhyung Kim count++; 302f8ebb0cdSNamhyung Kim } else { 303f8ebb0cdSNamhyung Kim pr_debug("Can't find the matched entry\n"); 304f8ebb0cdSNamhyung Kim return -1; 305f8ebb0cdSNamhyung Kim } 306f8ebb0cdSNamhyung Kim } 307f8ebb0cdSNamhyung Kim 308f8ebb0cdSNamhyung Kim node = rb_next(node); 309f8ebb0cdSNamhyung Kim } 310f8ebb0cdSNamhyung Kim 311f8ebb0cdSNamhyung Kim if (count != ARRAY_SIZE(fake_common_samples)) { 312f8ebb0cdSNamhyung Kim pr_debug("Invalid count for matched entries: %zd of %zd\n", 313f8ebb0cdSNamhyung Kim count, ARRAY_SIZE(fake_common_samples)); 314f8ebb0cdSNamhyung Kim return -1; 315f8ebb0cdSNamhyung Kim } 316f8ebb0cdSNamhyung Kim 317f8ebb0cdSNamhyung Kim return 0; 318f8ebb0cdSNamhyung Kim } 319f8ebb0cdSNamhyung Kim 320f8ebb0cdSNamhyung Kim static int validate_match(struct hists *leader, struct hists *other) 321f8ebb0cdSNamhyung Kim { 322f8ebb0cdSNamhyung Kim return __validate_match(leader) || __validate_match(other); 323f8ebb0cdSNamhyung Kim } 324f8ebb0cdSNamhyung Kim 325f8ebb0cdSNamhyung Kim static int __validate_link(struct hists *hists, int idx) 326f8ebb0cdSNamhyung Kim { 327f8ebb0cdSNamhyung Kim size_t count = 0; 328f8ebb0cdSNamhyung Kim size_t count_pair = 0; 329f8ebb0cdSNamhyung Kim size_t count_dummy = 0; 330f8ebb0cdSNamhyung Kim struct rb_root *root; 331f8ebb0cdSNamhyung Kim struct rb_node *node; 332f8ebb0cdSNamhyung Kim 333f8ebb0cdSNamhyung Kim /* 334f8ebb0cdSNamhyung Kim * Leader hists (idx = 0) will have dummy entries from other, 335f8ebb0cdSNamhyung Kim * and some entries will have no pair. However every entry 336f8ebb0cdSNamhyung Kim * in other hists should have (dummy) pair. 337f8ebb0cdSNamhyung Kim */ 338f8ebb0cdSNamhyung Kim if (sort__need_collapse) 339f8ebb0cdSNamhyung Kim root = &hists->entries_collapsed; 340f8ebb0cdSNamhyung Kim else 341f8ebb0cdSNamhyung Kim root = hists->entries_in; 342f8ebb0cdSNamhyung Kim 343f8ebb0cdSNamhyung Kim node = rb_first(root); 344f8ebb0cdSNamhyung Kim while (node) { 345f8ebb0cdSNamhyung Kim struct hist_entry *he; 346f8ebb0cdSNamhyung Kim 347f8ebb0cdSNamhyung Kim he = rb_entry(node, struct hist_entry, rb_node_in); 348f8ebb0cdSNamhyung Kim 349f8ebb0cdSNamhyung Kim if (hist_entry__has_pairs(he)) { 350f8ebb0cdSNamhyung Kim if (!find_sample(fake_common_samples, 351f8ebb0cdSNamhyung Kim ARRAY_SIZE(fake_common_samples), 352f8ebb0cdSNamhyung Kim he->thread, he->ms.map, he->ms.sym) && 353f8ebb0cdSNamhyung Kim !find_sample(fake_samples[idx], 354f8ebb0cdSNamhyung Kim ARRAY_SIZE(fake_samples[idx]), 355f8ebb0cdSNamhyung Kim he->thread, he->ms.map, he->ms.sym)) { 356f8ebb0cdSNamhyung Kim count_dummy++; 357f8ebb0cdSNamhyung Kim } 358f8ebb0cdSNamhyung Kim count_pair++; 359f8ebb0cdSNamhyung Kim } else if (idx) { 360f8ebb0cdSNamhyung Kim pr_debug("A entry from the other hists should have pair\n"); 361f8ebb0cdSNamhyung Kim return -1; 362f8ebb0cdSNamhyung Kim } 363f8ebb0cdSNamhyung Kim 364f8ebb0cdSNamhyung Kim count++; 365f8ebb0cdSNamhyung Kim node = rb_next(node); 366f8ebb0cdSNamhyung Kim } 367f8ebb0cdSNamhyung Kim 368f8ebb0cdSNamhyung Kim /* 369f8ebb0cdSNamhyung Kim * Note that we have a entry collapsed in the other (idx = 1) hists. 370f8ebb0cdSNamhyung Kim */ 371f8ebb0cdSNamhyung Kim if (idx == 0) { 372f8ebb0cdSNamhyung Kim if (count_dummy != ARRAY_SIZE(fake_samples[1]) - 1) { 373f8ebb0cdSNamhyung Kim pr_debug("Invalid count of dummy entries: %zd of %zd\n", 374f8ebb0cdSNamhyung Kim count_dummy, ARRAY_SIZE(fake_samples[1]) - 1); 375f8ebb0cdSNamhyung Kim return -1; 376f8ebb0cdSNamhyung Kim } 377f8ebb0cdSNamhyung Kim if (count != count_pair + ARRAY_SIZE(fake_samples[0])) { 378f8ebb0cdSNamhyung Kim pr_debug("Invalid count of total leader entries: %zd of %zd\n", 379f8ebb0cdSNamhyung Kim count, count_pair + ARRAY_SIZE(fake_samples[0])); 380f8ebb0cdSNamhyung Kim return -1; 381f8ebb0cdSNamhyung Kim } 382f8ebb0cdSNamhyung Kim } else { 383f8ebb0cdSNamhyung Kim if (count != count_pair) { 384f8ebb0cdSNamhyung Kim pr_debug("Invalid count of total other entries: %zd of %zd\n", 385f8ebb0cdSNamhyung Kim count, count_pair); 386f8ebb0cdSNamhyung Kim return -1; 387f8ebb0cdSNamhyung Kim } 388f8ebb0cdSNamhyung Kim if (count_dummy > 0) { 389f8ebb0cdSNamhyung Kim pr_debug("Other hists should not have dummy entries: %zd\n", 390f8ebb0cdSNamhyung Kim count_dummy); 391f8ebb0cdSNamhyung Kim return -1; 392f8ebb0cdSNamhyung Kim } 393f8ebb0cdSNamhyung Kim } 394f8ebb0cdSNamhyung Kim 395f8ebb0cdSNamhyung Kim return 0; 396f8ebb0cdSNamhyung Kim } 397f8ebb0cdSNamhyung Kim 398f8ebb0cdSNamhyung Kim static int validate_link(struct hists *leader, struct hists *other) 399f8ebb0cdSNamhyung Kim { 400f8ebb0cdSNamhyung Kim return __validate_link(leader, 0) || __validate_link(other, 1); 401f8ebb0cdSNamhyung Kim } 402f8ebb0cdSNamhyung Kim 403f8ebb0cdSNamhyung Kim static void print_hists(struct hists *hists) 404f8ebb0cdSNamhyung Kim { 405f8ebb0cdSNamhyung Kim int i = 0; 406f8ebb0cdSNamhyung Kim struct rb_root *root; 407f8ebb0cdSNamhyung Kim struct rb_node *node; 408f8ebb0cdSNamhyung Kim 409f8ebb0cdSNamhyung Kim if (sort__need_collapse) 410f8ebb0cdSNamhyung Kim root = &hists->entries_collapsed; 411f8ebb0cdSNamhyung Kim else 412f8ebb0cdSNamhyung Kim root = hists->entries_in; 413f8ebb0cdSNamhyung Kim 414f8ebb0cdSNamhyung Kim pr_info("----- %s --------\n", __func__); 415f8ebb0cdSNamhyung Kim node = rb_first(root); 416f8ebb0cdSNamhyung Kim while (node) { 417f8ebb0cdSNamhyung Kim struct hist_entry *he; 418f8ebb0cdSNamhyung Kim 419f8ebb0cdSNamhyung Kim he = rb_entry(node, struct hist_entry, rb_node_in); 420f8ebb0cdSNamhyung Kim 421f8ebb0cdSNamhyung Kim pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", 422f8ebb0cdSNamhyung Kim i, he->thread->comm, he->ms.map->dso->short_name, 423f8ebb0cdSNamhyung Kim he->ms.sym->name, he->stat.period); 424f8ebb0cdSNamhyung Kim 425f8ebb0cdSNamhyung Kim i++; 426f8ebb0cdSNamhyung Kim node = rb_next(node); 427f8ebb0cdSNamhyung Kim } 428f8ebb0cdSNamhyung Kim } 429f8ebb0cdSNamhyung Kim 430f8ebb0cdSNamhyung Kim int test__hists_link(void) 431f8ebb0cdSNamhyung Kim { 432f8ebb0cdSNamhyung Kim int err = -1; 433876650e6SArnaldo Carvalho de Melo struct machines machines; 434f8ebb0cdSNamhyung Kim struct machine *machine = NULL; 435f8ebb0cdSNamhyung Kim struct perf_evsel *evsel, *first; 436334fe7a3SNamhyung Kim struct perf_evlist *evlist = perf_evlist__new(); 437f8ebb0cdSNamhyung Kim 438f8ebb0cdSNamhyung Kim if (evlist == NULL) 439f8ebb0cdSNamhyung Kim return -ENOMEM; 440f8ebb0cdSNamhyung Kim 441d8f7bbc9SJiri Olsa err = parse_events(evlist, "cpu-clock"); 442f8ebb0cdSNamhyung Kim if (err) 443f8ebb0cdSNamhyung Kim goto out; 444d8f7bbc9SJiri Olsa err = parse_events(evlist, "task-clock"); 445f8ebb0cdSNamhyung Kim if (err) 446f8ebb0cdSNamhyung Kim goto out; 447f8ebb0cdSNamhyung Kim 448f8ebb0cdSNamhyung Kim /* default sort order (comm,dso,sym) will be used */ 44955309985SNamhyung Kim if (setup_sorting() < 0) 45055309985SNamhyung Kim goto out; 451f8ebb0cdSNamhyung Kim 452876650e6SArnaldo Carvalho de Melo machines__init(&machines); 453876650e6SArnaldo Carvalho de Melo 454f8ebb0cdSNamhyung Kim /* setup threads/dso/map/symbols also */ 455876650e6SArnaldo Carvalho de Melo machine = setup_fake_machine(&machines); 456f8ebb0cdSNamhyung Kim if (!machine) 457f8ebb0cdSNamhyung Kim goto out; 458f8ebb0cdSNamhyung Kim 459f8ebb0cdSNamhyung Kim if (verbose > 1) 460f8ebb0cdSNamhyung Kim machine__fprintf(machine, stderr); 461f8ebb0cdSNamhyung Kim 462f8ebb0cdSNamhyung Kim /* process sample events */ 463f8ebb0cdSNamhyung Kim err = add_hist_entries(evlist, machine); 464f8ebb0cdSNamhyung Kim if (err < 0) 465f8ebb0cdSNamhyung Kim goto out; 466f8ebb0cdSNamhyung Kim 467f8ebb0cdSNamhyung Kim list_for_each_entry(evsel, &evlist->entries, node) { 468f8ebb0cdSNamhyung Kim hists__collapse_resort(&evsel->hists); 469f8ebb0cdSNamhyung Kim 470f8ebb0cdSNamhyung Kim if (verbose > 2) 471f8ebb0cdSNamhyung Kim print_hists(&evsel->hists); 472f8ebb0cdSNamhyung Kim } 473f8ebb0cdSNamhyung Kim 474f8ebb0cdSNamhyung Kim first = perf_evlist__first(evlist); 475f8ebb0cdSNamhyung Kim evsel = perf_evlist__last(evlist); 476f8ebb0cdSNamhyung Kim 477f8ebb0cdSNamhyung Kim /* match common entries */ 478f8ebb0cdSNamhyung Kim hists__match(&first->hists, &evsel->hists); 479f8ebb0cdSNamhyung Kim err = validate_match(&first->hists, &evsel->hists); 480f8ebb0cdSNamhyung Kim if (err) 481f8ebb0cdSNamhyung Kim goto out; 482f8ebb0cdSNamhyung Kim 483f8ebb0cdSNamhyung Kim /* link common and/or dummy entries */ 484f8ebb0cdSNamhyung Kim hists__link(&first->hists, &evsel->hists); 485f8ebb0cdSNamhyung Kim err = validate_link(&first->hists, &evsel->hists); 486f8ebb0cdSNamhyung Kim if (err) 487f8ebb0cdSNamhyung Kim goto out; 488f8ebb0cdSNamhyung Kim 489f8ebb0cdSNamhyung Kim err = 0; 490f8ebb0cdSNamhyung Kim 491f8ebb0cdSNamhyung Kim out: 492f8ebb0cdSNamhyung Kim /* tear down everything */ 493f8ebb0cdSNamhyung Kim perf_evlist__delete(evlist); 494876650e6SArnaldo Carvalho de Melo machines__exit(&machines); 495f8ebb0cdSNamhyung Kim 496f8ebb0cdSNamhyung Kim return err; 497f8ebb0cdSNamhyung Kim } 498