aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel-shark.c448
-rw-r--r--kernel-shark.h5
-rw-r--r--trace-graph.c14
-rw-r--r--trace-graph.h3
-rw-r--r--trace-view-store.c1
5 files changed, 424 insertions, 47 deletions
diff --git a/kernel-shark.c b/kernel-shark.c
index b056420..e591657 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -64,6 +64,68 @@ void usage(char *prog)
64 printf(" -i input_file, default is %s\n", default_input_file); 64 printf(" -i input_file, default is %s\n", default_input_file);
65} 65}
66 66
67/*
68 * trace_sync_select_menu - helper function to the syncing of list and graph filters
69 *
70 * Creates a pop up dialog with the selections given. The selections will be
71 * radio buttons to the user. The keep is a value that will be set to the check
72 * box (default on) if the user wants to keep the selection persistant.
73 */
74static int trace_sync_select_menu(const gchar *title,
75 gchar **selections, gboolean *keep)
76{
77 GtkWidget *dialog;
78 GtkWidget *radio;
79 GtkWidget *check;
80 GSList *group;
81 int result;
82 int i;
83
84 dialog = gtk_dialog_new_with_buttons(title,
85 NULL,
86 GTK_DIALOG_MODAL,
87 "OK", GTK_RESPONSE_ACCEPT,
88 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
89 NULL);
90
91 radio = gtk_radio_button_new_with_label(NULL, selections[0]);
92 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0);
93 gtk_widget_show(radio);
94
95 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
96
97 for (i = 1; selections[i]; i++) {
98 radio = gtk_radio_button_new_with_label(group, selections[i]);
99 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0);
100 gtk_widget_show(radio);
101 }
102
103 check = gtk_check_button_new_with_label("Keep the filters in sync?");
104 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), check, TRUE, TRUE, 0);
105 gtk_widget_show(check);
106
107 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
108
109 result = gtk_dialog_run(GTK_DIALOG(dialog));
110 switch (result) {
111 case GTK_RESPONSE_ACCEPT:
112 i = 0;
113 for (i = 0; group; i++, group = g_slist_next(group)) {
114 radio = group->data;
115 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
116 break;
117 }
118 result = i;
119 *keep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
120 break;
121 default:
122 result = -1;
123 }
124
125 gtk_widget_destroy(dialog);
126 return result;
127}
128
67/* graph callbacks */ 129/* graph callbacks */
68 130
69/* convert_nano() and print_time() are copied from trace-graph.c for debugging 131/* convert_nano() and print_time() are copied from trace-graph.c for debugging
@@ -113,15 +175,30 @@ static void ks_graph_filter(struct graph_info *ginfo,
113 cbs = trace_graph_get_callbacks(ginfo); 175 cbs = trace_graph_get_callbacks(ginfo);
114 info = container_of(cbs, struct shark_info, graph_cbs); 176 info = container_of(cbs, struct shark_info, graph_cbs);
115 177
178 if (!info->sync_task_filters)
179 return;
180
116 if (info->list_filter_enabled) 181 if (info->list_filter_enabled)
117 trace_view_update_filters(info->treeview, 182 trace_view_update_filters(info->treeview,
118 task_filter, hide_tasks); 183 task_filter, hide_tasks);
184
185 if (filter_task_count(task_filter) ||
186 filter_task_count(hide_tasks))
187 info->list_filter_available = 1;
188 else {
189 info->list_filter_enabled = 0;
190 info->list_filter_available = 0;
191 }
119} 192}
120 193
121static void free_info(struct shark_info *info) 194static void free_info(struct shark_info *info)
122{ 195{
123 tracecmd_close(info->handle); 196 tracecmd_close(info->handle);
124 trace_graph_free_info(info->ginfo); 197 trace_graph_free_info(info->ginfo);
198
199 filter_task_hash_free(info->list_task_filter);
200 filter_task_hash_free(info->list_hide_tasks);
201
125 free(info->ginfo); 202 free(info->ginfo);
126 free(info); 203 free(info);
127} 204}
@@ -244,6 +321,99 @@ delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
244 321
245/* Callback for the clicked signal of the Events filter button */ 322/* Callback for the clicked signal of the Events filter button */
246static void 323static void
324sync_task_filter_clicked (GtkWidget *subitem, gpointer data)
325{
326 struct shark_info *info = data;
327 struct filter_task *task_filter;
328 struct filter_task *hide_tasks;
329 GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview);
330 GtkTreeModel *model;
331 TraceViewStore *store;
332 gboolean keep;
333 gchar *selections[] = { "Sync List Filter with Graph Filter",
334 "Sync Graph Filter with List Filter",
335 NULL };
336 int result;
337
338 if (info->sync_task_filters) {
339 /* Separate the List and Graph filters */
340
341 info->sync_task_filters = 0;
342 gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
343 "Sync Graph and List Task Filters");
344
345 /* The list now uses its own hash */
346 info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter);
347 info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks);
348 return;
349 }
350
351 model = gtk_tree_view_get_model(trace_tree);
352 if (!model)
353 return;
354
355 store = TRACE_VIEW_STORE(model);
356
357 /* Ask user which way to sync */
358 result = trace_sync_select_menu("Sync Task Filters",
359 selections, &keep);
360
361 switch (result) {
362 case 0:
363 /* Sync List Filter with Graph Filter */
364 filter_task_hash_free(info->list_task_filter);
365 filter_task_hash_free(info->list_hide_tasks);
366
367 info->list_task_filter = NULL;
368 info->list_hide_tasks = NULL;
369
370 task_filter = info->ginfo->task_filter;
371 hide_tasks = info->ginfo->hide_tasks;
372
373 if (!keep) {
374 info->list_task_filter = filter_task_hash_copy(task_filter);
375 info->list_hide_tasks = filter_task_hash_copy(hide_tasks);
376 }
377
378 if (info->list_filter_enabled)
379 trace_view_update_filters(info->treeview,
380 task_filter, hide_tasks);
381
382 if (!filter_task_count(task_filter) &&
383 !filter_task_count(hide_tasks)) {
384 info->list_filter_enabled = 0;
385 info->list_filter_available = 0;
386 } else
387 info->list_filter_available = 1;
388
389 break;
390 case 1:
391 /* Sync Graph Filter with List Filter */
392 trace_graph_update_filters(info->ginfo,
393 info->list_task_filter,
394 info->list_hide_tasks);
395
396 if (keep) {
397 filter_task_hash_free(info->list_task_filter);
398 filter_task_hash_free(info->list_hide_tasks);
399
400 info->list_task_filter = NULL;
401 info->list_hide_tasks = NULL;
402 }
403 break;
404 default:
405 keep = 0;
406 }
407
408 if (keep) {
409 info->sync_task_filters = 1;
410 gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu),
411 "Unsync Graph and List Task Filters");
412 }
413}
414
415/* Callback for the clicked signal of the Events filter button */
416static void
247list_events_clicked (gpointer data) 417list_events_clicked (gpointer data)
248{ 418{
249 struct shark_info *info = data; 419 struct shark_info *info = data;
@@ -510,26 +680,70 @@ static void
510filter_list_enable_clicked (gpointer data) 680filter_list_enable_clicked (gpointer data)
511{ 681{
512 struct shark_info *info = data; 682 struct shark_info *info = data;
683 struct filter_task *task_filter;
684 struct filter_task *hide_tasks;
513 685
514 info->list_filter_enabled ^= 1; 686 info->list_filter_enabled ^= 1;
515 687
688 if (info->sync_task_filters) {
689 task_filter = info->ginfo->task_filter;
690 hide_tasks = info->ginfo->hide_tasks;
691 } else {
692 task_filter = info->list_task_filter;
693 hide_tasks = info->list_hide_tasks;
694 }
695
516 if (info->list_filter_enabled) 696 if (info->list_filter_enabled)
517 trace_view_update_filters(info->treeview, 697 trace_view_update_filters(info->treeview,
518 info->ginfo->task_filter, 698 task_filter, hide_tasks);
519 info->ginfo->hide_tasks);
520 else 699 else
521 trace_view_update_filters(info->treeview, NULL, NULL); 700 trace_view_update_filters(info->treeview, NULL, NULL);
522} 701}
523 702
524static void 703static void
704filter_update_list_filter(struct shark_info *info,
705 struct filter_task *filter,
706 struct filter_task *other_filter)
707{
708 struct filter_task_item *task;
709 int pid = info->selected_task;
710
711 task = filter_task_find_pid(filter, pid);
712 if (task) {
713 filter_task_remove_pid(filter, pid);
714 if (!filter_task_count(filter) &&
715 !filter_task_count(other_filter)) {
716 info->list_filter_enabled = 0;
717 info->list_filter_available = 0;
718 }
719 } else {
720 filter_task_add_pid(filter, pid);
721 info->list_filter_available = 1;
722 }
723}
724
725static void
525filter_add_task_clicked (gpointer data) 726filter_add_task_clicked (gpointer data)
526{ 727{
527 struct shark_info *info = data; 728 struct shark_info *info = data;
729 int pid = info->selected_task;
528 730
529 trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); 731 if (info->sync_task_filters) {
732 trace_graph_filter_add_remove_task(info->ginfo, pid);
733 return;
734 }
530 735
531 if (!filter_task_count(info->ginfo->task_filter)) 736 filter_update_list_filter(info, info->list_task_filter, info->list_hide_tasks);
532 info->list_filter_enabled = 0; 737 trace_view_update_filters(info->treeview,
738 info->list_task_filter, info->list_hide_tasks);
739}
740
741static void
742filter_graph_add_task_clicked (gpointer data)
743{
744 struct shark_info *info = data;
745
746 trace_graph_filter_add_remove_task(info->ginfo, info->selected_task);
533} 747}
534 748
535static void 749static void
@@ -537,11 +751,22 @@ filter_hide_task_clicked (gpointer data)
537{ 751{
538 struct shark_info *info = data; 752 struct shark_info *info = data;
539 753
540 trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); 754 if (info->sync_task_filters) {
755 trace_graph_filter_hide_show_task(info->ginfo, info->selected_task);
756 return;
757 }
541 758
542 if (!filter_task_count(info->ginfo->task_filter) && 759 filter_update_list_filter(info, info->list_hide_tasks, info->list_task_filter);
543 !filter_task_count(info->ginfo->hide_tasks)) 760 trace_view_update_filters(info->treeview,
544 info->list_filter_enabled = 0; 761 info->list_task_filter, info->list_hide_tasks);
762}
763
764static void
765filter_graph_hide_task_clicked (gpointer data)
766{
767 struct shark_info *info = data;
768
769 trace_graph_filter_hide_show_task(info->ginfo, info->selected_task);
545} 770}
546 771
547static void 772static void
@@ -549,11 +774,27 @@ filter_clear_tasks_clicked (gpointer data)
549{ 774{
550 struct shark_info *info = data; 775 struct shark_info *info = data;
551 776
552 trace_graph_clear_tasks(info->ginfo); 777 if (info->sync_task_filters) {
778 trace_graph_clear_tasks(info->ginfo);
779 return;
780 }
553 781
782 filter_task_clear(info->list_task_filter);
783 filter_task_clear(info->list_hide_tasks);
784 trace_view_update_filters(info->treeview, NULL, NULL);
785
786 info->list_filter_available = 0;
554 info->list_filter_enabled = 0; 787 info->list_filter_enabled = 0;
555} 788}
556 789
790static void
791filter_graph_clear_tasks_clicked (gpointer data)
792{
793 struct shark_info *info = data;
794
795 trace_graph_clear_tasks(info->ginfo);
796}
797
557static void graph_check_toggle(gpointer data, GtkWidget *widget) 798static void graph_check_toggle(gpointer data, GtkWidget *widget)
558{ 799{
559 struct shark_info *info = data; 800 struct shark_info *info = data;
@@ -561,6 +802,17 @@ static void graph_check_toggle(gpointer data, GtkWidget *widget)
561 info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); 802 info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
562} 803}
563 804
805static void set_menu_label(GtkWidget *menu, const char *comm, int pid,
806 const char *fmt)
807{
808 int len = strlen(comm) + strlen(fmt) + 50;
809 char text[len];
810
811 snprintf(text, len, fmt, comm, pid);
812
813 gtk_menu_item_set_label(GTK_MENU_ITEM(menu), text);
814}
815
564static gboolean 816static gboolean
565do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) 817do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
566{ 818{
@@ -572,11 +824,13 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
572 static GtkWidget *menu_filter_add_task; 824 static GtkWidget *menu_filter_add_task;
573 static GtkWidget *menu_filter_hide_task; 825 static GtkWidget *menu_filter_hide_task;
574 static GtkWidget *menu_filter_clear_tasks; 826 static GtkWidget *menu_filter_clear_tasks;
827 static GtkWidget *menu_filter_graph_add_task;
828 static GtkWidget *menu_filter_graph_hide_task;
829 static GtkWidget *menu_filter_graph_clear_tasks;
575 struct record *record; 830 struct record *record;
576 TraceViewRecord *vrec; 831 TraceViewRecord *vrec;
577 GtkTreeModel *model; 832 GtkTreeModel *model;
578 const char *comm; 833 const char *comm;
579 gchar *text;
580 gint pid; 834 gint pid;
581 gint len; 835 gint len;
582 guint64 offset; 836 guint64 offset;
@@ -585,7 +839,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
585 839
586 if (!menu) { 840 if (!menu) {
587 menu = gtk_menu_new(); 841 menu = gtk_menu_new();
588 menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Filter"); 842 menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Task Filter");
589 gtk_widget_show(menu_filter_graph_enable); 843 gtk_widget_show(menu_filter_graph_enable);
590 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable); 844 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable);
591 845
@@ -593,7 +847,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
593 G_CALLBACK (filter_graph_enable_clicked), 847 G_CALLBACK (filter_graph_enable_clicked),
594 data); 848 data);
595 849
596 menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Filter"); 850 menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Task Filter");
597 gtk_widget_show(menu_filter_list_enable); 851 gtk_widget_show(menu_filter_list_enable);
598 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable); 852 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable);
599 853
@@ -609,6 +863,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
609 G_CALLBACK (filter_add_task_clicked), 863 G_CALLBACK (filter_add_task_clicked),
610 data); 864 data);
611 865
866 menu_filter_graph_add_task = gtk_menu_item_new_with_label("Add Task to Graph");
867 gtk_widget_show(menu_filter_graph_add_task);
868 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_add_task);
869
870 g_signal_connect_swapped (G_OBJECT (menu_filter_graph_add_task), "activate",
871 G_CALLBACK (filter_graph_add_task_clicked),
872 data);
873
612 menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); 874 menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task");
613 gtk_widget_show(menu_filter_hide_task); 875 gtk_widget_show(menu_filter_hide_task);
614 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); 876 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task);
@@ -617,6 +879,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
617 G_CALLBACK (filter_hide_task_clicked), 879 G_CALLBACK (filter_hide_task_clicked),
618 data); 880 data);
619 881
882 menu_filter_graph_hide_task = gtk_menu_item_new_with_label("Hide Task from Graph");
883 gtk_widget_show(menu_filter_graph_hide_task);
884 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_hide_task);
885
886 g_signal_connect_swapped (G_OBJECT (menu_filter_graph_hide_task), "activate",
887 G_CALLBACK (filter_graph_hide_task_clicked),
888 data);
889
620 menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); 890 menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter");
621 gtk_widget_show(menu_filter_clear_tasks); 891 gtk_widget_show(menu_filter_clear_tasks);
622 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); 892 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks);
@@ -625,6 +895,15 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
625 G_CALLBACK (filter_clear_tasks_clicked), 895 G_CALLBACK (filter_clear_tasks_clicked),
626 data); 896 data);
627 897
898 menu_filter_graph_clear_tasks =
899 gtk_menu_item_new_with_label("Clear Graph Task Filter");
900 gtk_widget_show(menu_filter_graph_clear_tasks);
901 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_clear_tasks);
902
903 g_signal_connect_swapped (G_OBJECT (menu_filter_graph_clear_tasks), "activate",
904 G_CALLBACK (filter_graph_clear_tasks_clicked),
905 data);
906
628 } 907 }
629 908
630 row = trace_view_get_selected_row(GTK_WIDGET(info->treeview)); 909 row = trace_view_get_selected_row(GTK_WIDGET(info->treeview));
@@ -642,29 +921,59 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
642 921
643 len = strlen(comm) + 50; 922 len = strlen(comm) + 50;
644 923
645 text = g_malloc(len); 924 if (info->sync_task_filters) {
646 g_assert(text); 925 if (trace_graph_filter_task_find_pid(ginfo, pid))
647 926 set_menu_label(menu_filter_add_task, comm, pid,
648 if (trace_graph_filter_task_find_pid(ginfo, pid)) 927 "Remove %s-%d from filters");
649 snprintf(text, len, "Remove %s-%d from filter", comm, pid); 928 else
650 else 929 set_menu_label(menu_filter_add_task, comm, pid,
651 snprintf(text, len, "Add %s-%d to filter", comm, pid); 930 "Add %s-%d to filters");
931
932 if (trace_graph_hide_task_find_pid(ginfo, pid))
933 set_menu_label(menu_filter_hide_task, comm, pid,
934 "Show %s-%d");
935 else
936 set_menu_label(menu_filter_hide_task, comm, pid,
937 "Hide %s-%d");
938
939 gtk_widget_hide(menu_filter_graph_add_task);
940 gtk_widget_hide(menu_filter_graph_hide_task);
941
942 } else {
943 if (filter_task_find_pid(info->list_task_filter, pid))
944 set_menu_label(menu_filter_add_task, comm, pid,
945 "Remove %s-%d from List filter");
946 else
947 set_menu_label(menu_filter_add_task, comm, pid,
948 "Add %s-%d to List filter");
949
950 if (filter_task_find_pid(info->list_hide_tasks, pid))
951 set_menu_label(menu_filter_hide_task, comm, pid,
952 "Show %s-%d in List");
953 else
954 set_menu_label(menu_filter_hide_task, comm, pid,
955 "Hide %s-%d from List");
956
957 if (trace_graph_filter_task_find_pid(ginfo, pid))
958 set_menu_label(menu_filter_graph_add_task, comm, pid,
959 "Remove %s-%d from Graph filter");
960 else
961 set_menu_label(menu_filter_graph_add_task, comm, pid,
962 "Add %s-%d to Graph filter");
963
964 if (trace_graph_hide_task_find_pid(ginfo, pid))
965 set_menu_label(menu_filter_graph_hide_task, comm, pid,
966 "Show %s-%d in Graph");
967 else
968 set_menu_label(menu_filter_graph_hide_task, comm, pid,
969 "Hide %s-%d from Graph");
970
971 gtk_widget_show(menu_filter_graph_add_task);
972 gtk_widget_show(menu_filter_graph_hide_task);
973 }
652 974
653 ginfo->filter_task_selected = pid; 975 ginfo->filter_task_selected = pid;
654 976
655 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task),
656 text);
657
658 if (trace_graph_hide_task_find_pid(ginfo, pid))
659 snprintf(text, len, "Show %s-%d", comm, pid);
660 else
661 snprintf(text, len, "Hide %s-%d", comm, pid);
662
663 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task),
664 text);
665
666 g_free(text);
667
668 info->selected_task = pid; 977 info->selected_task = pid;
669 978
670 gtk_widget_show(menu_filter_add_task); 979 gtk_widget_show(menu_filter_add_task);
@@ -674,35 +983,62 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
674 } else { 983 } else {
675 gtk_widget_hide(menu_filter_add_task); 984 gtk_widget_hide(menu_filter_add_task);
676 gtk_widget_hide(menu_filter_hide_task); 985 gtk_widget_hide(menu_filter_hide_task);
986 gtk_widget_hide(menu_filter_graph_add_task);
987 gtk_widget_hide(menu_filter_graph_hide_task);
677 } 988 }
678 989
679 if (ginfo->filter_enabled) 990 if (ginfo->filter_enabled)
680 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), 991 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
681 "Disable Graph Filter"); 992 "Disable Graph Task Filter");
682 else 993 else
683 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), 994 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
684 "Enable Graph Filter"); 995 "Enable Graph Task Filter");
685 996
686 if (info->list_filter_enabled) 997 if (info->list_filter_enabled)
687 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), 998 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
688 "Disable List Filter"); 999 "Disable List Task Filter");
689 else 1000 else
690 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), 1001 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
691 "Enable List Filter"); 1002 "Enable List Task Filter");
692 1003
693 if (ginfo->filter_available) { 1004 if (ginfo->filter_available)
694 gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE); 1005 gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE);
695 gtk_widget_set_sensitive(menu_filter_list_enable, TRUE); 1006 else
696 } else {
697 gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE); 1007 gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE);
698 gtk_widget_set_sensitive(menu_filter_list_enable, FALSE);
699 }
700 1008
701 if (filter_task_count(ginfo->task_filter) || 1009 if ((info->sync_task_filters && ginfo->filter_available) ||
702 filter_task_count(ginfo->hide_tasks)) 1010 (!info->sync_task_filters && info->list_filter_available))
703 gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); 1011 gtk_widget_set_sensitive(menu_filter_list_enable, TRUE);
704 else 1012 else
705 gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); 1013 gtk_widget_set_sensitive(menu_filter_list_enable, FALSE);
1014
1015 if (info->sync_task_filters) {
1016 if (filter_task_count(ginfo->task_filter) ||
1017 filter_task_count(ginfo->hide_tasks))
1018 gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
1019 else
1020 gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
1021
1022 set_menu_label(menu_filter_clear_tasks, comm, pid,
1023 "Clear Task Filter");
1024 gtk_widget_hide(menu_filter_graph_clear_tasks);
1025 } else {
1026 if (filter_task_count(ginfo->task_filter) ||
1027 filter_task_count(ginfo->hide_tasks))
1028 gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, TRUE);
1029 else
1030 gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, FALSE);
1031
1032 if (filter_task_count(info->list_task_filter) ||
1033 filter_task_count(info->list_hide_tasks))
1034 gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
1035 else
1036 gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE);
1037
1038 set_menu_label(menu_filter_clear_tasks, comm, pid,
1039 "Clear List Task Filter");
1040 gtk_widget_show(menu_filter_graph_clear_tasks);
1041 }
706 1042
707 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, 1043 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3,
708 gtk_get_current_event_time()); 1044 gtk_get_current_event_time());
@@ -785,6 +1121,7 @@ void kernel_shark(int argc, char **argv)
785 handle = NULL; 1121 handle = NULL;
786 1122
787 info->handle = handle; 1123 info->handle = handle;
1124 info->sync_task_filters = TRUE;
788 1125
789 /* --- Main window --- */ 1126 /* --- Main window --- */
790 1127
@@ -891,6 +1228,25 @@ void kernel_shark(int argc, char **argv)
891 menu = gtk_menu_new(); /* Don't need to show menus */ 1228 menu = gtk_menu_new(); /* Don't need to show menus */
892 1229
893 1230
1231
1232 /* --- Filter - Sync task Option --- */
1233
1234 sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Task Filters");
1235
1236 info->task_sync_menu = sub_item;
1237
1238 /* Add them to the menu */
1239 gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
1240
1241 /* We can attach the Quit menu item to our exit function */
1242 g_signal_connect (G_OBJECT (sub_item), "activate",
1243 G_CALLBACK (sync_task_filter_clicked),
1244 (gpointer) info);
1245
1246 /* We do need to show menu items */
1247 gtk_widget_show(sub_item);
1248
1249
894 /* --- Filter - List Events Option --- */ 1250 /* --- Filter - List Events Option --- */
895 1251
896 sub_item = gtk_menu_item_new_with_label("list events"); 1252 sub_item = gtk_menu_item_new_with_label("list events");
diff --git a/kernel-shark.h b/kernel-shark.h
index edb3787..f931406 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -30,10 +30,15 @@ struct shark_info {
30 struct tracecmd_input *handle; 30 struct tracecmd_input *handle;
31 GtkWidget *treeview; 31 GtkWidget *treeview;
32 GtkWidget *spin; 32 GtkWidget *spin;
33 GtkWidget *task_sync_menu;
33 struct graph_callbacks graph_cbs; 34 struct graph_callbacks graph_cbs;
34 gint selected_task; 35 gint selected_task;
35 gboolean list_filter_enabled; 36 gboolean list_filter_enabled;
37 gboolean list_filter_available;
36 gboolean graph_follows; 38 gboolean graph_follows;
39 gboolean sync_task_filters;
40 struct filter_task *list_task_filter;
41 struct filter_task *list_hide_tasks;
37}; 42};
38 43
39#define offset_of(type, field) (long)(&((type *)0)->field) 44#define offset_of(type, field) (long)(&((type *)0)->field)
diff --git a/trace-graph.c b/trace-graph.c
index 9e5cd19..2bbe73f 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -548,6 +548,20 @@ void trace_graph_clear_tasks(struct graph_info *ginfo)
548 redraw_graph(ginfo); 548 redraw_graph(ginfo);
549} 549}
550 550
551void trace_graph_update_filters(struct graph_info *ginfo,
552 struct filter_task *task_filter,
553 struct filter_task *hide_tasks)
554{
555 filter_task_hash_free(ginfo->task_filter);
556 filter_task_hash_free(ginfo->hide_tasks);
557
558 ginfo->task_filter = filter_task_hash_copy(task_filter);
559 ginfo->hide_tasks = filter_task_hash_copy(hide_tasks);
560
561 if (ginfo->filter_enabled)
562 redraw_graph(ginfo);
563}
564
551static void 565static void
552filter_clear_tasks_clicked (gpointer data) 566filter_clear_tasks_clicked (gpointer data)
553{ 567{
diff --git a/trace-graph.h b/trace-graph.h
index 916ad50..91194c1 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -311,6 +311,9 @@ int trace_graph_load_filters(struct graph_info *ginfo,
311 struct tracecmd_xml_handle *handle); 311 struct tracecmd_xml_handle *handle);
312int trace_graph_save_filters(struct graph_info *ginfo, 312int trace_graph_save_filters(struct graph_info *ginfo,
313 struct tracecmd_xml_handle *handle); 313 struct tracecmd_xml_handle *handle);
314void trace_graph_update_filters(struct graph_info *ginfo,
315 struct filter_task *task_filter,
316 struct filter_task *hide_tasks);
314 317
315/* plots */ 318/* plots */
316void trace_graph_plot_free(struct graph_info *ginfo); 319void trace_graph_plot_free(struct graph_info *ginfo);
diff --git a/trace-view-store.c b/trace-view-store.c
index ba40aad..6f70ca5 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -1330,7 +1330,6 @@ void trace_view_store_assign_filters(TraceViewStore *store,
1330 1330
1331 if (store->task_filter != task_filter) 1331 if (store->task_filter != task_filter)
1332 store->task_filter = filter_task_hash_copy(task_filter); 1332 store->task_filter = filter_task_hash_copy(task_filter);
1333
1334} 1333}
1335 1334
1336 1335