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