~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/tests/hists_cumulate.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php