diff options
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | kernel-shark.c | 285 | ||||
-rw-r--r-- | kernel-shark.h | 12 | ||||
-rw-r--r-- | trace-view-store.c | 8 |
4 files changed, 308 insertions, 7 deletions
@@ -19,7 +19,7 @@ CFLAGS = -g -Wall $(CONFIG_FLAGS) | |||
19 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ | 19 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ |
20 | 20 | ||
21 | TARGETS = libparsevent.a libtracecmd.a trace-cmd plugin_hrtimer.so plugin_mac80211.so \ | 21 | TARGETS = libparsevent.a libtracecmd.a trace-cmd plugin_hrtimer.so plugin_mac80211.so \ |
22 | plugin_sched_switch.so trace-graph trace-view | 22 | plugin_sched_switch.so trace-graph trace-view kernelshark |
23 | 23 | ||
24 | all: $(TARGETS) | 24 | all: $(TARGETS) |
25 | 25 | ||
@@ -38,16 +38,22 @@ trace-view-main.o:: $(HEADERS) trace-view-store.h trace-view.h | |||
38 | trace-filter.o:: $(HEADERS) | 38 | trace-filter.o:: $(HEADERS) |
39 | trace-graph.o:: $(HEADERS) trace-graph.h | 39 | trace-graph.o:: $(HEADERS) trace-graph.h |
40 | trace-graph-main.o:: $(HEADERS) trace-graph.h | 40 | trace-graph-main.o:: $(HEADERS) trace-graph.h |
41 | kernel-shark.o:: $(HEADERS) | ||
42 | |||
43 | TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o | ||
41 | 44 | ||
42 | trace-cmd:: trace-cmd.o trace-read.o | 45 | trace-cmd:: trace-cmd.o trace-read.o |
43 | $(CC) $^ -rdynamic -o $@ $(LIBS) | 46 | $(CC) $^ -rdynamic -o $@ $(LIBS) |
44 | 47 | ||
45 | trace-view:: trace-view-main.o trace-view.o trace-view-store.o trace-filter.o | 48 | trace-view:: trace-view-main.o $(TRACE_VIEW_OBJS) |
46 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS) | 49 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS) |
47 | 50 | ||
48 | trace-graph:: trace-graph-main.o trace-graph.o trace-compat.o | 51 | trace-graph:: trace-graph-main.o trace-graph.o trace-compat.o |
49 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS) | 52 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS) |
50 | 53 | ||
54 | kernelshark:: kernel-shark.o trace-compat.o $(TRACE_VIEW_OBJS) trace-graph.o | ||
55 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS) | ||
56 | |||
51 | .PHONY: gtk_depends | 57 | .PHONY: gtk_depends |
52 | view_depends: | 58 | view_depends: |
53 | @pkg-config --cflags $(PACKAGES) | 59 | @pkg-config --cflags $(PACKAGES) |
diff --git a/kernel-shark.c b/kernel-shark.c new file mode 100644 index 0000000..8fd16c9 --- /dev/null +++ b/kernel-shark.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
20 | */ | ||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <stdarg.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <unistd.h> | ||
26 | #include <gtk/gtk.h> | ||
27 | |||
28 | #include "trace-compat.h" | ||
29 | #include "trace-cmd.h" | ||
30 | #include "kernel-shark.h" | ||
31 | |||
32 | #define version "0.1.1" | ||
33 | |||
34 | #define TRACE_WIDTH 800 | ||
35 | #define TRACE_HEIGHT 600 | ||
36 | |||
37 | #define input_file "trace.dat" | ||
38 | |||
39 | |||
40 | /* Callback for the clicked signal of the Exit button */ | ||
41 | static void | ||
42 | exit_clicked (GtkWidget *widget, gpointer data) | ||
43 | { | ||
44 | gtk_widget_destroy (GTK_WIDGET (data)); /* the user data points to the main window */ | ||
45 | gtk_main_quit (); | ||
46 | } | ||
47 | |||
48 | /* Callback for the delete_event signal of the main application window */ | ||
49 | static gint | ||
50 | delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) | ||
51 | { | ||
52 | gtk_widget_destroy (widget); /* destroy the main window */ | ||
53 | gtk_main_quit (); | ||
54 | return TRUE; | ||
55 | } | ||
56 | |||
57 | /* Callback for the clicked signal of the Events filter button */ | ||
58 | static void | ||
59 | events_clicked (gpointer data) | ||
60 | { | ||
61 | struct shark_info *info = data; | ||
62 | |||
63 | trace_filter_event_dialog(info->treeview); | ||
64 | } | ||
65 | |||
66 | /* Callback for the clicked signal of the CPUs filter button */ | ||
67 | static void | ||
68 | cpus_clicked (gpointer data) | ||
69 | { | ||
70 | struct shark_info *info = data; | ||
71 | |||
72 | trace_filter_cpu_dialog(info->treeview); | ||
73 | } | ||
74 | |||
75 | void kernel_shark(int argc, char **argv) | ||
76 | { | ||
77 | struct tracecmd_input *handle; | ||
78 | struct shark_info *info; | ||
79 | GtkWidget *window; | ||
80 | GtkWidget *vbox; | ||
81 | GtkWidget *hbox; | ||
82 | GtkWidget *menu_bar; | ||
83 | GtkWidget *menu; | ||
84 | GtkWidget *menu_item; | ||
85 | GtkWidget *sub_item; | ||
86 | GtkWidget *scrollwin; | ||
87 | GtkWidget *draw; | ||
88 | GtkWidget *label; | ||
89 | GtkWidget *spin; | ||
90 | |||
91 | info = g_new0(typeof(*info), 1); | ||
92 | if (!info) | ||
93 | die("Unable to allocate info"); | ||
94 | |||
95 | handle = tracecmd_open(input_file); | ||
96 | |||
97 | if (!handle) | ||
98 | die("error reading header"); | ||
99 | |||
100 | if (tracecmd_read_headers(handle) < 0) | ||
101 | return; | ||
102 | |||
103 | if (tracecmd_init_data(handle) < 0) | ||
104 | die("failed to init data"); | ||
105 | |||
106 | gtk_init(&argc, &argv); | ||
107 | |||
108 | /* --- Main window --- */ | ||
109 | |||
110 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||
111 | |||
112 | /* --- Top Level Vbox --- */ | ||
113 | |||
114 | vbox = gtk_vbox_new(FALSE, 0); | ||
115 | gtk_container_add(GTK_CONTAINER (window), vbox); | ||
116 | gtk_widget_show(vbox); | ||
117 | |||
118 | /* --- Menu Bar --- */ | ||
119 | |||
120 | menu_bar = gtk_menu_bar_new(); | ||
121 | gtk_box_pack_start(GTK_BOX (vbox), menu_bar, FALSE, FALSE, 0); | ||
122 | gtk_widget_show(menu_bar); | ||
123 | |||
124 | /* --- File Option --- */ | ||
125 | |||
126 | menu_item = gtk_menu_item_new_with_label("File"); | ||
127 | gtk_widget_show(menu_item); | ||
128 | |||
129 | gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item); | ||
130 | |||
131 | menu = gtk_menu_new(); /* Don't need to show menus */ | ||
132 | |||
133 | |||
134 | /* --- File - Quit Option --- */ | ||
135 | |||
136 | sub_item = gtk_menu_item_new_with_label("Quit"); | ||
137 | |||
138 | /* Add them to the menu */ | ||
139 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
140 | |||
141 | /* We can attach the Quit menu item to our exit function */ | ||
142 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
143 | G_CALLBACK (exit_clicked), | ||
144 | (gpointer) window); | ||
145 | |||
146 | /* We do need to show menu items */ | ||
147 | gtk_widget_show(sub_item); | ||
148 | |||
149 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); | ||
150 | |||
151 | /* --- end File options --- */ | ||
152 | |||
153 | /* --- Filter Option --- */ | ||
154 | |||
155 | menu_item = gtk_menu_item_new_with_label("Filter"); | ||
156 | gtk_widget_show(menu_item); | ||
157 | |||
158 | gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item); | ||
159 | |||
160 | menu = gtk_menu_new(); /* Don't need to show menus */ | ||
161 | |||
162 | |||
163 | /* --- Filter - Events Option --- */ | ||
164 | |||
165 | sub_item = gtk_menu_item_new_with_label("events"); | ||
166 | |||
167 | /* Add them to the menu */ | ||
168 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
169 | |||
170 | /* We can attach the Quit menu item to our exit function */ | ||
171 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
172 | G_CALLBACK (events_clicked), | ||
173 | (gpointer) info); | ||
174 | |||
175 | /* We do need to show menu items */ | ||
176 | gtk_widget_show(sub_item); | ||
177 | |||
178 | |||
179 | /* --- Filter - CPUs Option --- */ | ||
180 | |||
181 | sub_item = gtk_menu_item_new_with_label("CPUs"); | ||
182 | |||
183 | /* Add them to the menu */ | ||
184 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
185 | |||
186 | /* We can attach the Quit menu item to our exit function */ | ||
187 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
188 | G_CALLBACK (cpus_clicked), | ||
189 | (gpointer) info); | ||
190 | |||
191 | /* We do need to show menu items */ | ||
192 | gtk_widget_show(sub_item); | ||
193 | |||
194 | |||
195 | /* --- End Filter Options --- */ | ||
196 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); | ||
197 | |||
198 | /* --- Top Level Hbox --- */ | ||
199 | |||
200 | hbox = gtk_hbox_new(FALSE, 0); | ||
201 | gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); | ||
202 | gtk_widget_show(hbox); | ||
203 | |||
204 | /* --- Scroll Window --- */ | ||
205 | scrollwin = gtk_scrolled_window_new(NULL, NULL); | ||
206 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), | ||
207 | GTK_POLICY_AUTOMATIC, | ||
208 | GTK_POLICY_AUTOMATIC); | ||
209 | gtk_box_pack_start(GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0); | ||
210 | gtk_widget_show(scrollwin); | ||
211 | |||
212 | /* --- Set up Drawing --- */ | ||
213 | |||
214 | info->ginfo = trace_graph_create(handle, GTK_SCROLLED_WINDOW(scrollwin)); | ||
215 | draw = trace_graph_get_draw(info->ginfo); | ||
216 | |||
217 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), | ||
218 | draw); | ||
219 | gtk_widget_show(draw); | ||
220 | |||
221 | |||
222 | |||
223 | /* --- Paging Hbox --- */ | ||
224 | |||
225 | hbox = gtk_hbox_new(FALSE, 0); | ||
226 | gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | ||
227 | gtk_widget_show(hbox); | ||
228 | |||
229 | /* --- Page Spin Button --- */ | ||
230 | |||
231 | label = gtk_label_new("Page"); | ||
232 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | ||
233 | gtk_widget_show(label); | ||
234 | |||
235 | spin = gtk_spin_button_new(NULL, 1.0, 0); | ||
236 | gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), 1, 1); | ||
237 | gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); | ||
238 | gtk_widget_show(spin); | ||
239 | |||
240 | /* --- Top Level Trace View Paging Hbox --- */ | ||
241 | |||
242 | hbox = gtk_hbox_new(FALSE, 0); | ||
243 | gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); | ||
244 | gtk_widget_show(hbox); | ||
245 | |||
246 | /* --- Scroll Window --- */ | ||
247 | scrollwin = gtk_scrolled_window_new(NULL, NULL); | ||
248 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), | ||
249 | GTK_POLICY_AUTOMATIC, | ||
250 | GTK_POLICY_AUTOMATIC); | ||
251 | gtk_box_pack_start(GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0); | ||
252 | gtk_widget_show(scrollwin); | ||
253 | |||
254 | /* --- Set up Trace Tree --- */ | ||
255 | |||
256 | info->treeview = gtk_tree_view_new(); | ||
257 | |||
258 | trace_view_load(info->treeview, handle, spin); | ||
259 | |||
260 | gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), | ||
261 | info->treeview); | ||
262 | gtk_widget_show(info->treeview); | ||
263 | |||
264 | |||
265 | /********************************************** | ||
266 | * Main Window | ||
267 | **********************************************/ | ||
268 | |||
269 | /* Connect to the delete_event signal and Run the application */ | ||
270 | |||
271 | gtk_signal_connect (GTK_OBJECT (window), "delete_event", | ||
272 | (GtkSignalFunc) delete_event, | ||
273 | NULL); | ||
274 | |||
275 | gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT); | ||
276 | |||
277 | gtk_widget_show (window); | ||
278 | gtk_main (); | ||
279 | } | ||
280 | |||
281 | int main(int argc, char **argv) | ||
282 | { | ||
283 | kernel_shark(argc, argv); | ||
284 | return 0; | ||
285 | } | ||
diff --git a/kernel-shark.h b/kernel-shark.h new file mode 100644 index 0000000..58761b0 --- /dev/null +++ b/kernel-shark.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _KERNEL_SHARK_H | ||
2 | #define _KERNEL_SHARK_H | ||
3 | |||
4 | #include "trace-graph.h" | ||
5 | #include "trace-view.h" | ||
6 | |||
7 | struct shark_info { | ||
8 | struct graph_info *ginfo; | ||
9 | GtkWidget *treeview; | ||
10 | }; | ||
11 | |||
12 | #endif /* _KERNEL_SHARK_H */ | ||
diff --git a/trace-view-store.c b/trace-view-store.c index f26351a..4c96336 100644 --- a/trace-view-store.c +++ b/trace-view-store.c | |||
@@ -854,11 +854,8 @@ trace_view_store_new (struct tracecmd_input *handle) | |||
854 | list = NULL; | 854 | list = NULL; |
855 | next = &list; | 855 | next = &list; |
856 | 856 | ||
857 | for (;;) { | 857 | data = tracecmd_read_cpu_first(handle, cpu); |
858 | data = tracecmd_read_data(handle, cpu); | 858 | while (data) { |
859 | if (!data) | ||
860 | break; | ||
861 | |||
862 | *next = rec = g_malloc(sizeof(*rec)); | 859 | *next = rec = g_malloc(sizeof(*rec)); |
863 | g_assert(rec != NULL); | 860 | g_assert(rec != NULL); |
864 | rec->offset = data->offset; | 861 | rec->offset = data->offset; |
@@ -867,6 +864,7 @@ trace_view_store_new (struct tracecmd_input *handle) | |||
867 | next = &rec->next; | 864 | next = &rec->next; |
868 | free(data); | 865 | free(data); |
869 | count++; | 866 | count++; |
867 | data = tracecmd_read_data(handle, cpu); | ||
870 | } | 868 | } |
871 | 869 | ||
872 | if (count) { | 870 | if (count) { |