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

TOMOYO Linux Cross Reference
Linux/tools/perf/ui/gtk/hists.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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 "gtk.h"
  3 #include "../evlist.h"
  4 #include "../callchain.h"
  5 #include "../evsel.h"
  6 #include "../sort.h"
  7 #include "../hist.h"
  8 #include "../helpline.h"
  9 #include "../string2.h"
 10 #include <signal.h>
 11 #include <stdlib.h>
 12 #include <linux/string.h>
 13 
 14 #define MAX_COLUMNS                     32
 15 
 16 static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
 17 {
 18         int ret = 0;
 19         int len;
 20         va_list args;
 21         double percent;
 22         const char *markup;
 23         char *buf = hpp->buf;
 24         size_t size = hpp->size;
 25 
 26         va_start(args, fmt);
 27         len = va_arg(args, int);
 28         percent = va_arg(args, double);
 29         va_end(args);
 30 
 31         markup = perf_gtk__get_percent_color(percent);
 32         if (markup)
 33                 ret += scnprintf(buf, size, markup);
 34 
 35         ret += scnprintf(buf + ret, size - ret, fmt, len, percent);
 36 
 37         if (markup)
 38                 ret += scnprintf(buf + ret, size - ret, "</span>");
 39 
 40         return ret;
 41 }
 42 
 43 #define __HPP_COLOR_PERCENT_FN(_type, _field)                                   \
 44 static u64 he_get_##_field(struct hist_entry *he)                               \
 45 {                                                                               \
 46         return he->stat._field;                                                 \
 47 }                                                                               \
 48                                                                                 \
 49 static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt,                \
 50                                        struct perf_hpp *hpp,                    \
 51                                        struct hist_entry *he)                   \
 52 {                                                                               \
 53         return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%",              \
 54                         __percent_color_snprintf, true);                        \
 55 }
 56 
 57 #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field)                               \
 58 static u64 he_get_acc_##_field(struct hist_entry *he)                           \
 59 {                                                                               \
 60         return he->stat_acc->_field;                                            \
 61 }                                                                               \
 62                                                                                 \
 63 static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt,                \
 64                                        struct perf_hpp *hpp,                    \
 65                                        struct hist_entry *he)                   \
 66 {                                                                               \
 67         return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%",      \
 68                             __percent_color_snprintf, true);                    \
 69 }
 70 
 71 __HPP_COLOR_PERCENT_FN(overhead, period)
 72 __HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
 73 __HPP_COLOR_PERCENT_FN(overhead_us, period_us)
 74 __HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
 75 __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
 76 __HPP_COLOR_ACC_PERCENT_FN(overhead_acc, period)
 77 
 78 #undef __HPP_COLOR_PERCENT_FN
 79 
 80 
 81 void perf_gtk__init_hpp(void)
 82 {
 83         perf_hpp__format[PERF_HPP__OVERHEAD].color =
 84                                 perf_gtk__hpp_color_overhead;
 85         perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
 86                                 perf_gtk__hpp_color_overhead_sys;
 87         perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
 88                                 perf_gtk__hpp_color_overhead_us;
 89         perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
 90                                 perf_gtk__hpp_color_overhead_guest_sys;
 91         perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
 92                                 perf_gtk__hpp_color_overhead_guest_us;
 93         perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color =
 94                                 perf_gtk__hpp_color_overhead_acc;
 95 }
 96 
 97 static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *store,
 98                                          GtkTreeIter *parent, int col, u64 total)
 99 {
100         struct rb_node *nd;
101         bool has_single_node = (rb_first(root) == rb_last(root));
102 
103         for (nd = rb_first(root); nd; nd = rb_next(nd)) {
104                 struct callchain_node *node;
105                 struct callchain_list *chain;
106                 GtkTreeIter iter, new_parent;
107                 bool need_new_parent;
108 
109                 node = rb_entry(nd, struct callchain_node, rb_node);
110 
111                 new_parent = *parent;
112                 need_new_parent = !has_single_node;
113 
114                 callchain_node__make_parent_list(node);
115 
116                 list_for_each_entry(chain, &node->parent_val, list) {
117                         char buf[128];
118 
119                         gtk_tree_store_append(store, &iter, &new_parent);
120 
121                         callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
122                         gtk_tree_store_set(store, &iter, 0, buf, -1);
123 
124                         callchain_list__sym_name(chain, buf, sizeof(buf), false);
125                         gtk_tree_store_set(store, &iter, col, buf, -1);
126 
127                         if (need_new_parent) {
128                                 /*
129                                  * Only show the top-most symbol in a callchain
130                                  * if it's not the only callchain.
131                                  */
132                                 new_parent = iter;
133                                 need_new_parent = false;
134                         }
135                 }
136 
137                 list_for_each_entry(chain, &node->val, list) {
138                         char buf[128];
139 
140                         gtk_tree_store_append(store, &iter, &new_parent);
141 
142                         callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
143                         gtk_tree_store_set(store, &iter, 0, buf, -1);
144 
145                         callchain_list__sym_name(chain, buf, sizeof(buf), false);
146                         gtk_tree_store_set(store, &iter, col, buf, -1);
147 
148                         if (need_new_parent) {
149                                 /*
150                                  * Only show the top-most symbol in a callchain
151                                  * if it's not the only callchain.
152                                  */
153                                 new_parent = iter;
154                                 need_new_parent = false;
155                         }
156                 }
157         }
158 }
159 
160 static void perf_gtk__add_callchain_folded(struct rb_root *root, GtkTreeStore *store,
161                                            GtkTreeIter *parent, int col, u64 total)
162 {
163         struct rb_node *nd;
164 
165         for (nd = rb_first(root); nd; nd = rb_next(nd)) {
166                 struct callchain_node *node;
167                 struct callchain_list *chain;
168                 GtkTreeIter iter;
169                 char buf[64];
170                 char *str, *str_alloc = NULL;
171                 bool first = true;
172 
173                 node = rb_entry(nd, struct callchain_node, rb_node);
174 
175                 callchain_node__make_parent_list(node);
176 
177                 list_for_each_entry(chain, &node->parent_val, list) {
178                         char name[1024];
179 
180                         callchain_list__sym_name(chain, name, sizeof(name), false);
181 
182                         if (asprintf(&str, "%s%s%s",
183                                      first ? "" : str_alloc,
184                                      first ? "" : symbol_conf.field_sep ?: "; ",
185                                      name) < 0)
186                                 return;
187 
188                         first = false;
189                         free(str_alloc);
190                         str_alloc = str;
191                 }
192 
193                 list_for_each_entry(chain, &node->val, list) {
194                         char name[1024];
195 
196                         callchain_list__sym_name(chain, name, sizeof(name), false);
197 
198                         if (asprintf(&str, "%s%s%s",
199                                      first ? "" : str_alloc,
200                                      first ? "" : symbol_conf.field_sep ?: "; ",
201                                      name) < 0)
202                                 return;
203 
204                         first = false;
205                         free(str_alloc);
206                         str_alloc = str;
207                 }
208 
209                 gtk_tree_store_append(store, &iter, parent);
210 
211                 callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
212                 gtk_tree_store_set(store, &iter, 0, buf, -1);
213 
214                 gtk_tree_store_set(store, &iter, col, str, -1);
215 
216                 free(str_alloc);
217         }
218 }
219 
220 static void perf_gtk__add_callchain_graph(struct rb_root *root, GtkTreeStore *store,
221                                           GtkTreeIter *parent, int col, u64 total)
222 {
223         struct rb_node *nd;
224         bool has_single_node = (rb_first(root) == rb_last(root));
225 
226         for (nd = rb_first(root); nd; nd = rb_next(nd)) {
227                 struct callchain_node *node;
228                 struct callchain_list *chain;
229                 GtkTreeIter iter, new_parent;
230                 bool need_new_parent;
231                 u64 child_total;
232 
233                 node = rb_entry(nd, struct callchain_node, rb_node);
234 
235                 new_parent = *parent;
236                 need_new_parent = !has_single_node && (node->val_nr > 1);
237 
238                 list_for_each_entry(chain, &node->val, list) {
239                         char buf[128];
240 
241                         gtk_tree_store_append(store, &iter, &new_parent);
242 
243                         callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
244                         gtk_tree_store_set(store, &iter, 0, buf, -1);
245 
246                         callchain_list__sym_name(chain, buf, sizeof(buf), false);
247                         gtk_tree_store_set(store, &iter, col, buf, -1);
248 
249                         if (need_new_parent) {
250                                 /*
251                                  * Only show the top-most symbol in a callchain
252                                  * if it's not the only callchain.
253                                  */
254                                 new_parent = iter;
255                                 need_new_parent = false;
256                         }
257                 }
258 
259                 if (callchain_param.mode == CHAIN_GRAPH_REL)
260                         child_total = node->children_hit;
261                 else
262                         child_total = total;
263 
264                 /* Now 'iter' contains info of the last callchain_list */
265                 perf_gtk__add_callchain_graph(&node->rb_root, store, &iter, col,
266                                               child_total);
267         }
268 }
269 
270 static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
271                                     GtkTreeIter *parent, int col, u64 total)
272 {
273         if (callchain_param.mode == CHAIN_FLAT)
274                 perf_gtk__add_callchain_flat(root, store, parent, col, total);
275         else if (callchain_param.mode == CHAIN_FOLDED)
276                 perf_gtk__add_callchain_folded(root, store, parent, col, total);
277         else
278                 perf_gtk__add_callchain_graph(root, store, parent, col, total);
279 }
280 
281 static void on_row_activated(GtkTreeView *view, GtkTreePath *path,
282                              GtkTreeViewColumn *col __maybe_unused,
283                              gpointer user_data __maybe_unused)
284 {
285         bool expanded = gtk_tree_view_row_expanded(view, path);
286 
287         if (expanded)
288                 gtk_tree_view_collapse_row(view, path);
289         else
290                 gtk_tree_view_expand_row(view, path, FALSE);
291 }
292 
293 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
294                                  float min_pcnt)
295 {
296         struct perf_hpp_fmt *fmt;
297         GType col_types[MAX_COLUMNS];
298         GtkCellRenderer *renderer;
299         GtkTreeStore *store;
300         struct rb_node *nd;
301         GtkWidget *view;
302         int col_idx;
303         int sym_col = -1;
304         int nr_cols;
305         char s[512];
306 
307         struct perf_hpp hpp = {
308                 .buf            = s,
309                 .size           = sizeof(s),
310         };
311 
312         nr_cols = 0;
313 
314         hists__for_each_format(hists, fmt)
315                 col_types[nr_cols++] = G_TYPE_STRING;
316 
317         store = gtk_tree_store_newv(nr_cols, col_types);
318 
319         view = gtk_tree_view_new();
320 
321         renderer = gtk_cell_renderer_text_new();
322 
323         col_idx = 0;
324 
325         hists__for_each_format(hists, fmt) {
326                 if (perf_hpp__should_skip(fmt, hists))
327                         continue;
328 
329                 /*
330                  * XXX no way to determine where symcol column is..
331                  *     Just use last column for now.
332                  */
333                 if (perf_hpp__is_sort_entry(fmt))
334                         sym_col = col_idx;
335 
336                 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
337                                                             -1, fmt->name,
338                                                             renderer, "markup",
339                                                             col_idx++, NULL);
340         }
341 
342         for (col_idx = 0; col_idx < nr_cols; col_idx++) {
343                 GtkTreeViewColumn *column;
344 
345                 column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_idx);
346                 gtk_tree_view_column_set_resizable(column, TRUE);
347 
348                 if (col_idx == sym_col) {
349                         gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view),
350                                                           column);
351                 }
352         }
353 
354         gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
355 
356         g_object_unref(GTK_TREE_MODEL(store));
357 
358         for (nd = rb_first_cached(&hists->entries); nd; nd = rb_next(nd)) {
359                 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
360                 GtkTreeIter iter;
361                 u64 total = hists__total_period(h->hists);
362                 float percent;
363 
364                 if (h->filtered)
365                         continue;
366 
367                 percent = hist_entry__get_percent_limit(h);
368                 if (percent < min_pcnt)
369                         continue;
370 
371                 gtk_tree_store_append(store, &iter, NULL);
372 
373                 col_idx = 0;
374 
375                 hists__for_each_format(hists, fmt) {
376                         if (perf_hpp__should_skip(fmt, h->hists))
377                                 continue;
378 
379                         if (fmt->color)
380                                 fmt->color(fmt, &hpp, h);
381                         else
382                                 fmt->entry(fmt, &hpp, h);
383 
384                         gtk_tree_store_set(store, &iter, col_idx++, s, -1);
385                 }
386 
387                 if (hist_entry__has_callchains(h) &&
388                     symbol_conf.use_callchain && hists__has(hists, sym)) {
389                         if (callchain_param.mode == CHAIN_GRAPH_REL)
390                                 total = symbol_conf.cumulate_callchain ?
391                                         h->stat_acc->period : h->stat.period;
392 
393                         perf_gtk__add_callchain(&h->sorted_chain, store, &iter,
394                                                 sym_col, total);
395                 }
396         }
397 
398         gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
399 
400         g_signal_connect(view, "row-activated",
401                          G_CALLBACK(on_row_activated), NULL);
402         gtk_container_add(GTK_CONTAINER(window), view);
403 }
404 
405 static void perf_gtk__add_hierarchy_entries(struct hists *hists,
406                                             struct rb_root_cached *root,
407                                             GtkTreeStore *store,
408                                             GtkTreeIter *parent,
409                                             struct perf_hpp *hpp,
410                                             float min_pcnt)
411 {
412         int col_idx = 0;
413         struct rb_node *node;
414         struct hist_entry *he;
415         struct perf_hpp_fmt *fmt;
416         struct perf_hpp_list_node *fmt_node;
417         u64 total = hists__total_period(hists);
418         int size;
419 
420         for (node = rb_first_cached(root); node; node = rb_next(node)) {
421                 GtkTreeIter iter;
422                 float percent;
423                 char *bf;
424 
425                 he = rb_entry(node, struct hist_entry, rb_node);
426                 if (he->filtered)
427                         continue;
428 
429                 percent = hist_entry__get_percent_limit(he);
430                 if (percent < min_pcnt)
431                         continue;
432 
433                 gtk_tree_store_append(store, &iter, parent);
434 
435                 col_idx = 0;
436 
437                 /* the first hpp_list_node is for overhead columns */
438                 fmt_node = list_first_entry(&hists->hpp_formats,
439                                             struct perf_hpp_list_node, list);
440                 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
441                         if (fmt->color)
442                                 fmt->color(fmt, hpp, he);
443                         else
444                                 fmt->entry(fmt, hpp, he);
445 
446                         gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
447                 }
448 
449                 bf = hpp->buf;
450                 size = hpp->size;
451                 perf_hpp_list__for_each_format(he->hpp_list, fmt) {
452                         int ret;
453 
454                         if (fmt->color)
455                                 ret = fmt->color(fmt, hpp, he);
456                         else
457                                 ret = fmt->entry(fmt, hpp, he);
458 
459                         snprintf(hpp->buf + ret, hpp->size - ret, "  ");
460                         advance_hpp(hpp, ret + 2);
461                 }
462 
463                 gtk_tree_store_set(store, &iter, col_idx, strim(bf), -1);
464 
465                 if (!he->leaf) {
466                         hpp->buf = bf;
467                         hpp->size = size;
468 
469                         perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
470                                                         store, &iter, hpp,
471                                                         min_pcnt);
472 
473                         if (!hist_entry__has_hierarchy_children(he, min_pcnt)) {
474                                 char buf[32];
475                                 GtkTreeIter child;
476 
477                                 snprintf(buf, sizeof(buf), "no entry >= %.2f%%",
478                                          min_pcnt);
479 
480                                 gtk_tree_store_append(store, &child, &iter);
481                                 gtk_tree_store_set(store, &child, col_idx, buf, -1);
482                         }
483                 }
484 
485                 if (he->leaf && hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
486                         if (callchain_param.mode == CHAIN_GRAPH_REL)
487                                 total = symbol_conf.cumulate_callchain ?
488                                         he->stat_acc->period : he->stat.period;
489 
490                         perf_gtk__add_callchain(&he->sorted_chain, store, &iter,
491                                                 col_idx, total);
492                 }
493         }
494 
495 }
496 
497 static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
498                                      float min_pcnt)
499 {
500         struct perf_hpp_fmt *fmt;
501         struct perf_hpp_list_node *fmt_node;
502         GType col_types[MAX_COLUMNS];
503         GtkCellRenderer *renderer;
504         GtkTreeStore *store;
505         GtkWidget *view;
506         int col_idx;
507         int nr_cols = 0;
508         char s[512];
509         char buf[512];
510         bool first_node, first_col;
511         struct perf_hpp hpp = {
512                 .buf            = s,
513                 .size           = sizeof(s),
514         };
515 
516         hists__for_each_format(hists, fmt) {
517                 if (perf_hpp__is_sort_entry(fmt) ||
518                     perf_hpp__is_dynamic_entry(fmt))
519                         break;
520 
521                 col_types[nr_cols++] = G_TYPE_STRING;
522         }
523         col_types[nr_cols++] = G_TYPE_STRING;
524 
525         store = gtk_tree_store_newv(nr_cols, col_types);
526         view = gtk_tree_view_new();
527         renderer = gtk_cell_renderer_text_new();
528 
529         col_idx = 0;
530 
531         /* the first hpp_list_node is for overhead columns */
532         fmt_node = list_first_entry(&hists->hpp_formats,
533                                     struct perf_hpp_list_node, list);
534         perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
535                 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
536                                                             -1, fmt->name,
537                                                             renderer, "markup",
538                                                             col_idx++, NULL);
539         }
540 
541         /* construct merged column header since sort keys share single column */
542         buf[0] = '\0';
543         first_node = true;
544         list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
545                 if (!first_node)
546                         strcat(buf, " / ");
547                 first_node = false;
548 
549                 first_col = true;
550                 perf_hpp_list__for_each_format(&fmt_node->hpp ,fmt) {
551                         if (perf_hpp__should_skip(fmt, hists))
552                                 continue;
553 
554                         if (!first_col)
555                                 strcat(buf, "+");
556                         first_col = false;
557 
558                         fmt->header(fmt, &hpp, hists, 0, NULL);
559                         strcat(buf, strim(hpp.buf));
560                 }
561         }
562 
563         gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
564                                                     -1, buf,
565                                                     renderer, "markup",
566                                                     col_idx++, NULL);
567 
568         for (col_idx = 0; col_idx < nr_cols; col_idx++) {
569                 GtkTreeViewColumn *column;
570 
571                 column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_idx);
572                 gtk_tree_view_column_set_resizable(column, TRUE);
573 
574                 if (col_idx == 0) {
575                         gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view),
576                                                           column);
577                 }
578         }
579 
580         gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
581         g_object_unref(GTK_TREE_MODEL(store));
582 
583         perf_gtk__add_hierarchy_entries(hists, &hists->entries, store,
584                                         NULL, &hpp, min_pcnt);
585 
586         gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
587 
588         g_signal_connect(view, "row-activated",
589                          G_CALLBACK(on_row_activated), NULL);
590         gtk_container_add(GTK_CONTAINER(window), view);
591 }
592 
593 int evlist__gtk_browse_hists(struct evlist *evlist, const char *help,
594                              struct hist_browser_timer *hbt __maybe_unused, float min_pcnt)
595 {
596         struct evsel *pos;
597         GtkWidget *vbox;
598         GtkWidget *notebook;
599         GtkWidget *info_bar;
600         GtkWidget *statbar;
601         GtkWidget *window;
602 
603         signal(SIGSEGV, perf_gtk__signal);
604         signal(SIGFPE,  perf_gtk__signal);
605         signal(SIGINT,  perf_gtk__signal);
606         signal(SIGQUIT, perf_gtk__signal);
607         signal(SIGTERM, perf_gtk__signal);
608 
609         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
610 
611         gtk_window_set_title(GTK_WINDOW(window), "perf report");
612 
613         g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
614 
615         pgctx = perf_gtk__activate_context(window);
616         if (!pgctx)
617                 return -1;
618 
619         vbox = gtk_vbox_new(FALSE, 0);
620 
621         notebook = gtk_notebook_new();
622 
623         gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
624 
625         info_bar = perf_gtk__setup_info_bar();
626         if (info_bar)
627                 gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
628 
629         statbar = perf_gtk__setup_statusbar();
630         gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
631 
632         gtk_container_add(GTK_CONTAINER(window), vbox);
633 
634         evlist__for_each_entry(evlist, pos) {
635                 struct hists *hists = evsel__hists(pos);
636                 const char *evname = evsel__name(pos);
637                 GtkWidget *scrolled_window;
638                 GtkWidget *tab_label;
639                 char buf[512];
640                 size_t size = sizeof(buf);
641 
642                 if (symbol_conf.event_group) {
643                         if (!evsel__is_group_leader(pos))
644                                 continue;
645 
646                         if (pos->core.nr_members > 1) {
647                                 evsel__group_desc(pos, buf, size);
648                                 evname = buf;
649                         }
650                 }
651 
652                 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
653 
654                 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
655                                                         GTK_POLICY_AUTOMATIC,
656                                                         GTK_POLICY_AUTOMATIC);
657 
658                 if (symbol_conf.report_hierarchy)
659                         perf_gtk__show_hierarchy(scrolled_window, hists, min_pcnt);
660                 else
661                         perf_gtk__show_hists(scrolled_window, hists, min_pcnt);
662 
663                 tab_label = gtk_label_new(evname);
664 
665                 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
666         }
667 
668         gtk_widget_show_all(window);
669 
670         perf_gtk__resize_window(window);
671 
672         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
673 
674         ui_helpline__push(help);
675 
676         gtk_main();
677 
678         perf_gtk__deactivate_context(&pgctx);
679 
680         return 0;
681 }
682 

~ [ 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