diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2010-01-04 11:52:51 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2010-01-04 11:52:51 -0500 |
| commit | 7d2d3fd2241384f6549bb1533345fcd21267c497 (patch) | |
| tree | 1723b36eee305775d877d4854a7f4e1559474fe9 | |
| parent | 2bd6ed2cacaa77311cc9d9897ecc00858c895166 (diff) | |
trace-graph: Move task filter code to trace-hash.[ch]
In order to make the trace tree of kernelshark work better with
the trace-graph, move the filtering code of tasks out of trace-graph.c
into trace-hash.c. This will allow the trace-tree to be more flexible
in its filtering too.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | kernel-shark.c | 2 | ||||
| -rw-r--r-- | trace-graph.c | 99 | ||||
| -rw-r--r-- | trace-graph.h | 11 | ||||
| -rw-r--r-- | trace-hash.c | 87 | ||||
| -rw-r--r-- | trace-hash.h | 22 |
5 files changed, 135 insertions, 86 deletions
diff --git a/kernel-shark.c b/kernel-shark.c index 6e92730..9cbc45a 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -287,7 +287,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 287 | else | 287 | else |
| 288 | gtk_widget_set_sensitive(menu_filter_enable, FALSE); | 288 | gtk_widget_set_sensitive(menu_filter_enable, FALSE); |
| 289 | 289 | ||
| 290 | if (ginfo->filter_task_count) | 290 | if (filter_task_count(ginfo->task_filter)) |
| 291 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | 291 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); |
| 292 | else | 292 | else |
| 293 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | 293 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); |
diff --git a/trace-graph.c b/trace-graph.c index 839aab6..0500e35 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -56,8 +56,6 @@ | |||
| 56 | #define CPU_LABEL(cpu) (CPU_TOP(cpu)) | 56 | #define CPU_LABEL(cpu) (CPU_TOP(cpu)) |
| 57 | #define CPU_X 5 | 57 | #define CPU_X 5 |
| 58 | 58 | ||
| 59 | #define FILTER_TASK_HASH_SIZE 256 | ||
| 60 | |||
| 61 | static gint ftrace_sched_switch_id = -1; | 59 | static gint ftrace_sched_switch_id = -1; |
| 62 | static gint event_sched_switch_id = -1; | 60 | static gint event_sched_switch_id = -1; |
| 63 | 61 | ||
| @@ -83,97 +81,45 @@ static void print_time(unsigned long long time) | |||
| 83 | printf("%lu.%06lu", sec, usec); | 81 | printf("%lu.%06lu", sec, usec); |
| 84 | } | 82 | } |
| 85 | 83 | ||
| 86 | struct filter_task * | 84 | struct filter_task_item * |
| 87 | trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid) | 85 | trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid) |
| 88 | { | 86 | { |
| 89 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | 87 | return filter_task_find_pid(ginfo->task_filter, pid); |
| 90 | struct filter_task *task = ginfo->filter_task_hash[key]; | ||
| 91 | |||
| 92 | while (task) { | ||
| 93 | if (task->pid == pid) | ||
| 94 | break; | ||
| 95 | task = task->next; | ||
| 96 | } | ||
| 97 | return task; | ||
| 98 | } | 88 | } |
| 99 | 89 | ||
| 100 | static void filter_task_add_pid(struct graph_info *ginfo, gint pid) | 90 | static void graph_filter_task_add_pid(struct graph_info *ginfo, gint pid) |
| 101 | { | 91 | { |
| 102 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | 92 | filter_task_add_pid(ginfo->task_filter, pid); |
| 103 | struct filter_task *task; | ||
| 104 | |||
| 105 | task = g_new0(typeof(*task), 1); | ||
| 106 | g_assert(task); | ||
| 107 | |||
| 108 | task->pid = pid; | ||
| 109 | task->next = ginfo->filter_task_hash[key]; | ||
| 110 | ginfo->filter_task_hash[key] = task; | ||
| 111 | 93 | ||
| 112 | ginfo->filter_task_count++; | ||
| 113 | ginfo->filter_available = 1; | 94 | ginfo->filter_available = 1; |
| 114 | } | 95 | } |
| 115 | 96 | ||
| 116 | static void filter_task_remove_pid(struct graph_info *ginfo, gint pid) | 97 | static void graph_filter_task_remove_pid(struct graph_info *ginfo, gint pid) |
| 117 | { | 98 | { |
| 118 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | 99 | filter_task_remove_pid(ginfo->task_filter, pid); |
| 119 | struct filter_task **next = &ginfo->filter_task_hash[key]; | ||
| 120 | struct filter_task *task; | ||
| 121 | 100 | ||
| 122 | while (*next) { | 101 | if (!filter_task_count(ginfo->task_filter)) { |
| 123 | if ((*next)->pid == pid) | 102 | ginfo->filter_available = 0; |
| 124 | break; | 103 | ginfo->filter_enabled = 0; |
| 125 | next = &(*next)->next; | ||
| 126 | } | 104 | } |
| 127 | if (!*next) | ||
| 128 | return; | ||
| 129 | |||
| 130 | task = *next; | ||
| 131 | |||
| 132 | *next = task->next; | ||
| 133 | |||
| 134 | g_free(task); | ||
| 135 | |||
| 136 | if (--ginfo->filter_task_count) | ||
| 137 | return; | ||
| 138 | |||
| 139 | ginfo->filter_available = 0; | ||
| 140 | ginfo->filter_enabled = 0; | ||
| 141 | } | 105 | } |
| 142 | 106 | ||
| 143 | static void filter_task_clear(struct graph_info *ginfo) | 107 | static void graph_filter_task_clear(struct graph_info *ginfo) |
| 144 | { | 108 | { |
| 145 | struct filter_task *task, *next;; | 109 | filter_task_clear(ginfo->task_filter); |
| 146 | gint i; | ||
| 147 | |||
| 148 | if (!ginfo->filter_task_count) | ||
| 149 | return; | ||
| 150 | |||
| 151 | for (i = 0; i < FILTER_TASK_HASH_SIZE; i++) { | ||
| 152 | next = ginfo->filter_task_hash[i]; | ||
| 153 | if (!next) | ||
| 154 | continue; | ||
| 155 | |||
| 156 | ginfo->filter_task_hash[i] = NULL; | ||
| 157 | while (next) { | ||
| 158 | task = next; | ||
| 159 | next = task->next; | ||
| 160 | g_free(task); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | 110 | ||
| 164 | ginfo->filter_task_count = 0; | ||
| 165 | ginfo->filter_available = 0; | 111 | ginfo->filter_available = 0; |
| 166 | ginfo->filter_enabled = 0; | 112 | ginfo->filter_enabled = 0; |
| 167 | } | 113 | } |
| 168 | 114 | ||
| 169 | gboolean filter_on_task(struct graph_info *ginfo, gint pid) | 115 | gboolean graph_filter_on_task(struct graph_info *ginfo, gint pid) |
| 170 | { | 116 | { |
| 171 | gboolean filter; | 117 | gboolean filter; |
| 172 | 118 | ||
| 173 | filter = FALSE; | 119 | filter = FALSE; |
| 174 | 120 | ||
| 175 | if (ginfo->filter_enabled && | 121 | if (ginfo->filter_enabled && |
| 176 | ginfo->filter_task_count && | 122 | filter_task_count(ginfo->task_filter) && |
| 177 | !trace_graph_filter_task_find_pid(ginfo, pid)) | 123 | !trace_graph_filter_task_find_pid(ginfo, pid)) |
| 178 | filter = TRUE; | 124 | filter = TRUE; |
| 179 | 125 | ||
| @@ -303,14 +249,14 @@ void trace_graph_filter_add_remove_task(struct graph_info *ginfo, | |||
| 303 | gint pid) | 249 | gint pid) |
| 304 | { | 250 | { |
| 305 | gint filter_enabled = ginfo->filter_enabled; | 251 | gint filter_enabled = ginfo->filter_enabled; |
| 306 | struct filter_task *task; | 252 | struct filter_task_item *task; |
| 307 | 253 | ||
| 308 | task = trace_graph_filter_task_find_pid(ginfo, pid); | 254 | task = trace_graph_filter_task_find_pid(ginfo, pid); |
| 309 | 255 | ||
| 310 | if (task) | 256 | if (task) |
| 311 | filter_task_remove_pid(ginfo, task->pid); | 257 | graph_filter_task_remove_pid(ginfo, task->pid); |
| 312 | else | 258 | else |
| 313 | filter_task_add_pid(ginfo, pid); | 259 | graph_filter_task_add_pid(ginfo, pid); |
| 314 | 260 | ||
| 315 | if (filter_enabled) | 261 | if (filter_enabled) |
| 316 | redraw_graph(ginfo); | 262 | redraw_graph(ginfo); |
| @@ -328,7 +274,7 @@ void trace_graph_clear_tasks(struct graph_info *ginfo) | |||
| 328 | { | 274 | { |
| 329 | gint filter_enabled = ginfo->filter_enabled; | 275 | gint filter_enabled = ginfo->filter_enabled; |
| 330 | 276 | ||
| 331 | filter_task_clear(ginfo); | 277 | graph_filter_task_clear(ginfo); |
| 332 | 278 | ||
| 333 | if (filter_enabled) | 279 | if (filter_enabled) |
| 334 | redraw_graph(ginfo); | 280 | redraw_graph(ginfo); |
| @@ -402,7 +348,7 @@ do_pop_up(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 402 | else | 348 | else |
| 403 | gtk_widget_set_sensitive(menu_filter_enable, FALSE); | 349 | gtk_widget_set_sensitive(menu_filter_enable, FALSE); |
| 404 | 350 | ||
| 405 | if (ginfo->filter_task_count) | 351 | if (filter_task_count(ginfo->task_filter)) |
| 406 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | 352 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); |
| 407 | else | 353 | else |
| 408 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | 354 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); |
| @@ -1195,7 +1141,7 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu, | |||
| 1195 | set_color_by_pid(ginfo->draw, gc, pid); | 1141 | set_color_by_pid(ginfo->draw, gc, pid); |
| 1196 | } | 1142 | } |
| 1197 | 1143 | ||
| 1198 | filter = filter_on_task(ginfo, last_pid); | 1144 | filter = graph_filter_on_task(ginfo, last_pid); |
| 1199 | 1145 | ||
| 1200 | if (!filter && last_pid) | 1146 | if (!filter && last_pid) |
| 1201 | 1147 | ||
| @@ -1210,7 +1156,7 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu, | |||
| 1210 | set_color_by_pid(ginfo->draw, gc, pid); | 1156 | set_color_by_pid(ginfo->draw, gc, pid); |
| 1211 | } | 1157 | } |
| 1212 | 1158 | ||
| 1213 | filter = filter_on_task(ginfo, pid); | 1159 | filter = graph_filter_on_task(ginfo, pid); |
| 1214 | 1160 | ||
| 1215 | if (!filter) | 1161 | if (!filter) |
| 1216 | gdk_draw_line(ginfo->curr_pixmap, gc, // ginfo->draw->style->black_gc, | 1162 | gdk_draw_line(ginfo->curr_pixmap, gc, // ginfo->draw->style->black_gc, |
| @@ -1244,7 +1190,7 @@ static void draw_cpu(struct graph_info *ginfo, gint cpu, | |||
| 1244 | p1, p2, ginfo->draw_width, width_16, font); | 1190 | p1, p2, ginfo->draw_width, width_16, font); |
| 1245 | 1191 | ||
| 1246 | if (last_pid > 0 && | 1192 | if (last_pid > 0 && |
| 1247 | !filter_on_task(ginfo, last_pid)) { | 1193 | !graph_filter_on_task(ginfo, last_pid)) { |
| 1248 | 1194 | ||
| 1249 | x = ginfo->draw_width; | 1195 | x = ginfo->draw_width; |
| 1250 | 1196 | ||
| @@ -1607,8 +1553,7 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle, | |||
| 1607 | ginfo->start_time = -1ULL; | 1553 | ginfo->start_time = -1ULL; |
| 1608 | ginfo->end_time = 0; | 1554 | ginfo->end_time = 0; |
| 1609 | 1555 | ||
| 1610 | ginfo->filter_task_hash = g_new0(typeof(*ginfo->filter_task_hash), | 1556 | ginfo->task_filter = filter_task_hash_alloc(); |
| 1611 | FILTER_TASK_HASH_SIZE); | ||
| 1612 | 1557 | ||
| 1613 | ginfo->widget = gtk_hbox_new(FALSE, 0); | 1558 | ginfo->widget = gtk_hbox_new(FALSE, 0); |
| 1614 | gtk_widget_show(ginfo->widget); | 1559 | gtk_widget_show(ginfo->widget); |
diff --git a/trace-graph.h b/trace-graph.h index ac52003..61d17db 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _TRACE_GRAPH_H | 2 | #define _TRACE_GRAPH_H |
| 3 | 3 | ||
| 4 | #include "trace-cmd.h" | 4 | #include "trace-cmd.h" |
| 5 | #include "trace-hash.h" | ||
| 5 | 6 | ||
| 6 | struct graph_info; | 7 | struct graph_info; |
| 7 | 8 | ||
| @@ -11,11 +12,6 @@ struct graph_callbacks { | |||
| 11 | graph_select_cb *select; | 12 | graph_select_cb *select; |
| 12 | }; | 13 | }; |
| 13 | 14 | ||
| 14 | struct filter_task { | ||
| 15 | struct filter_task *next; | ||
| 16 | gint pid; | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct graph_info { | 15 | struct graph_info { |
| 20 | struct tracecmd_input *handle; | 16 | struct tracecmd_input *handle; |
| 21 | struct pevent *pevent; | 17 | struct pevent *pevent; |
| @@ -55,8 +51,7 @@ struct graph_info { | |||
| 55 | int filter_enabled; | 51 | int filter_enabled; |
| 56 | int filter_available; | 52 | int filter_available; |
| 57 | 53 | ||
| 58 | struct filter_task **filter_task_hash; | 54 | struct filter_task *task_filter; |
| 59 | gint filter_task_count; | ||
| 60 | gint filter_task_selected; | 55 | gint filter_task_selected; |
| 61 | 56 | ||
| 62 | 57 | ||
| @@ -96,7 +91,7 @@ static inline GtkWidget *trace_graph_get_window(struct graph_info *ginfo) | |||
| 96 | return ginfo->widget; | 91 | return ginfo->widget; |
| 97 | } | 92 | } |
| 98 | 93 | ||
| 99 | struct filter_task * | 94 | struct filter_task_item * |
| 100 | trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid); | 95 | trace_graph_filter_task_find_pid(struct graph_info *ginfo, gint pid); |
| 101 | void trace_graph_filter_toggle(struct graph_info *ginfo); | 96 | void trace_graph_filter_toggle(struct graph_info *ginfo); |
| 102 | void trace_graph_filter_add_remove_task(struct graph_info *info, | 97 | void trace_graph_filter_add_remove_task(struct graph_info *info, |
diff --git a/trace-hash.c b/trace-hash.c index 9d830e2..99b9feb 100644 --- a/trace-hash.c +++ b/trace-hash.c | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include "trace-hash.h" | 5 | #include "trace-hash.h" |
| 6 | 6 | ||
| 7 | #define FILTER_TASK_HASH_SIZE 256 | ||
| 8 | |||
| 7 | guint trace_hash(gint val) | 9 | guint trace_hash(gint val) |
| 8 | { | 10 | { |
| 9 | gint hash, tmp; | 11 | gint hash, tmp; |
| @@ -29,3 +31,88 @@ guint trace_hash(gint val) | |||
| 29 | 31 | ||
| 30 | return hash; | 32 | return hash; |
| 31 | } | 33 | } |
| 34 | |||
| 35 | struct filter_task_item * | ||
| 36 | filter_task_find_pid(struct filter_task *hash, gint pid) | ||
| 37 | { | ||
| 38 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | ||
| 39 | struct filter_task_item *task = hash->hash[key]; | ||
| 40 | |||
| 41 | while (task) { | ||
| 42 | if (task->pid == pid) | ||
| 43 | break; | ||
| 44 | task = task->next; | ||
| 45 | } | ||
| 46 | return task; | ||
| 47 | } | ||
| 48 | |||
| 49 | void filter_task_add_pid(struct filter_task *hash, gint pid) | ||
| 50 | { | ||
| 51 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | ||
| 52 | struct filter_task_item *task; | ||
| 53 | |||
| 54 | task = g_new0(typeof(*task), 1); | ||
| 55 | g_assert(task); | ||
| 56 | |||
| 57 | task->pid = pid; | ||
| 58 | task->next = hash->hash[key]; | ||
| 59 | hash->hash[key] = task; | ||
| 60 | |||
| 61 | hash->count++; | ||
| 62 | } | ||
| 63 | |||
| 64 | void filter_task_remove_pid(struct filter_task *hash, gint pid) | ||
| 65 | { | ||
| 66 | gint key = trace_hash(pid) % FILTER_TASK_HASH_SIZE; | ||
| 67 | struct filter_task_item **next = &hash->hash[key]; | ||
| 68 | struct filter_task_item *task; | ||
| 69 | |||
| 70 | while (*next) { | ||
| 71 | if ((*next)->pid == pid) | ||
| 72 | break; | ||
| 73 | next = &(*next)->next; | ||
| 74 | } | ||
| 75 | if (!*next) | ||
| 76 | return; | ||
| 77 | |||
| 78 | g_assert(hash->count); | ||
| 79 | hash->count--; | ||
| 80 | |||
| 81 | task = *next; | ||
| 82 | |||
| 83 | *next = task->next; | ||
| 84 | |||
| 85 | g_free(task); | ||
| 86 | } | ||
| 87 | |||
| 88 | void filter_task_clear(struct filter_task *hash) | ||
| 89 | { | ||
| 90 | struct filter_task_item *task, *next;; | ||
| 91 | gint i; | ||
| 92 | |||
| 93 | for (i = 0; i < FILTER_TASK_HASH_SIZE; i++) { | ||
| 94 | next = hash->hash[i]; | ||
| 95 | if (!next) | ||
| 96 | continue; | ||
| 97 | |||
| 98 | hash->hash[i] = NULL; | ||
| 99 | while (next) { | ||
| 100 | task = next; | ||
| 101 | next = task->next; | ||
| 102 | g_free(task); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | hash->count = 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | struct filter_task *filter_task_hash_alloc(void) | ||
| 110 | { | ||
| 111 | struct filter_task *hash; | ||
| 112 | |||
| 113 | hash = g_new0(typeof(*hash), 1); | ||
| 114 | g_assert(hash); | ||
| 115 | hash->hash = g_new0(typeof(*hash->hash), FILTER_TASK_HASH_SIZE); | ||
| 116 | |||
| 117 | return hash; | ||
| 118 | } | ||
diff --git a/trace-hash.h b/trace-hash.h index 8a22044..cab6195 100644 --- a/trace-hash.h +++ b/trace-hash.h | |||
| @@ -3,6 +3,28 @@ | |||
| 3 | 3 | ||
| 4 | #include <glib.h> | 4 | #include <glib.h> |
| 5 | 5 | ||
| 6 | struct filter_task_item { | ||
| 7 | struct filter_task_item *next; | ||
| 8 | gint pid; | ||
| 9 | }; | ||
| 10 | |||
| 11 | struct filter_task { | ||
| 12 | struct filter_task_item **hash; | ||
| 13 | gint count; | ||
| 14 | }; | ||
| 15 | |||
| 6 | guint trace_hash(gint val); | 16 | guint trace_hash(gint val); |
| 7 | 17 | ||
| 18 | struct filter_task_item * | ||
| 19 | filter_task_find_pid(struct filter_task *hash, gint pid); | ||
| 20 | void filter_task_add_pid(struct filter_task *hash, gint pid); | ||
| 21 | void filter_task_remove_pid(struct filter_task *hash, gint pid); | ||
| 22 | void filter_task_clear(struct filter_task *hash); | ||
| 23 | struct filter_task *filter_task_hash_alloc(void); | ||
| 24 | |||
| 25 | static inline gint filter_task_count(struct filter_task *hash) | ||
| 26 | { | ||
| 27 | return hash->count; | ||
| 28 | } | ||
| 29 | |||
| 8 | #endif /* _TRACE_HASH_H */ | 30 | #endif /* _TRACE_HASH_H */ |
