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