Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Thomas Gleixner:
"Perf updates and fixes:

Kernel:
- Handle events which have the bpf_event attribute set as side band
events as they carry information about BPF programs.
- Add missing switch-case fall-through comments

Libraries:
- Fix leaks and double frees in error code paths.
- Prevent buffer overflows in libtraceevent

Tools:
- Improvements in handling Intel BT/PTS
- Add BTF ELF markers to perf trace BPF programs to improve output
- Support --time, --cpu, --pid and --tid filters for perf diff
- Calculate the column width in perf annotate as the hardcoded 6
characters for the instruction are not sufficient
- Small fixes all over the place"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (38 commits)
perf/core: Mark expected switch fall-through
perf/x86/intel/uncore: Fix client IMC events return huge result
perf/ring_buffer: Use high order allocations for AUX buffers optimistically
perf data: Force perf_data__open|close zero data->file.path
perf session: Fix double free in perf_data__close
perf evsel: Probe for precise_ip with simple attr
perf tools: Read and store caps/max_precise in perf_pmu
perf hist: Fix memory leak of srcline
perf hist: Add error path into hist_entry__init
perf c2c: Fix c2c report for empty numa node
perf script python: Add Python3 support to intel-pt-events.py
perf script python: Add Python3 support to event_analyzing_sample.py
perf script python: add Python3 support to check-perf-trace.py
perf script python: Add Python3 support to futex-contention.py
perf script python: Remove mixed indentation
perf diff: Support --pid/--tid filter options
perf diff: Support --cpu filter option
perf diff: Support --time filter option
perf thread: Generalize function to copy from thread addr space from intel-bts code
perf annotate: Calculate the max instruction name, align column to that
...

