aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-02-18 09:59:42 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-18 09:59:42 -0500
commitdf49e6a44d60740e6730e2b5255b53c900adc9a7 (patch)
tree381e23b44acdd509ca46ba749b9eb2ca578079e3
parentea645651cdc0ab38fddeb9f81b13eccc9a22d98d (diff)
trace-graph: Added CPU plotting menu
Added menu for adding and removing CPU plots and Tasks. Only CPU updates have been implemented in this change set. Task updates will follow. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--cpu.h34
-rw-r--r--trace-graph-main.c77
-rw-r--r--trace-graph.c6
-rw-r--r--trace-graph.h18
-rw-r--r--trace-plot-cpu.c111
-rw-r--r--trace-plot-task.c6
-rw-r--r--trace-plot.c13
7 files changed, 248 insertions, 17 deletions
diff --git a/cpu.h b/cpu.h
index dabf870..203d79a 100644
--- a/cpu.h
+++ b/cpu.h
@@ -57,4 +57,38 @@ static inline void set_cpus(guint64 *cpu_mask, gint cpus)
57 *(cpu_mask) = (1ULL << (cpus & ((1ULL << 6) - 1))) - 1; 57 *(cpu_mask) = (1ULL << (cpus & ((1ULL << 6) - 1))) - 1;
58} 58}
59 59
60static inline gboolean cpus_equal(guint64 *a_mask, guint64 *b_mask,
61 gint cpus)
62{
63 gint idx;
64
65 for (idx = 0; idx < (cpus >> 6) + 1; idx++) {
66 if (*(a_mask + idx) != *(b_mask + idx))
67 return FALSE;
68 }
69 return TRUE;
70}
71
72/* Hamming weight */
73static inline guint hweight(guint mask)
74{
75 guint64 w = mask;
76
77 w -= (w >> 1) & 0x5555555555555555ul;
78 w = (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul);
79 w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful;
80 return (w * 0x0101010101010101ul) >> 56;
81}
82
83static inline guint cpu_weight(guint64 *cpu_mask, guint cpus)
84{
85 guint weight = 0;
86 gint idx;
87
88 for (idx = 0; idx < (cpus >> 6) + 1; idx++)
89 weight += hweight(*(cpu_mask + idx));
90
91 return weight;
92}
93
60#endif /* _CPU_H */ 94#endif /* _CPU_H */
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 987a80d..adc05ca 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -120,6 +120,37 @@ adv_filter_clicked (gpointer data)
120 trace_graph_adv_filter_callback, ginfo); 120 trace_graph_adv_filter_callback, ginfo);
121} 121}
122 122
123/* Callback for the clicked signal of the plot CPUs button */
124static void
125plot_cpu_clicked (gpointer data)
126{
127 struct graph_info *ginfo = data;
128 gboolean all_cpus;
129 guint64 *cpu_mask;
130
131 if (!ginfo->handle)
132 return;
133
134 graph_plot_cpus_plotted(ginfo, &all_cpus, &cpu_mask);
135
136 trace_filter_cpu_dialog(all_cpus, cpu_mask, ginfo->cpus,
137 graph_plot_cpus_update_callback, ginfo);
138 g_free(cpu_mask);
139}
140
141/* Callback for the clicked signal of the plot tasks button */
142static void
143plot_tasks_clicked (gpointer data)
144{
145 struct graph_info *ginfo = data;
146 gboolean all_events = TRUE;
147
148 if (!ginfo->handle)
149 return;
150
151 all_events = ginfo->all_events;
152}
153
123void trace_graph(int argc, char **argv) 154void trace_graph(int argc, char **argv)
124{ 155{
125 struct tracecmd_input *handle = NULL; 156 struct tracecmd_input *handle = NULL;
@@ -276,6 +307,52 @@ void trace_graph(int argc, char **argv)
276 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); 307 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
277 308
278 309
310 /* --- Plot Option --- */
311
312 menu_item = gtk_menu_item_new_with_label("Plots");
313 gtk_widget_show(menu_item);
314
315 gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item);
316
317 menu = gtk_menu_new(); /* Don't need to show menus */
318
319
320 /* --- Plot - CPUs Option --- */
321
322 sub_item = gtk_menu_item_new_with_label("CPUs");
323
324 /* Add them to the menu */
325 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
326
327 /* We can attach the Quit menu item to our exit function */
328 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
329 G_CALLBACK (plot_cpu_clicked),
330 (gpointer) ginfo);
331
332 /* We do need to show menu items */
333 gtk_widget_show(sub_item);
334
335
336 /* --- Plot - Tasks Option --- */
337
338 sub_item = gtk_menu_item_new_with_label("Tasks");
339
340 /* Add them to the menu */
341 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
342
343 /* We can attach the Quit menu item to our exit function */
344 g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
345 G_CALLBACK (plot_tasks_clicked),
346 (gpointer) ginfo);
347
348 /* We do need to show menu items */
349 gtk_widget_show(sub_item);
350
351
352 /* --- End Plot Options --- */
353 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
354
355
279 /* --- Top Level Hbox --- */ 356 /* --- Top Level Hbox --- */
280 357
281 hbox = gtk_hbox_new(FALSE, 0); 358 hbox = gtk_hbox_new(FALSE, 0);
diff --git a/trace-graph.c b/trace-graph.c
index fa76874..3c3f98d 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -2076,6 +2076,12 @@ static int load_handle(struct graph_info *ginfo,
2076 return 0; 2076 return 0;
2077} 2077}
2078 2078
2079void trace_graph_refresh(struct graph_info *ginfo)
2080{
2081 update_label_window(ginfo);
2082 redraw_graph(ginfo);
2083}
2084
2079int trace_graph_load_handle(struct graph_info *ginfo, 2085int trace_graph_load_handle(struct graph_info *ginfo,
2080 struct tracecmd_input *handle) 2086 struct tracecmd_input *handle)
2081{ 2087{
diff --git a/trace-graph.h b/trace-graph.h
index ae5f50d..7fdc5f0 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -32,6 +32,13 @@ typedef void (graph_filter_cb)(struct graph_info *ginfo,
32 struct filter_task *task_filter, 32 struct filter_task *task_filter,
33 struct filter_task *hide_tasks); 33 struct filter_task *hide_tasks);
34 34
35/* Used for quereing what plots are defined */
36enum graph_plot_type {
37 PLOT_TYPE_OTHER,
38 PLOT_TYPE_CPU,
39 PLOT_TYPE_TASK,
40};
41
35struct graph_plot; 42struct graph_plot;
36 43
37struct plot_info { 44struct plot_info {
@@ -108,6 +115,7 @@ struct plot_callbacks {
108}; 115};
109 116
110struct graph_plot { 117struct graph_plot {
118 enum graph_plot_type type;
111 int pos; 119 int pos;
112 char *label; 120 char *label;
113 const struct plot_callbacks *cb; 121 const struct plot_callbacks *cb;
@@ -251,6 +259,8 @@ static inline GtkWidget *trace_graph_get_window(struct graph_info *ginfo)
251 return ginfo->widget; 259 return ginfo->widget;
252} 260}
253 261
262void trace_graph_refresh(struct graph_info *ginfo);
263
254struct filter_task_item * 264struct filter_task_item *
255trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid); 265trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid);
256struct filter_task_item * 266struct filter_task_item *
@@ -283,11 +293,13 @@ void trace_graph_plot_free(struct graph_info *ginfo);
283void trace_graph_plot_init(struct graph_info *ginfo); 293void trace_graph_plot_init(struct graph_info *ginfo);
284struct graph_plot *trace_graph_plot_append(struct graph_info *ginfo, 294struct graph_plot *trace_graph_plot_append(struct graph_info *ginfo,
285 const char *label, 295 const char *label,
296 enum graph_plot_type type,
286 const struct plot_callbacks *cb, 297 const struct plot_callbacks *cb,
287 void *data); 298 void *data);
288struct graph_plot *trace_graph_plot_insert(struct graph_info *ginfo, 299struct graph_plot *trace_graph_plot_insert(struct graph_info *ginfo,
289 int pos, 300 int pos,
290 const char *label, 301 const char *label,
302 enum graph_plot_type type,
291 const struct plot_callbacks *cb, 303 const struct plot_callbacks *cb,
292 void *data); 304 void *data);
293void trace_graph_plot_remove(struct graph_info *ginfo, struct graph_plot *plot); 305void trace_graph_plot_remove(struct graph_info *ginfo, struct graph_plot *plot);
@@ -341,6 +353,12 @@ int trace_graph_plot_display_info(struct graph_info *ginfo,
341 353
342/* cpu plot */ 354/* cpu plot */
343void graph_plot_init_cpus(struct graph_info *ginfo, int cpus); 355void graph_plot_init_cpus(struct graph_info *ginfo, int cpus);
356void graph_plot_cpus_plotted(struct graph_info *ginfo,
357 gboolean *all_cpus, guint64 **cpu_mask);
358void graph_plot_cpus_update_callback(gboolean accept,
359 gboolean all_cpus,
360 guint64 *selected_cpu_mask,
361 gpointer data);
344 362
345/* task plot */ 363/* task plot */
346void graph_plot_task(struct graph_info *ginfo, int pid, int pos); 364void graph_plot_task(struct graph_info *ginfo, int pid, int pos);
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c
index e591f04..e99fec8 100644
--- a/trace-plot-cpu.c
+++ b/trace-plot-cpu.c
@@ -21,6 +21,7 @@
21#include <string.h> 21#include <string.h>
22 22
23#include "trace-graph.h" 23#include "trace-graph.h"
24#include "cpu.h"
24 25
25struct cpu_plot_info { 26struct cpu_plot_info {
26 int cpu; 27 int cpu;
@@ -385,7 +386,7 @@ int cpu_plot_display_info(struct graph_info *ginfo,
385 return 1; 386 return 1;
386} 387}
387 388
388void cpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) 389static void cpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
389{ 390{
390 struct cpu_plot_info *cpu_info = plot->private; 391 struct cpu_plot_info *cpu_info = plot->private;
391 392
@@ -403,20 +404,112 @@ static const struct plot_callbacks cpu_plot_cb = {
403 .destroy = cpu_plot_destroy 404 .destroy = cpu_plot_destroy
404}; 405};
405 406
406void graph_plot_init_cpus(struct graph_info *ginfo, int cpus) 407static void add_cpu_plot(struct graph_info *ginfo, gint cpu)
407{ 408{
408 struct cpu_plot_info *cpu_info; 409 struct cpu_plot_info *cpu_info;
409 struct graph_plot *plot; 410 struct graph_plot *plot;
410 char label[100]; 411 char label[100];
411 long cpu;
412 412
413 for (cpu = 0; cpu < cpus; cpu++) { 413 cpu_info = malloc_or_die(sizeof(*cpu_info));
414 cpu_info = malloc_or_die(sizeof(*cpu_info)); 414 cpu_info->cpu = cpu;
415 cpu_info->cpu = cpu; 415
416 snprintf(label, 100, "CPU %d", cpu);
417
418 plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_CPU,
419 &cpu_plot_cb, cpu_info);
420 trace_graph_plot_add_cpu(ginfo, plot, cpu);
421}
422
423void graph_plot_cpus_update_callback(gboolean accept,
424 gboolean all_cpus,
425 guint64 *selected_cpu_mask,
426 gpointer data)
427{
428 struct graph_info *ginfo = data;
429 struct cpu_plot_info *cpu_info;
430 struct graph_plot *plot;
431 gboolean old_all_cpus;
432 guint64 *old_cpu_mask;
433 int i;
434
435 if (!accept)
436 return;
437
438 /* Get the current status */
439 graph_plot_cpus_plotted(ginfo, &old_all_cpus, &old_cpu_mask);
440
441 if (old_all_cpus == all_cpus ||
442 (selected_cpu_mask &&
443 cpus_equal(old_cpu_mask, selected_cpu_mask, ginfo->cpus))) {
444 /* Nothing to do */
445 g_free(old_cpu_mask);
446 return;
447 }
416 448
417 snprintf(label, 100, "CPU %ld", cpu); 449 if (!all_cpus) {
450 /*
451 * Remove any plots not selected.
452 * Go backwards, since removing a plot shifts the
453 * array from current position back.
454 */
455 for (i = ginfo->plots - 1; i >= 0; i--) {
456 plot = ginfo->plot_array[i];
457 if (plot->type != PLOT_TYPE_CPU)
458 continue;
459 cpu_info = plot->private;
460 if (!cpu_isset(selected_cpu_mask, cpu_info->cpu))
461 trace_graph_plot_remove(ginfo, plot);
462 }
463 }
418 464
419 plot = trace_graph_plot_append(ginfo, label, &cpu_plot_cb, cpu_info); 465 /* Now add any plots not set */
420 trace_graph_plot_add_cpu(ginfo, plot, cpu); 466 for (i = 0; i < ginfo->cpus; i++) {
467 if (!all_cpus && !cpu_isset(selected_cpu_mask, i))
468 continue;
469 if (cpu_isset(old_cpu_mask, i))
470 continue;
471 add_cpu_plot(ginfo, i);
421 } 472 }
473
474 g_free(old_cpu_mask);
475
476 trace_graph_refresh(ginfo);
477}
478
479/**
480 * graph_plot_cpus_plotted - return what CPUs are plotted
481 * @ginfo: the graph info structure
482 * @all_cpus: returns true if all CPUS are currently plotted
483 * @cpu_mask: returns an allocated mask of what cpus are set
484 *
485 * @cpu_mask must be freed with g_free() after this is called.
486 */
487void graph_plot_cpus_plotted(struct graph_info *ginfo,
488 gboolean *all_cpus, guint64 **cpu_mask)
489{
490 struct cpu_plot_info *cpu_info;
491 struct graph_plot *plot;
492 int i;
493
494 *cpu_mask = g_new0(guint64, (ginfo->cpus >> 6) + 1);
495 g_assert(*cpu_mask);
496
497 for (i = 0; i < ginfo->plots; i++) {
498 plot = ginfo->plot_array[i];
499 if (plot->type != PLOT_TYPE_CPU)
500 continue;
501 cpu_info = plot->private;
502 cpu_set(*cpu_mask, cpu_info->cpu);
503 }
504
505 *all_cpus = cpu_weight(*cpu_mask, ginfo->cpus) == ginfo->cpus ?
506 TRUE : FALSE;
507}
508
509void graph_plot_init_cpus(struct graph_info *ginfo, int cpus)
510{
511 long cpu;
512
513 for (cpu = 0; cpu < cpus; cpu++)
514 add_cpu_plot(ginfo, cpu);
422} 515}
diff --git a/trace-plot-task.c b/trace-plot-task.c
index b36d565..a5b8d79 100644
--- a/trace-plot-task.c
+++ b/trace-plot-task.c
@@ -632,7 +632,8 @@ void graph_plot_init_tasks(struct graph_info *ginfo)
632 task_info->pid = pid; 632 task_info->pid = pid;
633 633
634 snprintf(label, 100, "TASK %d", pid); 634 snprintf(label, 100, "TASK %d", pid);
635 trace_graph_plot_insert(ginfo, 1, label, &task_plot_cb, task_info); 635 trace_graph_plot_insert(ginfo, 1, label, PLOT_TYPE_TASK,
636 &task_plot_cb, task_info);
636} 637}
637 638
638void graph_plot_task(struct graph_info *ginfo, int pid, int pos) 639void graph_plot_task(struct graph_info *ginfo, int pid, int pos)
@@ -650,7 +651,8 @@ void graph_plot_task(struct graph_info *ginfo, int pid, int pos)
650 len = strlen(comm) + 100; 651 len = strlen(comm) + 100;
651 label = malloc_or_die(len); 652 label = malloc_or_die(len);
652 snprintf(label, len, "%s-%d", comm, pid); 653 snprintf(label, len, "%s-%d", comm, pid);
653 plot = trace_graph_plot_insert(ginfo, pos, label, &task_plot_cb, task_info); 654 plot = trace_graph_plot_insert(ginfo, pos, label, PLOT_TYPE_TASK,
655 &task_plot_cb, task_info);
654 free(label); 656 free(label);
655 657
656 trace_graph_plot_add_all_recs(ginfo, plot); 658 trace_graph_plot_add_all_recs(ginfo, plot);
diff --git a/trace-plot.c b/trace-plot.c
index 8376814..f8e23c0 100644
--- a/trace-plot.c
+++ b/trace-plot.c
@@ -75,13 +75,14 @@ allocate_plot(struct graph_info *ginfo,
75 75
76struct graph_plot * 76struct graph_plot *
77trace_graph_plot_append(struct graph_info *ginfo, 77trace_graph_plot_append(struct graph_info *ginfo,
78 const char *label, const struct plot_callbacks *cb, 78 const char *label, enum graph_plot_type type,
79 void *data) 79 const struct plot_callbacks *cb, void *data)
80{ 80{
81 struct graph_plot *plot; 81 struct graph_plot *plot;
82 82
83 plot = allocate_plot(ginfo, label, cb, data); 83 plot = allocate_plot(ginfo, label, cb, data);
84 84
85 plot->type = type;
85 plot->pos = ginfo->plots; 86 plot->pos = ginfo->plots;
86 87
87 if (!ginfo->plots) { 88 if (!ginfo->plots) {
@@ -105,21 +106,21 @@ trace_graph_plot_append(struct graph_info *ginfo,
105 106
106struct graph_plot * 107struct graph_plot *
107trace_graph_plot_insert(struct graph_info *ginfo, 108trace_graph_plot_insert(struct graph_info *ginfo,
108 int pos, 109 int pos, const char *label, enum graph_plot_type type,
109 const char *label, const struct plot_callbacks *cb, 110 const struct plot_callbacks *cb, void *data)
110 void *data)
111{ 111{
112 struct graph_plot *plot; 112 struct graph_plot *plot;
113 int i; 113 int i;
114 114
115 if (pos >= ginfo->plots) 115 if (pos >= ginfo->plots)
116 return trace_graph_plot_append(ginfo, label, cb, data); 116 return trace_graph_plot_append(ginfo, label, type, cb, data);
117 117
118 if (pos < 0) 118 if (pos < 0)
119 pos = 0; 119 pos = 0;
120 120
121 plot = allocate_plot(ginfo, label, cb, data); 121 plot = allocate_plot(ginfo, label, cb, data);
122 plot->pos = pos; 122 plot->pos = pos;
123 plot->type = type;
123 ginfo->plot_array = realloc(ginfo->plot_array, 124 ginfo->plot_array = realloc(ginfo->plot_array,
124 sizeof(ginfo->plot_array[0]) * 125 sizeof(ginfo->plot_array[0]) *
125 (ginfo->plots + 1)); 126 (ginfo->plots + 1));