Commit | Line | Data |
---|---|---|
9e01e6d4 | 1 | /* This file is part of the Linux Trace Toolkit viewer |
2 | * Copyright (C) 2003-2004 Mathieu Desnoyers | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License Version 2 as | |
6 | * published by the Free Software Foundation; | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program; if not, write to the Free Software | |
15 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
16 | * MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #ifdef HAVE_CONFIG_H | |
20 | #include <config.h> | |
21 | #endif | |
22 | ||
23 | #include <gtk/gtk.h> | |
24 | #include <gdk/gdk.h> | |
25 | #include <glib.h> | |
26 | #include <string.h> | |
27 | #include <stdlib.h> | |
28 | #include <math.h> | |
29 | ||
30 | #include "processlist.h" | |
31 | #include "drawing.h" | |
32 | #include "drawitem.h" | |
33 | ||
34 | #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) | |
58a9b31b | 35 | //#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) |
9e01e6d4 | 36 | |
37 | /* Preallocated Size of the index_to_pixmap array */ | |
38 | #define ALLOCATE_PROCESSES 1000 | |
39 | ||
40 | /***************************************************************************** | |
41 | * Methods to synchronize process list * | |
42 | *****************************************************************************/ | |
43 | ||
44 | ||
fb93b151 | 45 | gint resource_sort_func ( GtkTreeModel *model, |
46 | GtkTreeIter *it_a, | |
47 | GtkTreeIter *it_b, | |
48 | gpointer user_data) | |
49 | { | |
50 | gchar *a_name; | |
51 | gchar *b_name; | |
52 | ||
53 | gtk_tree_model_get(model, it_a, NAME_COLUMN, &a_name, -1); | |
54 | ||
55 | gtk_tree_model_get(model, it_b, NAME_COLUMN, &b_name, -1); | |
56 | ||
57 | return strcmp(a_name, b_name); | |
58 | } | |
9e01e6d4 | 59 | |
67f72973 | 60 | static guint ru_numeric_hash_fct(gconstpointer key) |
9e01e6d4 | 61 | { |
d0e4ae2f | 62 | ResourceUniqueNumeric *ru = (ResourceUniqueNumeric *)key; |
67f72973 | 63 | int tmp = (ru->trace_num << 8) ^ ru->id; |
64 | ||
65 | return g_int_hash(&tmp); | |
9e01e6d4 | 66 | } |
67 | ||
67f72973 | 68 | static gboolean ru_numeric_equ_fct(gconstpointer a, gconstpointer b) |
9e01e6d4 | 69 | { |
67f72973 | 70 | const ResourceUniqueNumeric *pa = (const ResourceUniqueNumeric *)a; |
71 | const ResourceUniqueNumeric *pb = (const ResourceUniqueNumeric *)b; | |
9e01e6d4 | 72 | |
67f72973 | 73 | if(pa->id == pb->id && pa->trace_num == pb->trace_num) |
74 | return TRUE; | |
9e01e6d4 | 75 | |
67f72973 | 76 | return FALSE; |
9e01e6d4 | 77 | } |
78 | ||
79 | void destroy_hash_key(gpointer key); | |
80 | ||
81 | void destroy_hash_data(gpointer data); | |
82 | ||
83 | ||
84 | gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) | |
85 | { | |
86 | ControlFlowData *control_flow_data = | |
87 | (ControlFlowData*)g_object_get_data( | |
88 | G_OBJECT(widget), | |
67f72973 | 89 | "resourceview_data"); |
8d8c5ea7 AM |
90 | unsigned int cell_height = |
91 | get_cell_height(GTK_TREE_VIEW(control_flow_data->process_list->process_list_widget)); | |
9e01e6d4 | 92 | |
93 | switch(event->direction) { | |
94 | case GDK_SCROLL_UP: | |
95 | gtk_adjustment_set_value(control_flow_data->v_adjust, | |
96 | gtk_adjustment_get_value(control_flow_data->v_adjust) - cell_height); | |
97 | break; | |
98 | case GDK_SCROLL_DOWN: | |
99 | gtk_adjustment_set_value(control_flow_data->v_adjust, | |
100 | gtk_adjustment_get_value(control_flow_data->v_adjust) + cell_height); | |
101 | break; | |
102 | default: | |
103 | g_error("should only scroll up and down."); | |
104 | } | |
8d8c5ea7 | 105 | return TRUE; |
9e01e6d4 | 106 | } |
107 | ||
27274b95 | 108 | void expand_event(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *arg2, gpointer user_data) |
109 | { | |
110 | ControlFlowData *resourceview_data = | |
111 | (ControlFlowData*)g_object_get_data( | |
112 | G_OBJECT(treeview), | |
113 | "resourceview_data"); | |
114 | ProcessList *process_list = (ProcessList *) user_data; | |
27274b95 | 115 | HashedResourceData *hrd; |
116 | gboolean result; | |
117 | ||
118 | GtkTreeModel *model; | |
119 | GtkTreeIter child; | |
120 | ||
121 | /* Determine which trace has been expanded */ | |
122 | model = gtk_tree_view_get_model(treeview); | |
123 | ||
124 | /* mark each of the trace's resources invisible */ | |
125 | result = gtk_tree_model_iter_children(model, &child, iter); | |
126 | ||
127 | /* for each child of the collapsed row */ | |
128 | while(result) { | |
129 | /* hide the item */ | |
130 | gtk_tree_model_get(model, &child, DATA_COLUMN, &hrd, -1); | |
131 | hrd->hidden=0; | |
132 | ||
133 | /* find next */ | |
134 | result = gtk_tree_model_iter_next(model, &child); | |
135 | } | |
136 | ||
137 | update_index_to_pixmap(process_list); | |
138 | ||
139 | gtk_widget_queue_draw(resourceview_data->drawing->drawing_area); | |
140 | } | |
141 | ||
142 | void collapse_event(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *arg2, gpointer user_data) | |
143 | { | |
144 | ControlFlowData *resourceview_data = | |
145 | (ControlFlowData*)g_object_get_data( | |
146 | G_OBJECT(treeview), | |
147 | "resourceview_data"); | |
148 | ProcessList *process_list = (ProcessList *) user_data; | |
27274b95 | 149 | HashedResourceData *hrd; |
150 | gboolean result; | |
151 | ||
152 | GtkTreeModel *model; | |
153 | GtkTreeIter child; | |
154 | ||
155 | /* Determine which trace has been expanded */ | |
156 | model = gtk_tree_view_get_model(treeview); | |
157 | ||
158 | /* mark each of the trace's resources invisible */ | |
159 | result = gtk_tree_model_iter_children(model, &child, iter); | |
160 | ||
161 | /* for each child of the collapsed row */ | |
162 | while(result) { | |
163 | char *name; | |
164 | /* hide the item */ | |
165 | gtk_tree_model_get(model, &child, NAME_COLUMN, &name, DATA_COLUMN, &hrd, -1); | |
166 | hrd->hidden=1; | |
167 | ||
168 | /* find next */ | |
169 | result = gtk_tree_model_iter_next(model, &child); | |
170 | } | |
171 | ||
172 | update_index_to_pixmap(process_list); | |
173 | ||
174 | gtk_widget_queue_draw(resourceview_data->drawing->drawing_area); | |
175 | } | |
176 | ||
67f72973 | 177 | static gboolean update_index_to_pixmap_each (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, UpdateIndexPixmapArg *arg) |
9e01e6d4 | 178 | { |
67f72973 | 179 | guint array_index = arg->count; |
180 | HashedResourceData *hdata; | |
181 | gchar *name; | |
182 | ||
183 | gtk_tree_model_get(model, iter, NAME_COLUMN, &name, DATA_COLUMN, &hdata, -1); | |
184 | ||
185 | g_assert(array_index < arg->process_list->index_to_pixmap->len); | |
9e01e6d4 | 186 | |
27274b95 | 187 | if(hdata->hidden == 0) { |
188 | GdkPixmap **pixmap = | |
189 | (GdkPixmap**)&g_ptr_array_index(arg->process_list->index_to_pixmap, array_index); | |
190 | *pixmap = hdata->pixmap; | |
9e01e6d4 | 191 | |
27274b95 | 192 | arg->count++; |
193 | } | |
9e01e6d4 | 194 | |
67f72973 | 195 | return FALSE; |
9e01e6d4 | 196 | } |
197 | ||
9e01e6d4 | 198 | void update_index_to_pixmap(ProcessList *process_list) |
199 | { | |
67f72973 | 200 | int i, items=0; |
201 | UpdateIndexPixmapArg arg; | |
202 | ||
203 | for(i=0; i<RV_RESOURCE_COUNT; i++) { | |
204 | items += g_hash_table_size(process_list->restypes[i].hash_table); | |
205 | } | |
206 | ||
27274b95 | 207 | /* we don't know the exact number of items there will be, |
208 | * so set an upper bound */ | |
67f72973 | 209 | g_ptr_array_set_size(process_list->index_to_pixmap, items); |
210 | ||
211 | arg.count = 0; | |
212 | arg.process_list = process_list; | |
213 | ||
53f78441 | 214 | /* If cell_height is still 0, the only element in the tree is a temporary |
215 | * element that has no pixmap, see also processlist_construct() */ | |
216 | if (process_list->cell_height != 0) { | |
217 | gtk_tree_model_foreach(GTK_TREE_MODEL(process_list->list_store), | |
67f72973 | 218 | (GtkTreeModelForeachFunc)update_index_to_pixmap_each, &arg); |
53f78441 | 219 | } |
27274b95 | 220 | |
221 | /* now that we know the exact number of items, set it */ | |
222 | g_ptr_array_set_size(process_list->index_to_pixmap, arg.count); | |
9e01e6d4 | 223 | } |
224 | ||
225 | ||
67f72973 | 226 | static void update_pixmap_size_each(void *key, |
58a9b31b | 227 | HashedResourceData *value, |
9e01e6d4 | 228 | guint width) |
229 | { | |
230 | GdkPixmap *old_pixmap = value->pixmap; | |
231 | ||
232 | value->pixmap = | |
233 | gdk_pixmap_new(old_pixmap, | |
234 | width, | |
235 | value->height, | |
236 | -1); | |
237 | ||
238 | gdk_pixmap_unref(old_pixmap); | |
239 | } | |
240 | ||
241 | ||
242 | void update_pixmap_size(ProcessList *process_list, guint width) | |
243 | { | |
67f72973 | 244 | int i; |
245 | for(i=0; i<RV_RESOURCE_COUNT; i++) { | |
43ed82b5 | 246 | g_hash_table_foreach(process_list->restypes[i].hash_table, |
247 | (GHFunc)update_pixmap_size_each, | |
248 | GUINT_TO_POINTER(width)); | |
67f72973 | 249 | } |
9e01e6d4 | 250 | } |
251 | ||
252 | ||
253 | typedef struct _CopyPixmap { | |
254 | GdkDrawable *dest; | |
255 | GdkGC *gc; | |
256 | GdkDrawable *src; | |
257 | gint xsrc, ysrc, xdest, ydest, width, height; | |
258 | } CopyPixmap; | |
259 | ||
67f72973 | 260 | static void copy_pixmap_region_each(void *key, |
58a9b31b | 261 | HashedResourceData *value, |
9e01e6d4 | 262 | CopyPixmap *cp) |
263 | { | |
264 | GdkPixmap *src = cp->src; | |
265 | GdkPixmap *dest = cp->dest; | |
266 | ||
267 | if(dest == NULL) | |
268 | dest = value->pixmap; | |
269 | if(src == NULL) | |
270 | src = value->pixmap; | |
271 | ||
272 | gdk_draw_drawable (dest, | |
273 | cp->gc, | |
274 | src, | |
275 | cp->xsrc, cp->ysrc, | |
276 | cp->xdest, cp->ydest, | |
277 | cp->width, cp->height); | |
278 | } | |
279 | ||
9e01e6d4 | 280 | void copy_pixmap_region(ProcessList *process_list, GdkDrawable *dest, |
281 | GdkGC *gc, GdkDrawable *src, | |
282 | gint xsrc, gint ysrc, | |
283 | gint xdest, gint ydest, gint width, gint height) | |
284 | { | |
67f72973 | 285 | int i; |
9e01e6d4 | 286 | CopyPixmap cp = { dest, gc, src, xsrc, ysrc, xdest, ydest, width, height }; |
287 | ||
67f72973 | 288 | for(i=0; i<RV_RESOURCE_COUNT; i++) { |
289 | g_hash_table_foreach(process_list->restypes[i].hash_table, | |
9e01e6d4 | 290 | (GHFunc)copy_pixmap_region_each, |
291 | &cp); | |
67f72973 | 292 | } |
9e01e6d4 | 293 | } |
294 | ||
295 | ||
296 | ||
297 | typedef struct _RectanglePixmap { | |
298 | gboolean filled; | |
299 | gint x, y, width, height; | |
300 | GdkGC *gc; | |
301 | } RectanglePixmap; | |
302 | ||
67f72973 | 303 | static void rectangle_pixmap_each(void *key, |
58a9b31b | 304 | HashedResourceData *value, |
9e01e6d4 | 305 | RectanglePixmap *rp) |
306 | { | |
307 | if(rp->height == -1) | |
308 | rp->height = value->height; | |
309 | ||
310 | gdk_draw_rectangle (value->pixmap, | |
311 | rp->gc, | |
312 | rp->filled, | |
313 | rp->x, rp->y, | |
314 | rp->width, rp->height); | |
315 | } | |
316 | ||
9e01e6d4 | 317 | void rectangle_pixmap(ProcessList *process_list, GdkGC *gc, |
318 | gboolean filled, gint x, gint y, gint width, gint height) | |
319 | { | |
67f72973 | 320 | int i; |
9e01e6d4 | 321 | RectanglePixmap rp = { filled, x, y, width, height, gc }; |
322 | ||
67f72973 | 323 | for(i=0; i<RV_RESOURCE_COUNT; i++) { |
324 | g_hash_table_foreach(process_list->restypes[i].hash_table, | |
9e01e6d4 | 325 | (GHFunc)rectangle_pixmap_each, |
326 | &rp); | |
67f72973 | 327 | } |
9e01e6d4 | 328 | } |
329 | ||
9e01e6d4 | 330 | /* Renders each pixmaps into on big drawable */ |
331 | void copy_pixmap_to_screen(ProcessList *process_list, | |
332 | GdkDrawable *dest, | |
333 | GdkGC *gc, | |
334 | gint x, gint y, | |
335 | gint width, gint height) | |
336 | { | |
337 | if(process_list->index_to_pixmap->len == 0) return; | |
338 | guint cell_height = process_list->cell_height; | |
339 | ||
340 | /* Get indexes */ | |
341 | gint begin = floor(y/(double)cell_height); | |
342 | gint end = MIN(ceil((y+height)/(double)cell_height), | |
343 | process_list->index_to_pixmap->len); | |
344 | gint i; | |
345 | ||
346 | for(i=begin; i<end; i++) { | |
347 | g_assert(i<process_list->index_to_pixmap->len); | |
348 | /* Render the pixmap to the screen */ | |
349 | GdkPixmap *pixmap = | |
350 | //(GdkPixmap*)g_ptr_array_index(process_list->index_to_pixmap, i); | |
351 | GDK_PIXMAP(g_ptr_array_index(process_list->index_to_pixmap, i)); | |
352 | ||
353 | gdk_draw_drawable (dest, | |
354 | gc, | |
355 | pixmap, | |
356 | x, 0, | |
357 | x, i*cell_height, | |
358 | width, cell_height); | |
359 | ||
360 | } | |
9e01e6d4 | 361 | } |
362 | ||
9e01e6d4 | 363 | ProcessList *processlist_construct(void) |
364 | { | |
365 | GtkTreeViewColumn *column; | |
366 | GtkCellRenderer *renderer; | |
367 | ||
368 | ProcessList* process_list = g_new(ProcessList,1); | |
369 | ||
370 | process_list->number_of_process = 0; | |
371 | ||
372 | process_list->current_hash_data = NULL; | |
373 | ||
374 | /* Create the Process list */ | |
67f72973 | 375 | process_list->list_store = gtk_tree_store_new ( N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER); |
9e01e6d4 | 376 | |
377 | process_list->process_list_widget = | |
378 | gtk_tree_view_new_with_model | |
379 | (GTK_TREE_MODEL (process_list->list_store)); | |
0dd8209a | 380 | g_object_set(process_list->process_list_widget, "enable-tree-lines", TRUE, NULL); |
9e01e6d4 | 381 | |
382 | g_object_unref (G_OBJECT (process_list->list_store)); | |
383 | ||
fb93b151 | 384 | gtk_tree_sortable_set_default_sort_func( |
385 | GTK_TREE_SORTABLE(process_list->list_store), | |
386 | resource_sort_func, | |
387 | NULL, | |
388 | NULL); | |
389 | ||
0dd8209a | 390 | |
fb93b151 | 391 | gtk_tree_sortable_set_sort_column_id( |
392 | GTK_TREE_SORTABLE(process_list->list_store), | |
393 | GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, | |
394 | GTK_SORT_ASCENDING); | |
9e01e6d4 | 395 | |
9e01e6d4 | 396 | gtk_tree_view_set_headers_visible( |
397 | GTK_TREE_VIEW(process_list->process_list_widget), TRUE); | |
398 | ||
399 | /* Create a column, associating the "text" attribute of the | |
400 | * cell_renderer to the first column of the model */ | |
401 | /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ | |
402 | renderer = gtk_cell_renderer_text_new (); | |
403 | process_list->renderer = renderer; | |
404 | ||
27274b95 | 405 | g_signal_connect(process_list->process_list_widget, "row-expanded", G_CALLBACK(expand_event), process_list); |
406 | g_signal_connect(process_list->process_list_widget, "row-collapsed", G_CALLBACK(collapse_event), process_list); | |
9e01e6d4 | 407 | |
53f78441 | 408 | /* Add a temporary row to the model to get the cell size when the first |
409 | * real process is added. */ | |
410 | GtkTreeIter iter; | |
411 | GtkTreePath *path; | |
412 | path = gtk_tree_path_new_first(); | |
413 | gtk_tree_model_get_iter (gtk_tree_view_get_model(GTK_TREE_VIEW( | |
414 | process_list->process_list_widget)), &iter, path); | |
415 | gtk_tree_store_append(process_list->list_store, &iter, NULL); | |
416 | gtk_tree_path_free(path); | |
417 | ||
418 | process_list->cell_height = 0; // not ready to get size yet. | |
9e01e6d4 | 419 | |
c4e6f4dc | 420 | column = gtk_tree_view_column_new_with_attributes ( "Resource", |
9e01e6d4 | 421 | renderer, |
422 | "text", | |
58a9b31b | 423 | NAME_COLUMN, |
9e01e6d4 | 424 | NULL); |
425 | gtk_tree_view_column_set_alignment (column, 0.0); | |
426 | gtk_tree_view_column_set_fixed_width (column, 45); | |
427 | gtk_tree_view_append_column ( | |
428 | GTK_TREE_VIEW (process_list->process_list_widget), column); | |
429 | ||
430 | process_list->button = column->button; | |
9e01e6d4 | 431 | |
432 | g_object_set_data_full( | |
433 | G_OBJECT(process_list->process_list_widget), | |
434 | "process_list_Data", | |
435 | process_list, | |
436 | (GDestroyNotify)processlist_destroy); | |
437 | ||
438 | process_list->index_to_pixmap = g_ptr_array_sized_new(ALLOCATE_PROCESSES); | |
67f72973 | 439 | |
440 | process_list->restypes[RV_RESOURCE_MACHINE].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); | |
441 | process_list->restypes[RV_RESOURCE_CPU].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); | |
442 | process_list->restypes[RV_RESOURCE_IRQ].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); | |
0305fe77 | 443 | process_list->restypes[RV_RESOURCE_SOFT_IRQ].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); |
38726a78 | 444 | process_list->restypes[RV_RESOURCE_TRAP].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); |
67f72973 | 445 | process_list->restypes[RV_RESOURCE_BDEV].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct); |
0dd8209a | 446 | |
9e01e6d4 | 447 | return process_list; |
448 | } | |
449 | ||
450 | void processlist_destroy(ProcessList *process_list) | |
451 | { | |
67f72973 | 452 | int i; |
453 | ||
9e01e6d4 | 454 | g_debug("processlist_destroy %p", process_list); |
67f72973 | 455 | |
456 | for(i=0; i<RV_RESOURCE_COUNT; i++) { | |
457 | g_hash_table_destroy(process_list->restypes[i].hash_table); | |
458 | process_list->restypes[i].hash_table = NULL; | |
459 | } | |
9e01e6d4 | 460 | g_ptr_array_free(process_list->index_to_pixmap, TRUE); |
461 | ||
462 | g_free(process_list); | |
463 | g_debug("processlist_destroy end"); | |
464 | } | |
465 | ||
67f72973 | 466 | static gboolean remove_hash_item(void *key, |
58a9b31b | 467 | HashedResourceData *hashed_process_data, |
9e01e6d4 | 468 | ProcessList *process_list) |
469 | { | |
470 | GtkTreeIter iter; | |
471 | ||
472 | iter = hashed_process_data->y_iter; | |
473 | ||
67f72973 | 474 | gtk_tree_store_remove (process_list->list_store, &iter); |
9e01e6d4 | 475 | gdk_pixmap_unref(hashed_process_data->pixmap); |
476 | ||
58a9b31b | 477 | // TODO pmf: check this; might be needed |
478 | // if(likely(process_list->current_hash_data != NULL)) { | |
479 | // if(likely(hashed_process_data == | |
480 | // process_list->current_hash_data[process_info->trace_num][process_info->cpu])) | |
481 | // process_list->current_hash_data[process_info->trace_num][process_info->cpu] = NULL; | |
482 | // } | |
9e01e6d4 | 483 | return TRUE; /* remove the element from the hash table */ |
484 | } | |
485 | ||
486 | void processlist_clear(ProcessList *process_list) | |
487 | { | |
67f72973 | 488 | int i; |
489 | ||
9e01e6d4 | 490 | g_info("processlist_clear %p", process_list); |
491 | ||
67f72973 | 492 | for(i=RV_RESOURCE_COUNT-1; i>=0; i--) { |
493 | g_hash_table_foreach_remove(process_list->restypes[i].hash_table, | |
494 | (GHRFunc)remove_hash_item, | |
495 | (gpointer)process_list); | |
496 | } | |
9e01e6d4 | 497 | process_list->number_of_process = 0; |
498 | update_index_to_pixmap(process_list); | |
499 | } | |
500 | ||
501 | ||
502 | GtkWidget *processlist_get_widget(ProcessList *process_list) | |
503 | { | |
504 | return process_list->process_list_widget; | |
505 | } | |
506 | ||
507 | ||
508 | void destroy_hash_key(gpointer key) | |
509 | { | |
510 | g_free(key); | |
511 | } | |
512 | ||
513 | void destroy_hash_data(gpointer data) | |
514 | { | |
515 | g_free(data); | |
516 | } | |
517 | ||
37b0f1ed | 518 | GQuark make_cpu_name(ControlFlowData *resourceview_data, guint trace_num, guint id) |
519 | { | |
520 | GQuark name; | |
521 | gchar *str; | |
522 | ||
523 | str = g_strdup_printf("CPU%u", id); | |
524 | name = g_quark_from_string(str); | |
525 | g_free(str); | |
526 | ||
527 | return name; | |
528 | } | |
529 | ||
530 | GQuark make_irq_name(ControlFlowData *resourceview_data, guint trace_num, guint id) | |
531 | { | |
532 | GQuark name; | |
533 | gchar *str; | |
534 | ||
535 | str = g_strdup_printf("IRQ %u", id); | |
536 | name = g_quark_from_string(str); | |
537 | g_free(str); | |
538 | ||
539 | return name; | |
540 | } | |
541 | ||
0305fe77 | 542 | GQuark make_soft_irq_name(ControlFlowData *resourceview_data, guint trace_num, guint id) |
543 | { | |
544 | GQuark name; | |
545 | gchar *str; | |
546 | ||
547 | str = g_strdup_printf("SOFTIRQ %u", id); | |
548 | name = g_quark_from_string(str); | |
549 | g_free(str); | |
550 | ||
551 | return name; | |
552 | } | |
553 | ||
38726a78 | 554 | GQuark make_trap_name(ControlFlowData *resourceview_data, guint trace_num, guint id) |
555 | { | |
556 | GQuark name; | |
557 | gchar *str; | |
558 | ||
559 | str = g_strdup_printf("Trap %u", id); | |
560 | name = g_quark_from_string(str); | |
561 | g_free(str); | |
562 | ||
563 | return name; | |
564 | } | |
565 | ||
37b0f1ed | 566 | GQuark make_bdev_name(ControlFlowData *resourceview_data, guint trace_num, guint id) |
567 | { | |
568 | GQuark name; | |
569 | gchar *str; | |
570 | ||
571 | str = g_strdup_printf("Block (%u,%u)", MAJOR(id), MINOR(id)); | |
572 | name = g_quark_from_string(str); | |
573 | g_free(str); | |
574 | ||
575 | return name; | |
576 | } | |
577 | ||
67f72973 | 578 | HashedResourceData *resourcelist_obtain_machine(ControlFlowData *resourceview_data, guint trace_num, guint id) |
9e01e6d4 | 579 | { |
67f72973 | 580 | ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1); |
581 | HashedResourceData *data = g_new(HashedResourceData, 1); | |
582 | ||
583 | /* Prepare hash key */ | |
584 | ru->trace_num = trace_num; | |
585 | ru->id = id; | |
586 | ||
587 | /* Search within hash table */ | |
588 | GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_MACHINE].hash_table; | |
589 | data = g_hash_table_lookup(ht, ru); | |
590 | ||
591 | /* If not found in hash table, add it */ | |
592 | if(data == NULL) { | |
593 | GQuark name; | |
594 | ||
595 | data = g_malloc(sizeof(HashedResourceData)); | |
596 | /* Prepare hashed data */ | |
597 | data->type = RV_RESOURCE_MACHINE; | |
598 | data->x.over = 0; | |
599 | data->x.over_used = FALSE; | |
600 | data->x.over_marked = FALSE; | |
601 | data->x.middle = 0; // last | |
602 | data->x.middle_used = FALSE; | |
603 | data->x.middle_marked = FALSE; | |
604 | data->x.under = 0; | |
605 | data->x.under_used = FALSE; | |
606 | data->x.under_marked = FALSE; | |
607 | data->next_good_time = ltt_time_zero; | |
27274b95 | 608 | data->hidden = 0; |
67f72973 | 609 | |
53f78441 | 610 | if (resourceview_data->process_list->cell_height == 0) { |
611 | GtkTreePath *path; | |
612 | GdkRectangle rect; | |
613 | GtkTreeIter iter; | |
614 | ||
615 | path = gtk_tree_path_new_first(); | |
616 | gtk_tree_model_get_iter(gtk_tree_view_get_model(GTK_TREE_VIEW( | |
617 | resourceview_data->process_list->process_list_widget)), | |
618 | &iter, path); | |
619 | gtk_tree_view_get_background_area(GTK_TREE_VIEW( | |
620 | resourceview_data->process_list->process_list_widget), | |
621 | path, NULL, &rect); | |
622 | gtk_tree_store_remove(resourceview_data->process_list->list_store, | |
623 | &iter); | |
624 | gtk_tree_path_free(path); | |
625 | resourceview_data->process_list->cell_height = rect.height; | |
626 | } | |
627 | ||
67f72973 | 628 | data->height = resourceview_data->process_list->cell_height; |
629 | data->pixmap = | |
630 | gdk_pixmap_new(resourceview_data->drawing->drawing_area->window, | |
631 | resourceview_data->drawing->alloc_width, | |
632 | data->height, | |
633 | -1); | |
634 | g_assert(data->pixmap); | |
58a9b31b | 635 | |
67f72973 | 636 | gdk_draw_rectangle (data->pixmap, |
637 | resourceview_data->drawing->drawing_area->style->black_gc, | |
638 | TRUE, | |
639 | 0, 0, | |
640 | resourceview_data->drawing->alloc_width, | |
641 | data->height); | |
642 | ||
643 | /* add to hash table */ | |
644 | g_hash_table_insert(ht, ru, data); | |
645 | resourceview_data->process_list->number_of_process++; // TODO: check | |
646 | ||
647 | /* add to process list */ | |
648 | { | |
649 | gchar *str; | |
650 | str = g_strdup_printf("Trace %u", id); | |
651 | name = g_quark_from_string(str); | |
652 | g_free(str); | |
653 | } | |
654 | ||
655 | gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, NULL); | |
656 | gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter, | |
657 | NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data, | |
658 | -1); | |
659 | ||
660 | update_index_to_pixmap(resourceview_data->process_list); | |
661 | ||
662 | int heightall = data->height * resourceview_data->process_list->number_of_process; | |
663 | ||
664 | gtk_widget_set_size_request(resourceview_data->drawing->drawing_area, | |
665 | -1, | |
666 | heightall); | |
9e01e6d4 | 667 | |
67f72973 | 668 | gtk_widget_queue_draw(resourceview_data->drawing->drawing_area); |
669 | } | |
670 | ||
27274b95 | 671 | /* expand the newly added machine */ |
672 | { | |
673 | GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget)); | |
674 | GtkTreePath *path; | |
675 | path = gtk_tree_model_get_path(model, &data->y_iter); | |
676 | ||
677 | gtk_tree_view_expand_row(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget), path, FALSE); | |
678 | ||
679 | gtk_tree_path_free(path); | |
680 | } | |
67f72973 | 681 | |
682 | return data; | |
683 | } | |
684 | ||
37b0f1ed | 685 | HashedResourceData *resourcelist_obtain_generic(ControlFlowData *resourceview_data, gint res_type, guint trace_num, guint id, GQuark (*make_name_func)(ControlFlowData *resourceview_data, guint trace_num, guint id)) |
67f72973 | 686 | { |
687 | ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1); | |
688 | HashedResourceData *data = g_new(HashedResourceData, 1); | |
9e01e6d4 | 689 | |
67f72973 | 690 | /* Prepare hash key */ |
27274b95 | 691 | ru->ru.type = &(resourceview_data->process_list->restypes[res_type]); |
67f72973 | 692 | ru->trace_num = trace_num; |
86f3d84b | 693 | g_assert(id != -1); |
67f72973 | 694 | ru->id = id; |
9e01e6d4 | 695 | |
67f72973 | 696 | /* Search within hash table */ |
37b0f1ed | 697 | GHashTable *ht = resourceview_data->process_list->restypes[res_type].hash_table; |
67f72973 | 698 | data = g_hash_table_lookup(ht, ru); |
699 | ||
700 | /* If not found in hash table, add it */ | |
701 | if(data == NULL) { | |
702 | GQuark name; | |
703 | HashedResourceData *parent; | |
704 | ||
705 | /* Find the parent machine */ | |
706 | parent = resourcelist_obtain_machine(resourceview_data, trace_num, trace_num); | |
707 | ||
708 | /* Prepare hashed data */ | |
709 | data = g_malloc(sizeof(HashedResourceData)); | |
710 | ||
37b0f1ed | 711 | data->type = res_type; |
67f72973 | 712 | data->x.over = 0; |
713 | data->x.over_used = FALSE; | |
714 | data->x.over_marked = FALSE; | |
715 | data->x.middle = 0; // last | |
716 | data->x.middle_used = FALSE; | |
717 | data->x.middle_marked = FALSE; | |
718 | data->x.under = 0; | |
719 | data->x.under_used = FALSE; | |
720 | data->x.under_marked = FALSE; | |
721 | data->next_good_time = ltt_time_zero; | |
722 | ||
53f78441 | 723 | if (resourceview_data->process_list->cell_height == 0) { |
724 | GtkTreePath *path; | |
725 | GdkRectangle rect; | |
726 | GtkTreeIter iter; | |
727 | ||
728 | path = gtk_tree_path_new_first(); | |
729 | gtk_tree_model_get_iter(gtk_tree_view_get_model(GTK_TREE_VIEW( | |
730 | resourceview_data->process_list->process_list_widget)), &iter, | |
731 | path); | |
732 | gtk_tree_view_get_background_area(GTK_TREE_VIEW( | |
733 | resourceview_data->process_list->process_list_widget), path, | |
734 | NULL, &rect); | |
735 | gtk_tree_store_remove(resourceview_data->process_list->list_store, | |
736 | &iter); | |
737 | gtk_tree_path_free(path); | |
738 | resourceview_data->process_list->cell_height = rect.height; | |
739 | } | |
740 | ||
67f72973 | 741 | data->height = resourceview_data->process_list->cell_height; |
742 | data->pixmap = | |
743 | gdk_pixmap_new(resourceview_data->drawing->drawing_area->window, | |
744 | resourceview_data->drawing->alloc_width, | |
745 | data->height, | |
746 | -1); | |
747 | ||
748 | gdk_draw_rectangle (data->pixmap, | |
749 | resourceview_data->drawing->drawing_area->style->black_gc, | |
750 | TRUE, | |
751 | 0, 0, | |
752 | resourceview_data->drawing->alloc_width, | |
753 | data->height); | |
9e01e6d4 | 754 | |
67f72973 | 755 | /* add to hash table */ |
756 | g_hash_table_insert(ht, ru, data); | |
757 | resourceview_data->process_list->number_of_process++; // TODO: check | |
9e01e6d4 | 758 | |
67f72973 | 759 | /* add to process list */ |
37b0f1ed | 760 | name = make_name_func(resourceview_data, trace_num, id); |
9e01e6d4 | 761 | |
67f72973 | 762 | gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, &parent->y_iter); |
763 | gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter, | |
764 | NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data, | |
765 | -1); | |
9e01e6d4 | 766 | |
27274b95 | 767 | /* Determine if we should add it hidden or not */ |
768 | { | |
27274b95 | 769 | GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget)); |
770 | GtkTreeIter parent_iter; | |
771 | ||
e865422c | 772 | gtk_tree_model_iter_parent(model, &parent_iter, &data->y_iter); |
27274b95 | 773 | GtkTreePath *path = gtk_tree_model_get_path(model, &parent_iter); |
774 | data->hidden = gtk_tree_view_row_expanded(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget), path)?0:1; | |
775 | gtk_tree_path_free(path); | |
776 | } | |
777 | ||
778 | ||
67f72973 | 779 | update_index_to_pixmap(resourceview_data->process_list); |
780 | ||
781 | int heightall = data->height * resourceview_data->process_list->number_of_process; | |
782 | ||
783 | gtk_widget_set_size_request(resourceview_data->drawing->drawing_area, | |
784 | -1, | |
785 | heightall); | |
786 | ||
787 | gtk_widget_queue_draw(resourceview_data->drawing->drawing_area); | |
788 | } | |
789 | ||
790 | return data; | |
791 | } | |
792 | ||
37b0f1ed | 793 | HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data, guint trace_num, guint id) |
67f72973 | 794 | { |
37b0f1ed | 795 | return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_CPU, trace_num, id, make_cpu_name); |
796 | } | |
67f72973 | 797 | |
37b0f1ed | 798 | HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data, guint trace_num, guint id) |
799 | { | |
800 | return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_IRQ, trace_num, id, make_irq_name); | |
67f72973 | 801 | } |
9e01e6d4 | 802 | |
0305fe77 | 803 | HashedResourceData *resourcelist_obtain_soft_irq(ControlFlowData *resourceview_data, guint trace_num, guint id) |
804 | { | |
805 | return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_SOFT_IRQ, trace_num, id, make_soft_irq_name); | |
806 | } | |
807 | ||
38726a78 | 808 | HashedResourceData *resourcelist_obtain_trap(ControlFlowData *resourceview_data, guint trace_num, guint id) |
809 | { | |
810 | return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_TRAP, trace_num, id, make_trap_name); | |
811 | } | |
812 | ||
67f72973 | 813 | HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data, guint trace_num, guint id) |
9e01e6d4 | 814 | { |
37b0f1ed | 815 | return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_BDEV, trace_num, id, make_bdev_name); |
9e01e6d4 | 816 | } |
37b0f1ed | 817 |