aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-08-12 06:16:11 -0400
committerIngo Molnar <mingo@kernel.org>2015-08-12 06:16:11 -0400
commit5f1230c9b80b89f404938ff88dfa64a963f74f2c (patch)
treef829a0246125b517443de57b883bc663aad82d9d
parent709bc871923c12b284424f9d47b99dc975ba8b29 (diff)
parent4605bb55b91449a1a953a51f0334d3bc02351adb (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Introduce 'srcfile' sort key: (Andi Kleen) # perf record -F 10000 usleep 1 # perf report --stdio --dsos '[kernel.vmlinux]' -s srcfile <SNIP> # Overhead Source File 26.49% copy_page_64.S 5.49% signal.c 0.51% msr.h # It can be combined with other fields, for instance, experiment with '-s srcfile,symbol'. There are some oddities in some distros and with some specific DSOs, being investigated, so your mileage may vary. - Update the column width for the "srcline" sort key (Arnaldo Carvalho de Melo) - Support per-event 'freq' term: (Namhyung Kim) $ perf record -e 'cpu/instructions,freq=1234/',cycles -c 1000 sleep 1 $ perf evlist -F cpu/instructions,freq=1234/: sample_freq=1234 cycles: sample_period=1000 $ Infrastructure changes: - Move perf_counts struct and functions into separate object (Jiri Olsa) - Unset perf_event_attr::freq when period term is set (Jiri Olsa) - Move callchain option parsing code to util.c (Kan Liang) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-record.txt1
-rw-r--r--tools/perf/Documentation/perf-report.txt4
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/builtin-stat.c1
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/callchain.c89
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/counts.c52
-rw-r--r--tools/perf/util/counts.h37
-rw-r--r--tools/perf/util/evsel.c14
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/hist.c9
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/parse-events.c6
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/pmu.c2
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/sort.c52
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/srcline.c6
-rw-r--r--tools/perf/util/stat.c49
-rw-r--r--tools/perf/util/stat.h30
-rw-r--r--tools/perf/util/util.c90
-rw-r--r--tools/perf/util/util.h3
27 files changed, 292 insertions, 173 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 0d852d1bc90f..afbe45ef7e3e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -49,6 +49,7 @@ OPTIONS
49 These params can be used to overload default config values per event. 49 These params can be used to overload default config values per event.
50 Here is a list of the params. 50 Here is a list of the params.
51 - 'period': Set event sampling period 51 - 'period': Set event sampling period
52 - 'freq': Set event sampling frequency
52 - 'time': Disable/enable time stamping. Acceptable values are 1 for 53 - 'time': Disable/enable time stamping. Acceptable values are 1 for
53 enabling time stamping. 0 for disabling time stamping. 54 enabling time stamping. 0 for disabling time stamping.
54 The default is 1. 55 The default is 1.
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 960da203ec11..7b07d19e2d54 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -81,6 +81,8 @@ OPTIONS
81 - cpu: cpu number the task ran at the time of sample 81 - cpu: cpu number the task ran at the time of sample
82 - srcline: filename and line number executed at the time of sample. The 82 - srcline: filename and line number executed at the time of sample. The
83 DWARF debugging info must be provided. 83 DWARF debugging info must be provided.
84 - srcfile: file name of the source file of the same. Requires dwarf
85 information.
84 - weight: Event specific weight, e.g. memory latency or transaction 86 - weight: Event specific weight, e.g. memory latency or transaction
85 abort cost. This is the global weight. 87 abort cost. This is the global weight.
86 - local_weight: Local weight version of the weight above. 88 - local_weight: Local weight version of the weight above.
@@ -354,6 +356,8 @@ OPTIONS
354 356
355 To disable decoding entirely, use --no-itrace. 357 To disable decoding entirely, use --no-itrace.
356 358
359--full-source-path::
360 Show the full path for source files for srcline output.
357 361
358include::callchain-overhead-calculation.txt[] 362include::callchain-overhead-calculation.txt[]
359 363
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index e2fec5fc21e7..8e9be1f9c1dd 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -260,6 +260,9 @@ OPTIONS
260 260
261 To disable decoding entirely, use --no-itrace. 261 To disable decoding entirely, use --no-itrace.
262 262
263--full-source-path::
264 Show the full path for source files for srcline output.
265
263SEE ALSO 266SEE ALSO
264-------- 267--------
265linkperf:perf-record[1], linkperf:perf-script-perl[1], 268linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3a9d1b659fcd..f301e865001f 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -738,6 +738,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
738 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 738 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
739 "Instruction Tracing options", 739 "Instruction Tracing options",
740 itrace_parse_synth_opts), 740 itrace_parse_synth_opts),
741 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
742 "Show full source file name path for source lines"),
741 OPT_END() 743 OPT_END()
742 }; 744 };
743 struct perf_data_file file = { 745 struct perf_data_file file = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7912feb9a024..7b376d215e94 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1653,6 +1653,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1653 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 1653 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1654 "Instruction Tracing options", 1654 "Instruction Tracing options",
1655 itrace_parse_synth_opts), 1655 itrace_parse_synth_opts),
1656 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
1657 "Show full source file name path for source lines"),
1656 OPT_END() 1658 OPT_END()
1657 }; 1659 };
1658 const char * const script_subcommands[] = { "record", "report", NULL }; 1660 const char * const script_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a054ddc0b2a0..7aa039bd379a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -58,6 +58,7 @@
58#include "util/cpumap.h" 58#include "util/cpumap.h"
59#include "util/thread.h" 59#include "util/thread.h"
60#include "util/thread_map.h" 60#include "util/thread_map.h"
61#include "util/counts.h"
61 62
62#include <stdlib.h> 63#include <stdlib.h>
63#include <sys/prctl.h> 64#include <sys/prctl.h>
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 2ee81d74cf45..1ce0adc8b3cb 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -68,6 +68,7 @@ libperf-y += target.o
68libperf-y += rblist.o 68libperf-y += rblist.o
69libperf-y += intlist.o 69libperf-y += intlist.o
70libperf-y += vdso.o 70libperf-y += vdso.o
71libperf-y += counts.o
71libperf-y += stat.o 72libperf-y += stat.o
72libperf-y += stat-shadow.o 73libperf-y += stat-shadow.o
73libperf-y += record.o 74libperf-y += record.o
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 931cca8e6ae8..773fe13ce627 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,96 +25,9 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29static int get_stack_size(const char *str, unsigned long *_size)
30{
31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
34
35 size = strtoul(str, &endptr, 0);
36
37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
46 return 0;
47
48 } while (0);
49
50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
51 max_size, str);
52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
55
56int parse_callchain_record_opt(const char *arg, struct callchain_param *param) 28int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
57{ 29{
58 char *tok, *name, *saveptr = NULL; 30 return parse_callchain_record(arg, param);
59 char *buf;
60 int ret = -1;
61
62 /* We need buffer that we know we can write to. */
63 buf = malloc(strlen(arg) + 1);
64 if (!buf)
65 return -ENOMEM;
66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 param->record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for --call-graph fp\n");
81 break;
82
83#ifdef HAVE_DWARF_UNWIND_SUPPORT
84 /* Dwarf style */
85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
86 const unsigned long default_stack_dump_size = 8192;
87
88 ret = 0;
89 param->record_mode = CALLCHAIN_DWARF;
90 param->dump_size = default_stack_dump_size;
91
92 tok = strtok_r(NULL, ",", &saveptr);
93 if (tok) {
94 unsigned long size = 0;
95
96 ret = get_stack_size(tok, &size);
97 param->dump_size = size;
98 }
99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
100 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
101 if (!strtok_r(NULL, ",", &saveptr)) {
102 param->record_mode = CALLCHAIN_LBR;
103 ret = 0;
104 } else
105 pr_err("callchain: No more arguments "
106 "needed for --call-graph lbr\n");
107 break;
108 } else {
109 pr_err("callchain: Unknown --call-graph option "
110 "value: %s\n", arg);
111 break;
112 }
113
114 } while (0);
115
116 free(buf);
117 return ret;
118} 31}
119 32
120static int parse_callchain_mode(const char *value) 33static int parse_callchain_mode(const char *value)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 68a32c2fe87a..acee2b3cd801 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -177,6 +177,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
177 bool hide_unresolved); 177 bool hide_unresolved);
178 178
179extern const char record_callchain_help[]; 179extern const char record_callchain_help[];
180extern int parse_callchain_record(const char *arg, struct callchain_param *param);
180int parse_callchain_record_opt(const char *arg, struct callchain_param *param); 181int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
181int parse_callchain_report_opt(const char *arg); 182int parse_callchain_report_opt(const char *arg);
182int perf_callchain_config(const char *var, const char *value); 183int perf_callchain_config(const char *var, const char *value);
diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c
new file mode 100644
index 000000000000..e3fde313deb2
--- /dev/null
+++ b/tools/perf/util/counts.c
@@ -0,0 +1,52 @@
1#include <stdlib.h>
2#include "evsel.h"
3#include "counts.h"
4
5struct perf_counts *perf_counts__new(int ncpus, int nthreads)
6{
7 struct perf_counts *counts = zalloc(sizeof(*counts));
8
9 if (counts) {
10 struct xyarray *values;
11
12 values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
13 if (!values) {
14 free(counts);
15 return NULL;
16 }
17
18 counts->values = values;
19 }
20
21 return counts;
22}
23
24void perf_counts__delete(struct perf_counts *counts)
25{
26 if (counts) {
27 xyarray__delete(counts->values);
28 free(counts);
29 }
30}
31
32static void perf_counts__reset(struct perf_counts *counts)
33{
34 xyarray__reset(counts->values);
35}
36
37void perf_evsel__reset_counts(struct perf_evsel *evsel)
38{
39 perf_counts__reset(evsel->counts);
40}
41
42int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
43{
44 evsel->counts = perf_counts__new(ncpus, nthreads);
45 return evsel->counts != NULL ? 0 : -ENOMEM;
46}
47
48void perf_evsel__free_counts(struct perf_evsel *evsel)
49{
50 perf_counts__delete(evsel->counts);
51 evsel->counts = NULL;
52}
diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h
new file mode 100644
index 000000000000..34d8baaf558a
--- /dev/null
+++ b/tools/perf/util/counts.h
@@ -0,0 +1,37 @@
1#ifndef __PERF_COUNTS_H
2#define __PERF_COUNTS_H
3
4#include "xyarray.h"
5
6struct perf_counts_values {
7 union {
8 struct {
9 u64 val;
10 u64 ena;
11 u64 run;
12 };
13 u64 values[3];
14 };
15};
16
17struct perf_counts {
18 s8 scaled;
19 struct perf_counts_values aggr;
20 struct xyarray *values;
21};
22
23
24static inline struct perf_counts_values*
25perf_counts(struct perf_counts *counts, int cpu, int thread)
26{
27 return xyarray__entry(counts->values, cpu, thread);
28}
29
30struct perf_counts *perf_counts__new(int ncpus, int nthreads);
31void perf_counts__delete(struct perf_counts *counts);
32
33void perf_evsel__reset_counts(struct perf_evsel *evsel);
34int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads);
35void perf_evsel__free_counts(struct perf_evsel *evsel);
36
37#endif /* __PERF_COUNTS_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f572f469a30d..04fddddc6b6f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -598,6 +598,11 @@ static void apply_config_terms(struct perf_evsel *evsel)
598 switch (term->type) { 598 switch (term->type) {
599 case PERF_EVSEL__CONFIG_TERM_PERIOD: 599 case PERF_EVSEL__CONFIG_TERM_PERIOD:
600 attr->sample_period = term->val.period; 600 attr->sample_period = term->val.period;
601 attr->freq = 0;
602 break;
603 case PERF_EVSEL__CONFIG_TERM_FREQ:
604 attr->sample_freq = term->val.freq;
605 attr->freq = 1;
601 break; 606 break;
602 case PERF_EVSEL__CONFIG_TERM_TIME: 607 case PERF_EVSEL__CONFIG_TERM_TIME:
603 if (term->val.time) 608 if (term->val.time)
@@ -2153,8 +2158,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2153 printed += perf_event_attr__fprintf(fp, &evsel->attr, 2158 printed += perf_event_attr__fprintf(fp, &evsel->attr,
2154 __print_attr__fprintf, &first); 2159 __print_attr__fprintf, &first);
2155 } else if (details->freq) { 2160 } else if (details->freq) {
2156 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, 2161 const char *term = "sample_freq";
2157 (u64)evsel->attr.sample_freq); 2162
2163 if (!evsel->attr.freq)
2164 term = "sample_period";
2165
2166 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
2167 term, (u64)evsel->attr.sample_freq);
2158 } 2168 }
2159out: 2169out:
2160 fputc('\n', fp); 2170 fputc('\n', fp);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6a129081f3ad..fdf2674ab339 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -9,7 +9,7 @@
9#include "xyarray.h" 9#include "xyarray.h"
10#include "symbol.h" 10#include "symbol.h"
11#include "cpumap.h" 11#include "cpumap.h"
12#include "stat.h" 12#include "counts.h"
13 13
14struct perf_evsel; 14struct perf_evsel;
15 15
@@ -39,6 +39,7 @@ struct cgroup_sel;
39*/ 39*/
40enum { 40enum {
41 PERF_EVSEL__CONFIG_TERM_PERIOD, 41 PERF_EVSEL__CONFIG_TERM_PERIOD,
42 PERF_EVSEL__CONFIG_TERM_FREQ,
42 PERF_EVSEL__CONFIG_TERM_TIME, 43 PERF_EVSEL__CONFIG_TERM_TIME,
43 PERF_EVSEL__CONFIG_TERM_MAX, 44 PERF_EVSEL__CONFIG_TERM_MAX,
44}; 45};
@@ -48,6 +49,7 @@ struct perf_evsel_config_term {
48 int type; 49 int type;
49 union { 50 union {
50 u64 period; 51 u64 period;
52 u64 freq;
51 bool time; 53 bool time;
52 } val; 54 } val;
53}; 55};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a6e9ddd37913..6bccfae334b1 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -151,6 +151,12 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
151 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 151 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
152 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 152 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
153 153
154 if (h->srcline)
155 hists__new_col_len(hists, HISTC_SRCLINE, strlen(h->srcline));
156
157 if (h->srcfile)
158 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile));
159
154 if (h->transaction) 160 if (h->transaction)
155 hists__new_col_len(hists, HISTC_TRANSACTION, 161 hists__new_col_len(hists, HISTC_TRANSACTION,
156 hist_entry__transaction_len()); 162 hist_entry__transaction_len());
@@ -761,6 +767,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
761 struct hist_entry **he_cache = iter->priv; 767 struct hist_entry **he_cache = iter->priv;
762 struct hist_entry *he; 768 struct hist_entry *he;
763 struct hist_entry he_tmp = { 769 struct hist_entry he_tmp = {
770 .hists = evsel__hists(evsel),
764 .cpu = al->cpu, 771 .cpu = al->cpu,
765 .thread = al->thread, 772 .thread = al->thread,
766 .comm = thread__comm(al->thread), 773 .comm = thread__comm(al->thread),
@@ -945,6 +952,8 @@ void hist_entry__delete(struct hist_entry *he)
945 952
946 zfree(&he->stat_acc); 953 zfree(&he->stat_acc);
947 free_srcline(he->srcline); 954 free_srcline(he->srcline);
955 if (he->srcfile && he->srcfile[0])
956 free(he->srcfile);
948 free_callchain(he->callchain); 957 free_callchain(he->callchain);
949 free(he); 958 free(he);
950} 959}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index e2f712f85d2e..bc528d54e457 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -30,6 +30,7 @@ enum hist_column {
30 HISTC_PARENT, 30 HISTC_PARENT,
31 HISTC_CPU, 31 HISTC_CPU,
32 HISTC_SRCLINE, 32 HISTC_SRCLINE,
33 HISTC_SRCFILE,
33 HISTC_MISPREDICT, 34 HISTC_MISPREDICT,
34 HISTC_IN_TX, 35 HISTC_IN_TX,
35 HISTC_ABORT, 36 HISTC_ABORT,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 828936dc3f1e..dbf315df4220 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -597,6 +597,9 @@ do { \
597 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 597 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
598 CHECK_TYPE_VAL(NUM); 598 CHECK_TYPE_VAL(NUM);
599 break; 599 break;
600 case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
601 CHECK_TYPE_VAL(NUM);
602 break;
600 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 603 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
601 /* 604 /*
602 * TODO uncomment when the field is available 605 * TODO uncomment when the field is available
@@ -659,6 +662,9 @@ do { \
659 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 662 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
660 ADD_CONFIG_TERM(PERIOD, period, term->val.num); 663 ADD_CONFIG_TERM(PERIOD, period, term->val.num);
661 break; 664 break;
665 case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
666 ADD_CONFIG_TERM(FREQ, freq, term->val.num);
667 break;
662 case PARSE_EVENTS__TERM_TYPE_TIME: 668 case PARSE_EVENTS__TERM_TYPE_TIME:
663 ADD_CONFIG_TERM(TIME, time, term->val.num); 669 ADD_CONFIG_TERM(TIME, time, term->val.num);
664 break; 670 break;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e6f9aacc1cce..ce2d13a16226 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -62,6 +62,7 @@ enum {
62 PARSE_EVENTS__TERM_TYPE_CONFIG2, 62 PARSE_EVENTS__TERM_TYPE_CONFIG2,
63 PARSE_EVENTS__TERM_TYPE_NAME, 63 PARSE_EVENTS__TERM_TYPE_NAME,
64 PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, 64 PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
65 PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ,
65 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, 66 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
66 PARSE_EVENTS__TERM_TYPE_TIME, 67 PARSE_EVENTS__TERM_TYPE_TIME,
67}; 68};
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index f5427505ae77..4306f5ad75c7 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -182,6 +182,7 @@ config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
182config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } 182config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
183name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } 183name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
184period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 184period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
185freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
185branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 186branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
186time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
187, { return ','; } 188, { return ','; }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d4b0e6454bc6..d85f11b8cacf 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -634,7 +634,7 @@ static char *formats_error_string(struct list_head *formats)
634{ 634{
635 struct perf_pmu_format *format; 635 struct perf_pmu_format *format;
636 char *err, *str; 636 char *err, *str;
637 static const char *static_terms = "config,config1,config2,name,period,branch_type,time\n"; 637 static const char *static_terms = "config,config1,config2,name,period,freq,branch_type,time\n";
638 unsigned i = 0; 638 unsigned i = 0;
639 639
640 if (!asprintf(&str, "valid terms:")) 640 if (!asprintf(&str, "valid terms:"))
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 0766d98c5da5..51be28b1bca2 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -16,7 +16,7 @@ util/util.c
16util/xyarray.c 16util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/stat.c 19util/counts.c
20util/strlist.c 20util/strlist.c
21util/trace-event.c 21util/trace-event.c
22../lib/rbtree.c 22../lib/rbtree.c
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5177088a71d3..c0c32b050e45 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -319,6 +319,57 @@ struct sort_entry sort_srcline = {
319 .se_width_idx = HISTC_SRCLINE, 319 .se_width_idx = HISTC_SRCLINE,
320}; 320};
321 321
322/* --sort srcfile */
323
324static char no_srcfile[1];
325
326static char *get_srcfile(struct hist_entry *e)
327{
328 char *sf, *p;
329 struct map *map = e->ms.map;
330
331 sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip),
332 e->ms.sym, true);
333 p = strchr(sf, ':');
334 if (p && *sf) {
335 *p = 0;
336 return sf;
337 }
338 free(sf);
339 return no_srcfile;
340}
341
342static int64_t
343sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
344{
345 if (!left->srcfile) {
346 if (!left->ms.map)
347 left->srcfile = no_srcfile;
348 else
349 left->srcfile = get_srcfile(left);
350 }
351 if (!right->srcfile) {
352 if (!right->ms.map)
353 right->srcfile = no_srcfile;
354 else
355 right->srcfile = get_srcfile(right);
356 }
357 return strcmp(right->srcfile, left->srcfile);
358}
359
360static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
361 size_t size, unsigned int width)
362{
363 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
364}
365
366struct sort_entry sort_srcfile = {
367 .se_header = "Source File",
368 .se_cmp = sort__srcfile_cmp,
369 .se_snprintf = hist_entry__srcfile_snprintf,
370 .se_width_idx = HISTC_SRCFILE,
371};
372
322/* --sort parent */ 373/* --sort parent */
323 374
324static int64_t 375static int64_t
@@ -1196,6 +1247,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1196 DIM(SORT_PARENT, "parent", sort_parent), 1247 DIM(SORT_PARENT, "parent", sort_parent),
1197 DIM(SORT_CPU, "cpu", sort_cpu), 1248 DIM(SORT_CPU, "cpu", sort_cpu),
1198 DIM(SORT_SRCLINE, "srcline", sort_srcline), 1249 DIM(SORT_SRCLINE, "srcline", sort_srcline),
1250 DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
1199 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 1251 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1200 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 1252 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1201 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1253 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index bc6c87a76d16..3c2a399f8f5b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -114,6 +114,7 @@ struct hist_entry {
114 }; 114 };
115 }; 115 };
116 char *srcline; 116 char *srcline;
117 char *srcfile;
117 struct symbol *parent; 118 struct symbol *parent;
118 struct rb_root sorted_chain; 119 struct rb_root sorted_chain;
119 struct branch_info *branch_info; 120 struct branch_info *branch_info;
@@ -172,6 +173,7 @@ enum sort_type {
172 SORT_PARENT, 173 SORT_PARENT,
173 SORT_CPU, 174 SORT_CPU,
174 SORT_SRCLINE, 175 SORT_SRCLINE,
176 SORT_SRCFILE,
175 SORT_LOCAL_WEIGHT, 177 SORT_LOCAL_WEIGHT,
176 SORT_GLOBAL_WEIGHT, 178 SORT_GLOBAL_WEIGHT,
177 SORT_TRANSACTION, 179 SORT_TRANSACTION,
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index c93fb0c5bd0b..fc08248f08ca 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -10,6 +10,8 @@
10 10
11#include "symbol.h" 11#include "symbol.h"
12 12
13bool srcline_full_filename;
14
13#ifdef HAVE_LIBBFD_SUPPORT 15#ifdef HAVE_LIBBFD_SUPPORT
14 16
15/* 17/*
@@ -277,7 +279,9 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
277 if (!addr2line(dso_name, addr, &file, &line, dso)) 279 if (!addr2line(dso_name, addr, &file, &line, dso))
278 goto out; 280 goto out;
279 281
280 if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) { 282 if (asprintf(&srcline, "%s:%u",
283 srcline_full_filename ? file : basename(file),
284 line) < 0) {
281 free(file); 285 free(file);
282 goto out; 286 goto out;
283 } 287 }
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index c5c709cdc3ce..415c359de465 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -97,55 +97,6 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
97 } 97 }
98} 98}
99 99
100struct perf_counts *perf_counts__new(int ncpus, int nthreads)
101{
102 struct perf_counts *counts = zalloc(sizeof(*counts));
103
104 if (counts) {
105 struct xyarray *values;
106
107 values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
108 if (!values) {
109 free(counts);
110 return NULL;
111 }
112
113 counts->values = values;
114 }
115
116 return counts;
117}
118
119void perf_counts__delete(struct perf_counts *counts)
120{
121 if (counts) {
122 xyarray__delete(counts->values);
123 free(counts);
124 }
125}
126
127static void perf_counts__reset(struct perf_counts *counts)
128{
129 xyarray__reset(counts->values);
130}
131
132void perf_evsel__reset_counts(struct perf_evsel *evsel)
133{
134 perf_counts__reset(evsel->counts);
135}
136
137int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
138{
139 evsel->counts = perf_counts__new(ncpus, nthreads);
140 return evsel->counts != NULL ? 0 : -ENOMEM;
141}
142
143void perf_evsel__free_counts(struct perf_evsel *evsel)
144{
145 perf_counts__delete(evsel->counts);
146 evsel->counts = NULL;
147}
148
149void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) 100void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
150{ 101{
151 int i; 102 int i;
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0b897b083682..62448c8175d3 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -33,23 +33,6 @@ enum aggr_mode {
33 AGGR_THREAD, 33 AGGR_THREAD,
34}; 34};
35 35
36struct perf_counts_values {
37 union {
38 struct {
39 u64 val;
40 u64 ena;
41 u64 run;
42 };
43 u64 values[3];
44 };
45};
46
47struct perf_counts {
48 s8 scaled;
49 struct perf_counts_values aggr;
50 struct xyarray *values;
51};
52
53struct perf_stat_config { 36struct perf_stat_config {
54 enum aggr_mode aggr_mode; 37 enum aggr_mode aggr_mode;
55 bool scale; 38 bool scale;
@@ -57,12 +40,6 @@ struct perf_stat_config {
57 unsigned int interval; 40 unsigned int interval;
58}; 41};
59 42
60static inline struct perf_counts_values*
61perf_counts(struct perf_counts *counts, int cpu, int thread)
62{
63 return xyarray__entry(counts->values, cpu, thread);
64}
65
66void update_stats(struct stats *stats, u64 val); 43void update_stats(struct stats *stats, u64 val);
67double avg_stats(struct stats *stats); 44double avg_stats(struct stats *stats);
68double stddev_stats(struct stats *stats); 45double stddev_stats(struct stats *stats);
@@ -96,13 +73,6 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
96void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, 73void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
97 double avg, int cpu, enum aggr_mode aggr); 74 double avg, int cpu, enum aggr_mode aggr);
98 75
99struct perf_counts *perf_counts__new(int ncpus, int nthreads);
100void perf_counts__delete(struct perf_counts *counts);
101
102void perf_evsel__reset_counts(struct perf_evsel *evsel);
103int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads);
104void perf_evsel__free_counts(struct perf_evsel *evsel);
105
106void perf_evsel__reset_stat_priv(struct perf_evsel *evsel); 76void perf_evsel__reset_stat_priv(struct perf_evsel *evsel);
107int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel); 77int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel);
108void perf_evsel__free_stat_priv(struct perf_evsel *evsel); 78void perf_evsel__free_stat_priv(struct perf_evsel *evsel);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index edc2d633b332..f7adf1203df1 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -566,6 +566,96 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
566 return (unsigned long) -1; 566 return (unsigned long) -1;
567} 567}
568 568
569int get_stack_size(const char *str, unsigned long *_size)
570{
571 char *endptr;
572 unsigned long size;
573 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
574
575 size = strtoul(str, &endptr, 0);
576
577 do {
578 if (*endptr)
579 break;
580
581 size = round_up(size, sizeof(u64));
582 if (!size || size > max_size)
583 break;
584
585 *_size = size;
586 return 0;
587
588 } while (0);
589
590 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
591 max_size, str);
592 return -1;
593}
594
595int parse_callchain_record(const char *arg, struct callchain_param *param)
596{
597 char *tok, *name, *saveptr = NULL;
598 char *buf;
599 int ret = -1;
600
601 /* We need buffer that we know we can write to. */
602 buf = malloc(strlen(arg) + 1);
603 if (!buf)
604 return -ENOMEM;
605
606 strcpy(buf, arg);
607
608 tok = strtok_r((char *)buf, ",", &saveptr);
609 name = tok ? : (char *)buf;
610
611 do {
612 /* Framepointer style */
613 if (!strncmp(name, "fp", sizeof("fp"))) {
614 if (!strtok_r(NULL, ",", &saveptr)) {
615 param->record_mode = CALLCHAIN_FP;
616 ret = 0;
617 } else
618 pr_err("callchain: No more arguments "
619 "needed for --call-graph fp\n");
620 break;
621
622#ifdef HAVE_DWARF_UNWIND_SUPPORT
623 /* Dwarf style */
624 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
625 const unsigned long default_stack_dump_size = 8192;
626
627 ret = 0;
628 param->record_mode = CALLCHAIN_DWARF;
629 param->dump_size = default_stack_dump_size;
630
631 tok = strtok_r(NULL, ",", &saveptr);
632 if (tok) {
633 unsigned long size = 0;
634
635 ret = get_stack_size(tok, &size);
636 param->dump_size = size;
637 }
638#endif /* HAVE_DWARF_UNWIND_SUPPORT */
639 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
640 if (!strtok_r(NULL, ",", &saveptr)) {
641 param->record_mode = CALLCHAIN_LBR;
642 ret = 0;
643 } else
644 pr_err("callchain: No more arguments "
645 "needed for --call-graph lbr\n");
646 break;
647 } else {
648 pr_err("callchain: Unknown --call-graph option "
649 "value: %s\n", arg);
650 break;
651 }
652
653 } while (0);
654
655 free(buf);
656 return ret;
657}
658
569int filename__read_str(const char *filename, char **buf, size_t *sizep) 659int filename__read_str(const char *filename, char **buf, size_t *sizep)
570{ 660{
571 size_t size = 0, alloc_size = 0; 661 size_t size = 0, alloc_size = 0;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 20d625a4cacf..88a891562a47 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -318,6 +318,7 @@ static inline int path__join3(char *bf, size_t size,
318struct dso; 318struct dso;
319struct symbol; 319struct symbol;
320 320
321extern bool srcline_full_filename;
321char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 322char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
322 bool show_sym); 323 bool show_sym);
323void free_srcline(char *srcline); 324void free_srcline(char *srcline);
@@ -351,4 +352,6 @@ static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int
351 return asprintf_expr_inout_ints(var, false, nints, ints); 352 return asprintf_expr_inout_ints(var, false, nints, ints);
352} 353}
353 354
355int get_stack_size(const char *str, unsigned long *_size);
356
354#endif /* GIT_COMPAT_UTIL_H */ 357#endif /* GIT_COMPAT_UTIL_H */