aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--kernel-shark.c77
-rw-r--r--kernel-shark.h1
-rw-r--r--trace-view-store.c37
-rw-r--r--trace-view-store.h3
-rw-r--r--trace-view.c95
-rw-r--r--trace-view.h2
7 files changed, 201 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index de83e44..46f47ed 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ all: $(TARGETS)
28 28
29LIB_FILE = libtracecmd.a 29LIB_FILE = libtracecmd.a
30 30
31HEADERS = parse-events.h trace-cmd.h trace-local.h 31HEADERS = parse-events.h trace-cmd.h trace-local.h trace-hash.h
32 32
33trace-read.o:: $(HEADERS) 33trace-read.o:: $(HEADERS)
34trace-cmd.o:: $(HEADERS) $(LIB_FILE) 34trace-cmd.o:: $(HEADERS) $(LIB_FILE)
@@ -43,7 +43,8 @@ trace-graph.o:: $(HEADERS) trace-graph.h
43trace-graph-main.o:: $(HEADERS) trace-graph.h 43trace-graph-main.o:: $(HEADERS) trace-graph.h
44kernel-shark.o:: $(HEADERS) kernel-shark.h 44kernel-shark.o:: $(HEADERS) kernel-shark.h
45 45
46TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o trace-compat.o 46TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o trace-compat.o \
47 trace-hash.o
47 48
48trace-cmd:: trace-cmd.o trace-read.o 49trace-cmd:: trace-cmd.o trace-read.o
49 $(CC) $^ -rdynamic -o $@ $(LIBS) 50 $(CC) $^ -rdynamic -o $@ $(LIBS)
diff --git a/kernel-shark.c b/kernel-shark.c
index 9cbc45a..fbc5a5f 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -156,7 +156,7 @@ static void row_double_clicked(GtkTreeView *treeview,
156} 156}
157 157
158static void 158static void
159filter_enable_clicked (gpointer data) 159filter_graph_enable_clicked (gpointer data)
160{ 160{
161 struct shark_info *info = data; 161 struct shark_info *info = data;
162 162
@@ -164,11 +164,36 @@ filter_enable_clicked (gpointer data)
164} 164}
165 165
166static void 166static void
167filter_list_enable_clicked (gpointer data)
168{
169 struct shark_info *info = data;
170
171 info->list_filter_enabled ^= 1;
172
173 if (info->list_filter_enabled)
174 trace_view_update_task_filter(info->treeview,
175 info->ginfo->task_filter);
176 else
177 trace_view_update_task_filter(info->treeview, NULL);
178}
179
180static void
167filter_add_task_clicked (gpointer data) 181filter_add_task_clicked (gpointer data)
168{ 182{
169 struct shark_info *info = data; 183 struct shark_info *info = data;
170 184
171 trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); 185 trace_graph_filter_add_remove_task(info->ginfo, info->selected_task);
186
187 if (info->list_filter_enabled) {
188 if (filter_task_count(info->ginfo->task_filter))
189 trace_view_update_task_filter(info->treeview,
190 info->ginfo->task_filter);
191 else
192 trace_view_update_task_filter(info->treeview, NULL);
193 }
194
195 if (!filter_task_count(info->ginfo->task_filter))
196 info->list_filter_enabled = 0;
172} 197}
173 198
174static void 199static void
@@ -177,6 +202,11 @@ filter_clear_tasks_clicked (gpointer data)
177 struct shark_info *info = data; 202 struct shark_info *info = data;
178 203
179 trace_graph_clear_tasks(info->ginfo); 204 trace_graph_clear_tasks(info->ginfo);
205
206 if (info->list_filter_enabled)
207 trace_view_update_task_filter(info->treeview, NULL);
208
209 info->list_filter_enabled = 0;
180} 210}
181 211
182static gboolean 212static gboolean
@@ -185,7 +215,8 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
185 struct shark_info *info = data; 215 struct shark_info *info = data;
186 struct graph_info *ginfo = info->ginfo; 216 struct graph_info *ginfo = info->ginfo;
187 static GtkWidget *menu; 217 static GtkWidget *menu;
188 static GtkWidget *menu_filter_enable; 218 static GtkWidget *menu_filter_graph_enable;
219 static GtkWidget *menu_filter_list_enable;
189 static GtkWidget *menu_filter_add_task; 220 static GtkWidget *menu_filter_add_task;
190 static GtkWidget *menu_filter_clear_tasks; 221 static GtkWidget *menu_filter_clear_tasks;
191 struct record *record; 222 struct record *record;
@@ -205,12 +236,20 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
205 236
206 if (!menu) { 237 if (!menu) {
207 menu = gtk_menu_new(); 238 menu = gtk_menu_new();
208 menu_filter_enable = gtk_menu_item_new_with_label("Enable Filter"); 239 menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Filter");
209 gtk_widget_show(menu_filter_enable); 240 gtk_widget_show(menu_filter_graph_enable);
210 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_enable); 241 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable);
211 242
212 g_signal_connect_swapped (G_OBJECT (menu_filter_enable), "activate", 243 g_signal_connect_swapped (G_OBJECT (menu_filter_graph_enable), "activate",
213 G_CALLBACK (filter_enable_clicked), 244 G_CALLBACK (filter_graph_enable_clicked),
245 data);
246
247 menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Filter");
248 gtk_widget_show(menu_filter_list_enable);
249 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable);
250
251 g_signal_connect_swapped (G_OBJECT (menu_filter_list_enable), "activate",
252 G_CALLBACK (filter_list_enable_clicked),
214 data); 253 data);
215 254
216 menu_filter_add_task = gtk_menu_item_new_with_label("Add Task"); 255 menu_filter_add_task = gtk_menu_item_new_with_label("Add Task");
@@ -276,16 +315,26 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data)
276 gtk_widget_hide(menu_filter_add_task); 315 gtk_widget_hide(menu_filter_add_task);
277 316
278 if (ginfo->filter_enabled) 317 if (ginfo->filter_enabled)
279 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable), 318 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
280 "Disable Filter"); 319 "Disable Graph Filter");
281 else 320 else
282 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable), 321 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable),
283 "Enable Filter"); 322 "Enable Graph Filter");
284 323
285 if (ginfo->filter_available) 324 if (info->list_filter_enabled)
286 gtk_widget_set_sensitive(menu_filter_enable, TRUE); 325 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
326 "Disable List Filter");
287 else 327 else
288 gtk_widget_set_sensitive(menu_filter_enable, FALSE); 328 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable),
329 "Enable List Filter");
330
331 if (ginfo->filter_available) {
332 gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE);
333 gtk_widget_set_sensitive(menu_filter_list_enable, TRUE);
334 } else {
335 gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE);
336 gtk_widget_set_sensitive(menu_filter_list_enable, FALSE);
337 }
289 338
290 if (filter_task_count(ginfo->task_filter)) 339 if (filter_task_count(ginfo->task_filter))
291 gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); 340 gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE);
diff --git a/kernel-shark.h b/kernel-shark.h
index 59d7b7a..34b2031 100644
--- a/kernel-shark.h
+++ b/kernel-shark.h
@@ -11,6 +11,7 @@ struct shark_info {
11 GtkWidget *treeview; 11 GtkWidget *treeview;
12 struct graph_callbacks graph_cbs; 12 struct graph_callbacks graph_cbs;
13 gint selected_task; 13 gint selected_task;
14 gboolean list_filter_enabled;
14}; 15};
15 16
16#define offset_of(type, field) (long)(&((type *)0)->field) 17#define offset_of(type, field) (long)(&((type *)0)->field)
diff --git a/trace-view-store.c b/trace-view-store.c
index 04debbb..1f1e952 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -1075,6 +1075,43 @@ guint64 trace_view_store_get_offset_from_row(TraceViewStore *store, gint row)
1075 return store->rows[row]->offset; 1075 return store->rows[row]->offset;
1076} 1076}
1077 1077
1078void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter)
1079{
1080 struct tracecmd_input *handle;
1081 struct pevent *pevent;
1082 struct record *record;
1083 gint pid;
1084 gint cpu;
1085 gint i;
1086
1087 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
1088
1089 handle = store->handle;
1090 pevent = tracecmd_get_pevent(store->handle);
1091
1092 for (cpu = 0; cpu < store->cpus; cpu++) {
1093 record = tracecmd_read_cpu_first(handle, cpu);
1094
1095 for (i = 0; i < store->cpu_items[cpu]; i++) {
1096
1097 g_assert(record->offset == store->cpu_list[cpu][i].offset);
1098
1099 /* TODO: put event filter check here */
1100 pid = pevent_data_pid(pevent, record);
1101 if (!filter || filter_task_find_pid(filter, pid))
1102 store->cpu_list[cpu][i].visible = 1;
1103 else
1104 store->cpu_list[cpu][i].visible = 0;
1105
1106 free_record(record);
1107 record = tracecmd_read_data(handle, cpu);
1108 }
1109 g_assert(record == NULL);
1110 }
1111
1112 merge_sort_rows_ts(store);
1113}
1114
1078/***************************************************************************** 1115/*****************************************************************************
1079 * 1116 *
1080 * trace_view_store_append_record: Empty lists are boring. This function can 1117 * trace_view_store_append_record: Empty lists are boring. This function can
diff --git a/trace-view-store.h b/trace-view-store.h
index 687a946..c7738da 100644
--- a/trace-view-store.h
+++ b/trace-view-store.h
@@ -3,6 +3,7 @@
3 3
4#include <gtk/gtk.h> 4#include <gtk/gtk.h>
5#include "trace-cmd.h" 5#include "trace-cmd.h"
6#include "trace-hash.h"
6 7
7/* Some boilerplate GObject defines. 'klass' is used 8/* Some boilerplate GObject defines. 'klass' is used
8 * instead of 'class', because 'class' is a C++ keyword */ 9 * instead of 'class', because 'class' is a C++ keyword */
@@ -118,6 +119,8 @@ guint64 trace_view_store_get_time_from_row(TraceViewStore *store, gint row);
118 119
119guint64 trace_view_store_get_offset_from_row(TraceViewStore *store, gint row); 120guint64 trace_view_store_get_offset_from_row(TraceViewStore *store, gint row);
120 121
122void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter);
123
121/* TraceViewStoreClass: more boilerplate GObject stuff */ 124/* TraceViewStoreClass: more boilerplate GObject stuff */
122 125
123struct _TraceViewStoreClass 126struct _TraceViewStoreClass
diff --git a/trace-view.c b/trace-view.c
index 6dd72ee..f9083f4 100644
--- a/trace-view.c
+++ b/trace-view.c
@@ -207,6 +207,96 @@ trace_view_load(GtkWidget *view, struct tracecmd_input *handle,
207 g_object_unref(model); /* destroy model automatically with view */ 207 g_object_unref(model); /* destroy model automatically with view */
208} 208}
209 209
210/**
211 * trace_view_get_selected_row - return the selected row
212 * @treeview: The tree view
213 *
214 * Returns the selected row number (or -1 if none is selected)
215 */
216gint trace_view_get_selected_row(GtkWidget *treeview)
217{
218 GtkTreeView *tree = GTK_TREE_VIEW(treeview);
219 GtkTreeSelection *selection;
220 GtkTreeModel *model;
221 GtkTreePath *path;
222 gchar *spath;
223 GList *glist;
224 gint row;
225
226 model = gtk_tree_view_get_model(tree);
227 if (!model)
228 return -1;
229
230 selection = gtk_tree_view_get_selection(tree);
231 glist = gtk_tree_selection_get_selected_rows(selection, &model);
232 if (!glist)
233 return -1;
234
235 /* Only one row may be selected */
236 path = glist->data;
237 spath = gtk_tree_path_to_string(path);
238 row = atoi(spath);
239 g_free(spath);
240
241 gtk_tree_path_free(path);
242 g_list_free(glist);
243
244 return row;
245}
246
247void trace_view_make_selection_visible(GtkWidget *treeview)
248{
249 GtkTreeView *tree = GTK_TREE_VIEW(treeview);
250 GtkTreePath *path;
251 gchar *spath;
252 GString *gstr;
253 gint row;
254
255 row = trace_view_get_selected_row(treeview);
256 if (row < 0)
257 return;
258
259 gstr = g_string_new("");
260 g_string_printf(gstr, "%d", row);
261 spath = g_string_free(gstr, FALSE);
262
263 path = gtk_tree_path_new_from_string(spath);
264 g_free(spath);
265
266 gtk_tree_view_scroll_to_cell(tree, path, NULL, TRUE, 0.5, 0.0);
267
268 gtk_tree_path_free(path);
269}
270
271void trace_view_update_task_filter(GtkWidget *treeview, struct filter_task *filter)
272{
273 GtkTreeView *tree = GTK_TREE_VIEW(treeview);
274 GtkTreeModel *model;
275 guint64 time;
276 gint row;
277
278 model = gtk_tree_view_get_model(tree);
279 if (!model)
280 return;
281
282 /* Keep track of the currently selected row */
283 row = trace_view_get_selected_row(treeview);
284 if (row >= 0)
285 time = trace_view_store_get_time_from_row(TRACE_VIEW_STORE(model), row);
286
287 g_object_ref(model);
288 gtk_tree_view_set_model(tree, NULL);
289
290 trace_view_store_filter_tasks(TRACE_VIEW_STORE(model), filter);
291
292 gtk_tree_view_set_model(tree, model);
293 g_object_unref(model);
294
295 /* Keep selection near previous selection */
296 if (row >= 0)
297 trace_view_select(treeview, time);
298}
299
210void trace_view_select(GtkWidget *treeview, guint64 time) 300void trace_view_select(GtkWidget *treeview, guint64 time)
211{ 301{
212 GtkTreeView *tree = GTK_TREE_VIEW(treeview); 302 GtkTreeView *tree = GTK_TREE_VIEW(treeview);
@@ -251,9 +341,8 @@ void trace_view_select(GtkWidget *treeview, guint64 time)
251 341
252 selection = gtk_tree_view_get_selection(tree); 342 selection = gtk_tree_view_get_selection(tree);
253 gtk_tree_selection_select_path(selection, path); 343 gtk_tree_selection_select_path(selection, path);
344 gtk_tree_path_free(path);
254 345
255 /* finally, make it visible */ 346 /* finally, make it visible */
256 gtk_tree_view_scroll_to_cell(tree, path, NULL, TRUE, 0.5, 0.0); 347 trace_view_make_selection_visible(treeview);
257
258 gtk_tree_path_free(path);
259} 348}
diff --git a/trace-view.h b/trace-view.h
index 57662df..03d331c 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -9,6 +9,8 @@ trace_view_load(GtkWidget *view, struct tracecmd_input *handle,
9 9
10void trace_view(int argc, char **argv); 10void trace_view(int argc, char **argv);
11 11
12void trace_view_update_task_filter(GtkWidget *treeview, struct filter_task *filter);
13void trace_view_make_selection_visible(GtkWidget *treeview);
12 14
13/* We use void because this can be used by non gtk files */ 15/* We use void because this can be used by non gtk files */
14void trace_filter_event_dialog(void *traceview); 16void trace_filter_event_dialog(void *traceview);