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

TOMOYO Linux Cross Reference
Linux/tools/perf/ui/browsers/annotate-data.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <inttypes.h>
  3 #include <string.h>
  4 #include <linux/zalloc.h>
  5 #include <sys/ttydefaults.h>
  6 
  7 #include "ui/browser.h"
  8 #include "ui/helpline.h"
  9 #include "ui/keysyms.h"
 10 #include "ui/ui.h"
 11 #include "util/annotate.h"
 12 #include "util/annotate-data.h"
 13 #include "util/evsel.h"
 14 #include "util/evlist.h"
 15 #include "util/sort.h"
 16 
 17 struct annotated_data_browser {
 18         struct ui_browser b;
 19         struct list_head entries;
 20         int nr_events;
 21 };
 22 
 23 struct browser_entry {
 24         struct list_head node;
 25         struct annotated_member *data;
 26         struct type_hist_entry *hists;
 27         int indent;
 28 };
 29 
 30 static struct annotated_data_browser *get_browser(struct ui_browser *uib)
 31 {
 32         return container_of(uib, struct annotated_data_browser, b);
 33 }
 34 
 35 static void update_hist_entry(struct type_hist_entry *dst,
 36                               struct type_hist_entry *src)
 37 {
 38         dst->nr_samples += src->nr_samples;
 39         dst->period += src->period;
 40 }
 41 
 42 static int get_member_overhead(struct annotated_data_type *adt,
 43                                struct browser_entry *entry,
 44                                struct evsel *leader)
 45 {
 46         struct annotated_member *member = entry->data;
 47         int i, k;
 48 
 49         for (i = 0; i < member->size; i++) {
 50                 struct type_hist *h;
 51                 struct evsel *evsel;
 52                 int offset = member->offset + i;
 53 
 54                 for_each_group_evsel(evsel, leader) {
 55                         h = adt->histograms[evsel->core.idx];
 56                         k = evsel__group_idx(evsel);
 57                         update_hist_entry(&entry->hists[k], &h->addr[offset]);
 58                 }
 59         }
 60         return 0;
 61 }
 62 
 63 static int add_child_entries(struct annotated_data_browser *browser,
 64                              struct annotated_data_type *adt,
 65                              struct annotated_member *member,
 66                              struct evsel *evsel, int indent)
 67 {
 68         struct annotated_member *pos;
 69         struct browser_entry *entry;
 70         int nr_entries = 0;
 71 
 72         entry = zalloc(sizeof(*entry));
 73         if (entry == NULL)
 74                 return -1;
 75 
 76         entry->hists = calloc(browser->nr_events, sizeof(*entry->hists));
 77         if (entry->hists == NULL) {
 78                 free(entry);
 79                 return -1;
 80         }
 81 
 82         entry->data = member;
 83         entry->indent = indent;
 84         if (get_member_overhead(adt, entry, evsel) < 0) {
 85                 free(entry);
 86                 return -1;
 87         }
 88 
 89         list_add_tail(&entry->node, &browser->entries);
 90         nr_entries++;
 91 
 92         list_for_each_entry(pos, &member->children, node) {
 93                 int nr = add_child_entries(browser, adt, pos, evsel, indent + 1);
 94 
 95                 if (nr < 0)
 96                         return nr;
 97 
 98                 nr_entries += nr;
 99         }
100 
101         /* add an entry for the closing bracket ("}") */
102         if (!list_empty(&member->children)) {
103                 entry = zalloc(sizeof(*entry));
104                 if (entry == NULL)
105                         return -1;
106 
107                 entry->indent = indent;
108                 list_add_tail(&entry->node, &browser->entries);
109                 nr_entries++;
110         }
111 
112         return nr_entries;
113 }
114 
115 static int annotated_data_browser__collect_entries(struct annotated_data_browser *browser)
116 {
117         struct hist_entry *he = browser->b.priv;
118         struct annotated_data_type *adt = he->mem_type;
119         struct evsel *evsel = hists_to_evsel(he->hists);
120 
121         INIT_LIST_HEAD(&browser->entries);
122         browser->b.entries = &browser->entries;
123         browser->b.nr_entries = add_child_entries(browser, adt, &adt->self,
124                                                   evsel, /*indent=*/0);
125         return 0;
126 }
127 
128 static void annotated_data_browser__delete_entries(struct annotated_data_browser *browser)
129 {
130         struct browser_entry *pos, *tmp;
131 
132         list_for_each_entry_safe(pos, tmp, &browser->entries, node) {
133                 list_del_init(&pos->node);
134                 zfree(&pos->hists);
135                 free(pos);
136         }
137 }
138 
139 static unsigned int browser__refresh(struct ui_browser *uib)
140 {
141         return ui_browser__list_head_refresh(uib);
142 }
143 
144 static int browser__show(struct ui_browser *uib)
145 {
146         struct hist_entry *he = uib->priv;
147         struct annotated_data_type *adt = he->mem_type;
148         struct annotated_data_browser *browser = get_browser(uib);
149         const char *help = "Press 'h' for help on key bindings";
150         char title[256];
151 
152         snprintf(title, sizeof(title), "Annotate type: '%s' (%d samples)",
153                  adt->self.type_name, he->stat.nr_events);
154 
155         if (ui_browser__show(uib, title, help) < 0)
156                 return -1;
157 
158         /* second line header */
159         ui_browser__gotorc_title(uib, 0, 0);
160         ui_browser__set_color(uib, HE_COLORSET_ROOT);
161 
162         if (symbol_conf.show_total_period)
163                 strcpy(title, "Period");
164         else if (symbol_conf.show_nr_samples)
165                 strcpy(title, "Samples");
166         else
167                 strcpy(title, "Percent");
168 
169         ui_browser__printf(uib, "%*s %10s %10s %10s  %s",
170                            11 * (browser->nr_events - 1), "",
171                            title, "Offset", "Size", "Field");
172         ui_browser__write_nstring(uib, "", uib->width);
173         return 0;
174 }
175 
176 static void browser__write_overhead(struct ui_browser *uib,
177                                     struct type_hist *total,
178                                     struct type_hist_entry *hist, int row)
179 {
180         u64 period = hist->period;
181         double percent = total->period ? (100.0 * period / total->period) : 0;
182         bool current = ui_browser__is_current_entry(uib, row);
183         int nr_samples = 0;
184 
185         ui_browser__set_percent_color(uib, percent, current);
186 
187         if (symbol_conf.show_total_period)
188                 ui_browser__printf(uib, " %10" PRIu64, period);
189         else if (symbol_conf.show_nr_samples)
190                 ui_browser__printf(uib, " %10d", nr_samples);
191         else
192                 ui_browser__printf(uib, " %10.2f", percent);
193 
194         ui_browser__set_percent_color(uib, 0, current);
195 }
196 
197 static void browser__write(struct ui_browser *uib, void *entry, int row)
198 {
199         struct annotated_data_browser *browser = get_browser(uib);
200         struct browser_entry *be = entry;
201         struct annotated_member *member = be->data;
202         struct hist_entry *he = uib->priv;
203         struct annotated_data_type *adt = he->mem_type;
204         struct evsel *leader = hists_to_evsel(he->hists);
205         struct evsel *evsel;
206 
207         if (member == NULL) {
208                 bool current = ui_browser__is_current_entry(uib, row);
209 
210                 /* print the closing bracket */
211                 ui_browser__set_percent_color(uib, 0, current);
212                 ui_browser__write_nstring(uib, "", 11 * browser->nr_events);
213                 ui_browser__printf(uib, " %10s %10s  %*s};",
214                                    "", "", be->indent * 4, "");
215                 ui_browser__write_nstring(uib, "", uib->width);
216                 return;
217         }
218 
219         /* print the number */
220         for_each_group_evsel(evsel, leader) {
221                 struct type_hist *h = adt->histograms[evsel->core.idx];
222                 int idx = evsel__group_idx(evsel);
223 
224                 browser__write_overhead(uib, h, &be->hists[idx], row);
225         }
226 
227         /* print type info */
228         if (be->indent == 0 && !member->var_name) {
229                 ui_browser__printf(uib, " %10d %10d  %s%s",
230                                    member->offset, member->size,
231                                    member->type_name,
232                                    list_empty(&member->children) ? ";" : " {");
233         } else {
234                 ui_browser__printf(uib, " %10d %10d  %*s%s\t%s%s",
235                                    member->offset, member->size,
236                                    be->indent * 4, "", member->type_name,
237                                    member->var_name ?: "",
238                                    list_empty(&member->children) ? ";" : " {");
239         }
240         /* fill the rest */
241         ui_browser__write_nstring(uib, "", uib->width);
242 }
243 
244 static int annotated_data_browser__run(struct annotated_data_browser *browser,
245                                        struct evsel *evsel __maybe_unused,
246                                        struct hist_browser_timer *hbt)
247 {
248         int delay_secs = hbt ? hbt->refresh : 0;
249         int key;
250 
251         if (browser__show(&browser->b) < 0)
252                 return -1;
253 
254         while (1) {
255                 key = ui_browser__run(&browser->b, delay_secs);
256 
257                 switch (key) {
258                 case K_TIMER:
259                         if (hbt)
260                                 hbt->timer(hbt->arg);
261                         continue;
262                 case K_F1:
263                 case 'h':
264                         ui_browser__help_window(&browser->b,
265                 "UP/DOWN/PGUP\n"
266                 "PGDN/SPACE    Navigate\n"
267                 "</>           Move to prev/next symbol\n"
268                 "q/ESC/CTRL+C  Exit\n\n");
269                         continue;
270                 case K_LEFT:
271                 case '<':
272                 case '>':
273                 case K_ESC:
274                 case 'q':
275                 case CTRL('c'):
276                         goto out;
277                 default:
278                         continue;
279                 }
280         }
281 out:
282         ui_browser__hide(&browser->b);
283         return key;
284 }
285 
286 int hist_entry__annotate_data_tui(struct hist_entry *he, struct evsel *evsel,
287                                   struct hist_browser_timer *hbt)
288 {
289         struct annotated_data_browser browser = {
290                 .b = {
291                         .refresh = browser__refresh,
292                         .seek    = ui_browser__list_head_seek,
293                         .write   = browser__write,
294                         .priv    = he,
295                         .extra_title_lines = 1,
296                 },
297                 .nr_events = 1,
298         };
299         int ret;
300 
301         ui_helpline__push("Press ESC to exit");
302 
303         if (evsel__is_group_event(evsel))
304                 browser.nr_events = evsel->core.nr_members;
305 
306         ret = annotated_data_browser__collect_entries(&browser);
307         if (ret == 0)
308                 ret = annotated_data_browser__run(&browser, evsel, hbt);
309 
310         annotated_data_browser__delete_entries(&browser);
311 
312         return ret;
313 }
314 

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

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

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

sflogo.php