diff options
author | Andi Kleen <ak@linux.intel.com> | 2013-09-20 10:40:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-10-04 04:06:12 -0400 |
commit | 475eeab9f3c1579c8da89667496084db4867bf7c (patch) | |
tree | cacc059c63a8091d69f2cd024dba7c74a6b0d1d8 | |
parent | 0126d493b62e1306db09e1019c05e0bfe84ae8e7 (diff) |
tools/perf: Add support for record transaction flags
Add support for recording and displaying the transaction flags.
They are essentially a new sort key. Also display them
in a nice way to the user.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1379688044-14173-6-git-send-email-andi@firstfloor.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 4 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 4 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 8 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 5 | ||||
-rw-r--r-- | tools/perf/perf.h | 1 | ||||
-rw-r--r-- | tools/perf/tests/hists_link.c | 6 | ||||
-rw-r--r-- | tools/perf/util/event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 9 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 7 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 4 | ||||
-rw-r--r-- | tools/perf/util/session.c | 3 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 73 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 2 |
17 files changed, 122 insertions, 15 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 6bec1c944849..f732eaa6a500 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -179,12 +179,14 @@ is enabled for all the sampling events. The sampled branch type is the same for | |||
179 | The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k | 179 | The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k |
180 | Note that this feature may not be available on all processors. | 180 | Note that this feature may not be available on all processors. |
181 | 181 | ||
182 | -W:: | ||
183 | --weight:: | 182 | --weight:: |
184 | Enable weightened sampling. An additional weight is recorded per sample and can be | 183 | Enable weightened sampling. An additional weight is recorded per sample and can be |
185 | displayed with the weight and local_weight sort keys. This currently works for TSX | 184 | displayed with the weight and local_weight sort keys. This currently works for TSX |
186 | abort events and some memory events in precise mode on modern Intel CPUs. | 185 | abort events and some memory events in precise mode on modern Intel CPUs. |
187 | 186 | ||
187 | --transaction:: | ||
188 | Record transaction flags for transaction related events. | ||
189 | |||
188 | SEE ALSO | 190 | SEE ALSO |
189 | -------- | 191 | -------- |
190 | linkperf:perf-stat[1], linkperf:perf-list[1] | 192 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index ae337e38cff5..be5ad87b6c3d 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -72,6 +72,10 @@ OPTIONS | |||
72 | - cpu: cpu number the task ran at the time of sample | 72 | - cpu: cpu number the task ran at the time of sample |
73 | - srcline: filename and line number executed at the time of sample. The | 73 | - srcline: filename and line number executed at the time of sample. The |
74 | DWARF debugging info must be provided. | 74 | DWARF debugging info must be provided. |
75 | - weight: Event specific weight, e.g. memory latency or transaction | ||
76 | abort cost. This is the global weight. | ||
77 | - local_weight: Local weight version of the weight above. | ||
78 | - transaction: Transaction abort flags. | ||
75 | 79 | ||
76 | By default, comm, dso and symbol keys are used. | 80 | By default, comm, dso and symbol keys are used. |
77 | (i.e. --sort comm,dso,symbol) | 81 | (i.e. --sort comm,dso,symbol) |
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index f852eb5d988d..6d70fbfe28a2 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -113,7 +113,7 @@ Default is to monitor all CPUS. | |||
113 | -s:: | 113 | -s:: |
114 | --sort:: | 114 | --sort:: |
115 | Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, | 115 | Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, |
116 | local_weight, abort, in_tx | 116 | local_weight, abort, in_tx, transaction |
117 | 117 | ||
118 | -n:: | 118 | -n:: |
119 | --show-nr-samples:: | 119 | --show-nr-samples:: |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5ebd0c3b71b6..0393d9800516 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -63,7 +63,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1); | 66 | he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1, 0); |
67 | if (he == NULL) | 67 | if (he == NULL) |
68 | return -ENOMEM; | 68 | return -ENOMEM; |
69 | 69 | ||
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f28799e94f2a..2a78dc806c39 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -304,9 +304,10 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, | |||
304 | 304 | ||
305 | static int hists__add_entry(struct hists *self, | 305 | static int hists__add_entry(struct hists *self, |
306 | struct addr_location *al, u64 period, | 306 | struct addr_location *al, u64 period, |
307 | u64 weight) | 307 | u64 weight, u64 transaction) |
308 | { | 308 | { |
309 | if (__hists__add_entry(self, al, NULL, period, weight) != NULL) | 309 | if (__hists__add_entry(self, al, NULL, period, weight, transaction) |
310 | != NULL) | ||
310 | return 0; | 311 | return 0; |
311 | return -ENOMEM; | 312 | return -ENOMEM; |
312 | } | 313 | } |
@@ -328,7 +329,8 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
328 | if (al.filtered) | 329 | if (al.filtered) |
329 | return 0; | 330 | return 0; |
330 | 331 | ||
331 | if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) { | 332 | if (hists__add_entry(&evsel->hists, &al, sample->period, |
333 | sample->weight, sample->transaction)) { | ||
332 | pr_warning("problem incrementing symbol period, skipping event\n"); | 334 | pr_warning("problem incrementing symbol period, skipping event\n"); |
333 | return -1; | 335 | return -1; |
334 | } | 336 | } |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8384b54e1eba..a78db3f31b25 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -894,6 +894,8 @@ const struct option record_options[] = { | |||
894 | parse_branch_stack), | 894 | parse_branch_stack), |
895 | OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, | 895 | OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, |
896 | "sample by weight (on special events only)"), | 896 | "sample by weight (on special events only)"), |
897 | OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, | ||
898 | "sample transaction flags (special events only)"), | ||
897 | OPT_END() | 899 | OPT_END() |
898 | }; | 900 | }; |
899 | 901 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 89b188d64ea9..06e1abe351dd 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -259,7 +259,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
259 | } | 259 | } |
260 | 260 | ||
261 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period, | 261 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period, |
262 | sample->weight); | 262 | sample->weight, sample->transaction); |
263 | if (he == NULL) | 263 | if (he == NULL) |
264 | return -ENOMEM; | 264 | return -ENOMEM; |
265 | 265 | ||
@@ -787,7 +787,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
787 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," | 787 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," |
788 | " dso_to, dso_from, symbol_to, symbol_from, mispredict," | 788 | " dso_to, dso_from, symbol_to, symbol_from, mispredict," |
789 | " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, " | 789 | " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, " |
790 | "snoop, locked, abort, in_tx"), | 790 | "snoop, locked, abort, in_tx, transaction"), |
791 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | 791 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, |
792 | "Show sample percentage for different cpu modes"), | 792 | "Show sample percentage for different cpu modes"), |
793 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 793 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6534a37d66fe..b3e0229ee38f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -247,9 +247,8 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
247 | 247 | ||
248 | pthread_mutex_lock(&evsel->hists.lock); | 248 | pthread_mutex_lock(&evsel->hists.lock); |
249 | he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, | 249 | he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, |
250 | sample->weight); | 250 | sample->weight, sample->transaction); |
251 | pthread_mutex_unlock(&evsel->hists.lock); | 251 | pthread_mutex_unlock(&evsel->hists.lock); |
252 | |||
253 | if (he == NULL) | 252 | if (he == NULL) |
254 | return NULL; | 253 | return NULL; |
255 | 254 | ||
@@ -1104,7 +1103,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1104 | "be more verbose (show counter open errors, etc)"), | 1103 | "be more verbose (show counter open errors, etc)"), |
1105 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 1104 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
1106 | "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight," | 1105 | "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight," |
1107 | " abort, in_tx"), | 1106 | " abort, in_tx, transaction"), |
1108 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1107 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1109 | "Show a column with the number of samples"), | 1108 | "Show a column with the number of samples"), |
1110 | OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, | 1109 | OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index acf3d665474d..84502e88488b 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -233,6 +233,7 @@ struct perf_record_opts { | |||
233 | u64 default_interval; | 233 | u64 default_interval; |
234 | u64 user_interval; | 234 | u64 user_interval; |
235 | u16 stack_dump_size; | 235 | u16 stack_dump_size; |
236 | bool sample_transaction; | ||
236 | }; | 237 | }; |
237 | 238 | ||
238 | #endif | 239 | #endif |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 4228ffc0d968..025503a22ff7 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -222,7 +222,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
222 | &sample) < 0) | 222 | &sample) < 0) |
223 | goto out; | 223 | goto out; |
224 | 224 | ||
225 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); | 225 | he = __hists__add_entry(&evsel->hists, &al, NULL, |
226 | 1, 1, 0); | ||
226 | if (he == NULL) | 227 | if (he == NULL) |
227 | goto out; | 228 | goto out; |
228 | 229 | ||
@@ -244,7 +245,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
244 | &sample) < 0) | 245 | &sample) < 0) |
245 | goto out; | 246 | goto out; |
246 | 247 | ||
247 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); | 248 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1, |
249 | 0); | ||
248 | if (he == NULL) | 250 | if (he == NULL) |
249 | goto out; | 251 | goto out; |
250 | 252 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c67ecc457d29..17d9e167a7b9 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -111,6 +111,7 @@ struct perf_sample { | |||
111 | u64 stream_id; | 111 | u64 stream_id; |
112 | u64 period; | 112 | u64 period; |
113 | u64 weight; | 113 | u64 weight; |
114 | u64 transaction; | ||
114 | u32 cpu; | 115 | u32 cpu; |
115 | u32 raw_size; | 116 | u32 raw_size; |
116 | u64 data_src; | 117 | u64 data_src; |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0ce9febf1ba0..abe69af58b62 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -681,6 +681,9 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
681 | attr->mmap2 = track && !perf_missing_features.mmap2; | 681 | attr->mmap2 = track && !perf_missing_features.mmap2; |
682 | attr->comm = track; | 682 | attr->comm = track; |
683 | 683 | ||
684 | if (opts->sample_transaction) | ||
685 | attr->sample_type |= PERF_SAMPLE_TRANSACTION; | ||
686 | |||
684 | /* | 687 | /* |
685 | * XXX see the function comment above | 688 | * XXX see the function comment above |
686 | * | 689 | * |
@@ -1470,6 +1473,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
1470 | array++; | 1473 | array++; |
1471 | } | 1474 | } |
1472 | 1475 | ||
1476 | data->transaction = 0; | ||
1477 | if (type & PERF_SAMPLE_TRANSACTION) { | ||
1478 | data->transaction = *array; | ||
1479 | array++; | ||
1480 | } | ||
1481 | |||
1473 | return 0; | 1482 | return 0; |
1474 | } | 1483 | } |
1475 | 1484 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 97dc2808885d..f3278a388e9a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -160,6 +160,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
160 | hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); | 160 | hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); |
161 | hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); | 161 | hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); |
162 | hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); | 162 | hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); |
163 | |||
164 | if (h->transaction) | ||
165 | hists__new_col_len(hists, HISTC_TRANSACTION, | ||
166 | hist_entry__transaction_len()); | ||
163 | } | 167 | } |
164 | 168 | ||
165 | void hists__output_recalc_col_len(struct hists *hists, int max_rows) | 169 | void hists__output_recalc_col_len(struct hists *hists, int max_rows) |
@@ -466,7 +470,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, | |||
466 | struct hist_entry *__hists__add_entry(struct hists *self, | 470 | struct hist_entry *__hists__add_entry(struct hists *self, |
467 | struct addr_location *al, | 471 | struct addr_location *al, |
468 | struct symbol *sym_parent, u64 period, | 472 | struct symbol *sym_parent, u64 period, |
469 | u64 weight) | 473 | u64 weight, u64 transaction) |
470 | { | 474 | { |
471 | struct hist_entry entry = { | 475 | struct hist_entry entry = { |
472 | .thread = al->thread, | 476 | .thread = al->thread, |
@@ -487,6 +491,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, | |||
487 | .hists = self, | 491 | .hists = self, |
488 | .branch_info = NULL, | 492 | .branch_info = NULL, |
489 | .mem_info = NULL, | 493 | .mem_info = NULL, |
494 | .transaction = transaction, | ||
490 | }; | 495 | }; |
491 | 496 | ||
492 | return add_hist_entry(self, &entry, al, period, weight); | 497 | return add_hist_entry(self, &entry, al, period, weight); |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f743e96005f2..6a048c09cd64 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -59,6 +59,7 @@ enum hist_column { | |||
59 | HISTC_MEM_TLB, | 59 | HISTC_MEM_TLB, |
60 | HISTC_MEM_LVL, | 60 | HISTC_MEM_LVL, |
61 | HISTC_MEM_SNOOP, | 61 | HISTC_MEM_SNOOP, |
62 | HISTC_TRANSACTION, | ||
62 | HISTC_NR_COLS, /* Last entry */ | 63 | HISTC_NR_COLS, /* Last entry */ |
63 | }; | 64 | }; |
64 | 65 | ||
@@ -84,9 +85,10 @@ struct hists { | |||
84 | struct hist_entry *__hists__add_entry(struct hists *self, | 85 | struct hist_entry *__hists__add_entry(struct hists *self, |
85 | struct addr_location *al, | 86 | struct addr_location *al, |
86 | struct symbol *parent, u64 period, | 87 | struct symbol *parent, u64 period, |
87 | u64 weight); | 88 | u64 weight, u64 transaction); |
88 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); | 89 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); |
89 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); | 90 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); |
91 | int hist_entry__transaction_len(void); | ||
90 | int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, | 92 | int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, |
91 | struct hists *hists); | 93 | struct hists *hists); |
92 | void hist_entry__free(struct hist_entry *); | 94 | void hist_entry__free(struct hist_entry *); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 70ffa41518f3..211b325791ad 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -858,6 +858,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, | |||
858 | if (sample_type & PERF_SAMPLE_DATA_SRC) | 858 | if (sample_type & PERF_SAMPLE_DATA_SRC) |
859 | printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); | 859 | printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); |
860 | 860 | ||
861 | if (sample_type & PERF_SAMPLE_TRANSACTION) | ||
862 | printf("... transaction: %" PRIx64 "\n", sample->transaction); | ||
863 | |||
861 | if (sample_type & PERF_SAMPLE_READ) | 864 | if (sample_type & PERF_SAMPLE_READ) |
862 | sample_read__printf(sample, evsel->attr.read_format); | 865 | sample_read__printf(sample, evsel->attr.read_format); |
863 | } | 866 | } |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1771566858cc..b4ecc0e4c908 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -907,6 +907,78 @@ struct sort_entry sort_in_tx = { | |||
907 | .se_width_idx = HISTC_IN_TX, | 907 | .se_width_idx = HISTC_IN_TX, |
908 | }; | 908 | }; |
909 | 909 | ||
910 | static int64_t | ||
911 | sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right) | ||
912 | { | ||
913 | return left->transaction - right->transaction; | ||
914 | } | ||
915 | |||
916 | static inline char *add_str(char *p, const char *str) | ||
917 | { | ||
918 | strcpy(p, str); | ||
919 | return p + strlen(str); | ||
920 | } | ||
921 | |||
922 | static struct txbit { | ||
923 | unsigned flag; | ||
924 | const char *name; | ||
925 | int skip_for_len; | ||
926 | } txbits[] = { | ||
927 | { PERF_TXN_ELISION, "EL ", 0 }, | ||
928 | { PERF_TXN_TRANSACTION, "TX ", 1 }, | ||
929 | { PERF_TXN_SYNC, "SYNC ", 1 }, | ||
930 | { PERF_TXN_ASYNC, "ASYNC ", 0 }, | ||
931 | { PERF_TXN_RETRY, "RETRY ", 0 }, | ||
932 | { PERF_TXN_CONFLICT, "CON ", 0 }, | ||
933 | { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 }, | ||
934 | { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 }, | ||
935 | { 0, NULL, 0 } | ||
936 | }; | ||
937 | |||
938 | int hist_entry__transaction_len(void) | ||
939 | { | ||
940 | int i; | ||
941 | int len = 0; | ||
942 | |||
943 | for (i = 0; txbits[i].name; i++) { | ||
944 | if (!txbits[i].skip_for_len) | ||
945 | len += strlen(txbits[i].name); | ||
946 | } | ||
947 | len += 4; /* :XX<space> */ | ||
948 | return len; | ||
949 | } | ||
950 | |||
951 | static int hist_entry__transaction_snprintf(struct hist_entry *self, char *bf, | ||
952 | size_t size, unsigned int width) | ||
953 | { | ||
954 | u64 t = self->transaction; | ||
955 | char buf[128]; | ||
956 | char *p = buf; | ||
957 | int i; | ||
958 | |||
959 | buf[0] = 0; | ||
960 | for (i = 0; txbits[i].name; i++) | ||
961 | if (txbits[i].flag & t) | ||
962 | p = add_str(p, txbits[i].name); | ||
963 | if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC))) | ||
964 | p = add_str(p, "NEITHER "); | ||
965 | if (t & PERF_TXN_ABORT_MASK) { | ||
966 | sprintf(p, ":%" PRIx64, | ||
967 | (t & PERF_TXN_ABORT_MASK) >> | ||
968 | PERF_TXN_ABORT_SHIFT); | ||
969 | p += strlen(p); | ||
970 | } | ||
971 | |||
972 | return repsep_snprintf(bf, size, "%-*s", width, buf); | ||
973 | } | ||
974 | |||
975 | struct sort_entry sort_transaction = { | ||
976 | .se_header = "Transaction ", | ||
977 | .se_cmp = sort__transaction_cmp, | ||
978 | .se_snprintf = hist_entry__transaction_snprintf, | ||
979 | .se_width_idx = HISTC_TRANSACTION, | ||
980 | }; | ||
981 | |||
910 | struct sort_dimension { | 982 | struct sort_dimension { |
911 | const char *name; | 983 | const char *name; |
912 | struct sort_entry *entry; | 984 | struct sort_entry *entry; |
@@ -925,6 +997,7 @@ static struct sort_dimension common_sort_dimensions[] = { | |||
925 | DIM(SORT_SRCLINE, "srcline", sort_srcline), | 997 | DIM(SORT_SRCLINE, "srcline", sort_srcline), |
926 | DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), | 998 | DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), |
927 | DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), | 999 | DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), |
1000 | DIM(SORT_TRANSACTION, "transaction", sort_transaction), | ||
928 | }; | 1001 | }; |
929 | 1002 | ||
930 | #undef DIM | 1003 | #undef DIM |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 9dad3a0440dc..bf4333694d3a 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -85,6 +85,7 @@ struct hist_entry { | |||
85 | struct map_symbol ms; | 85 | struct map_symbol ms; |
86 | struct thread *thread; | 86 | struct thread *thread; |
87 | u64 ip; | 87 | u64 ip; |
88 | u64 transaction; | ||
88 | s32 cpu; | 89 | s32 cpu; |
89 | 90 | ||
90 | struct hist_entry_diff diff; | 91 | struct hist_entry_diff diff; |
@@ -145,6 +146,7 @@ enum sort_type { | |||
145 | SORT_SRCLINE, | 146 | SORT_SRCLINE, |
146 | SORT_LOCAL_WEIGHT, | 147 | SORT_LOCAL_WEIGHT, |
147 | SORT_GLOBAL_WEIGHT, | 148 | SORT_GLOBAL_WEIGHT, |
149 | SORT_TRANSACTION, | ||
148 | 150 | ||
149 | /* branch stack specific sort keys */ | 151 | /* branch stack specific sort keys */ |
150 | __SORT_BRANCH_STACK, | 152 | __SORT_BRANCH_STACK, |