aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trace-compat.h2
-rw-r--r--trace-filter.c264
-rw-r--r--trace-graph.c10
-rw-r--r--trace-hash.c44
-rw-r--r--trace-hash.h2
-rw-r--r--trace-view-main.c3
-rw-r--r--trace-view-store.c221
-rw-r--r--trace-view-store.h38
8 files changed, 570 insertions, 14 deletions
diff --git a/trace-compat.h b/trace-compat.h
index 8f8ad11..1d9099c 100644
--- a/trace-compat.h
+++ b/trace-compat.h
@@ -16,7 +16,7 @@ void gtk_cell_renderer_get_padding(GtkCellRenderer *cell,
16 16
17void gtk_menu_item_set_label(GtkMenuItem *menu_item, const gchar *label); 17void gtk_menu_item_set_label(GtkMenuItem *menu_item, const gchar *label);
18 18
19#endif /* version < 2.18.0 */ 19#endif /* version < 2.16.0 */
20 20
21#if GTK_VERSION < CALC_GTK_VERSION(2,14,0) 21#if GTK_VERSION < CALC_GTK_VERSION(2,14,0)
22 22
diff --git a/trace-filter.c b/trace-filter.c
index 3c1e23b..ba3b0fd 100644
--- a/trace-filter.c
+++ b/trace-filter.c
@@ -35,6 +35,9 @@ struct dialog_helper {
35 35
36enum { 36enum {
37 COL_EVENT, 37 COL_EVENT,
38 COL_ACTIVE,
39 COL_ACTIVE_START,
40 COL_EVENT_ID,
38 NUM_EVENT_COLS, 41 NUM_EVENT_COLS,
39}; 42};
40 43
@@ -49,18 +52,27 @@ create_tree_event_model(GtkWidget *tree_view)
49 struct event_format **events; 52 struct event_format **events;
50 struct event_format *event; 53 struct event_format *event;
51 char *last_system = NULL; 54 char *last_system = NULL;
55 gboolean all_events;
56 gboolean sysactive;
57 gboolean active;
52 gint i; 58 gint i;
53 59
54 model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)); 60 model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
55 trace_view = TRACE_VIEW_STORE(model); 61 trace_view = TRACE_VIEW_STORE(model);
56 62
63 all_events = trace_view_store_get_all_events_enabled(trace_view);
64
57 pevent = tracecmd_get_pevent(trace_view->handle); 65 pevent = tracecmd_get_pevent(trace_view->handle);
58 66
59 treestore = gtk_tree_store_new(NUM_EVENT_COLS, G_TYPE_STRING); 67 treestore = gtk_tree_store_new(NUM_EVENT_COLS, G_TYPE_STRING,
68 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
69 G_TYPE_INT);
60 70
61 gtk_tree_store_append(treestore, &iter_all, NULL); 71 gtk_tree_store_append(treestore, &iter_all, NULL);
62 gtk_tree_store_set(treestore, &iter_all, 72 gtk_tree_store_set(treestore, &iter_all,
63 COL_EVENT, "All", 73 COL_EVENT, "All",
74 COL_ACTIVE, all_events,
75 COL_ACTIVE_START, FALSE,
64 -1); 76 -1);
65 77
66 events = pevent_list_events(pevent, EVENT_SORT_SYSTEM); 78 events = pevent_list_events(pevent, EVENT_SORT_SYSTEM);
@@ -71,15 +83,22 @@ create_tree_event_model(GtkWidget *tree_view)
71 event = events[i]; 83 event = events[i];
72 if (!last_system || strcmp(last_system, event->system) != 0) { 84 if (!last_system || strcmp(last_system, event->system) != 0) {
73 gtk_tree_store_append(treestore, &iter_sys, &iter_all); 85 gtk_tree_store_append(treestore, &iter_sys, &iter_all);
86 sysactive = all_events ||
87 trace_view_store_system_enabled(trace_view, event->system);
74 gtk_tree_store_set(treestore, &iter_sys, 88 gtk_tree_store_set(treestore, &iter_sys,
75 COL_EVENT, event->system, 89 COL_EVENT, event->system,
90 COL_ACTIVE, sysactive,
76 -1); 91 -1);
77 last_system = event->system; 92 last_system = event->system;
78 } 93 }
79 94
95 active = all_events || sysactive ||
96 trace_view_store_event_enabled(trace_view, event->id);
80 gtk_tree_store_append(treestore, &iter_events, &iter_sys); 97 gtk_tree_store_append(treestore, &iter_events, &iter_sys);
81 gtk_tree_store_set(treestore, &iter_events, 98 gtk_tree_store_set(treestore, &iter_events,
82 COL_EVENT, event->name, 99 COL_EVENT, event->name,
100 COL_ACTIVE, active,
101 COL_EVENT_ID, event->id,
83 -1); 102 -1);
84 103
85 } 104 }
@@ -87,10 +106,134 @@ create_tree_event_model(GtkWidget *tree_view)
87 return GTK_TREE_MODEL(treestore); 106 return GTK_TREE_MODEL(treestore);
88} 107}
89 108
109static void update_active_events(GtkTreeModel *model, GtkTreeIter *parent,
110 gboolean active)
111{
112 GtkTreeIter event;
113
114 if (!gtk_tree_model_iter_children(model, &event, parent))
115 return;
116
117 for (;;) {
118 gtk_tree_store_set(GTK_TREE_STORE(model), &event,
119 COL_ACTIVE, active,
120 -1);
121
122 if (!gtk_tree_model_iter_next(model, &event))
123 break;
124 }
125}
126
127static void update_active_systems(GtkTreeModel *model, GtkTreeIter *parent,
128 gboolean active)
129{
130 GtkTreeIter sys;
131
132 if (!gtk_tree_model_iter_children(model, &sys, parent))
133 return;
134
135 for (;;) {
136 gtk_tree_store_set(GTK_TREE_STORE(model), &sys,
137 COL_ACTIVE, active,
138 -1);
139
140 update_active_events(model, &sys, active);
141
142 if (!gtk_tree_model_iter_next(model, &sys))
143 break;
144 }
145}
146
147static void event_cursor_changed(GtkTreeView *treeview, gpointer data)
148{
149 GtkTreeModel *model;
150 GtkTreePath *path;
151 GtkTreeIter iter, parent, grandparent;
152 gboolean active, start;
153 gint depth;
154
155 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
156 if (!model)
157 return;
158
159 gtk_tree_view_get_cursor(treeview, &path, NULL);
160 if (!path)
161 return;
162
163 if (!gtk_tree_model_get_iter(model, &iter, path))
164 goto free;
165
166 depth = gtk_tree_path_get_depth(path);
167
168 if (depth == 1) {
169 /*
170 * The first time we start up, the cursor will
171 * select the "All Events" row, and call
172 * this routine. But we don't want to do anything.
173 * Check and activate.
174 */
175 gtk_tree_model_get(model, &iter,
176 COL_ACTIVE_START, &start,
177 -1);
178 if (!start) {
179 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
180 COL_ACTIVE_START, TRUE,
181 -1);
182 goto free;
183 }
184 }
185
186 gtk_tree_model_get(model, &iter,
187 COL_ACTIVE, &active,
188 -1);
189
190 active = active ? FALSE : TRUE;
191
192 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
193 COL_ACTIVE, active,
194 -1);
195
196 if (depth == 1) {
197
198 if (active)
199 /* Set all rows */
200 update_active_systems(model, &iter, TRUE);
201
202 } else if (depth == 2) {
203 if (active) {
204 /* set this system */
205 update_active_events(model, &iter, TRUE);
206 } else {
207 /* disable the all events toggle */
208 gtk_tree_model_iter_parent(model, &parent, &iter);
209 gtk_tree_store_set(GTK_TREE_STORE(model), &parent,
210 COL_ACTIVE, FALSE,
211 -1);
212 }
213
214 } else {
215 if (!active) {
216 /* disable system and all events toggles */
217 gtk_tree_model_iter_parent(model, &parent, &iter);
218 gtk_tree_store_set(GTK_TREE_STORE(model), &parent,
219 COL_ACTIVE, FALSE,
220 -1);
221 gtk_tree_model_iter_parent(model, &grandparent, &parent);
222 gtk_tree_store_set(GTK_TREE_STORE(model), &grandparent,
223 COL_ACTIVE, FALSE,
224 -1);
225 }
226 }
227
228 free:
229 gtk_tree_path_free(path);
230}
231
90static GtkWidget *create_event_list_view(GtkWidget *tree_view) 232static GtkWidget *create_event_list_view(GtkWidget *tree_view)
91{ 233{
92 GtkTreeViewColumn *col; 234 GtkTreeViewColumn *col;
93 GtkCellRenderer *renderer; 235 GtkCellRenderer *renderer;
236 GtkCellRenderer *togrend;
94 GtkWidget *view; 237 GtkWidget *view;
95 GtkTreeModel *model; 238 GtkTreeModel *model;
96 239
@@ -106,7 +249,11 @@ static GtkWidget *create_event_list_view(GtkWidget *tree_view)
106 249
107 renderer = gtk_cell_renderer_text_new(); 250 renderer = gtk_cell_renderer_text_new();
108 251
109 gtk_tree_view_column_pack_start(col, renderer, TRUE); 252 togrend = gtk_cell_renderer_toggle_new();
253
254 gtk_tree_view_column_pack_start(col, togrend, FALSE);
255 gtk_tree_view_column_pack_start(col, renderer, FALSE);
256 gtk_tree_view_column_add_attribute(col, togrend, "active", COL_ACTIVE);
110 257
111 gtk_tree_view_column_add_attribute(col, renderer, "text", COL_EVENT); 258 gtk_tree_view_column_add_attribute(col, renderer, "text", COL_EVENT);
112 259
@@ -117,23 +264,125 @@ static GtkWidget *create_event_list_view(GtkWidget *tree_view)
117 g_object_unref(model); 264 g_object_unref(model);
118 265
119 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), 266 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
120 GTK_SELECTION_MULTIPLE); 267 GTK_SELECTION_NONE);
121 268
122 gtk_tree_view_expand_all(GTK_TREE_VIEW(view)); 269 gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
123 270
271 g_signal_connect_swapped (view, "cursor-changed",
272 G_CALLBACK (event_cursor_changed),
273 (gpointer) view);
274
124 return view; 275 return view;
125} 276}
126 277
278static void update_events(TraceViewStore *store,
279 GtkTreeModel *model,
280 GtkTreeIter *parent)
281{
282 GtkTreeIter event;
283 gboolean active;
284 gint id;
285
286 if (!gtk_tree_model_iter_children(model, &event, parent))
287 return;
288
289 for (;;) {
290
291 gtk_tree_model_get(model, &event,
292 COL_ACTIVE, &active,
293 COL_EVENT_ID, &id,
294 -1);
295
296 if (active)
297 trace_view_store_set_event_enabled(store, id);
298
299 if (!gtk_tree_model_iter_next(model, &event))
300 break;
301 }
302}
303
304static void update_system_events(TraceViewStore *store,
305 GtkTreeModel *model,
306 GtkTreeIter *parent)
307{
308 GtkTreeIter sys;
309 gboolean active;
310 gchar *system;
311
312 if (!gtk_tree_model_iter_children(model, &sys, parent))
313 return;
314
315 for (;;) {
316
317 gtk_tree_model_get(model, &sys,
318 COL_ACTIVE, &active,
319 COL_EVENT, &system,
320 -1);
321
322 if (active)
323 trace_view_store_set_system_enabled(store, system);
324 else
325 update_events(store, model, &sys);
326
327 g_free(system);
328
329 if (!gtk_tree_model_iter_next(model, &sys))
330 break;
331 }
332}
333
334static void accept_events(GtkWidget *trace_tree_view, GtkTreeView *view)
335{
336 GtkTreeModel *model;
337 TraceViewStore *store;
338 GtkTreeIter iter;
339 gboolean active;
340
341 model = gtk_tree_view_get_model(GTK_TREE_VIEW(trace_tree_view));
342 if (!model)
343 return;
344
345 store = TRACE_VIEW_STORE(model);
346
347 model = gtk_tree_view_get_model(view);
348 if (!model)
349 return;
350
351 if (!gtk_tree_model_get_iter_first(model, &iter))
352 return;
353
354 gtk_tree_model_get(model, &iter,
355 COL_ACTIVE, &active,
356 -1);
357
358 if (active) {
359 if (trace_view_store_get_all_events_enabled(store))
360 return;
361
362 trace_view_store_set_all_events_enabled(store);
363 } else
364 update_system_events(store, model, &iter);
365
366 /* Force an update */
367 g_object_ref(store);
368 gtk_tree_view_set_model(GTK_TREE_VIEW(trace_tree_view), NULL);
369 trace_view_store_update_filter(store);
370 gtk_tree_view_set_model(GTK_TREE_VIEW(trace_tree_view), GTK_TREE_MODEL(store));
371 g_object_unref(store);
372
373}
127 374
128/* Callback for the clicked signal of the Events filter button */ 375/* Callback for the clicked signal of the Events filter button */
129static void 376static void
130event_dialog_response (gpointer data, gint response_id) 377event_dialog_response (gpointer data, gint response_id)
131{ 378{
132 struct dialog_helper *helper = data; 379 struct dialog_helper *helper = data;
380 GtkTreeView *view = helper->data;
133 381
134 switch (response_id) { 382 switch (response_id) {
135 case GTK_RESPONSE_ACCEPT: 383 case GTK_RESPONSE_ACCEPT:
136 printf("accept!\n"); 384 printf("accept!\n");
385 accept_events(helper->trace_tree, view);
137 break; 386 break;
138 case GTK_RESPONSE_REJECT: 387 case GTK_RESPONSE_REJECT:
139 printf("reject!\n"); 388 printf("reject!\n");
@@ -177,7 +426,11 @@ void trace_filter_event_dialog(void *trace_tree)
177 (gpointer) helper); 426 (gpointer) helper);
178 427
179 scrollwin = gtk_scrolled_window_new(NULL, NULL); 428 scrollwin = gtk_scrolled_window_new(NULL, NULL);
429 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
430 GTK_POLICY_AUTOMATIC,
431 GTK_POLICY_AUTOMATIC);
180 view = create_event_list_view(tree_view); 432 view = create_event_list_view(tree_view);
433 helper->data = view;
181 434
182 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); 435 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
183 gtk_container_add(GTK_CONTAINER(scrollwin), view); 436 gtk_container_add(GTK_CONTAINER(scrollwin), view);
@@ -341,6 +594,9 @@ void trace_filter_cpu_dialog(void *trace_tree)
341 (gpointer) helper); 594 (gpointer) helper);
342 595
343 scrollwin = gtk_scrolled_window_new(NULL, NULL); 596 scrollwin = gtk_scrolled_window_new(NULL, NULL);
597 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
598 GTK_POLICY_AUTOMATIC,
599 GTK_POLICY_AUTOMATIC);
344 600
345 viewport = gtk_viewport_new(NULL, NULL); 601 viewport = gtk_viewport_new(NULL, NULL);
346 gtk_widget_show(viewport); 602 gtk_widget_show(viewport);
diff --git a/trace-graph.c b/trace-graph.c
index 0500e35..5f1464c 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -1078,6 +1078,7 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu,
1078 gint last_event_id = 0; 1078 gint last_event_id = 0;
1079 gint event_id; 1079 gint event_id;
1080 gboolean filter; 1080 gboolean filter;
1081 gboolean is_sched_switch;
1081 const char *comm; 1082 const char *comm;
1082 1083
1083 /* Calculate the size of 16 characters */ 1084 /* Calculate the size of 16 characters */
@@ -1118,8 +1119,10 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu,
1118 1119
1119 x = (gint)((gdouble)ts * ginfo->resolution); 1120 x = (gint)((gdouble)ts * ginfo->resolution);
1120 1121
1122 is_sched_switch = FALSE;
1121 1123
1122 if (check_sched_switch(ginfo, record, &pid, &comm)) { 1124 if (check_sched_switch(ginfo, record, &pid, &comm)) {
1125 is_sched_switch = TRUE;
1123 if (read_comms) { 1126 if (read_comms) {
1124 /* 1127 /*
1125 * First time through, register any missing 1128 * First time through, register any missing
@@ -1151,13 +1154,18 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu,
1151 x - last_x, CPU_BOX_SIZE); 1154 x - last_x, CPU_BOX_SIZE);
1152 1155
1153 last_x = x; 1156 last_x = x;
1154 last_pid = pid;
1155 1157
1156 set_color_by_pid(ginfo->draw, gc, pid); 1158 set_color_by_pid(ginfo->draw, gc, pid);
1157 } 1159 }
1158 1160
1159 filter = graph_filter_on_task(ginfo, pid); 1161 filter = graph_filter_on_task(ginfo, pid);
1160 1162
1163 /* Also show the task switching out */
1164 if (filter && is_sched_switch)
1165 filter = graph_filter_on_task(ginfo, last_pid);
1166
1167 last_pid = pid;
1168
1161 if (!filter) 1169 if (!filter)
1162 gdk_draw_line(ginfo->curr_pixmap, gc, // ginfo->draw->style->black_gc, 1170 gdk_draw_line(ginfo->curr_pixmap, gc, // ginfo->draw->style->black_gc,
1163 x, CPU_TOP(cpu), x, CPU_BOTTOM(cpu)); 1171 x, CPU_TOP(cpu), x, CPU_BOTTOM(cpu));
diff --git a/trace-hash.c b/trace-hash.c
index 99b9feb..8435e6c 100644
--- a/trace-hash.c
+++ b/trace-hash.c
@@ -116,3 +116,47 @@ struct filter_task *filter_task_hash_alloc(void)
116 116
117 return hash; 117 return hash;
118} 118}
119
120void filter_task_hash_free(struct filter_task *hash)
121{
122 if (!hash)
123 return;
124
125 filter_task_clear(hash);
126 g_free(hash->hash);
127 g_free(hash);
128}
129
130struct filter_task *filter_task_hash_copy(struct filter_task *hash)
131{
132 struct filter_task *new_hash;
133 struct filter_task_item *task, **ptask;
134 gint i;
135
136 if (!hash)
137 return NULL;
138
139 new_hash = filter_task_hash_alloc();
140 g_assert(new_hash);
141
142 for (i = 0; i < FILTER_TASK_HASH_SIZE; i++) {
143 task = hash->hash[i];
144 if (!task)
145 continue;
146
147 ptask = &new_hash->hash[i];
148
149 while (task) {
150
151 *ptask = g_new0(typeof(*task), 1);
152 g_assert(*ptask);
153 **ptask = *task;
154
155 ptask = &(*ptask)->next;
156 task = task->next;
157 }
158 }
159
160 return new_hash;
161}
162
diff --git a/trace-hash.h b/trace-hash.h
index cab6195..9948138 100644
--- a/trace-hash.h
+++ b/trace-hash.h
@@ -21,6 +21,8 @@ void filter_task_add_pid(struct filter_task *hash, gint pid);
21void filter_task_remove_pid(struct filter_task *hash, gint pid); 21void filter_task_remove_pid(struct filter_task *hash, gint pid);
22void filter_task_clear(struct filter_task *hash); 22void filter_task_clear(struct filter_task *hash);
23struct filter_task *filter_task_hash_alloc(void); 23struct filter_task *filter_task_hash_alloc(void);
24void filter_task_hash_free(struct filter_task *hash);
25struct filter_task *filter_task_hash_copy(struct filter_task *hash);
24 26
25static inline gint filter_task_count(struct filter_task *hash) 27static inline gint filter_task_count(struct filter_task *hash)
26{ 28{
diff --git a/trace-view-main.c b/trace-view-main.c
index 5b6eb7b..2f4042e 100644
--- a/trace-view-main.c
+++ b/trace-view-main.c
@@ -248,8 +248,7 @@ void trace_view(int argc, char **argv)
248 248
249 trace_view_load(trace_tree, handle, spin); 249 trace_view_load(trace_tree, handle, spin);
250 250
251 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), 251 gtk_container_add(GTK_CONTAINER(scrollwin), trace_tree);
252 trace_tree);
253 gtk_widget_show(trace_tree); 252 gtk_widget_show(trace_tree);
254 253
255 254
diff --git a/trace-view-store.c b/trace-view-store.c
index be86662..9ad2073 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -1,5 +1,6 @@
1#include "trace-view-store.h" 1#include "trace-view-store.h"
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h>
3 4
4#include "cpu.h" 5#include "cpu.h"
5 6
@@ -207,6 +208,8 @@ trace_view_store_finalize (GObject *object)
207 g_free(store->rows); 208 g_free(store->rows);
208 g_free(store->cpu_items); 209 g_free(store->cpu_items);
209 210
211 filter_task_hash_free(store->task_filter);
212
210 if (store->spin) { 213 if (store->spin) {
211 gtk_widget_destroy(store->spin); 214 gtk_widget_destroy(store->spin);
212 store->spin = NULL; 215 store->spin = NULL;
@@ -490,6 +493,183 @@ trace_view_store_get_value (GtkTreeModel *tree_model,
490 } 493 }
491} 494}
492 495
496int str_cmp(const void *a, const void *b)
497{
498 char * const * sa = a;
499 char * const * sb = b;
500
501 return strcmp(*sa, *sb);
502}
503
504int id_cmp(const void *a, const void *b)
505{
506 const gint *ia = a;
507 const gint *ib = b;
508
509 if (*ia > *ib)
510 return 1;
511 if (*ia < *ib)
512 return -1;
513 return 0;
514}
515
516gboolean trace_view_store_system_enabled(TraceViewStore *store, const gchar *system)
517{
518 const gchar **sys = &system;
519
520 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
521
522 if (store->all_events)
523 return TRUE;
524
525 if (!store->systems)
526 return FALSE;
527
528 sys = bsearch(sys, store->systems, store->systems_size,
529 sizeof(system), str_cmp);
530
531 return sys != NULL;
532}
533
534gboolean trace_view_store_event_enabled(TraceViewStore *store, gint event_id)
535{
536 gint key = event_id;
537 gint *ret;
538
539 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
540
541 if (store->all_events)
542 return TRUE;
543
544 /* TODO: search for the system of the event? */
545
546 if (!store->event_types)
547 return FALSE;
548
549 ret = bsearch(&key, store->event_types, store->event_types_size,
550 sizeof(gint), id_cmp);
551
552 return ret != NULL;
553}
554
555void trace_view_store_set_all_events_enabled(TraceViewStore *store)
556{
557 gint i;
558
559 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
560
561 if (store->all_events)
562 return;
563
564 if (store->systems_size) {
565 for (i = 0; i < store->systems_size; i++)
566 g_free(store->systems[i]);
567
568 g_free(store->systems);
569 store->systems = NULL;
570 store->systems_size = 0;
571 }
572
573 g_free(store->event_types);
574 store->event_types = NULL;
575 store->event_types_size = 0;
576
577 store->all_events = 1;
578}
579
580static void remove_system(TraceViewStore *store, const gchar *system)
581{
582 const gchar **sys = &system;
583
584 if (!store->systems)
585 return;
586
587 sys = bsearch(sys, store->systems, store->systems_size,
588 sizeof(system), str_cmp);
589
590 if (!sys)
591 return;
592
593 g_free(*((gchar **)sys));
594
595 g_memmove(sys, sys+1, sizeof(*sys) * (store->systems_size -
596 ((gchar **)sys - store->systems)));
597 store->systems_size--;
598 store->systems[store->systems_size] = NULL;
599}
600
601void trace_view_store_set_system_enabled(TraceViewStore *store, const gchar *system)
602{
603 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
604
605 if (store->all_events)
606 /*
607 * We are adding a new filter, so this is the
608 * only system enabled.
609 */
610 store->all_events = 0;
611
612 if (trace_view_store_system_enabled(store, system))
613 return;
614
615 if (!store->systems) {
616 store->systems = g_new0(gchar *, 2);
617 store->systems[0] = g_strdup(system);
618 store->systems_size++;
619 return;
620 }
621
622 store->systems_size++;
623 store->systems = g_realloc(store->systems,
624 sizeof(*store->systems) * (store->systems_size+1));
625 store->systems[store->systems_size - 1] = g_strdup(system);
626 store->systems[store->systems_size] = NULL;
627
628 qsort(store->systems, store->systems_size, sizeof(gchar *), str_cmp);
629}
630
631
632void trace_view_store_set_event_enabled(TraceViewStore *store, gint event_id)
633{
634 struct pevent *pevent;
635 struct event_format *event;
636
637 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
638
639 pevent = tracecmd_get_pevent(store->handle);
640 event = pevent_find_event(pevent, event_id);
641 if (!event)
642 return;
643
644 if (store->all_events)
645 /*
646 * We are adding a new filter, so this is the
647 * only system enabled.
648 */
649 store->all_events = 0;
650
651 remove_system(store, event->system);
652
653 if (trace_view_store_event_enabled(store, event_id))
654 return;
655
656 if (!store->event_types) {
657 store->event_types = g_new0(gint, 2);
658 store->event_types[0] = event_id;
659 store->event_types[1] = -1;
660 store->event_types_size++;
661 return;
662 }
663
664 store->event_types_size++;
665 store->event_types = g_realloc(store->event_types,
666 sizeof(*store->event_types) * (store->event_types_size+1));
667 store->event_types[store->event_types_size - 1] = event_id;
668 store->event_types[store->event_types_size] = -1;
669
670 qsort(store->event_types, store->event_types_size, sizeof(gint), id_cmp);
671}
672
493 673
494/***************************************************************************** 674/*****************************************************************************
495 * 675 *
@@ -1059,7 +1239,7 @@ gint get_next_pid(TraceViewStore *store, struct pevent *pevent, struct record *r
1059 unsigned long long val; 1239 unsigned long long val;
1060 int ret; 1240 int ret;
1061 1241
1062 ret = pevent_read_number_field(store->sched_switch_next_field, record, &val); 1242 ret = pevent_read_number_field(store->sched_switch_next_field, record->data, &val);
1063 1243
1064 return val; 1244 return val;
1065} 1245}
@@ -1067,14 +1247,23 @@ gint get_next_pid(TraceViewStore *store, struct pevent *pevent, struct record *r
1067void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter) 1247void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter)
1068{ 1248{
1069 struct tracecmd_input *handle; 1249 struct tracecmd_input *handle;
1250 struct event_format *event;
1070 struct pevent *pevent; 1251 struct pevent *pevent;
1071 struct record *record; 1252 struct record *record;
1253 gint last_event_id = -1;
1254 gint event_id;
1072 gint pid; 1255 gint pid;
1073 gint cpu; 1256 gint cpu;
1074 gint i; 1257 gint i;
1075 1258
1076 g_return_if_fail (TRACE_VIEW_IS_LIST (store)); 1259 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
1077 1260
1261 /* We may pass in the store->task_filter. Don't free it if we do */
1262 if (store->task_filter && store->task_filter != filter)
1263 filter_task_hash_free(store->task_filter);
1264
1265 store->task_filter = filter_task_hash_copy(filter);
1266
1078 handle = store->handle; 1267 handle = store->handle;
1079 pevent = tracecmd_get_pevent(store->handle); 1268 pevent = tracecmd_get_pevent(store->handle);
1080 1269
@@ -1094,7 +1283,22 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1094 1283
1095 g_assert(record->offset == store->cpu_list[cpu][i].offset); 1284 g_assert(record->offset == store->cpu_list[cpu][i].offset);
1096 1285
1097 /* TODO: put event filter check here */ 1286 /* The record may be filtered by the events */
1287 if (!store->all_events) {
1288 event_id = pevent_data_type(pevent, record);
1289 if (last_event_id != event_id) {
1290 /* optimize: only search event when new */
1291 event = pevent_find_event(pevent, event_id);
1292 g_assert(event);
1293 }
1294 last_event_id = event_id;
1295 if (!trace_view_store_system_enabled(store, event->system) &&
1296 !trace_view_store_event_enabled(store, event_id)) {
1297 store->cpu_list[cpu][i].visible = 0;
1298 goto skip;
1299 }
1300 }
1301
1098 pid = pevent_data_pid(pevent, record); 1302 pid = pevent_data_pid(pevent, record);
1099 if (!filter || filter_task_find_pid(filter, pid)) 1303 if (!filter || filter_task_find_pid(filter, pid))
1100 store->cpu_list[cpu][i].visible = 1; 1304 store->cpu_list[cpu][i].visible = 1;
@@ -1108,10 +1312,11 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1108 store->cpu_list[cpu][i].visible = 1; 1312 store->cpu_list[cpu][i].visible = 1;
1109 else 1313 else
1110 store->cpu_list[cpu][i].visible = 0; 1314 store->cpu_list[cpu][i].visible = 0;
1111 } 1315 } else
1112 store->cpu_list[cpu][i].visible = 0; 1316 store->cpu_list[cpu][i].visible = 0;
1113 } 1317 }
1114 1318
1319 skip:
1115 free_record(record); 1320 free_record(record);
1116 record = tracecmd_read_data(handle, cpu); 1321 record = tracecmd_read_data(handle, cpu);
1117 } 1322 }
@@ -1121,6 +1326,14 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
1121 merge_sort_rows_ts(store); 1326 merge_sort_rows_ts(store);
1122} 1327}
1123 1328
1329void trace_view_store_update_filter(TraceViewStore *store)
1330{
1331 g_return_if_fail (TRACE_VIEW_IS_LIST (store));
1332
1333 trace_view_store_filter_tasks(store, store->task_filter);
1334}
1335
1336
1124/***************************************************************************** 1337/*****************************************************************************
1125 * 1338 *
1126 * trace_view_store_append_record: Empty lists are boring. This function can 1339 * 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 08caf3f..60f90a5 100644
--- a/trace-view-store.h
+++ b/trace-view-store.h
@@ -94,7 +94,10 @@ struct trace_view_store
94 gint all_events; /* set 1 when all events are enabled */ 94 gint all_events; /* set 1 when all events are enabled */
95 /* else */ 95 /* else */
96 gchar **systems; /* sorted list of systems that are enabled */ 96 gchar **systems; /* sorted list of systems that are enabled */
97 gint **event_types; /* sorted list of events that are enabled */ 97 gint *event_types; /* sorted list of events that are enabled */
98 gint systems_size; /* size of systems array */
99 gint event_types_size; /* size of event_types array */
100 struct filter_task *task_filter; /* hash of tasks to filter on */
98 101
99 gint all_cpus; /* set 1 when all cpus are enabled */ 102 gint all_cpus; /* set 1 when all cpus are enabled */
100 /* else */ 103 /* else */
@@ -121,7 +124,19 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi
121 124
122TraceViewRecord *trace_view_store_get_row(TraceViewStore *store, gint row); 125TraceViewRecord *trace_view_store_get_row(TraceViewStore *store, gint row);
123 126
124/* TraceViewStore methos */ 127gboolean trace_view_store_system_enabled(TraceViewStore *store, const gchar *system);
128
129gboolean trace_view_store_event_enabled(TraceViewStore *store, gint event_id);
130
131void trace_view_store_set_all_events_enabled(TraceViewStore *store);
132
133void trace_view_store_set_system_enabled(TraceViewStore *store, const gchar *system);
134
135void trace_view_store_set_event_enabled(TraceViewStore *store, gint event_id);
136
137void trace_view_store_update_filter(TraceViewStore *store);
138
139/* TraceViewStore methods */
125GtkTreeModelFlags trace_view_store_get_flags (GtkTreeModel *tree_model); 140GtkTreeModelFlags trace_view_store_get_flags (GtkTreeModel *tree_model);
126 141
127gint trace_view_store_get_n_columns (GtkTreeModel *tree_model); 142gint trace_view_store_get_n_columns (GtkTreeModel *tree_model);
@@ -187,4 +202,23 @@ static inline GtkWidget *trace_view_store_get_spin(TraceViewStore *store)
187 return store->spin; 202 return store->spin;
188} 203}
189 204
205static inline gboolean trace_view_store_get_all_events_enabled(TraceViewStore *store)
206{
207 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE);
208 return store->all_events;
209}
210
211static inline gchar **trace_view_store_get_systems_enabled(TraceViewStore *store)
212{
213 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), NULL);
214 return store->systems;
215}
216
217static inline gint *trace_view_store_get_events_enabled(TraceViewStore *store)
218{
219 g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), NULL);
220 return store->event_types;
221}
222
223
190#endif /* _trace_view_store_h_included_ */ 224#endif /* _trace_view_store_h_included_ */