+996 -465
+1
arch/x86/events/intel/uncore.c
··· 732 732 /* fixed counters have event field hardcoded to zero */ 733 733 hwc->config = 0ULL; 734 734 } else if (is_freerunning_event(event)) { 735 + hwc->config = event->attr.config; 735 736 if (!check_valid_freerunning_event(box, event)) 736 737 return -EINVAL; 737 738 event->hw.idx = UNCORE_PMC_IDX_FREERUNNING;
+6 -6
arch/x86/events/intel/uncore.h
··· 292 292 unsigned int uncore_freerunning_counter(struct intel_uncore_box *box, 293 293 struct perf_event *event) 294 294 { 295 - unsigned int type = uncore_freerunning_type(event->attr.config); 296 - unsigned int idx = uncore_freerunning_idx(event->attr.config); 295 + unsigned int type = uncore_freerunning_type(event->hw.config); 296 + unsigned int idx = uncore_freerunning_idx(event->hw.config); 297 297 struct intel_uncore_pmu *pmu = box->pmu; 298 298 299 299 return pmu->type->freerunning[type].counter_base + ··· 377 377 unsigned int uncore_freerunning_bits(struct intel_uncore_box *box, 378 378 struct perf_event *event) 379 379 { 380 - unsigned int type = uncore_freerunning_type(event->attr.config); 380 + unsigned int type = uncore_freerunning_type(event->hw.config); 381 381 382 382 return box->pmu->type->freerunning[type].bits; 383 383 } ··· 385 385 static inline int uncore_num_freerunning(struct intel_uncore_box *box, 386 386 struct perf_event *event) 387 387 { 388 - unsigned int type = uncore_freerunning_type(event->attr.config); 388 + unsigned int type = uncore_freerunning_type(event->hw.config); 389 389 390 390 return box->pmu->type->freerunning[type].num_counters; 391 391 } ··· 399 399 static inline bool check_valid_freerunning_event(struct intel_uncore_box *box, 400 400 struct perf_event *event) 401 401 { 402 - unsigned int type = uncore_freerunning_type(event->attr.config); 403 - unsigned int idx = uncore_freerunning_idx(event->attr.config); 402 + unsigned int type = uncore_freerunning_type(event->hw.config); 403 + unsigned int idx = uncore_freerunning_idx(event->hw.config); 404 404 405 405 return (type < uncore_num_freerunning_types(box, event)) && 406 406 (idx < uncore_num_freerunning(box, event));
+3 -1
arch/x86/events/intel/uncore_snb.c
··· 442 442 443 443 /* must be done before validate_group */ 444 444 event->hw.event_base = base; 445 - event->hw.config = cfg; 446 445 event->hw.idx = idx; 446 + 447 + /* Convert to standard encoding format for freerunning counters */ 448 + event->hw.config = ((cfg - 1) << 8) | 0x10ff; 447 449 448 450 /* no group validation needed, we have free running counters */ 449 451
+3 -1
kernel/events/core.c
··· 4238 4238 if (attr->mmap || attr->mmap_data || attr->mmap2 || 4239 4239 attr->comm || attr->comm_exec || 4240 4240 attr->task || attr->ksymbol || 4241 - attr->context_switch) 4241 + attr->context_switch || 4242 + attr->bpf_event) 4242 4243 return true; 4243 4244 return false; 4244 4245 } ··· 9175 9174 case IF_SRC_KERNELADDR: 9176 9175 case IF_SRC_KERNEL: 9177 9176 kernel = 1; 9177 + /* fall through */ 9178 9178 9179 9179 case IF_SRC_FILEADDR: 9180 9180 case IF_SRC_FILE:
+15 -17
kernel/events/ring_buffer.c
··· 598 598 { 599 599 bool overwrite = !(flags & RING_BUFFER_WRITABLE); 600 600 int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu); 601 - int ret = -ENOMEM, max_order = 0; 601 + int ret = -ENOMEM, max_order; 602 602 603 603 if (!has_aux(event)) 604 604 return -EOPNOTSUPP; 605 605 606 - if (event->pmu->capabilities & PERF_PMU_CAP_AUX_NO_SG) { 607 - /* 608 - * We need to start with the max_order that fits in nr_pages, 609 - * not the other way around, hence ilog2() and not get_order. 610 - */ 611 - max_order = ilog2(nr_pages); 606 + /* 607 + * We need to start with the max_order that fits in nr_pages, 608 + * not the other way around, hence ilog2() and not get_order. 609 + */ 610 + max_order = ilog2(nr_pages); 612 611 613 - /* 614 - * PMU requests more than one contiguous chunks of memory 615 - * for SW double buffering 616 - */ 617 - if ((event->pmu->capabilities & PERF_PMU_CAP_AUX_SW_DOUBLEBUF) && 618 - !overwrite) { 619 - if (!max_order) 620 - return -EINVAL; 612 + /* 613 + * PMU requests more than one contiguous chunks of memory 614 + * for SW double buffering 615 + */ 616 + if ((event->pmu->capabilities & PERF_PMU_CAP_AUX_SW_DOUBLEBUF) && 617 + !overwrite) { 618 + if (!max_order) 619 + return -EINVAL; 621 620 622 - max_order--; 623 - } 621 + max_order--; 624 622 } 625 623 626 624 rb->aux_pages = kcalloc_node(nr_pages, sizeof(void *), GFP_KERNEL,
+1 -1
tools/lib/traceevent/event-parse.c
··· 2457 2457 static char *arg_eval (struct tep_print_arg *arg) 2458 2458 { 2459 2459 long long val; 2460 - static char buf[20]; 2460 + static char buf[24]; 2461 2461 2462 2462 switch (arg->type) { 2463 2463 case TEP_PRINT_ATOM:
+56
tools/perf/Documentation/perf-diff.txt
··· 118 118 sum of shown entries will be always 100%. "absolute" means it retains 119 119 the original value before and after the filter is applied. 120 120 121 + --time:: 122 + Analyze samples within given time window. It supports time 123 + percent with multiple time ranges. Time string is 'a%/n,b%/m,...' 124 + or 'a%-b%,c%-%d,...'. 125 + 126 + For example: 127 + 128 + Select the second 10% time slice to diff: 129 + 130 + perf diff --time 10%/2 131 + 132 + Select from 0% to 10% time slice to diff: 133 + 134 + perf diff --time 0%-10% 135 + 136 + Select the first and the second 10% time slices to diff: 137 + 138 + perf diff --time 10%/1,10%/2 139 + 140 + Select from 0% to 10% and 30% to 40% slices to diff: 141 + 142 + perf diff --time 0%-10%,30%-40% 143 + 144 + It also supports analyzing samples within a given time window 145 + <start>,<stop>. Times have the format seconds.microseconds. If 'start' 146 + is not given (i.e., time string is ',x.y') then analysis starts at 147 + the beginning of the file. If stop time is not given (i.e, time 148 + string is 'x.y,') then analysis goes to the end of the file. Time string is 149 + 'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different 150 + perf.data files. 151 + 152 + For example, we get the timestamp information from 'perf script'. 153 + 154 + perf script -i perf.data.old 155 + mgen 13940 [000] 3946.361400: ... 156 + 157 + perf script -i perf.data 158 + mgen 13940 [000] 3971.150589 ... 159 + 160 + perf diff --time 3946.361400,:3971.150589, 161 + 162 + It analyzes the perf.data.old from the timestamp 3946.361400 to 163 + the end of perf.data.old and analyzes the perf.data from the 164 + timestamp 3971.150589 to the end of perf.data. 165 + 166 + --cpu:: Only diff samples for the list of CPUs provided. Multiple CPUs can 167 + be provided as a comma-separated list with no space: 0,1. Ranges of 168 + CPUs are specified with -: 0-2. Default is to report samples on all 169 + CPUs. 170 + 171 + --pid=:: 172 + Only diff samples for given process ID (comma separated list). 173 + 174 + --tid=:: 175 + Only diff samples for given thread ID (comma separated list). 176 + 121 177 COMPARISON 122 178 ---------- 123 179 The comparison is governed by the baseline file. The baseline perf.data
+1 -1
tools/perf/arch/arm64/annotate/instructions.c
··· 58 58 } 59 59 60 60 static int mov__scnprintf(struct ins *ins, char *bf, size_t size, 61 - struct ins_operands *ops); 61 + struct ins_operands *ops, int max_ins_name); 62 62 63 63 static struct ins_ops arm64_mov_ops = { 64 64 .parse = arm64_mov__parse,
+1 -1
tools/perf/arch/s390/annotate/instructions.c
··· 46 46 } 47 47 48 48 static int call__scnprintf(struct ins *ins, char *bf, size_t size, 49 - struct ins_operands *ops); 49 + struct ins_operands *ops, int max_ins_name); 50 50 51 51 static struct ins_ops s390_call_ops = { 52 52 .parse = s390_call__parse,
+6 -2
tools/perf/builtin-c2c.c
··· 2056 2056 if (!set) 2057 2057 return -ENOMEM; 2058 2058 2059 + nodes[node] = set; 2060 + 2061 + /* empty node, skip */ 2062 + if (cpu_map__empty(map)) 2063 + continue; 2064 + 2059 2065 for (cpu = 0; cpu < map->nr; cpu++) { 2060 2066 set_bit(map->map[cpu], set); 2061 2067 ··· 2070 2064 2071 2065 cpu2node[map->map[cpu]] = node; 2072 2066 } 2073 - 2074 - nodes[node] = set; 2075 2067 } 2076 2068 2077 2069 setup_nodes_header();
+154 -14
tools/perf/builtin-diff.c
··· 19 19 #include "util/util.h" 20 20 #include "util/data.h" 21 21 #include "util/config.h" 22 + #include "util/time-utils.h" 22 23 23 24 #include <errno.h> 24 25 #include <inttypes.h> 25 26 #include <stdlib.h> 26 27 #include <math.h> 28 + 29 + struct perf_diff { 30 + struct perf_tool tool; 31 + const char *time_str; 32 + struct perf_time_interval *ptime_range; 33 + int range_size; 34 + int range_num; 35 + }; 27 36 28 37 /* Diff command specific HPP columns. */ 29 38 enum { ··· 82 73 83 74 static s64 compute_wdiff_w1; 84 75 static s64 compute_wdiff_w2; 76 + 77 + static const char *cpu_list; 78 + static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 85 79 86 80 enum { 87 81 COMPUTE_DELTA, ··· 335 323 return -1; 336 324 } 337 325 338 - static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, 326 + static int diff__process_sample_event(struct perf_tool *tool, 339 327 union perf_event *event, 340 328 struct perf_sample *sample, 341 329 struct perf_evsel *evsel, 342 330 struct machine *machine) 343 331 { 332 + struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool); 344 333 struct addr_location al; 345 334 struct hists *hists = evsel__hists(evsel); 346 335 int ret = -1; 336 + 337 + if (perf_time__ranges_skip_sample(pdiff->ptime_range, pdiff->range_num, 338 + sample->time)) { 339 + return 0; 340 + } 347 341 348 342 if (machine__resolve(machine, &al, sample) < 0) { 349 343 pr_warning("problem processing %d event, skipping it.\n", 350 344 event->header.type); 351 345 return -1; 346 + } 347 + 348 + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) { 349 + ret = 0; 350 + goto out_put; 352 351 } 353 352 354 353 if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) { ··· 382 359 return ret; 383 360 } 384 361 385 - static struct perf_tool tool = { 386 - .sample = diff__process_sample_event, 387 - .mmap = perf_event__process_mmap, 388 - .mmap2 = perf_event__process_mmap2, 389 - .comm = perf_event__process_comm, 390 - .exit = perf_event__process_exit, 391 - .fork = perf_event__process_fork, 392 - .lost = perf_event__process_lost, 393 - .namespaces = perf_event__process_namespaces, 394 - .ordered_events = true, 395 - .ordering_requires_timestamps = true, 362 + static struct perf_diff pdiff = { 363 + .tool = { 364 + .sample = diff__process_sample_event, 365 + .mmap = perf_event__process_mmap, 366 + .mmap2 = perf_event__process_mmap2, 367 + .comm = perf_event__process_comm, 368 + .exit = perf_event__process_exit, 369 + .fork = perf_event__process_fork, 370 + .lost = perf_event__process_lost, 371 + .namespaces = perf_event__process_namespaces, 372 + .ordered_events = true, 373 + .ordering_requires_timestamps = true, 374 + }, 396 375 }; 397 376 398 377 static struct perf_evsel *evsel_match(struct perf_evsel *evsel, ··· 796 771 } 797 772 } 798 773 774 + static int abstime_str_dup(char **pstr) 775 + { 776 + char *str = NULL; 777 + 778 + if (pdiff.time_str && strchr(pdiff.time_str, ':')) { 779 + str = strdup(pdiff.time_str); 780 + if (!str) 781 + return -ENOMEM; 782 + } 783 + 784 + *pstr = str; 785 + return 0; 786 + } 787 + 788 + static int parse_absolute_time(struct data__file *d, char **pstr) 789 + { 790 + char *p = *pstr; 791 + int ret; 792 + 793 + /* 794 + * Absolute timestamp for one file has the format: a.b,c.d 795 + * For multiple files, the format is: a.b,c.d:a.b,c.d 796 + */ 797 + p = strchr(*pstr, ':'); 798 + if (p) { 799 + if (p == *pstr) { 800 + pr_err("Invalid time string\n"); 801 + return -EINVAL; 802 + } 803 + 804 + *p = 0; 805 + p++; 806 + if (*p == 0) { 807 + pr_err("Invalid time string\n"); 808 + return -EINVAL; 809 + } 810 + } 811 + 812 + ret = perf_time__parse_for_ranges(*pstr, d->session, 813 + &pdiff.ptime_range, 814 + &pdiff.range_size, 815 + &pdiff.range_num); 816 + if (ret < 0) 817 + return ret; 818 + 819 + if (!p || *p == 0) 820 + *pstr = NULL; 821 + else 822 + *pstr = p; 823 + 824 + return ret; 825 + } 826 + 827 + static int parse_percent_time(struct data__file *d) 828 + { 829 + int ret; 830 + 831 + ret = perf_time__parse_for_ranges(pdiff.time_str, d->session, 832 + &pdiff.ptime_range, 833 + &pdiff.range_size, 834 + &pdiff.range_num); 835 + return ret; 836 + } 837 + 838 + static int parse_time_str(struct data__file *d, char *abstime_ostr, 839 + char **pabstime_tmp) 840 + { 841 + int ret = 0; 842 + 843 + if (abstime_ostr) 844 + ret = parse_absolute_time(d, pabstime_tmp); 845 + else if (pdiff.time_str) 846 + ret = parse_percent_time(d); 847 + 848 + return ret; 849 + } 850 + 799 851 static int __cmd_diff(void) 800 852 { 801 853 struct data__file *d; 802 - int ret = -EINVAL, i; 854 + int ret, i; 855 + char *abstime_ostr, *abstime_tmp; 856 + 857 + ret = abstime_str_dup(&abstime_ostr); 858 + if (ret) 859 + return ret; 860 + 861 + abstime_tmp = abstime_ostr; 862 + ret = -EINVAL; 803 863 804 864 data__for_each_file(i, d) { 805 - d->session = perf_session__new(&d->data, false, &tool); 865 + d->session = perf_session__new(&d->data, false, &pdiff.tool); 806 866 if (!d->session) { 807 867 pr_err("Failed to open %s\n", d->data.path); 808 868 ret = -1; 809 869 goto out_delete; 870 + } 871 + 872 + if (pdiff.time_str) { 873 + ret = parse_time_str(d, abstime_ostr, &abstime_tmp); 874 + if (ret < 0) 875 + goto out_delete; 876 + } 877 + 878 + if (cpu_list) { 879 + ret = perf_session__cpu_bitmap(d->session, cpu_list, 880 + cpu_bitmap); 881 + if (ret < 0) 882 + goto out_delete; 810 883 } 811 884 812 885 ret = perf_session__process_events(d->session); ··· 914 791 } 915 792 916 793 perf_evlist__collapse_resort(d->session->evlist); 794 + 795 + if (pdiff.ptime_range) 796 + zfree(&pdiff.ptime_range); 917 797 } 918 798 919 799 data_process(); ··· 928 802 } 929 803 930 804 free(data__files); 805 + 806 + if (pdiff.ptime_range) 807 + zfree(&pdiff.ptime_range); 808 + 809 + if (abstime_ostr) 810 + free(abstime_ostr); 811 + 931 812 return ret; 932 813 } 933 814 ··· 982 849 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 983 850 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 984 851 "How to display percentage of filtered entries", parse_filter_percentage), 852 + OPT_STRING(0, "time", &pdiff.time_str, "str", 853 + "Time span (time percent or absolute timestamp)"), 854 + OPT_STRING(0, "cpu", &cpu_list, "cpu", "list of cpus to profile"), 855 + OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]", 856 + "only consider symbols in these pids"), 857 + OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 858 + "only consider symbols in these tids"), 985 859 OPT_END() 986 860 }; 987 861
+8 -30
tools/perf/builtin-report.c
··· 1375 1375 if (symbol__init(&session->header.env) < 0) 1376 1376 goto error; 1377 1377 1378 - report.ptime_range = perf_time__range_alloc(report.time_str, 1379 - &report.range_size); 1380 - if (!report.ptime_range) { 1381 - ret = -ENOMEM; 1382 - goto error; 1383 - } 1384 - 1385 - if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) { 1386 - if (session->evlist->first_sample_time == 0 && 1387 - session->evlist->last_sample_time == 0) { 1388 - pr_err("HINT: no first/last sample time found in perf data.\n" 1389 - "Please use latest perf binary to execute 'perf record'\n" 1390 - "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n"); 1391 - ret = -EINVAL; 1378 + if (report.time_str) { 1379 + ret = perf_time__parse_for_ranges(report.time_str, session, 1380 + &report.ptime_range, 1381 + &report.range_size, 1382 + &report.range_num); 1383 + if (ret < 0) 1392 1384 goto error; 1393 - } 1394 - 1395 - report.range_num = perf_time__percent_parse_str( 1396 - report.ptime_range, report.range_size, 1397 - report.time_str, 1398 - session->evlist->first_sample_time, 1399 - session->evlist->last_sample_time); 1400 - 1401 - if (report.range_num < 0) { 1402 - pr_err("Invalid time string\n"); 1403 - ret = -EINVAL; 1404 - goto error; 1405 - } 1406 - } else { 1407 - report.range_num = 1; 1408 1385 } 1409 1386 1410 1387 if (session->tevent.pevent && ··· 1403 1426 ret = 0; 1404 1427 1405 1428 error: 1406 - zfree(&report.ptime_range); 1429 + if (report.ptime_range) 1430 + zfree(&report.ptime_range); 1407 1431 1408 1432 perf_session__delete(session); 1409 1433 return ret;
+8 -31
tools/perf/builtin-script.c
··· 3699 3699 if (err < 0) 3700 3700 goto out_delete; 3701 3701 3702 - script.ptime_range = perf_time__range_alloc(script.time_str, 3703 - &script.range_size); 3704 - if (!script.ptime_range) { 3705 - err = -ENOMEM; 3706 - goto out_delete; 3707 - } 3708 - 3709 - /* needs to be parsed after looking up reference time */ 3710 - if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) { 3711 - if (session->evlist->first_sample_time == 0 && 3712 - session->evlist->last_sample_time == 0) { 3713 - pr_err("HINT: no first/last sample time found in perf data.\n" 3714 - "Please use latest perf binary to execute 'perf record'\n" 3715 - "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n"); 3716 - err = -EINVAL; 3702 + if (script.time_str) { 3703 + err = perf_time__parse_for_ranges(script.time_str, session, 3704 + &script.ptime_range, 3705 + &script.range_size, 3706 + &script.range_num); 3707 + if (err < 0) 3717 3708 goto out_delete; 3718 - } 3719 - 3720 - script.range_num = perf_time__percent_parse_str( 3721 - script.ptime_range, script.range_size, 3722 - script.time_str, 3723 - session->evlist->first_sample_time, 3724 - session->evlist->last_sample_time); 3725 - 3726 - if (script.range_num < 0) { 3727 - pr_err("Invalid time string\n"); 3728 - err = -EINVAL; 3729 - goto out_delete; 3730 - } 3731 - } else { 3732 - script.range_num = 1; 3733 3709 } 3734 3710 3735 3711 err = __cmd_script(&script); ··· 3713 3737 flush_scripting(); 3714 3738 3715 3739 out_delete: 3716 - zfree(&script.ptime_range); 3740 + if (script.ptime_range) 3741 + zfree(&script.ptime_range); 3717 3742 3718 3743 perf_evlist__free_stats(session->evlist); 3719 3744 perf_session__delete(session);
+7 -1
tools/perf/include/bpf/bpf.h
··· 24 24 .key_size = sizeof(type_key), \ 25 25 .value_size = sizeof(type_val), \ 26 26 .max_entries = _max_entries, \ 27 - } 27 + }; \ 28 + struct ____btf_map_##name { \ 29 + type_key key; \ 30 + type_val value; \ 31 + }; \ 32 + struct ____btf_map_##name __attribute__((section(".maps." #name), used)) \ 33 + ____btf_map_##name = { } 28 34 29 35 /* 30 36 * FIXME: this should receive .max_entries as a parameter, as careful
+39 -37
tools/perf/scripts/python/check-perf-trace.py
··· 7 7 # events, etc. Basically, if this script runs successfully and 8 8 # displays expected results, Python scripting support should be ok. 9 9 10 + from __future__ import print_function 11 + 10 12 import os 11 13 import sys 12 14 ··· 21 19 unhandled = autodict() 22 20 23 21 def trace_begin(): 24 - print "trace_begin" 22 + print("trace_begin") 25 23 pass 26 24 27 25 def trace_end(): 28 - print_unhandled() 26 + print_unhandled() 29 27 30 28 def irq__softirq_entry(event_name, context, common_cpu, 31 - common_secs, common_nsecs, common_pid, common_comm, 32 - common_callchain, vec): 33 - print_header(event_name, common_cpu, common_secs, common_nsecs, 34 - common_pid, common_comm) 29 + common_secs, common_nsecs, common_pid, common_comm, 30 + common_callchain, vec): 31 + print_header(event_name, common_cpu, common_secs, common_nsecs, 32 + common_pid, common_comm) 35 33 36 - print_uncommon(context) 34 + print_uncommon(context) 37 35 38 - print "vec=%s\n" % \ 39 - (symbol_str("irq__softirq_entry", "vec", vec)), 36 + print("vec=%s" % (symbol_str("irq__softirq_entry", "vec", vec))) 40 37 41 38 def kmem__kmalloc(event_name, context, common_cpu, 42 - common_secs, common_nsecs, common_pid, common_comm, 43 - common_callchain, call_site, ptr, bytes_req, bytes_alloc, 44 - gfp_flags): 45 - print_header(event_name, common_cpu, common_secs, common_nsecs, 46 - common_pid, common_comm) 39 + common_secs, common_nsecs, common_pid, common_comm, 40 + common_callchain, call_site, ptr, bytes_req, bytes_alloc, 41 + gfp_flags): 42 + print_header(event_name, common_cpu, common_secs, common_nsecs, 43 + common_pid, common_comm) 47 44 48 - print_uncommon(context) 45 + print_uncommon(context) 49 46 50 - print "call_site=%u, ptr=%u, bytes_req=%u, " \ 51 - "bytes_alloc=%u, gfp_flags=%s\n" % \ 47 + print("call_site=%u, ptr=%u, bytes_req=%u, " 48 + "bytes_alloc=%u, gfp_flags=%s" % 52 49 (call_site, ptr, bytes_req, bytes_alloc, 53 - 54 - flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)), 50 + flag_str("kmem__kmalloc", "gfp_flags", gfp_flags))) 55 51 56 52 def trace_unhandled(event_name, context, event_fields_dict): 57 - try: 58 - unhandled[event_name] += 1 59 - except TypeError: 60 - unhandled[event_name] = 1 53 + try: 54 + unhandled[event_name] += 1 55 + except TypeError: 56 + unhandled[event_name] = 1 61 57 62 58 def print_header(event_name, cpu, secs, nsecs, pid, comm): 63 - print "%-20s %5u %05u.%09u %8u %-20s " % \ 64 - (event_name, cpu, secs, nsecs, pid, comm), 59 + print("%-20s %5u %05u.%09u %8u %-20s " % 60 + (event_name, cpu, secs, nsecs, pid, comm), 61 + end=' ') 65 62 66 63 # print trace fields not included in handler args 67 64 def print_uncommon(context): 68 - print "common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, " \ 69 - % (common_pc(context), trace_flag_str(common_flags(context)), \ 70 - common_lock_depth(context)) 65 + print("common_preempt_count=%d, common_flags=%s, " 66 + "common_lock_depth=%d, " % 67 + (common_pc(context), trace_flag_str(common_flags(context)), 68 + common_lock_depth(context))) 71 69 72 70 def print_unhandled(): 73 - keys = unhandled.keys() 74 - if not keys: 75 - return 71 + keys = unhandled.keys() 72 + if not keys: 73 + return 76 74 77 - print "\nunhandled events:\n\n", 75 + print("\nunhandled events:\n") 78 76 79 - print "%-40s %10s\n" % ("event", "count"), 80 - print "%-40s %10s\n" % ("----------------------------------------", \ 81 - "-----------"), 77 + print("%-40s %10s" % ("event", "count")) 78 + print("%-40s %10s" % ("----------------------------------------", 79 + "-----------")) 82 80 83 - for event_name in keys: 84 - print "%-40s %10d\n" % (event_name, unhandled[event_name]) 81 + for event_name in keys: 82 + print("%-40s %10d\n" % (event_name, unhandled[event_name]))
+4 -4
tools/perf/scripts/python/compaction-times.py
··· 216 216 pair(nr_migrated, nr_failed), None, None) 217 217 218 218 def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu, 219 - common_secs, common_nsecs, common_pid, common_comm, 220 - common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 219 + common_secs, common_nsecs, common_pid, common_comm, 220 + common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 221 221 222 222 chead.increment_pending(common_pid, 223 223 None, pair(nr_scanned, nr_taken), None) 224 224 225 225 def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu, 226 - common_secs, common_nsecs, common_pid, common_comm, 227 - common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 226 + common_secs, common_nsecs, common_pid, common_comm, 227 + common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 228 228 229 229 chead.increment_pending(common_pid, 230 230 None, None, pair(nr_scanned, nr_taken))
+25 -23
tools/perf/scripts/python/event_analyzing_sample.py
··· 15 15 # for a x86 HW PMU event: PEBS with load latency data. 16 16 # 17 17 18 + from __future__ import print_function 19 + 18 20 import os 19 21 import sys 20 22 import math ··· 39 37 con.isolation_level = None 40 38 41 39 def trace_begin(): 42 - print "In trace_begin:\n" 40 + print("In trace_begin:\n") 43 41 44 42 # 45 43 # Will create several tables at the start, pebs_ll is for PEBS data with ··· 78 76 name = param_dict["ev_name"] 79 77 80 78 # Symbol and dso info are not always resolved 81 - if (param_dict.has_key("dso")): 79 + if ("dso" in param_dict): 82 80 dso = param_dict["dso"] 83 81 else: 84 82 dso = "Unknown_dso" 85 83 86 - if (param_dict.has_key("symbol")): 84 + if ("symbol" in param_dict): 87 85 symbol = param_dict["symbol"] 88 86 else: 89 87 symbol = "Unknown_symbol" ··· 104 102 event.ip, event.status, event.dse, event.dla, event.lat)) 105 103 106 104 def trace_end(): 107 - print "In trace_end:\n" 105 + print("In trace_end:\n") 108 106 # We show the basic info for the 2 type of event classes 109 107 show_general_events() 110 108 show_pebs_ll() ··· 125 123 # Check the total record number in the table 126 124 count = con.execute("select count(*) from gen_events") 127 125 for t in count: 128 - print "There is %d records in gen_events table" % t[0] 126 + print("There is %d records in gen_events table" % t[0]) 129 127 if t[0] == 0: 130 128 return 131 129 132 - print "Statistics about the general events grouped by thread/symbol/dso: \n" 130 + print("Statistics about the general events grouped by thread/symbol/dso: \n") 133 131 134 132 # Group by thread 135 133 commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") 136 - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 134 + print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42)) 137 135 for row in commq: 138 - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 136 + print("%16s %8d %s" % (row[0], row[1], num2sym(row[1]))) 139 137 140 138 # Group by symbol 141 - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 139 + print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58)) 142 140 symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") 143 141 for row in symbolq: 144 - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 142 + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) 145 143 146 144 # Group by dso 147 - print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) 145 + print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74)) 148 146 dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") 149 147 for row in dsoq: 150 - print "%40s %8d %s" % (row[0], row[1], num2sym(row[1])) 148 + print("%40s %8d %s" % (row[0], row[1], num2sym(row[1]))) 151 149 152 150 # 153 151 # This function just shows the basic info, and we could do more with the ··· 158 156 159 157 count = con.execute("select count(*) from pebs_ll") 160 158 for t in count: 161 - print "There is %d records in pebs_ll table" % t[0] 159 + print("There is %d records in pebs_ll table" % t[0]) 162 160 if t[0] == 0: 163 161 return 164 162 165 - print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" 163 + print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n") 166 164 167 165 # Group by thread 168 166 commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") 169 - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 167 + print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42)) 170 168 for row in commq: 171 - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 169 + print("%16s %8d %s" % (row[0], row[1], num2sym(row[1]))) 172 170 173 171 # Group by symbol 174 - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 172 + print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58)) 175 173 symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") 176 174 for row in symbolq: 177 - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 175 + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) 178 176 179 177 # Group by dse 180 178 dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") 181 - print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) 179 + print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58)) 182 180 for row in dseq: 183 - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 181 + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) 184 182 185 183 # Group by latency 186 184 latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") 187 - print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) 185 + print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58)) 188 186 for row in latq: 189 - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 187 + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) 190 188 191 189 def trace_unhandled(event_name, context, event_fields_dict): 192 - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 190 + print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
+10 -6
tools/perf/scripts/python/export-to-postgresql.py
··· 394 394 'call_id bigint,' 395 395 'return_id bigint,' 396 396 'parent_call_path_id bigint,' 397 - 'flags integer)') 397 + 'flags integer,' 398 + 'parent_id bigint)') 398 399 399 400 do_query(query, 'CREATE VIEW machines_view AS ' 400 401 'SELECT ' ··· 479 478 'branch_count,' 480 479 'call_id,' 481 480 'return_id,' 482 - 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 483 - 'parent_call_path_id' 481 + 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,' 482 + 'parent_call_path_id,' 483 + 'calls.parent_id' 484 484 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 485 485 486 486 do_query(query, 'CREATE VIEW samples_view AS ' ··· 577 575 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 578 576 if perf_db_export_calls or perf_db_export_callchains: 579 577 call_path_table(0, 0, 0, 0) 578 + call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 580 579 581 580 unhandled_count = 0 582 581 ··· 660 657 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' 661 658 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') 662 659 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 660 + do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 663 661 664 662 if (unhandled_count): 665 663 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" ··· 732 728 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) 733 729 call_path_file.write(value) 734 730 735 - def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): 736 - fmt = "!hiqiqiqiqiqiqiqiqiqiqii" 737 - value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) 731 + def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, *x): 732 + fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiq" 733 + value = struct.pack(fmt, 12, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id) 738 734 call_file.write(value)
+8 -4
tools/perf/scripts/python/export-to-sqlite.py
··· 222 222 'call_id bigint,' 223 223 'return_id bigint,' 224 224 'parent_call_path_id bigint,' 225 - 'flags integer)') 225 + 'flags integer,' 226 + 'parent_id bigint)') 226 227 227 228 # printf was added to sqlite in version 3.8.3 228 229 sqlite_has_printf = False ··· 322 321 'call_id,' 323 322 'return_id,' 324 323 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 325 - 'parent_call_path_id' 324 + 'parent_call_path_id,' 325 + 'parent_id' 326 326 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 327 327 328 328 do_query(query, 'CREATE VIEW samples_view AS ' ··· 375 373 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)") 376 374 if perf_db_export_calls: 377 375 call_query = QSqlQuery(db) 378 - call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 376 + call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 379 377 380 378 def trace_begin(): 381 379 print datetime.datetime.today(), "Writing records..." ··· 390 388 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 391 389 if perf_db_export_calls or perf_db_export_callchains: 392 390 call_path_table(0, 0, 0, 0) 391 + call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 393 392 394 393 unhandled_count = 0 395 394 ··· 400 397 print datetime.datetime.today(), "Adding indexes" 401 398 if perf_db_export_calls: 402 399 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 400 + do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') 403 401 404 402 if (unhandled_count): 405 403 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" ··· 456 452 bind_exec(call_path_query, 4, x) 457 453 458 454 def call_return_table(*x): 459 - bind_exec(call_query, 11, x) 455 + bind_exec(call_query, 12, x)
+279 -75
tools/perf/scripts/python/exported-sql-viewer.py
··· 167 167 168 168 class TreeModel(QAbstractItemModel): 169 169 170 - def __init__(self, root, parent=None): 170 + def __init__(self, glb, parent=None): 171 171 super(TreeModel, self).__init__(parent) 172 - self.root = root 172 + self.glb = glb 173 + self.root = self.GetRoot() 173 174 self.last_row_read = 0 174 175 175 176 def Item(self, parent): ··· 558 557 self.child_items.append(child_item) 559 558 self.child_count += 1 560 559 561 - # Context-sensitive call graph data model 560 + # Context-sensitive call graph data model base 562 561 563 - class CallGraphModel(TreeModel): 562 + class CallGraphModelBase(TreeModel): 564 563 565 564 def __init__(self, glb, parent=None): 566 - super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent) 567 - self.glb = glb 568 - 569 - def columnCount(self, parent=None): 570 - return 7 571 - 572 - def columnHeader(self, column): 573 - headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] 574 - return headers[column] 575 - 576 - def columnAlignment(self, column): 577 - alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] 578 - return alignment[column] 565 + super(CallGraphModelBase, self).__init__(glb, parent) 579 566 580 567 def FindSelect(self, value, pattern, query): 581 568 if pattern: ··· 583 594 match = " GLOB '" + str(value) + "'" 584 595 else: 585 596 match = " = '" + str(value) + "'" 586 - QueryExec(query, "SELECT call_path_id, comm_id, thread_id" 587 - " FROM calls" 588 - " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" 589 - " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" 590 - " WHERE symbols.name" + match + 591 - " GROUP BY comm_id, thread_id, call_path_id" 592 - " ORDER BY comm_id, thread_id, call_path_id") 593 - 594 - def FindPath(self, query): 595 - # Turn the query result into a list of ids that the tree view can walk 596 - # to open the tree at the right place. 597 - ids = [] 598 - parent_id = query.value(0) 599 - while parent_id: 600 - ids.insert(0, parent_id) 601 - q2 = QSqlQuery(self.glb.db) 602 - QueryExec(q2, "SELECT parent_id" 603 - " FROM call_paths" 604 - " WHERE id = " + str(parent_id)) 605 - if not q2.next(): 606 - break 607 - parent_id = q2.value(0) 608 - # The call path root is not used 609 - if ids[0] == 1: 610 - del ids[0] 611 - ids.insert(0, query.value(2)) 612 - ids.insert(0, query.value(1)) 613 - return ids 597 + self.DoFindSelect(query, match) 614 598 615 599 def Found(self, query, found): 616 600 if found: ··· 637 675 def FindDone(self, thread, callback, ids): 638 676 callback(ids) 639 677 678 + # Context-sensitive call graph data model 679 + 680 + class CallGraphModel(CallGraphModelBase): 681 + 682 + def __init__(self, glb, parent=None): 683 + super(CallGraphModel, self).__init__(glb, parent) 684 + 685 + def GetRoot(self): 686 + return CallGraphRootItem(self.glb) 687 + 688 + def columnCount(self, parent=None): 689 + return 7 690 + 691 + def columnHeader(self, column): 692 + headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] 693 + return headers[column] 694 + 695 + def columnAlignment(self, column): 696 + alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] 697 + return alignment[column] 698 + 699 + def DoFindSelect(self, query, match): 700 + QueryExec(query, "SELECT call_path_id, comm_id, thread_id" 701 + " FROM calls" 702 + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" 703 + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" 704 + " WHERE symbols.name" + match + 705 + " GROUP BY comm_id, thread_id, call_path_id" 706 + " ORDER BY comm_id, thread_id, call_path_id") 707 + 708 + def FindPath(self, query): 709 + # Turn the query result into a list of ids that the tree view can walk 710 + # to open the tree at the right place. 711 + ids = [] 712 + parent_id = query.value(0) 713 + while parent_id: 714 + ids.insert(0, parent_id) 715 + q2 = QSqlQuery(self.glb.db) 716 + QueryExec(q2, "SELECT parent_id" 717 + " FROM call_paths" 718 + " WHERE id = " + str(parent_id)) 719 + if not q2.next(): 720 + break 721 + parent_id = q2.value(0) 722 + # The call path root is not used 723 + if ids[0] == 1: 724 + del ids[0] 725 + ids.insert(0, query.value(2)) 726 + ids.insert(0, query.value(1)) 727 + return ids 728 + 729 + # Call tree data model level 2+ item base 730 + 731 + class CallTreeLevelTwoPlusItemBase(CallGraphLevelItemBase): 732 + 733 + def __init__(self, glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item): 734 + super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, row, parent_item) 735 + self.comm_id = comm_id 736 + self.thread_id = thread_id 737 + self.calls_id = calls_id 738 + self.branch_count = branch_count 739 + self.time = time 740 + 741 + def Select(self): 742 + self.query_done = True; 743 + if self.calls_id == 0: 744 + comm_thread = " AND comm_id = " + str(self.comm_id) + " AND thread_id = " + str(self.thread_id) 745 + else: 746 + comm_thread = "" 747 + query = QSqlQuery(self.glb.db) 748 + QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time, branch_count" 749 + " FROM calls" 750 + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" 751 + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" 752 + " INNER JOIN dsos ON symbols.dso_id = dsos.id" 753 + " WHERE calls.parent_id = " + str(self.calls_id) + comm_thread + 754 + " ORDER BY call_time, calls.id") 755 + while query.next(): 756 + child_item = CallTreeLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self) 757 + self.child_items.append(child_item) 758 + self.child_count += 1 759 + 760 + # Call tree data model level three item 761 + 762 + class CallTreeLevelThreeItem(CallTreeLevelTwoPlusItemBase): 763 + 764 + def __init__(self, glb, row, comm_id, thread_id, calls_id, name, dso, count, time, branch_count, parent_item): 765 + super(CallTreeLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item) 766 + dso = dsoname(dso) 767 + self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ] 768 + self.dbid = calls_id 769 + 770 + # Call tree data model level two item 771 + 772 + class CallTreeLevelTwoItem(CallTreeLevelTwoPlusItemBase): 773 + 774 + def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item): 775 + super(CallTreeLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 0, 0, 0, parent_item) 776 + self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""] 777 + self.dbid = thread_id 778 + 779 + def Select(self): 780 + super(CallTreeLevelTwoItem, self).Select() 781 + for child_item in self.child_items: 782 + self.time += child_item.time 783 + self.branch_count += child_item.branch_count 784 + for child_item in self.child_items: 785 + child_item.data[4] = PercentToOneDP(child_item.time, self.time) 786 + child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) 787 + 788 + # Call tree data model level one item 789 + 790 + class CallTreeLevelOneItem(CallGraphLevelItemBase): 791 + 792 + def __init__(self, glb, row, comm_id, comm, parent_item): 793 + super(CallTreeLevelOneItem, self).__init__(glb, row, parent_item) 794 + self.data = [comm, "", "", "", "", "", ""] 795 + self.dbid = comm_id 796 + 797 + def Select(self): 798 + self.query_done = True; 799 + query = QSqlQuery(self.glb.db) 800 + QueryExec(query, "SELECT thread_id, pid, tid" 801 + " FROM comm_threads" 802 + " INNER JOIN threads ON thread_id = threads.id" 803 + " WHERE comm_id = " + str(self.dbid)) 804 + while query.next(): 805 + child_item = CallTreeLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self) 806 + self.child_items.append(child_item) 807 + self.child_count += 1 808 + 809 + # Call tree data model root item 810 + 811 + class CallTreeRootItem(CallGraphLevelItemBase): 812 + 813 + def __init__(self, glb): 814 + super(CallTreeRootItem, self).__init__(glb, 0, None) 815 + self.dbid = 0 816 + self.query_done = True; 817 + query = QSqlQuery(glb.db) 818 + QueryExec(query, "SELECT id, comm FROM comms") 819 + while query.next(): 820 + if not query.value(0): 821 + continue 822 + child_item = CallTreeLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self) 823 + self.child_items.append(child_item) 824 + self.child_count += 1 825 + 826 + # Call Tree data model 827 + 828 + class CallTreeModel(CallGraphModelBase): 829 + 830 + def __init__(self, glb, parent=None): 831 + super(CallTreeModel, self).__init__(glb, parent) 832 + 833 + def GetRoot(self): 834 + return CallTreeRootItem(self.glb) 835 + 836 + def columnCount(self, parent=None): 837 + return 7 838 + 839 + def columnHeader(self, column): 840 + headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] 841 + return headers[column] 842 + 843 + def columnAlignment(self, column): 844 + alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] 845 + return alignment[column] 846 + 847 + def DoFindSelect(self, query, match): 848 + QueryExec(query, "SELECT calls.id, comm_id, thread_id" 849 + " FROM calls" 850 + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" 851 + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" 852 + " WHERE symbols.name" + match + 853 + " ORDER BY comm_id, thread_id, call_time, calls.id") 854 + 855 + def FindPath(self, query): 856 + # Turn the query result into a list of ids that the tree view can walk 857 + # to open the tree at the right place. 858 + ids = [] 859 + parent_id = query.value(0) 860 + while parent_id: 861 + ids.insert(0, parent_id) 862 + q2 = QSqlQuery(self.glb.db) 863 + QueryExec(q2, "SELECT parent_id" 864 + " FROM calls" 865 + " WHERE id = " + str(parent_id)) 866 + if not q2.next(): 867 + break 868 + parent_id = q2.value(0) 869 + ids.insert(0, query.value(2)) 870 + ids.insert(0, query.value(1)) 871 + return ids 872 + 640 873 # Vertical widget layout 641 874 642 875 class VBox(): ··· 850 693 def Widget(self): 851 694 return self.vbox 852 695 853 - # Context-sensitive call graph window 696 + # Tree window base 854 697 855 - class CallGraphWindow(QMdiSubWindow): 698 + class TreeWindowBase(QMdiSubWindow): 856 699 857 - def __init__(self, glb, parent=None): 858 - super(CallGraphWindow, self).__init__(parent) 700 + def __init__(self, parent=None): 701 + super(TreeWindowBase, self).__init__(parent) 859 702 860 - self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 861 - 862 - self.view = QTreeView() 863 - self.view.setModel(self.model) 864 - 865 - for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): 866 - self.view.setColumnWidth(c, w) 867 - 868 - self.find_bar = FindBar(self, self) 869 - 870 - self.vbox = VBox(self.view, self.find_bar.Widget()) 871 - 872 - self.setWidget(self.vbox.Widget()) 873 - 874 - AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") 703 + self.model = None 704 + self.view = None 705 + self.find_bar = None 875 706 876 707 def DisplayFound(self, ids): 877 708 if not len(ids): ··· 891 746 self.find_bar.Idle() 892 747 if not found: 893 748 self.find_bar.NotFound() 749 + 750 + 751 + # Context-sensitive call graph window 752 + 753 + class CallGraphWindow(TreeWindowBase): 754 + 755 + def __init__(self, glb, parent=None): 756 + super(CallGraphWindow, self).__init__(parent) 757 + 758 + self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 759 + 760 + self.view = QTreeView() 761 + self.view.setModel(self.model) 762 + 763 + for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): 764 + self.view.setColumnWidth(c, w) 765 + 766 + self.find_bar = FindBar(self, self) 767 + 768 + self.vbox = VBox(self.view, self.find_bar.Widget()) 769 + 770 + self.setWidget(self.vbox.Widget()) 771 + 772 + AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") 773 + 774 + # Call tree window 775 + 776 + class CallTreeWindow(TreeWindowBase): 777 + 778 + def __init__(self, glb, parent=None): 779 + super(CallTreeWindow, self).__init__(parent) 780 + 781 + self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 782 + 783 + self.view = QTreeView() 784 + self.view.setModel(self.model) 785 + 786 + for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): 787 + self.view.setColumnWidth(c, w) 788 + 789 + self.find_bar = FindBar(self, self) 790 + 791 + self.vbox = VBox(self.view, self.find_bar.Widget()) 792 + 793 + self.setWidget(self.vbox.Widget()) 794 + 795 + AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree") 894 796 895 797 # Child data item finder 896 798 ··· 1519 1327 progress = Signal(object) 1520 1328 1521 1329 def __init__(self, glb, event_id, where_clause, parent=None): 1522 - super(BranchModel, self).__init__(BranchRootItem(), parent) 1523 - self.glb = glb 1330 + super(BranchModel, self).__init__(glb, parent) 1524 1331 self.event_id = event_id 1525 1332 self.more = True 1526 1333 self.populated = 0 ··· 1542 1351 self.fetcher = SQLFetcher(glb, sql, BranchDataPrep, self.AddSample) 1543 1352 self.fetcher.done.connect(self.Update) 1544 1353 self.fetcher.Fetch(glb_chunk_sz) 1354 + 1355 + def GetRoot(self): 1356 + return BranchRootItem() 1545 1357 1546 1358 def columnCount(self, parent=None): 1547 1359 return 8 ··· 2057 1863 2058 1864 # Is a table selectable 2059 1865 2060 - def IsSelectable(db, table): 1866 + def IsSelectable(db, table, sql = ""): 2061 1867 query = QSqlQuery(db) 2062 1868 try: 2063 - QueryExec(query, "SELECT * FROM " + table + " LIMIT 1") 1869 + QueryExec(query, "SELECT * FROM " + table + " " + sql + " LIMIT 1") 2064 1870 except: 2065 1871 return False 2066 1872 return True ··· 2469 2275 </style> 2470 2276 <p class=c1><a href=#reports>1. Reports</a></p> 2471 2277 <p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p> 2472 - <p class=c2><a href=#allbranches>1.2 All branches</a></p> 2473 - <p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p> 2474 - <p class=c2><a href=#topcallsbyelapsedtime>1.4 Top calls by elapsed time</a></p> 2278 + <p class=c2><a href=#calltree>1.2 Call Tree</a></p> 2279 + <p class=c2><a href=#allbranches>1.3 All branches</a></p> 2280 + <p class=c2><a href=#selectedbranches>1.4 Selected branches</a></p> 2281 + <p class=c2><a href=#topcallsbyelapsedtime>1.5 Top calls by elapsed time</a></p> 2475 2282 <p class=c1><a href=#tables>2. Tables</a></p> 2476 2283 <h1 id=reports>1. Reports</h1> 2477 2284 <h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2> ··· 2508 2313 <h3>Find</h3> 2509 2314 Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match. 2510 2315 The pattern matching symbols are ? for any character and * for zero or more characters. 2511 - <h2 id=allbranches>1.2 All branches</h2> 2316 + <h2 id=calltree>1.2 Call Tree</h2> 2317 + The Call Tree report is very similar to the Context-Sensitive Call Graph, but the data is not aggregated. 2318 + Also the 'Count' column, which would be always 1, is replaced by the 'Call Time'. 2319 + <h2 id=allbranches>1.3 All branches</h2> 2512 2320 The All branches report displays all branches in chronological order. 2513 2321 Not all data is fetched immediately. More records can be fetched using the Fetch bar provided. 2514 2322 <h3>Disassembly</h3> ··· 2537 2339 Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. 2538 2340 Refer to Python documentation for the regular expression syntax. 2539 2341 All columns are searched, but only currently fetched rows are searched. 2540 - <h2 id=selectedbranches>1.3 Selected branches</h2> 2342 + <h2 id=selectedbranches>1.4 Selected branches</h2> 2541 2343 This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced 2542 2344 by various selection criteria. A dialog box displays available criteria which are AND'ed together. 2543 - <h3>1.3.1 Time ranges</h3> 2345 + <h3>1.4.1 Time ranges</h3> 2544 2346 The time ranges hint text shows the total time range. Relative time ranges can also be entered in 2545 2347 ms, us or ns. Also, negative values are relative to the end of trace. Examples: 2546 2348 <pre> ··· 2551 2353 -10ms- The last 10ms 2552 2354 </pre> 2553 2355 N.B. Due to the granularity of timestamps, there could be no branches in any given time range. 2554 - <h2 id=topcallsbyelapsedtime>1.4 Top calls by elapsed time</h2> 2356 + <h2 id=topcallsbyelapsedtime>1.5 Top calls by elapsed time</h2> 2555 2357 The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned. 2556 2358 The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together. 2557 2359 If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar. ··· 2687 2489 if IsSelectable(glb.db, "calls"): 2688 2490 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) 2689 2491 2492 + if IsSelectable(glb.db, "calls", "WHERE parent_id >= 0"): 2493 + reports_menu.addAction(CreateAction("Call &Tree", "Create a new window containing a call tree", self.NewCallTree, self)) 2494 + 2690 2495 self.EventMenu(GetEventList(glb.db), reports_menu) 2691 2496 2692 2497 if IsSelectable(glb.db, "calls"): ··· 2749 2548 2750 2549 def NewCallGraph(self): 2751 2550 CallGraphWindow(self.glb, self) 2551 + 2552 + def NewCallTree(self): 2553 + CallTreeWindow(self.glb, self) 2752 2554 2753 2555 def NewTopCalls(self): 2754 2556 dialog = TopCallsDialog(self.glb, self)
+17 -17
tools/perf/scripts/python/failed-syscalls-by-pid.py
··· 58 58 raw_syscalls__sys_exit(**locals()) 59 59 60 60 def print_error_totals(): 61 - if for_comm is not None: 62 - print("\nsyscall errors for %s:\n" % (for_comm)) 63 - else: 64 - print("\nsyscall errors:\n") 61 + if for_comm is not None: 62 + print("\nsyscall errors for %s:\n" % (for_comm)) 63 + else: 64 + print("\nsyscall errors:\n") 65 65 66 - print("%-30s %10s" % ("comm [pid]", "count")) 67 - print("%-30s %10s" % ("------------------------------", "----------")) 66 + print("%-30s %10s" % ("comm [pid]", "count")) 67 + print("%-30s %10s" % ("------------------------------", "----------")) 68 68 69 - comm_keys = syscalls.keys() 70 - for comm in comm_keys: 71 - pid_keys = syscalls[comm].keys() 72 - for pid in pid_keys: 73 - print("\n%s [%d]" % (comm, pid)) 74 - id_keys = syscalls[comm][pid].keys() 75 - for id in id_keys: 76 - print(" syscall: %-16s" % syscall_name(id)) 77 - ret_keys = syscalls[comm][pid][id].keys() 78 - for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): 79 - print(" err = %-20s %10d" % (strerror(ret), val)) 69 + comm_keys = syscalls.keys() 70 + for comm in comm_keys: 71 + pid_keys = syscalls[comm].keys() 72 + for pid in pid_keys: 73 + print("\n%s [%d]" % (comm, pid)) 74 + id_keys = syscalls[comm][pid].keys() 75 + for id in id_keys: 76 + print(" syscall: %-16s" % syscall_name(id)) 77 + ret_keys = syscalls[comm][pid][id].keys() 78 + for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): 79 + print(" err = %-20s %10d" % (strerror(ret), val))
+6 -4
tools/perf/scripts/python/futex-contention.py
··· 10 10 # 11 11 # Measures futex contention 12 12 13 + from __future__ import print_function 14 + 13 15 import os, sys 14 16 sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 15 17 from Util import * ··· 35 33 36 34 def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, 37 35 nr, ret): 38 - if thread_blocktime.has_key(tid): 36 + if tid in thread_blocktime: 39 37 elapsed = nsecs(s, ns) - thread_blocktime[tid] 40 38 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed) 41 39 del thread_blocktime[tid] 42 40 del thread_thislock[tid] 43 41 44 42 def trace_begin(): 45 - print "Press control+C to stop and show the summary" 43 + print("Press control+C to stop and show the summary") 46 44 47 45 def trace_end(): 48 46 for (tid, lock) in lock_waits: 49 47 min, max, avg, count = lock_waits[tid, lock] 50 - print "%s[%d] lock %x contended %d times, %d avg ns" % \ 51 - (process_names[tid], tid, lock, count, avg) 48 + print("%s[%d] lock %x contended %d times, %d avg ns" % 49 + (process_names[tid], tid, lock, count, avg)) 52 50
+31 -25
tools/perf/scripts/python/intel-pt-events.py
··· 10 10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 11 # more details. 12 12 13 + from __future__ import print_function 14 + 13 15 import os 14 16 import sys 15 17 import struct ··· 24 22 #from Core import * 25 23 26 24 def trace_begin(): 27 - print "Intel PT Power Events and PTWRITE" 25 + print("Intel PT Power Events and PTWRITE") 28 26 29 27 def trace_end(): 30 - print "End" 28 + print("End") 31 29 32 30 def trace_unhandled(event_name, context, event_fields_dict): 33 - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 31 + print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])) 34 32 35 33 def print_ptwrite(raw_buf): 36 34 data = struct.unpack_from("<IQ", raw_buf) 37 35 flags = data[0] 38 36 payload = data[1] 39 37 exact_ip = flags & 1 40 - print "IP: %u payload: %#x" % (exact_ip, payload), 38 + print("IP: %u payload: %#x" % (exact_ip, payload), end=' ') 41 39 42 40 def print_cbr(raw_buf): 43 41 data = struct.unpack_from("<BBBBII", raw_buf) 44 42 cbr = data[0] 45 43 f = (data[4] + 500) / 1000 46 44 p = ((cbr * 1000 / data[2]) + 5) / 10 47 - print "%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), 45 + print("%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), end=' ') 48 46 49 47 def print_mwait(raw_buf): 50 48 data = struct.unpack_from("<IQ", raw_buf) 51 49 payload = data[1] 52 50 hints = payload & 0xff 53 51 extensions = (payload >> 32) & 0x3 54 - print "hints: %#x extensions: %#x" % (hints, extensions), 52 + print("hints: %#x extensions: %#x" % (hints, extensions), end=' ') 55 53 56 54 def print_pwre(raw_buf): 57 55 data = struct.unpack_from("<IQ", raw_buf) ··· 59 57 hw = (payload >> 7) & 1 60 58 cstate = (payload >> 12) & 0xf 61 59 subcstate = (payload >> 8) & 0xf 62 - print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), 60 + print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), 61 + end=' ') 63 62 64 63 def print_exstop(raw_buf): 65 64 data = struct.unpack_from("<I", raw_buf) 66 65 flags = data[0] 67 66 exact_ip = flags & 1 68 - print "IP: %u" % (exact_ip), 67 + print("IP: %u" % (exact_ip), end=' ') 69 68 70 69 def print_pwrx(raw_buf): 71 70 data = struct.unpack_from("<IQ", raw_buf) ··· 74 71 deepest_cstate = payload & 0xf 75 72 last_cstate = (payload >> 4) & 0xf 76 73 wake_reason = (payload >> 8) & 0xf 77 - print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason), 74 + print("deepest cstate: %u last cstate: %u wake reason: %#x" % 75 + (deepest_cstate, last_cstate, wake_reason), end=' ') 78 76 79 77 def print_common_start(comm, sample, name): 80 78 ts = sample["time"] 81 79 cpu = sample["cpu"] 82 80 pid = sample["pid"] 83 81 tid = sample["tid"] 84 - print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), 82 + print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" % 83 + (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), 84 + end=' ') 85 85 86 86 def print_common_ip(sample, symbol, dso): 87 87 ip = sample["ip"] 88 - print "%16x %s (%s)" % (ip, symbol, dso) 88 + print("%16x %s (%s)" % (ip, symbol, dso)) 89 89 90 90 def process_event(param_dict): 91 - event_attr = param_dict["attr"] 92 - sample = param_dict["sample"] 93 - raw_buf = param_dict["raw_buf"] 94 - comm = param_dict["comm"] 95 - name = param_dict["ev_name"] 91 + event_attr = param_dict["attr"] 92 + sample = param_dict["sample"] 93 + raw_buf = param_dict["raw_buf"] 94 + comm = param_dict["comm"] 95 + name = param_dict["ev_name"] 96 96 97 - # Symbol and dso info are not always resolved 98 - if (param_dict.has_key("dso")): 99 - dso = param_dict["dso"] 100 - else: 101 - dso = "[unknown]" 97 + # Symbol and dso info are not always resolved 98 + if "dso" in param_dict: 99 + dso = param_dict["dso"] 100 + else: 101 + dso = "[unknown]" 102 102 103 - if (param_dict.has_key("symbol")): 104 - symbol = param_dict["symbol"] 105 - else: 106 - symbol = "[unknown]" 103 + if "symbol" in param_dict: 104 + symbol = param_dict["symbol"] 105 + else: 106 + symbol = "[unknown]" 107 107 108 108 if name == "ptwrite": 109 109 print_common_start(comm, sample, name)
+4 -3
tools/perf/scripts/python/mem-phys-addr.py
··· 44 44 print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='') 45 45 print("%-40s %10s %10s\n" % ("----------------------------------------", 46 46 "-----------", "-----------"), 47 - end=''); 47 + end=''); 48 48 total = sum(load_mem_type_cnt.values()) 49 49 for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ 50 50 key = lambda kv: (kv[1], kv[0]), reverse = True): 51 - print("%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), 52 - end='') 51 + print("%-40s %10d %10.1f%%\n" % 52 + (mem_type, count, 100 * count / total), 53 + end='') 53 54 54 55 def trace_begin(): 55 56 parse_iomem()
+1 -1
tools/perf/scripts/python/net_dropmonitor.py
··· 7 7 import sys 8 8 9 9 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 10 - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 10 + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 11 11 12 12 from perf_trace_context import * 13 13 from Core import *
+7 -5
tools/perf/scripts/python/netdev-times.py
··· 124 124 event = event_list[i] 125 125 if event['event_name'] == 'napi_poll': 126 126 print(PF_NAPI_POLL % 127 - (diff_msec(base_t, event['event_t']), event['dev'])) 127 + (diff_msec(base_t, event['event_t']), 128 + event['dev'])) 128 129 if i == len(event_list) - 1: 129 130 print("") 130 131 else: 131 132 print(PF_JOINT) 132 133 else: 133 134 print(PF_NET_RECV % 134 - (diff_msec(base_t, event['event_t']), event['skbaddr'], 135 + (diff_msec(base_t, event['event_t']), 136 + event['skbaddr'], 135 137 event['len'])) 136 138 if 'comm' in event.keys(): 137 139 print(PF_WJOINT) ··· 258 256 all_event_list.append(event_info) 259 257 260 258 def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, 261 - dev_name, work=None, budget=None): 259 + dev_name, work=None, budget=None): 262 260 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 263 261 napi, dev_name, work, budget) 264 262 all_event_list.append(event_info) ··· 355 353 if irq_list == [] or event_list == 0: 356 354 return 357 355 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time, 358 - 'irq_list':irq_list, 'event_list':event_list} 356 + 'irq_list':irq_list, 'event_list':event_list} 359 357 # merge information realted to a NET_RX softirq 360 358 receive_hunk_list.append(rec_data) 361 359 ··· 392 390 skbaddr, skblen, dev_name) = event_info 393 391 if cpu in net_rx_dic.keys(): 394 392 rec_data = {'event_name':'netif_receive_skb', 395 - 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} 393 + 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} 396 394 event_list = net_rx_dic[cpu]['event_list'] 397 395 event_list.append(rec_data) 398 396 rx_skb_list.insert(0, rec_data)
+3 -3
tools/perf/scripts/python/sched-migration.py
··· 14 14 15 15 from collections import defaultdict 16 16 try: 17 - from UserList import UserList 17 + from UserList import UserList 18 18 except ImportError: 19 - # Python 3: UserList moved to the collections package 20 - from collections import UserList 19 + # Python 3: UserList moved to the collections package 20 + from collections import UserList 21 21 22 22 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 23 23 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+7 -6
tools/perf/scripts/python/sctop.py
··· 13 13 import os, sys, time 14 14 15 15 try: 16 - import thread 16 + import thread 17 17 except ImportError: 18 - import _thread as thread 18 + import _thread as thread 19 19 20 20 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 21 21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') ··· 75 75 76 76 print("%-40s %10s" % ("event", "count")) 77 77 print("%-40s %10s" % 78 - ("----------------------------------------", 79 - "----------")) 78 + ("----------------------------------------", 79 + "----------")) 80 80 81 - for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ 82 - reverse = True): 81 + for id, val in sorted(syscalls.items(), 82 + key = lambda kv: (kv[1], kv[0]), 83 + reverse = True): 83 84 try: 84 85 print("%-40s %10d" % (syscall_name(id), val)) 85 86 except TypeError:
+1 -1
tools/perf/scripts/python/stackcollapse.py
··· 27 27 from optparse import OptionParser, make_option 28 28 29 29 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 30 - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 30 + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 31 31 32 32 from perf_trace_context import * 33 33 from Core import *
+21 -22
tools/perf/scripts/python/syscall-counts-by-pid.py
··· 39 39 print_syscall_totals() 40 40 41 41 def raw_syscalls__sys_enter(event_name, context, common_cpu, 42 - common_secs, common_nsecs, common_pid, common_comm, 43 - common_callchain, id, args): 44 - 42 + common_secs, common_nsecs, common_pid, common_comm, 43 + common_callchain, id, args): 45 44 if (for_comm and common_comm != for_comm) or \ 46 - (for_pid and common_pid != for_pid ): 45 + (for_pid and common_pid != for_pid ): 47 46 return 48 47 try: 49 48 syscalls[common_comm][common_pid][id] += 1 ··· 50 51 syscalls[common_comm][common_pid][id] = 1 51 52 52 53 def syscalls__sys_enter(event_name, context, common_cpu, 53 - common_secs, common_nsecs, common_pid, common_comm, 54 - id, args): 54 + common_secs, common_nsecs, common_pid, common_comm, 55 + id, args): 55 56 raw_syscalls__sys_enter(**locals()) 56 57 57 58 def print_syscall_totals(): 58 - if for_comm is not None: 59 - print("\nsyscall events for %s:\n" % (for_comm)) 60 - else: 61 - print("\nsyscall events by comm/pid:\n") 59 + if for_comm is not None: 60 + print("\nsyscall events for %s:\n" % (for_comm)) 61 + else: 62 + print("\nsyscall events by comm/pid:\n") 62 63 63 - print("%-40s %10s" % ("comm [pid]/syscalls", "count")) 64 - print("%-40s %10s" % ("----------------------------------------", 65 - "----------")) 64 + print("%-40s %10s" % ("comm [pid]/syscalls", "count")) 65 + print("%-40s %10s" % ("----------------------------------------", 66 + "----------")) 66 67 67 - comm_keys = syscalls.keys() 68 - for comm in comm_keys: 69 - pid_keys = syscalls[comm].keys() 70 - for pid in pid_keys: 71 - print("\n%s [%d]" % (comm, pid)) 72 - id_keys = syscalls[comm][pid].keys() 73 - for id, val in sorted(syscalls[comm][pid].items(), \ 74 - key = lambda kv: (kv[1], kv[0]), reverse = True): 75 - print(" %-38s %10d" % (syscall_name(id), val)) 68 + comm_keys = syscalls.keys() 69 + for comm in comm_keys: 70 + pid_keys = syscalls[comm].keys() 71 + for pid in pid_keys: 72 + print("\n%s [%d]" % (comm, pid)) 73 + id_keys = syscalls[comm][pid].keys() 74 + for id, val in sorted(syscalls[comm][pid].items(), 75 + key = lambda kv: (kv[1], kv[0]), reverse = True): 76 + print(" %-38s %10d" % (syscall_name(id), val))
+13 -14
tools/perf/scripts/python/syscall-counts.py
··· 36 36 print_syscall_totals() 37 37 38 38 def raw_syscalls__sys_enter(event_name, context, common_cpu, 39 - common_secs, common_nsecs, common_pid, common_comm, 40 - common_callchain, id, args): 39 + common_secs, common_nsecs, common_pid, common_comm, 40 + common_callchain, id, args): 41 41 if for_comm is not None: 42 42 if common_comm != for_comm: 43 43 return ··· 47 47 syscalls[id] = 1 48 48 49 49 def syscalls__sys_enter(event_name, context, common_cpu, 50 - common_secs, common_nsecs, common_pid, common_comm, 51 - id, args): 50 + common_secs, common_nsecs, common_pid, common_comm, id, args): 52 51 raw_syscalls__sys_enter(**locals()) 53 52 54 53 def print_syscall_totals(): 55 - if for_comm is not None: 56 - print("\nsyscall events for %s:\n" % (for_comm)) 57 - else: 58 - print("\nsyscall events:\n") 54 + if for_comm is not None: 55 + print("\nsyscall events for %s:\n" % (for_comm)) 56 + else: 57 + print("\nsyscall events:\n") 59 58 60 - print("%-40s %10s" % ("event", "count")) 61 - print("%-40s %10s" % ("----------------------------------------", 62 - "-----------")) 59 + print("%-40s %10s" % ("event", "count")) 60 + print("%-40s %10s" % ("----------------------------------------", 61 + "-----------")) 63 62 64 - for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ 65 - reverse = True): 66 - print("%-40s %10d" % (syscall_name(id), val)) 63 + for id, val in sorted(syscalls.items(), 64 + key = lambda kv: (kv[1], kv[0]), reverse = True): 65 + print("%-40s %10d" % (syscall_name(id), val))
+1 -1
tools/perf/trace/beauty/msg_flags.c
··· 29 29 return scnprintf(bf, size, "NONE"); 30 30 #define P_MSG_FLAG(n) \ 31 31 if (flags & MSG_##n) { \ 32 - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ 32 + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ 33 33 flags &= ~MSG_##n; \ 34 34 } 35 35
+46 -28
tools/perf/util/annotate.c
··· 198 198 } 199 199 200 200 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, 201 - struct ins_operands *ops) 201 + struct ins_operands *ops, int max_ins_name) 202 202 { 203 - return scnprintf(bf, size, "%-6s %s", ins->name, ops->raw); 203 + return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw); 204 204 } 205 205 206 206 int ins__scnprintf(struct ins *ins, char *bf, size_t size, 207 - struct ins_operands *ops) 207 + struct ins_operands *ops, int max_ins_name) 208 208 { 209 209 if (ins->ops->scnprintf) 210 - return ins->ops->scnprintf(ins, bf, size, ops); 210 + return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name); 211 211 212 - return ins__raw_scnprintf(ins, bf, size, ops); 212 + return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name); 213 213 } 214 214 215 215 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2) ··· 273 273 } 274 274 275 275 static int call__scnprintf(struct ins *ins, char *bf, size_t size, 276 - struct ins_operands *ops) 276 + struct ins_operands *ops, int max_ins_name) 277 277 { 278 278 if (ops->target.sym) 279 - return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); 279 + return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name); 280 280 281 281 if (ops->target.addr == 0) 282 - return ins__raw_scnprintf(ins, bf, size, ops); 282 + return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name); 283 283 284 284 if (ops->target.name) 285 - return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name); 285 + return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name); 286 286 287 - return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr); 287 + return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr); 288 288 } 289 289 290 290 static struct ins_ops call_ops = { ··· 388 388 } 389 389 390 390 static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 391 - struct ins_operands *ops) 391 + struct ins_operands *ops, int max_ins_name) 392 392 { 393 393 const char *c; 394 394 395 395 if (!ops->target.addr || ops->target.offset < 0) 396 - return ins__raw_scnprintf(ins, bf, size, ops); 396 + return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name); 397 397 398 398 if (ops->target.outside && ops->target.sym != NULL) 399 - return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); 399 + return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name); 400 400 401 401 c = strchr(ops->raw, ','); 402 402 c = validate_comma(c, ops); ··· 415 415 c++; 416 416 } 417 417 418 - return scnprintf(bf, size, "%-6s %.*s%" PRIx64, 418 + return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name, 419 419 ins->name, c ? c - ops->raw : 0, ops->raw, 420 420 ops->target.offset); 421 421 } ··· 483 483 } 484 484 485 485 static int lock__scnprintf(struct ins *ins, char *bf, size_t size, 486 - struct ins_operands *ops) 486 + struct ins_operands *ops, int max_ins_name) 487 487 { 488 488 int printed; 489 489 490 490 if (ops->locked.ins.ops == NULL) 491 - return ins__raw_scnprintf(ins, bf, size, ops); 491 + return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name); 492 492 493 - printed = scnprintf(bf, size, "%-6s ", ins->name); 493 + printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name); 494 494 return printed + ins__scnprintf(&ops->locked.ins, bf + printed, 495 - size - printed, ops->locked.ops); 495 + size - printed, ops->locked.ops, max_ins_name); 496 496 } 497 497 498 498 static void lock__delete(struct ins_operands *ops) ··· 564 564 } 565 565 566 566 static int mov__scnprintf(struct ins *ins, char *bf, size_t size, 567 - struct ins_operands *ops) 567 + struct ins_operands *ops, int max_ins_name) 568 568 { 569 - return scnprintf(bf, size, "%-6s %s,%s", ins->name, 569 + return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name, 570 570 ops->source.name ?: ops->source.raw, 571 571 ops->target.name ?: ops->target.raw); 572 572 } ··· 604 604 } 605 605 606 606 static int dec__scnprintf(struct ins *ins, char *bf, size_t size, 607 - struct ins_operands *ops) 607 + struct ins_operands *ops, int max_ins_name) 608 608 { 609 - return scnprintf(bf, size, "%-6s %s", ins->name, 609 + return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, 610 610 ops->target.name ?: ops->target.raw); 611 611 } 612 612 ··· 616 616 }; 617 617 618 618 static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, 619 - struct ins_operands *ops __maybe_unused) 619 + struct ins_operands *ops __maybe_unused, int max_ins_name) 620 620 { 621 - return scnprintf(bf, size, "%-6s", "nop"); 621 + return scnprintf(bf, size, "%-*s", max_ins_name, "nop"); 622 622 } 623 623 624 624 static struct ins_ops nop_ops = { ··· 1232 1232 annotation_line__delete(&dl->al); 1233 1233 } 1234 1234 1235 - int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw) 1235 + int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name) 1236 1236 { 1237 1237 if (raw || !dl->ins.ops) 1238 - return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw); 1238 + return scnprintf(bf, size, "%-*s %s", max_ins_name, dl->ins.name, dl->ops.raw); 1239 1239 1240 - return ins__scnprintf(&dl->ins, bf, size, &dl->ops); 1240 + return ins__scnprintf(&dl->ins, bf, size, &dl->ops, max_ins_name); 1241 1241 } 1242 1242 1243 1243 static void annotation_line__add(struct annotation_line *al, struct list_head *head) ··· 2414 2414 return 1; 2415 2415 } 2416 2416 2417 + static int annotation__max_ins_name(struct annotation *notes) 2418 + { 2419 + int max_name = 0, len; 2420 + struct annotation_line *al; 2421 + 2422 + list_for_each_entry(al, &notes->src->source, node) { 2423 + if (al->offset == -1) 2424 + continue; 2425 + 2426 + len = strlen(disasm_line(al)->ins.name); 2427 + if (max_name < len) 2428 + max_name = len; 2429 + } 2430 + 2431 + return max_name; 2432 + } 2433 + 2417 2434 void annotation__init_column_widths(struct annotation *notes, struct symbol *sym) 2418 2435 { 2419 2436 notes->widths.addr = notes->widths.target = 2420 2437 notes->widths.min_addr = hex_width(symbol__size(sym)); 2421 2438 notes->widths.max_addr = hex_width(sym->end); 2422 2439 notes->widths.jumps = width_jumps(notes->max_jump_sources); 2440 + notes->widths.max_ins_name = annotation__max_ins_name(notes); 2423 2441 } 2424 2442 2425 2443 void annotation__update_column_widths(struct annotation *notes) ··· 2601 2583 obj__printf(obj, " "); 2602 2584 } 2603 2585 2604 - disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset); 2586 + disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name); 2605 2587 } 2606 2588 2607 2589 static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
+4 -3
tools/perf/util/annotate.h
··· 59 59 void (*free)(struct ins_operands *ops); 60 60 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms); 61 61 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 62 - struct ins_operands *ops); 62 + struct ins_operands *ops, int max_ins_name); 63 63 }; 64 64 65 65 bool ins__is_jump(const struct ins *ins); 66 66 bool ins__is_call(const struct ins *ins); 67 67 bool ins__is_ret(const struct ins *ins); 68 68 bool ins__is_lock(const struct ins *ins); 69 - int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 69 + int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops, int max_ins_name); 70 70 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 71 71 72 72 #define ANNOTATION__IPC_WIDTH 6 ··· 219 219 struct perf_evsel *evsel, 220 220 bool show_freq); 221 221 222 - int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 222 + int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name); 223 223 size_t disasm__fprintf(struct list_head *head, FILE *fp); 224 224 void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 225 225 ··· 289 289 u8 target; 290 290 u8 min_addr; 291 291 u8 max_addr; 292 + u8 max_ins_name; 292 293 } widths; 293 294 bool have_cycles; 294 295 struct annotated_source *src;
+2 -1
tools/perf/util/auxtrace.c
··· 1918 1918 if (!map) 1919 1919 return NULL; 1920 1920 1921 - map__load(map); 1921 + if (map__load(map) < 0) 1922 + pr_err("File '%s' not found or has no symbols.\n", name); 1922 1923 1923 1924 dso = dso__get(map->dso); 1924 1925
+1 -1
tools/perf/util/c++/clang.cpp
··· 156 156 #endif 157 157 if (NotAdded) { 158 158 llvm::errs() << "TargetMachine can't emit a file of this type\n"; 159 - return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; 159 + return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr); 160 160 } 161 161 PM.run(*Module); 162 162
+2 -2
tools/perf/util/data.c
··· 237 237 open_file_read(data) : open_file_write(data); 238 238 239 239 if (fd < 0) { 240 - free(data->file.path); 240 + zfree(&data->file.path); 241 241 return -1; 242 242 } 243 243 ··· 270 270 271 271 void perf_data__close(struct perf_data *data) 272 272 { 273 - free(data->file.path); 273 + zfree(&data->file.path); 274 274 close(data->file.fd); 275 275 } 276 276
+10 -5
tools/perf/util/db-export.c
··· 510 510 return 0; 511 511 } 512 512 513 - int db_export__call_return(struct db_export *dbe, struct call_return *cr) 513 + int db_export__call_return(struct db_export *dbe, struct call_return *cr, 514 + u64 *parent_db_id) 514 515 { 515 516 int err; 516 - 517 - if (cr->db_id) 518 - return 0; 519 517 520 518 err = db_export__call_path(dbe, cr->cp); 521 519 if (err) 522 520 return err; 523 521 524 - cr->db_id = ++dbe->call_return_last_db_id; 522 + if (!cr->db_id) 523 + cr->db_id = ++dbe->call_return_last_db_id; 524 + 525 + if (parent_db_id) { 526 + if (!*parent_db_id) 527 + *parent_db_id = ++dbe->call_return_last_db_id; 528 + cr->parent_db_id = *parent_db_id; 529 + } 525 530 526 531 if (dbe->export_call_return) 527 532 return dbe->export_call_return(dbe, cr);
+2 -1
tools/perf/util/db-export.h
··· 104 104 int db_export__branch_types(struct db_export *dbe); 105 105 106 106 int db_export__call_path(struct db_export *dbe, struct call_path *cp); 107 - int db_export__call_return(struct db_export *dbe, struct call_return *cr); 107 + int db_export__call_return(struct db_export *dbe, struct call_return *cr, 108 + u64 *parent_db_id); 108 109 109 110 #endif
+20 -5
tools/perf/util/evlist.c
··· 230 230 } 231 231 } 232 232 233 - void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) 233 + void perf_event_attr__set_max_precise_ip(struct perf_event_attr *pattr) 234 234 { 235 - attr->precise_ip = 3; 235 + struct perf_event_attr attr = { 236 + .type = PERF_TYPE_HARDWARE, 237 + .config = PERF_COUNT_HW_CPU_CYCLES, 238 + .exclude_kernel = 1, 239 + .precise_ip = 3, 240 + }; 236 241 237 - while (attr->precise_ip != 0) { 238 - int fd = sys_perf_event_open(attr, 0, -1, -1, 0); 242 + event_attr_init(&attr); 243 + 244 + /* 245 + * Unnamed union member, not supported as struct member named 246 + * initializer in older compilers such as gcc 4.4.7 247 + */ 248 + attr.sample_period = 1; 249 + 250 + while (attr.precise_ip != 0) { 251 + int fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 239 252 if (fd != -1) { 240 253 close(fd); 241 254 break; 242 255 } 243 - --attr->precise_ip; 256 + --attr.precise_ip; 244 257 } 258 + 259 + pattr->precise_ip = attr.precise_ip; 245 260 } 246 261 247 262 int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
-8
tools/perf/util/evsel.c
··· 294 294 295 295 if (!precise) 296 296 goto new_event; 297 - /* 298 - * Unnamed union member, not supported as struct member named 299 - * initializer in older compilers such as gcc 4.4.7 300 - * 301 - * Just for probing the precise_ip: 302 - */ 303 - attr.sample_period = 1; 304 297 305 298 perf_event_attr__set_max_precise_ip(&attr); 306 299 /* 307 300 * Now let the usual logic to set up the perf_event_attr defaults 308 301 * to kick in when we return and before perf_evsel__open() is called. 309 302 */ 310 - attr.sample_period = 0; 311 303 new_event: 312 304 evsel = perf_evsel__new(&attr); 313 305 if (evsel == NULL)
+31 -22
tools/perf/util/hist.c
··· 396 396 * adding new entries. So we need to save a copy. 397 397 */ 398 398 he->branch_info = malloc(sizeof(*he->branch_info)); 399 - if (he->branch_info == NULL) { 400 - map__zput(he->ms.map); 401 - free(he->stat_acc); 402 - return -ENOMEM; 403 - } 399 + if (he->branch_info == NULL) 400 + goto err; 404 401 405 402 memcpy(he->branch_info, template->branch_info, 406 403 sizeof(*he->branch_info)); ··· 416 419 417 420 if (he->raw_data) { 418 421 he->raw_data = memdup(he->raw_data, he->raw_size); 419 - 420 - if (he->raw_data == NULL) { 421 - map__put(he->ms.map); 422 - if (he->branch_info) { 423 - map__put(he->branch_info->from.map); 424 - map__put(he->branch_info->to.map); 425 - free(he->branch_info); 426 - } 427 - if (he->mem_info) { 428 - map__put(he->mem_info->iaddr.map); 429 - map__put(he->mem_info->daddr.map); 430 - } 431 - free(he->stat_acc); 432 - return -ENOMEM; 433 - } 422 + if (he->raw_data == NULL) 423 + goto err_infos; 434 424 } 425 + 426 + if (he->srcline) { 427 + he->srcline = strdup(he->srcline); 428 + if (he->srcline == NULL) 429 + goto err_rawdata; 430 + } 431 + 435 432 INIT_LIST_HEAD(&he->pairs.node); 436 433 thread__get(he->thread); 437 434 he->hroot_in = RB_ROOT_CACHED; ··· 435 444 he->leaf = true; 436 445 437 446 return 0; 447 + 448 + err_rawdata: 449 + free(he->raw_data); 450 + 451 + err_infos: 452 + if (he->branch_info) { 453 + map__put(he->branch_info->from.map); 454 + map__put(he->branch_info->to.map); 455 + free(he->branch_info); 456 + } 457 + if (he->mem_info) { 458 + map__put(he->mem_info->iaddr.map); 459 + map__put(he->mem_info->daddr.map); 460 + } 461 + err: 462 + map__zput(he->ms.map); 463 + free(he->stat_acc); 464 + return -ENOMEM; 438 465 } 439 466 440 467 static void *hist_entry__zalloc(size_t size) ··· 615 606 .map = al->map, 616 607 .sym = al->sym, 617 608 }, 618 - .srcline = al->srcline ? strdup(al->srcline) : NULL, 609 + .srcline = (char *) al->srcline, 619 610 .socket = al->socket, 620 611 .cpu = al->cpu, 621 612 .cpumode = al->cpumode, ··· 972 963 .map = al->map, 973 964 .sym = al->sym, 974 965 }, 975 - .srcline = al->srcline ? strdup(al->srcline) : NULL, 966 + .srcline = (char *) al->srcline, 976 967 .parent = iter->parent, 977 968 .raw_data = sample->raw_data, 978 969 .raw_size = sample->raw_size,
+2 -18
tools/perf/util/intel-bts.c
··· 328 328 { 329 329 struct machine *machine = btsq->bts->machine; 330 330 struct thread *thread; 331 - struct addr_location al; 332 331 unsigned char buf[INTEL_PT_INSN_BUF_SZ]; 333 332 ssize_t len; 334 - int x86_64; 335 - uint8_t cpumode; 333 + bool x86_64; 336 334 int err = -1; 337 - 338 - if (machine__kernel_ip(machine, ip)) 339 - cpumode = PERF_RECORD_MISC_KERNEL; 340 - else 341 - cpumode = PERF_RECORD_MISC_USER; 342 335 343 336 thread = machine__find_thread(machine, -1, btsq->tid); 344 337 if (!thread) 345 338 return -1; 346 339 347 - if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso) 348 - goto out_put; 349 - 350 - len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, 351 - INTEL_PT_INSN_BUF_SZ); 340 + len = thread__memcpy(thread, machine, buf, ip, INTEL_PT_INSN_BUF_SZ, &x86_64); 352 341 if (len <= 0) 353 342 goto out_put; 354 - 355 - /* Load maps to ensure dso->is_64_bit has been updated */ 356 - map__load(al.map); 357 - 358 - x86_64 = al.map->dso->is_64_bit; 359 343 360 344 if (intel_pt_get_insn(buf, len, x86_64, &btsq->intel_pt_insn)) 361 345 goto out_put;
+2
tools/perf/util/intel-pt.c
··· 2531 2531 } 2532 2532 2533 2533 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2534 + if (pt->timeless_decoding && !pt->tc.time_mult) 2535 + pt->tc.time_mult = 1; 2534 2536 pt->have_tsc = intel_pt_have_tsc(pt); 2535 2537 pt->sampling_mode = false; 2536 2538 pt->est_tsc = !pt->timeless_decoding;
+14
tools/perf/util/pmu.c
··· 752 752 return NULL; 753 753 } 754 754 755 + static int pmu_max_precise(const char *name) 756 + { 757 + char path[PATH_MAX]; 758 + int max_precise = -1; 759 + 760 + scnprintf(path, PATH_MAX, 761 + "bus/event_source/devices/%s/caps/max_precise", 762 + name); 763 + 764 + sysfs__read_int(path, &max_precise); 765 + return max_precise; 766 + } 767 + 755 768 static struct perf_pmu *pmu_lookup(const char *name) 756 769 { 757 770 struct perf_pmu *pmu; ··· 797 784 pmu->name = strdup(name); 798 785 pmu->type = type; 799 786 pmu->is_uncore = pmu_is_uncore(name); 787 + pmu->max_precise = pmu_max_precise(name); 800 788 pmu_add_cpu_aliases(&aliases, pmu); 801 789 802 790 INIT_LIST_HEAD(&pmu->format);
+1
tools/perf/util/pmu.h
··· 26 26 __u32 type; 27 27 bool selectable; 28 28 bool is_uncore; 29 + int max_precise; 29 30 struct perf_event_attr *default_config; 30 31 struct cpu_map *cpus; 31 32 struct list_head format; /* HEAD struct perf_pmu_format -> list */
+6 -3
tools/perf/util/probe-event.c
··· 472 472 strcpy(reason, "(unknown)"); 473 473 } else 474 474 dso__strerror_load(dso, reason, STRERR_BUFSIZE); 475 - if (!silent) 476 - pr_err("Failed to find the path for %s: %s\n", 477 - module ?: "kernel", reason); 475 + if (!silent) { 476 + if (module) 477 + pr_err("Module %s is not loaded, please specify its full path name.\n", module); 478 + else 479 + pr_err("Failed to find the path for the kernel: %s\n", reason); 480 + } 478 481 return NULL; 479 482 } 480 483 path = dso->long_name;
+5 -3
tools/perf/util/scripting-engines/trace-event-python.c
··· 1173 1173 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; 1174 1174 PyObject *t; 1175 1175 1176 - t = tuple_new(11); 1176 + t = tuple_new(12); 1177 1177 1178 1178 tuple_set_u64(t, 0, cr->db_id); 1179 1179 tuple_set_u64(t, 1, cr->thread->db_id); ··· 1186 1186 tuple_set_u64(t, 8, cr->return_ref); 1187 1187 tuple_set_u64(t, 9, cr->cp->parent->db_id); 1188 1188 tuple_set_s32(t, 10, cr->flags); 1189 + tuple_set_u64(t, 11, cr->parent_db_id); 1189 1190 1190 1191 call_object(tables->call_return_handler, t, "call_return_table"); 1191 1192 ··· 1195 1194 return 0; 1196 1195 } 1197 1196 1198 - static int python_process_call_return(struct call_return *cr, void *data) 1197 + static int python_process_call_return(struct call_return *cr, u64 *parent_db_id, 1198 + void *data) 1199 1199 { 1200 1200 struct db_export *dbe = data; 1201 1201 1202 - return db_export__call_return(dbe, cr); 1202 + return db_export__call_return(dbe, cr, parent_db_id); 1203 1203 } 1204 1204 1205 1205 static void python_process_general_event(struct perf_sample *sample,
+1 -3
tools/perf/util/session.c
··· 140 140 141 141 if (perf_data__is_read(data)) { 142 142 if (perf_session__open(session) < 0) 143 - goto out_close; 143 + goto out_delete; 144 144 145 145 /* 146 146 * set session attributes that are present in perf.data ··· 181 181 182 182 return session; 183 183 184 - out_close: 185 - perf_data__close(data); 186 184 out_delete: 187 185 perf_session__delete(session); 188 186 out:
+14 -2
tools/perf/util/thread-stack.c
··· 49 49 * @timestamp: timestamp (if known) 50 50 * @ref: external reference (e.g. db_id of sample) 51 51 * @branch_count: the branch count when the entry was created 52 + * @db_id: id used for db-export 52 53 * @cp: call path 53 54 * @no_call: a 'call' was not seen 54 55 * @trace_end: a 'call' but trace ended ··· 60 59 u64 timestamp; 61 60 u64 ref; 62 61 u64 branch_count; 62 + u64 db_id; 63 63 struct call_path *cp; 64 64 bool no_call; 65 65 bool trace_end; ··· 282 280 .comm = ts->comm, 283 281 .db_id = 0, 284 282 }; 283 + u64 *parent_db_id; 285 284 286 285 tse = &ts->stack[idx]; 287 286 cr.cp = tse->cp; 288 287 cr.call_time = tse->timestamp; 289 288 cr.return_time = timestamp; 290 289 cr.branch_count = ts->branch_count - tse->branch_count; 290 + cr.db_id = tse->db_id; 291 291 cr.call_ref = tse->ref; 292 292 cr.return_ref = ref; 293 293 if (tse->no_call) ··· 299 295 if (tse->non_call) 300 296 cr.flags |= CALL_RETURN_NON_CALL; 301 297 302 - return crp->process(&cr, crp->data); 298 + /* 299 + * The parent db_id must be assigned before exporting the child. Note 300 + * it is not possible to export the parent first because its information 301 + * is not yet complete because its 'return' has not yet been processed. 302 + */ 303 + parent_db_id = idx ? &(tse - 1)->db_id : NULL; 304 + 305 + return crp->process(&cr, parent_db_id, crp->data); 303 306 } 304 307 305 308 static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts) ··· 495 484 } 496 485 497 486 struct call_return_processor * 498 - call_return_processor__new(int (*process)(struct call_return *cr, void *data), 487 + call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data), 499 488 void *data) 500 489 { 501 490 struct call_return_processor *crp; ··· 548 537 tse->no_call = no_call; 549 538 tse->trace_end = trace_end; 550 539 tse->non_call = false; 540 + tse->db_id = 0; 551 541 552 542 return 0; 553 543 }
+4 -2
tools/perf/util/thread-stack.h
··· 55 55 * @call_ref: external reference to 'call' sample (e.g. db_id) 56 56 * @return_ref: external reference to 'return' sample (e.g. db_id) 57 57 * @db_id: id used for db-export 58 + * @parent_db_id: id of parent call used for db-export 58 59 * @flags: Call/Return flags 59 60 */ 60 61 struct call_return { ··· 68 67 u64 call_ref; 69 68 u64 return_ref; 70 69 u64 db_id; 70 + u64 parent_db_id; 71 71 u32 flags; 72 72 }; 73 73 ··· 81 79 */ 82 80 struct call_return_processor { 83 81 struct call_path_root *cpr; 84 - int (*process)(struct call_return *cr, void *data); 82 + int (*process)(struct call_return *cr, u64 *parent_db_id, void *data); 85 83 void *data; 86 84 }; 87 85 ··· 95 93 size_t thread_stack__depth(struct thread *thread, int cpu); 96 94 97 95 struct call_return_processor * 98 - call_return_processor__new(int (*process)(struct call_return *cr, void *data), 96 + call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data), 99 97 void *data); 100 98 void call_return_processor__free(struct call_return_processor *crp); 101 99 int thread_stack__process(struct thread *thread, struct comm *comm,
+23
tools/perf/util/thread.c
··· 12 12 #include "debug.h" 13 13 #include "namespaces.h" 14 14 #include "comm.h" 15 + #include "map.h" 15 16 #include "symbol.h" 16 17 #include "unwind.h" 17 18 ··· 393 392 return NULL; 394 393 395 394 return machine__find_thread(machine, thread->pid_, thread->pid_); 395 + } 396 + 397 + int thread__memcpy(struct thread *thread, struct machine *machine, 398 + void *buf, u64 ip, int len, bool *is64bit) 399 + { 400 + u8 cpumode = PERF_RECORD_MISC_USER; 401 + struct addr_location al; 402 + long offset; 403 + 404 + if (machine__kernel_ip(machine, ip)) 405 + cpumode = PERF_RECORD_MISC_KERNEL; 406 + 407 + if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso || 408 + al.map->dso->data.status == DSO_DATA_STATUS_ERROR || 409 + map__load(al.map) < 0) 410 + return -1; 411 + 412 + offset = al.map->map_ip(al.map, ip); 413 + if (is64bit) 414 + *is64bit = al.map->dso->is_64_bit; 415 + 416 + return dso__data_read_offset(al.map->dso, machine, offset, buf, len); 396 417 }
+3
tools/perf/util/thread.h
··· 113 113 void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 114 114 struct addr_location *al); 115 115 116 + int thread__memcpy(struct thread *thread, struct machine *machine, 117 + void *buf, u64 ip, int len, bool *is64bit); 118 + 116 119 static inline void *thread__priv(struct thread *thread) 117 120 { 118 121 return thread->priv;
+50 -1
tools/perf/util/time-utils.c
··· 11 11 #include "perf.h" 12 12 #include "debug.h" 13 13 #include "time-utils.h" 14 + #include "session.h" 15 + #include "evlist.h" 14 16 15 17 int parse_nsec_time(const char *str, u64 *ptime) 16 18 { ··· 376 374 struct perf_time_interval *ptime; 377 375 int i; 378 376 379 - if ((timestamp == 0) || (num == 0)) 377 + if ((!ptime_buf) || (timestamp == 0) || (num == 0)) 380 378 return false; 381 379 382 380 if (num == 1) ··· 396 394 } 397 395 398 396 return (i == num) ? true : false; 397 + } 398 + 399 + int perf_time__parse_for_ranges(const char *time_str, 400 + struct perf_session *session, 401 + struct perf_time_interval **ranges, 402 + int *range_size, int *range_num) 403 + { 404 + struct perf_time_interval *ptime_range; 405 + int size, num, ret; 406 + 407 + ptime_range = perf_time__range_alloc(time_str, &size); 408 + if (!ptime_range) 409 + return -ENOMEM; 410 + 411 + if (perf_time__parse_str(ptime_range, time_str) != 0) { 412 + if (session->evlist->first_sample_time == 0 && 413 + session->evlist->last_sample_time == 0) { 414 + pr_err("HINT: no first/last sample time found in perf data.\n" 415 + "Please use latest perf binary to execute 'perf record'\n" 416 + "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n"); 417 + ret = -EINVAL; 418 + goto error; 419 + } 420 + 421 + num = perf_time__percent_parse_str( 422 + ptime_range, size, 423 + time_str, 424 + session->evlist->first_sample_time, 425 + session->evlist->last_sample_time); 426 + 427 + if (num < 0) { 428 + pr_err("Invalid time string\n"); 429 + ret = -EINVAL; 430 + goto error; 431 + } 432 + } else { 433 + num = 1; 434 + } 435 + 436 + *range_size = size; 437 + *range_num = num; 438 + *ranges = ptime_range; 439 + return 0; 440 + 441 + error: 442 + free(ptime_range); 443 + return ret; 399 444 } 400 445 401 446 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
+6
tools/perf/util/time-utils.h
··· 23 23 bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf, 24 24 int num, u64 timestamp); 25 25 26 + struct perf_session; 27 + 28 + int perf_time__parse_for_ranges(const char *str, struct perf_session *session, 29 + struct perf_time_interval **ranges, 30 + int *range_size, int *range_num); 31 + 26 32 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 27 33 28 34 int fetch_current_timestamp(char *buf, size_t sz);