1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
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;
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.
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,
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
25 /* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
52 //#define PANGO_ENABLE_BACKEND
61 //#include <pango/pango.h>
63 #include <lttv/lttv.h>
64 #include <lttv/hook.h>
65 #include <lttv/state.h>
66 #include <lttvwindow/lttvwindow.h>
67 #include <lttvwindow/lttvwindowtraces.h>
68 #include <lttvwindow/support.h>
71 #include "eventhooks.h"
73 #include "processlist.h"
77 #define MAX_PATH_LEN 256
78 #define STATE_LINE_WIDTH 6
79 #define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
81 extern GSList
*g_legend_list
;
84 /* Action to do when background computation completed.
86 * Wait for all the awaited computations to be over.
89 static gint
background_ready(void *hook_data
, void *call_data
)
91 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
93 resourceview_data
->background_info_waiting
--;
95 if(resourceview_data
->background_info_waiting
== 0) {
96 g_message("control flow viewer : background computation data ready.");
98 drawing_clear(resourceview_data
->drawing
);
99 processlist_clear(resourceview_data
->process_list
);
100 gtk_widget_set_size_request(
101 resourceview_data
->drawing
->drawing_area
,
102 -1, processlist_get_height(resourceview_data
->process_list
));
103 redraw_notify(resourceview_data
, NULL
);
110 /* Request background computation. Verify if it is in progress or ready first.
111 * Only for each trace in the tab's traceset.
113 static void request_background_data(ControlFlowData
*resourceview_data
)
116 lttvwindow_get_traceset(resourceview_data
->tab
);
117 gint num_traces
= lttv_traceset_number(ts
);
120 LttvTraceState
*tstate
;
122 LttvHooks
*background_ready_hook
=
124 lttv_hooks_add(background_ready_hook
, background_ready
, resourceview_data
,
126 resourceview_data
->background_info_waiting
= 0;
128 for(i
=0;i
<num_traces
;i
++) {
129 trace
= lttv_traceset_get(ts
, i
);
131 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
132 && !ts
->has_precomputed_states
) {
134 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
136 /* We first remove requests that could have been done for the same
137 * information. Happens when two viewers ask for it before servicing
140 if(!lttvwindowtraces_background_request_find(trace
, "state"))
141 lttvwindowtraces_background_request_queue(
142 main_window_get_widget(resourceview_data
->tab
), trace
, "state");
143 lttvwindowtraces_background_notify_queue(resourceview_data
,
147 background_ready_hook
);
148 resourceview_data
->background_info_waiting
++;
149 } else { /* in progress */
151 lttvwindowtraces_background_notify_current(resourceview_data
,
155 background_ready_hook
);
156 resourceview_data
->background_info_waiting
++;
159 /* Data ready. By its nature, this viewer doesn't need to have
160 * its data ready hook called there, because a background
161 * request is always linked with a redraw.
166 lttv_hooks_destroy(background_ready_hook
);
171 * Event Viewer's constructor hook
173 * This constructor is given as a parameter to the menuitem and toolbar button
174 * registration. It creates the list.
175 * @param tab A pointer to the parent tab.
176 * @return The widget created.
179 h_resourceview(LttvPlugin
*plugin
)
181 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
182 Tab
*tab
= ptab
->tab
;
183 g_info("h_guicontrolflow, %p", tab
);
184 ControlFlowData
*resourceview_data
= resourceview(ptab
);
186 resourceview_data
->tab
= tab
;
188 // Unreg done in the GuiControlFlow_Destructor
189 lttvwindow_register_traceset_notify(tab
,
193 lttvwindow_register_time_window_notify(tab
,
194 update_time_window_hook
,
196 lttvwindow_register_current_time_notify(tab
,
197 update_current_time_hook
,
199 lttvwindow_register_redraw_notify(tab
,
202 lttvwindow_register_continue_notify(tab
,
205 request_background_data(resourceview_data
);
208 return guicontrolflow_get_widget(resourceview_data
) ;
212 void legend_destructor(GtkWindow
*legend
)
214 g_legend_list
= g_slist_remove(g_legend_list
, legend
);
217 /* Create a popup legend */
219 h_legend(LttvPlugin
*plugin
)
221 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
222 Tab
*tab
= ptab
->tab
;
223 g_info("h_legend, %p", tab
);
225 GtkWindow
*legend
= GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL
));
227 g_legend_list
= g_slist_append(
231 g_object_set_data_full(
235 (GDestroyNotify
)legend_destructor
);
237 gtk_window_set_title(legend
, "Control Flow View Legend");
239 GtkWidget
*pixmap
= create_pixmap(GTK_WIDGET(legend
), "lttv-color-list.png");
241 gtk_container_add(GTK_CONTAINER(legend
), GTK_WIDGET(pixmap
));
243 gtk_widget_show(GTK_WIDGET(pixmap
));
244 gtk_widget_show(GTK_WIDGET(legend
));
247 return NULL
; /* This is a popup window */
251 int event_selected_hook(void *hook_data
, void *call_data
)
253 guint
*event_number
= (guint
*) call_data
;
255 g_debug("DEBUG : event selected by main window : %u", *event_number
);
260 static void cpu_set_line_color(PropertiesLine
*prop_line
, LttvCPUState
*s
)
262 GQuark present_state
;
264 if(s
->mode_stack
->len
== 0)
265 present_state
= LTTV_CPU_UNKNOWN
;
267 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
269 if(present_state
== LTTV_CPU_IDLE
) {
270 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IDLE
];
272 else if(present_state
== LTTV_CPU_BUSY
) {
273 prop_line
->color
= drawing_colors_cpu
[COL_CPU_BUSY
];
275 else if(present_state
== LTTV_CPU_IRQ
) {
276 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IRQ
];
278 else if(present_state
== LTTV_CPU_SOFT_IRQ
) {
279 prop_line
->color
= drawing_colors_cpu
[COL_CPU_SOFT_IRQ
];
281 else if(present_state
== LTTV_CPU_TRAP
) {
282 prop_line
->color
= drawing_colors_cpu
[COL_CPU_TRAP
];
284 prop_line
->color
= drawing_colors_cpu
[COL_CPU_UNKNOWN
];
288 static void irq_set_line_color(PropertiesLine
*prop_line
, LttvIRQState
*s
)
290 GQuark present_state
;
291 if(s
->mode_stack
->len
== 0)
292 present_state
= LTTV_IRQ_UNKNOWN
;
294 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
296 if(present_state
== LTTV_IRQ_IDLE
) {
297 prop_line
->color
= drawing_colors_irq
[COL_IRQ_IDLE
];
299 else if(present_state
== LTTV_IRQ_BUSY
) {
300 prop_line
->color
= drawing_colors_irq
[COL_IRQ_BUSY
];
303 prop_line
->color
= drawing_colors_irq
[COL_IRQ_UNKNOWN
];
307 static void soft_irq_set_line_color(PropertiesLine
*prop_line
, LttvSoftIRQState
*s
)
310 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_BUSY
];
312 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_PENDING
];
314 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_IDLE
];
317 static void trap_set_line_color(PropertiesLine
*prop_line
, LttvTrapState
*s
)
320 prop_line
->color
= drawing_colors_trap
[COL_TRAP_IDLE
];
322 prop_line
->color
= drawing_colors_trap
[COL_TRAP_BUSY
];
325 static void bdev_set_line_color(PropertiesLine
*prop_line
, LttvBdevState
*s
)
327 GQuark present_state
;
328 if(s
== 0 || s
->mode_stack
->len
== 0)
329 present_state
= LTTV_BDEV_UNKNOWN
;
331 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
333 if(present_state
== LTTV_BDEV_IDLE
) {
334 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_IDLE
];
336 else if(present_state
== LTTV_BDEV_BUSY_READING
) {
337 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_BUSY_READING
];
339 else if(present_state
== LTTV_BDEV_BUSY_WRITING
) {
340 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_BUSY_WRITING
];
343 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_UNKNOWN
];
347 /* before_schedchange_hook
349 * This function basically draw lines and icons. Two types of lines are drawn :
350 * one small (3 pixels?) representing the state of the process and the second
351 * type is thicker (10 pixels?) representing on which CPU a process is running
352 * (and this only in running state).
354 * Extremums of the lines :
355 * x_min : time of the last event context for this process kept in memory.
356 * x_max : time of the current event.
357 * y : middle of the process in the process list. The process is found in the
358 * list, therefore is it's position in pixels.
360 * The choice of lines'color is defined by the context of the last event for this
365 int before_schedchange_hook(void *hook_data
, void *call_data
)
371 event
= (LttvEvent
*) call_data
;
372 if (strcmp(lttv_traceset_get_name_from_event(event
),"sched_switch") != 0)
375 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
377 LttTime evtime
= lttv_event_get_timestamp(event
);
379 /* we are in a schedchange, before the state update. We must draw the
380 * items corresponding to the state before it changes : now is the right
385 pid_out
= lttv_event_get_long(event
, "prev_tid");
386 // TODO: can't we reenable this? pmf
387 // if(pid_in != 0 && pid_out != 0) {
388 // /* not a transition to/from idle */
393 guint cpu
= lttv_traceset_get_cpuid_from_event(event
);
396 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
398 /* Add process to process list (if not present) */
399 HashedResourceData
*hashed_process_data
= NULL
;
401 hashed_process_data
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
403 /* Now, the process is in the state hash and our own process hash.
404 * We definitely can draw the items related to the ending state.
407 if(ltt_time_compare(hashed_process_data
->next_good_time
,
410 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
412 TimeWindow time_window
=
413 lttvwindow_get_time_window(resourceview_data
->tab
);
415 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
416 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
419 Drawing_t
*drawing
= resourceview_data
->drawing
;
420 guint width
= drawing
->width
;
422 convert_time_to_pixels(
428 /* Draw collision indicator */
429 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
430 gdk_draw_point(hashed_process_data
->pixmap
,
433 COLLISION_POSITION(hashed_process_data
->height
));
434 hashed_process_data
->x
.middle_marked
= TRUE
;
437 TimeWindow time_window
=
438 lttvwindow_get_time_window(resourceview_data
->tab
);
440 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
441 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
444 Drawing_t
*drawing
= resourceview_data
->drawing
;
445 guint width
= drawing
->width
;
447 convert_time_to_pixels(
453 /* Jump over draw if we are at the same x position */
454 if(x
== hashed_process_data
->x
.middle
&&
455 hashed_process_data
->x
.middle_used
)
457 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
458 /* Draw collision indicator */
459 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
460 gdk_draw_point(hashed_process_data
->pixmap
,
463 COLLISION_POSITION(hashed_process_data
->height
));
464 hashed_process_data
->x
.middle_marked
= TRUE
;
468 DrawContext draw_context
;
470 /* Now create the drawing context that will be used to draw
471 * items related to the last state. */
472 draw_context
.drawable
= hashed_process_data
->pixmap
;
473 draw_context
.gc
= drawing
->gc
;
474 draw_context
.pango_layout
= drawing
->pango_layout
;
475 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
476 draw_context
.drawinfo
.end
.x
= x
;
478 draw_context
.drawinfo
.y
.over
= 1;
479 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
480 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
482 draw_context
.drawinfo
.start
.offset
.over
= 0;
483 draw_context
.drawinfo
.start
.offset
.middle
= 0;
484 draw_context
.drawinfo
.start
.offset
.under
= 0;
485 draw_context
.drawinfo
.end
.offset
.over
= 0;
486 draw_context
.drawinfo
.end
.offset
.middle
= 0;
487 draw_context
.drawinfo
.end
.offset
.under
= 0;
491 //PropertiesLine prop_line = prepare_s_e_line(process);
492 PropertiesLine prop_line
;
493 prop_line
.line_width
= STATE_LINE_WIDTH
;
494 prop_line
.style
= GDK_LINE_SOLID
;
495 prop_line
.y
= MIDDLE
;
496 cpu_set_line_color(&prop_line
, &(ts
->cpu_states
[cpu
]));
497 draw_line((void*)&prop_line
, (void*)&draw_context
);
500 /* become the last x position */
501 hashed_process_data
->x
.middle
= x
;
502 hashed_process_data
->x
.middle_used
= TRUE
;
503 hashed_process_data
->x
.middle_marked
= FALSE
;
505 /* Calculate the next good time */
506 convert_pixels_to_time(width
, x
+1, time_window
,
507 &hashed_process_data
->next_good_time
);
514 /* after_schedchange_hook
516 * The draw after hook is called by the reading API to have a
517 * particular event drawn on the screen.
518 * @param hook_data ControlFlowData structure of the viewer.
519 * @param call_data Event context.
521 * This function adds items to be drawn in a queue for each process.
524 int after_schedchange_hook(void *hook_data
, void *call_data
)
528 event
= (LttvEvent
*) call_data
;
530 if (strcmp(lttv_traceset_get_name_from_event(event
),"sched_switch") != 0)
533 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
535 LttvTraceState
*ts
= event
->state
;
537 LttvFilter
*filter
= resourceview_data
->filter
;
538 if(filter
!= NULL
&& filter
->head
!= NULL
)
539 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
540 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
544 LttTime evtime
= lttv_event_get_timestamp(event
);
546 /* Add process to process list (if not present) */
547 LttvProcessState
*process_in
;
548 HashedResourceData
*hashed_process_data_in
= NULL
;
550 ProcessList
*process_list
= resourceview_data
->process_list
;
552 /* Find process pid_in in the list... */
553 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
554 //process_in = tfs->process;
555 guint cpu
= lttv_traceset_get_cpuid_from_event(event
);
556 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
557 process_in
= ts
->running_process
[cpu
];
558 /* It should exist, because we are after the state update. */
560 g_assert(process_in
!= NULL
);
563 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
564 hashed_process_data_in
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
566 /* Set the current process */
567 process_list
->current_hash_data
[trace_num
][process_in
->cpu
] =
568 hashed_process_data_in
;
570 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
573 TimeWindow time_window
=
574 lttvwindow_get_time_window(resourceview_data
->tab
);
577 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
578 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
581 Drawing_t
*drawing
= resourceview_data
->drawing
;
582 guint width
= drawing
->width
;
585 convert_time_to_pixels(
591 if(hashed_process_data_in
->x
.middle
!= new_x
) {
592 hashed_process_data_in
->x
.middle
= new_x
;
593 hashed_process_data_in
->x
.middle_used
= FALSE
;
594 hashed_process_data_in
->x
.middle_marked
= FALSE
;
600 int before_execmode_hook_irq(void *hook_data
, void *call_data
);
601 int before_execmode_hook_soft_irq(void *hook_data
, void *call_data
);
602 int before_execmode_hook_trap(void *hook_data
, void *call_data
);
604 /* before_execmode_hook
606 * This function basically draw lines and icons. Two types of lines are drawn :
607 * one small (3 pixels?) representing the state of the process and the second
608 * type is thicker (10 pixels?) representing on which CPU a process is running
609 * (and this only in running state).
611 * Extremums of the lines :
612 * x_min : time of the last event context for this process kept in memory.
613 * x_max : time of the current event.
614 * y : middle of the process in the process list. The process is found in the
615 * list, therefore is it's position in pixels.
617 * The choice of lines'color is defined by the context of the last event for this
621 int before_execmode_hook(void *hook_data
, void *call_data
)
627 LttvProcessState
*process
;
629 before_execmode_hook_irq(hook_data
, call_data
);
630 before_execmode_hook_soft_irq(hook_data
, call_data
);
632 before_execmode_hook_trap(hook_data
, call_data
);
634 /* we are in a execmode, before the state update. We must draw the
635 * items corresponding to the state before it changes : now is the right
638 event
= (LttvEvent
*) call_data
;
639 if ((strncmp(lttv_traceset_get_name_from_event(event
),"sys_", sizeof("sys_") - 1) == 0)
640 ||(strcmp(lttv_traceset_get_name_from_event(event
),"exit_syscall") == 0)
641 ||(strncmp(lttv_traceset_get_name_from_event(event
),"irq_handler_",sizeof("irq_handler_") -1) == 0)
642 ||(strncmp(lttv_traceset_get_name_from_event(event
),"softirq_", sizeof("softirq_") - 1) == 0)) {
644 LttTime evtime
= lttv_event_get_timestamp(event
);
645 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
648 LttvTraceset
*traceSet
= lttvwindow_get_traceset(resourceview_data
->tab
);
650 cpu
= lttv_traceset_get_cpuid_from_event(event
);
653 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
655 process
= ts
->running_process
[cpu
];
656 g_assert(process
!= NULL
);
658 /* Well, the process_out existed : we must get it in the process hash
659 * or add it, and draw its items.
661 /* Add process to process list (if not present) */
662 HashedResourceData
*hashed_process_data
= NULL
;
663 ProcessList
*process_list
= resourceview_data
->process_list
;
665 if(likely(process_list
->current_hash_data
[trace_num
][cpu
] != NULL
)) {
666 hashed_process_data
= process_list
->current_hash_data
[trace_num
][cpu
];
668 hashed_process_data
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
670 /* Set the current process */
671 process_list
->current_hash_data
[trace_num
][process
->cpu
] =
675 /* Now, the process is in the state hash and our own process hash.
676 * We definitely can draw the items related to the ending state.
679 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
682 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
683 TimeWindow time_window
=
684 lttvwindow_get_time_window(resourceview_data
->tab
);
687 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
688 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
691 Drawing_t
*drawing
= resourceview_data
->drawing
;
692 guint width
= drawing
->width
;
694 convert_time_to_pixels(
700 /* Draw collision indicator */
701 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
702 gdk_draw_point(hashed_process_data
->pixmap
,
705 COLLISION_POSITION(hashed_process_data
->height
));
706 hashed_process_data
->x
.middle_marked
= TRUE
;
710 TimeWindow time_window
=
711 lttvwindow_get_time_window(resourceview_data
->tab
);
714 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
715 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
718 Drawing_t
*drawing
= resourceview_data
->drawing
;
719 guint width
= drawing
->width
;
722 convert_time_to_pixels(
729 /* Jump over draw if we are at the same x position */
730 if(unlikely(x
== hashed_process_data
->x
.middle
&&
731 hashed_process_data
->x
.middle_used
))
733 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
734 /* Draw collision indicator */
735 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
736 gdk_draw_point(hashed_process_data
->pixmap
,
739 COLLISION_POSITION(hashed_process_data
->height
));
740 hashed_process_data
->x
.middle_marked
= TRUE
;
746 DrawContext draw_context
;
747 /* Now create the drawing context that will be used to draw
748 * items related to the last state. */
749 draw_context
.drawable
= hashed_process_data
->pixmap
;
750 draw_context
.gc
= drawing
->gc
;
751 draw_context
.pango_layout
= drawing
->pango_layout
;
752 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
753 draw_context
.drawinfo
.end
.x
= x
;
755 draw_context
.drawinfo
.y
.over
= 1;
756 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
757 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
759 draw_context
.drawinfo
.start
.offset
.over
= 0;
760 draw_context
.drawinfo
.start
.offset
.middle
= 0;
761 draw_context
.drawinfo
.start
.offset
.under
= 0;
762 draw_context
.drawinfo
.end
.offset
.over
= 0;
763 draw_context
.drawinfo
.end
.offset
.middle
= 0;
764 draw_context
.drawinfo
.end
.offset
.under
= 0;
768 PropertiesLine prop_line
;
769 prop_line
.line_width
= STATE_LINE_WIDTH
;
770 prop_line
.style
= GDK_LINE_SOLID
;
771 prop_line
.y
= MIDDLE
;
772 cpu_set_line_color(&prop_line
, &ts
->cpu_states
[cpu
]);
773 draw_line((void*)&prop_line
, (void*)&draw_context
);
775 /* become the last x position */
776 hashed_process_data
->x
.middle
= x
;
777 hashed_process_data
->x
.middle_used
= TRUE
;
778 hashed_process_data
->x
.middle_marked
= FALSE
;
780 /* Calculate the next good time */
781 convert_pixels_to_time(width
, x
+1, time_window
,
782 &hashed_process_data
->next_good_time
);
789 int before_execmode_hook_irq(void *hook_data
, void *call_data
)
793 event
= (LttvEvent
*) call_data
;
795 LttTime evtime
= lttv_event_get_timestamp(event
);
796 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
798 /* we are in a execmode, before the state update. We must draw the
799 * items corresponding to the state before it changes : now is the right
805 guint cpu
= lttv_traceset_get_cpuid_from_event(event
);
806 LttvTraceset
*traceSet
= lttvwindow_get_traceset(resourceview_data
->tab
);
807 LttvTraceState
*ts
= event
->state
;;
810 * Check for LTT_CHANNEL_KERNEL channel name and event ID
811 * corresponding to LTT_EVENT_IRQ_ENTRY or LTT_EVENT_IRQ_EXIT.
813 if (strncmp(lttv_traceset_get_name_from_event(event
),"irq_handler_entry",sizeof("irq_handler_entry")) == 0) {
814 irq
= lttv_event_get_long(event
, "irq");
815 } else if (strncmp(lttv_traceset_get_name_from_event(event
),"irq_handler_exit",sizeof("irq_handler_exit")) == 0) {
816 gint len
= ts
->cpu_states
[cpu
].irq_stack
->len
;
818 irq
= g_array_index(ts
->cpu_states
[cpu
].irq_stack
, gint
, len
-1);
826 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
828 /* Well, the process_out existed : we must get it in the process hash
829 * or add it, and draw its items.
831 /* Add process to process list (if not present) */
832 HashedResourceData
*hashed_process_data
= NULL
;
834 hashed_process_data
= resourcelist_obtain_irq(resourceview_data
, trace_num
, irq
);
835 // TODO: fix this, it's ugly and slow:
839 str
= g_strdup_printf("IRQ %" PRIu64
" [%s]", irq
,
840 (char*)g_quark_to_string(ts
->name_tables
->irq_names
[irq
]));
841 name
= g_quark_from_string(str
);
844 gtk_tree_store_set(resourceview_data
->process_list
->list_store
, &hashed_process_data
->y_iter
, NAME_COLUMN
, g_quark_to_string(name
), -1);
846 /* Now, the process is in the state hash and our own process hash.
847 * We definitely can draw the items related to the ending state.
850 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
853 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
854 TimeWindow time_window
=
855 lttvwindow_get_time_window(resourceview_data
->tab
);
858 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
859 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
862 Drawing_t
*drawing
= resourceview_data
->drawing
;
863 guint width
= drawing
->width
;
865 convert_time_to_pixels(
871 /* Draw collision indicator */
872 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
873 gdk_draw_point(hashed_process_data
->pixmap
,
876 COLLISION_POSITION(hashed_process_data
->height
));
877 hashed_process_data
->x
.middle_marked
= TRUE
;
881 TimeWindow time_window
=
882 lttvwindow_get_time_window(resourceview_data
->tab
);
885 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
886 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
889 Drawing_t
*drawing
= resourceview_data
->drawing
;
890 guint width
= drawing
->width
;
893 convert_time_to_pixels(
900 /* Jump over draw if we are at the same x position */
901 if(unlikely(x
== hashed_process_data
->x
.middle
&&
902 hashed_process_data
->x
.middle_used
))
904 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
905 /* Draw collision indicator */
906 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
907 gdk_draw_point(hashed_process_data
->pixmap
,
910 COLLISION_POSITION(hashed_process_data
->height
));
911 hashed_process_data
->x
.middle_marked
= TRUE
;
917 DrawContext draw_context
;
918 /* Now create the drawing context that will be used to draw
919 * items related to the last state. */
920 draw_context
.drawable
= hashed_process_data
->pixmap
;
921 draw_context
.gc
= drawing
->gc
;
922 draw_context
.pango_layout
= drawing
->pango_layout
;
923 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
924 draw_context
.drawinfo
.end
.x
= x
;
926 draw_context
.drawinfo
.y
.over
= 1;
927 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
928 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
930 draw_context
.drawinfo
.start
.offset
.over
= 0;
931 draw_context
.drawinfo
.start
.offset
.middle
= 0;
932 draw_context
.drawinfo
.start
.offset
.under
= 0;
933 draw_context
.drawinfo
.end
.offset
.over
= 0;
934 draw_context
.drawinfo
.end
.offset
.middle
= 0;
935 draw_context
.drawinfo
.end
.offset
.under
= 0;
939 PropertiesLine prop_line
;
940 prop_line
.line_width
= STATE_LINE_WIDTH
;
941 prop_line
.style
= GDK_LINE_SOLID
;
942 prop_line
.y
= MIDDLE
;
943 irq_set_line_color(&prop_line
, &ts
->irq_states
[irq
]);
944 draw_line((void*)&prop_line
, (void*)&draw_context
);
946 /* become the last x position */
947 hashed_process_data
->x
.middle
= x
;
948 hashed_process_data
->x
.middle_used
= TRUE
;
949 hashed_process_data
->x
.middle_marked
= FALSE
;
951 /* Calculate the next good time */
952 convert_pixels_to_time(width
, x
+1, time_window
,
953 &hashed_process_data
->next_good_time
);
960 int before_execmode_hook_soft_irq(void *hook_data
, void *call_data
)
966 event
= (LttvEvent
*) call_data
;
971 /* we are in a execmode, before the state update. We must draw the
972 * items corresponding to the state before it changes : now is the right
981 * Check for LTT_CHANNEL_KERNEL channel name and event ID
982 * corresponding to LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY
983 * or LTT_EVENT_SOFT_IRQ_EXIT.
986 if (strncmp(lttv_traceset_get_name_from_event(event
),"softirq_entry",sizeof("softirq_entry")) == 0
987 || strncmp(lttv_traceset_get_name_from_event(event
),"softirq_raise",sizeof("softirq_raise")) == 0
988 || strncmp(lttv_traceset_get_name_from_event(event
),"softirq_exit",sizeof("softirq_exit")) == 0 ) {
990 softirq
= lttv_event_get_long_unsigned(event
, "vec");
996 LttTime evtime
= lttv_event_get_timestamp(event
);
997 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
998 LttvTraceset
*traceSet
= lttvwindow_get_traceset(resourceview_data
->tab
);
999 guint cpu
= lttv_traceset_get_cpuid_from_event(event
);
1001 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
1003 /* Well, the process_out existed : we must get it in the process hash
1004 * or add it, and draw its items.
1006 /* Add process to process list (if not present) */
1007 HashedResourceData
*hashed_process_data
= NULL
;
1009 hashed_process_data
= resourcelist_obtain_soft_irq(resourceview_data
, trace_num
, softirq
);
1011 /* Now, the process is in the state hash and our own process hash.
1012 * We definitely can draw the items related to the ending state.
1015 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1018 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1019 TimeWindow time_window
=
1020 lttvwindow_get_time_window(resourceview_data
->tab
);
1023 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1024 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1026 #endif //EXTRA_CHECK
1027 Drawing_t
*drawing
= resourceview_data
->drawing
;
1028 guint width
= drawing
->width
;
1030 convert_time_to_pixels(
1036 /* Draw collision indicator */
1037 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1038 gdk_draw_point(hashed_process_data
->pixmap
,
1041 COLLISION_POSITION(hashed_process_data
->height
));
1042 hashed_process_data
->x
.middle_marked
= TRUE
;
1046 TimeWindow time_window
=
1047 lttvwindow_get_time_window(resourceview_data
->tab
);
1050 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1051 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1053 #endif //EXTRA_CHECK
1054 Drawing_t
*drawing
= resourceview_data
->drawing
;
1055 guint width
= drawing
->width
;
1058 convert_time_to_pixels(
1065 /* Jump over draw if we are at the same x position */
1066 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1067 hashed_process_data
->x
.middle_used
))
1069 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1070 /* Draw collision indicator */
1071 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1072 gdk_draw_point(hashed_process_data
->pixmap
,
1075 COLLISION_POSITION(hashed_process_data
->height
));
1076 hashed_process_data
->x
.middle_marked
= TRUE
;
1082 DrawContext draw_context
;
1083 /* Now create the drawing context that will be used to draw
1084 * items related to the last state. */
1085 draw_context
.drawable
= hashed_process_data
->pixmap
;
1086 draw_context
.gc
= drawing
->gc
;
1087 draw_context
.pango_layout
= drawing
->pango_layout
;
1088 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1089 draw_context
.drawinfo
.end
.x
= x
;
1091 draw_context
.drawinfo
.y
.over
= 1;
1092 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1093 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1095 draw_context
.drawinfo
.start
.offset
.over
= 0;
1096 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1097 draw_context
.drawinfo
.start
.offset
.under
= 0;
1098 draw_context
.drawinfo
.end
.offset
.over
= 0;
1099 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1100 draw_context
.drawinfo
.end
.offset
.under
= 0;
1104 PropertiesLine prop_line
;
1105 prop_line
.line_width
= STATE_LINE_WIDTH
;
1106 prop_line
.style
= GDK_LINE_SOLID
;
1107 prop_line
.y
= MIDDLE
;
1108 soft_irq_set_line_color(&prop_line
, &ts
->soft_irq_states
[softirq
]);
1109 draw_line((void*)&prop_line
, (void*)&draw_context
);
1111 /* become the last x position */
1112 hashed_process_data
->x
.middle
= x
;
1113 hashed_process_data
->x
.middle_used
= TRUE
;
1114 hashed_process_data
->x
.middle_marked
= FALSE
;
1116 /* Calculate the next good time */
1117 convert_pixels_to_time(width
, x
+1, time_window
,
1118 &hashed_process_data
->next_good_time
);
1124 #ifdef TRAP_NO_EXIST
1125 int before_execmode_hook_trap(void *hook_data
, void *call_data
)
1127 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
1128 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
1129 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
1131 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1133 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1134 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1135 struct marker_info
*minfo
;
1138 e
= ltt_tracefile_get_event(tfc
->tf
);
1140 LttTime evtime
= ltt_event_time(e
);
1142 /* we are in a execmode, before the state update. We must draw the
1143 * items corresponding to the state before it changes : now is the right
1149 guint cpu
= tfs
->cpu
;
1152 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1153 * corresponding to LTT_EVENT_TRAP/PAGE_FAULT_ENTRY or
1154 * LTT_EVENT_TRAP/PAGE_FAULT_EXIT.
1156 if (tfc
->tf
->name
!= LTT_CHANNEL_KERNEL
)
1158 minfo
= marker_get_info_from_id(tfc
->tf
->mdata
, e
->event_id
);
1159 g_assert(minfo
!= NULL
);
1160 if (minfo
->name
== LTT_EVENT_TRAP_ENTRY
1161 || minfo
->name
== LTT_EVENT_PAGE_FAULT_ENTRY
1162 || minfo
->name
== LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
) {
1163 trap
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
1164 } else if (minfo
->name
== LTT_EVENT_TRAP_EXIT
1165 || minfo
->name
== LTT_EVENT_PAGE_FAULT_EXIT
1166 || minfo
->name
== LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
) {
1167 gint len
= ts
->cpu_states
[cpu
].trap_stack
->len
;
1169 trap
= g_array_index(ts
->cpu_states
[cpu
].trap_stack
, gint
, len
-1);
1177 guint trace_num
= ts
->parent
.index
;
1179 /* Well, the process_out existed : we must get it in the process hash
1180 * or add it, and draw its items.
1182 /* Add process to process list (if not present) */
1183 HashedResourceData
*hashed_process_data
= NULL
;
1185 hashed_process_data
= resourcelist_obtain_trap(resourceview_data
, trace_num
, trap
);
1187 /* Now, the process is in the state hash and our own process hash.
1188 * We definitely can draw the items related to the ending state.
1191 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1194 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1195 TimeWindow time_window
=
1196 lttvwindow_get_time_window(resourceview_data
->tab
);
1199 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1200 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1202 #endif //EXTRA_CHECK
1203 Drawing_t
*drawing
= resourceview_data
->drawing
;
1204 guint width
= drawing
->width
;
1206 convert_time_to_pixels(
1212 /* Draw collision indicator */
1213 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1214 gdk_draw_point(hashed_process_data
->pixmap
,
1217 COLLISION_POSITION(hashed_process_data
->height
));
1218 hashed_process_data
->x
.middle_marked
= TRUE
;
1222 TimeWindow time_window
=
1223 lttvwindow_get_time_window(resourceview_data
->tab
);
1226 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1227 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1229 #endif //EXTRA_CHECK
1230 Drawing_t
*drawing
= resourceview_data
->drawing
;
1231 guint width
= drawing
->width
;
1234 convert_time_to_pixels(
1241 /* Jump over draw if we are at the same x position */
1242 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1243 hashed_process_data
->x
.middle_used
))
1245 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1246 /* Draw collision indicator */
1247 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1248 gdk_draw_point(hashed_process_data
->pixmap
,
1251 COLLISION_POSITION(hashed_process_data
->height
));
1252 hashed_process_data
->x
.middle_marked
= TRUE
;
1258 DrawContext draw_context
;
1259 /* Now create the drawing context that will be used to draw
1260 * items related to the last state. */
1261 draw_context
.drawable
= hashed_process_data
->pixmap
;
1262 draw_context
.gc
= drawing
->gc
;
1263 draw_context
.pango_layout
= drawing
->pango_layout
;
1264 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1265 draw_context
.drawinfo
.end
.x
= x
;
1267 draw_context
.drawinfo
.y
.over
= 1;
1268 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1269 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1271 draw_context
.drawinfo
.start
.offset
.over
= 0;
1272 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1273 draw_context
.drawinfo
.start
.offset
.under
= 0;
1274 draw_context
.drawinfo
.end
.offset
.over
= 0;
1275 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1276 draw_context
.drawinfo
.end
.offset
.under
= 0;
1280 PropertiesLine prop_line
;
1281 prop_line
.line_width
= STATE_LINE_WIDTH
;
1282 prop_line
.style
= GDK_LINE_SOLID
;
1283 prop_line
.y
= MIDDLE
;
1284 trap_set_line_color(&prop_line
, &ts
->trap_states
[trap
]);
1285 draw_line((void*)&prop_line
, (void*)&draw_context
);
1287 /* become the last x position */
1288 hashed_process_data
->x
.middle
= x
;
1289 hashed_process_data
->x
.middle_used
= TRUE
;
1290 hashed_process_data
->x
.middle_marked
= FALSE
;
1292 /* Calculate the next good time */
1293 convert_pixels_to_time(width
, x
+1, time_window
,
1294 &hashed_process_data
->next_good_time
);
1301 #ifdef BABEL_CLEANUP
1302 //TODO investigate the use of block dev resource
1303 int before_bdev_event_hook(void *hook_data
, void *call_data
)
1309 LttvProcessState
*process
;
1312 /* we are in a execmode, before the state update. We must draw the
1313 * items corresponding to the state before it changes : now is the right
1317 event
= (LttvEvent
*) call_data
;
1318 if (strcmp(lttv_traceset_get_name_from_event(event
),"block_rq_issue") != 0 && strcmp(lttv_traceset_get_name_from_event(event
),"block_rq_complete") != 0)
1322 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1324 LttvTraceState
*ts
= event
->state
;
1327 guint8 major
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
1328 guint8 minor
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
1329 gint devcode_gint
= MKDEV(major
,minor
);
1331 guint trace_num
= lttv_traceset_get_trace_index_from_event(event
);
1333 LttvBdevState
*bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1334 /* the result of the lookup might be NULL. that's ok, the rest of the function
1335 should understand it was not found and that its state is unknown */
1337 /* Well, the process_out existed : we must get it in the process hash
1338 * or add it, and draw its items.
1340 /* Add process to process list (if not present) */
1341 HashedResourceData
*hashed_process_data
= NULL
;
1342 // LttTime birth = process->creation_time;
1344 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1345 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1347 hashed_process_data
= resourcelist_obtain_bdev(resourceview_data
, trace_num
, devcode_gint
);
1348 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
1349 // hashed_process_data = processlist_get_process_data(process_list,
1355 /* Set the current process */
1356 // process_list->current_hash_data[trace_num][process->cpu] =
1357 // hashed_process_data;
1360 /* Now, the process is in the state hash and our own process hash.
1361 * We definitely can draw the items related to the ending state.
1364 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1367 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1368 TimeWindow time_window
=
1369 lttvwindow_get_time_window(resourceview_data
->tab
);
1372 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1373 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1375 #endif //EXTRA_CHECK
1376 Drawing_t
*drawing
= resourceview_data
->drawing
;
1377 guint width
= drawing
->width
;
1379 convert_time_to_pixels(
1385 /* Draw collision indicator */
1386 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1387 gdk_draw_point(hashed_process_data
->pixmap
,
1390 COLLISION_POSITION(hashed_process_data
->height
));
1391 hashed_process_data
->x
.middle_marked
= TRUE
;
1395 TimeWindow time_window
=
1396 lttvwindow_get_time_window(resourceview_data
->tab
);
1399 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1400 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1402 #endif //EXTRA_CHECK
1403 Drawing_t
*drawing
= resourceview_data
->drawing
;
1404 guint width
= drawing
->width
;
1407 convert_time_to_pixels(
1414 /* Jump over draw if we are at the same x position */
1415 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1416 hashed_process_data
->x
.middle_used
))
1418 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1419 /* Draw collision indicator */
1420 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1421 gdk_draw_point(hashed_process_data
->pixmap
,
1424 COLLISION_POSITION(hashed_process_data
->height
));
1425 hashed_process_data
->x
.middle_marked
= TRUE
;
1431 DrawContext draw_context
;
1432 /* Now create the drawing context that will be used to draw
1433 * items related to the last state. */
1434 draw_context
.drawable
= hashed_process_data
->pixmap
;
1435 draw_context
.gc
= drawing
->gc
;
1436 draw_context
.pango_layout
= drawing
->pango_layout
;
1437 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1438 draw_context
.drawinfo
.end
.x
= x
;
1440 draw_context
.drawinfo
.y
.over
= 1;
1441 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1442 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1444 draw_context
.drawinfo
.start
.offset
.over
= 0;
1445 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1446 draw_context
.drawinfo
.start
.offset
.under
= 0;
1447 draw_context
.drawinfo
.end
.offset
.over
= 0;
1448 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1449 draw_context
.drawinfo
.end
.offset
.under
= 0;
1453 PropertiesLine prop_line
;
1454 prop_line
.line_width
= STATE_LINE_WIDTH
;
1455 prop_line
.style
= GDK_LINE_SOLID
;
1456 prop_line
.y
= MIDDLE
;
1457 bdev_set_line_color(&prop_line
, bdev
);
1458 draw_line((void*)&prop_line
, (void*)&draw_context
);
1460 /* become the last x position */
1461 hashed_process_data
->x
.middle
= x
;
1462 hashed_process_data
->x
.middle_used
= TRUE
;
1463 hashed_process_data
->x
.middle_marked
= FALSE
;
1465 /* Calculate the next good time */
1466 convert_pixels_to_time(width
, x
+1, time_window
,
1467 &hashed_process_data
->next_good_time
);
1474 gint
update_time_window_hook(void *hook_data
, void *call_data
)
1476 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1477 Drawing_t
*drawing
= resourceview_data
->drawing
;
1478 ProcessList
*process_list
= resourceview_data
->process_list
;
1480 const TimeWindowNotifyData
*time_window_nofify_data
=
1481 ((const TimeWindowNotifyData
*)call_data
);
1483 TimeWindow
*old_time_window
=
1484 time_window_nofify_data
->old_time_window
;
1485 TimeWindow
*new_time_window
=
1486 time_window_nofify_data
->new_time_window
;
1488 /* Update the ruler */
1489 drawing_update_ruler(resourceview_data
->drawing
,
1493 /* Two cases : zoom in/out or scrolling */
1495 /* In order to make sure we can reuse the old drawing, the scale must
1496 * be the same and the new time interval being partly located in the
1497 * currently shown time interval. (reuse is only for scrolling)
1500 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1501 old_time_window
->start_time
.tv_sec
,
1502 old_time_window
->start_time
.tv_nsec
,
1503 old_time_window
->time_width
.tv_sec
,
1504 old_time_window
->time_width
.tv_nsec
);
1506 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1507 new_time_window
->start_time
.tv_sec
,
1508 new_time_window
->start_time
.tv_nsec
,
1509 new_time_window
->time_width
.tv_sec
,
1510 new_time_window
->time_width
.tv_nsec
);
1512 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
1513 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
1515 /* Same scale (scrolling) */
1516 g_info("scrolling");
1517 LttTime
*ns
= &new_time_window
->start_time
;
1518 LttTime
*os
= &old_time_window
->start_time
;
1519 LttTime old_end
= old_time_window
->end_time
;
1520 LttTime new_end
= new_time_window
->end_time
;
1522 //if(ns<os+w && os+w<ns+w)
1523 //if(ns<old_end && os<ns)
1524 if(ltt_time_compare(*ns
, old_end
) == -1
1525 && ltt_time_compare(*os
, *ns
) == -1)
1527 g_info("scrolling near right");
1528 /* Scroll right, keep right part of the screen */
1530 guint width
= resourceview_data
->drawing
->width
;
1531 convert_time_to_pixels(
1537 /* Copy old data to new location */
1538 copy_pixmap_region(process_list
,
1540 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1544 resourceview_data
->drawing
->width
-x
+SAFETY
, -1);
1546 if(drawing
->damage_begin
== drawing
->damage_end
)
1547 drawing
->damage_begin
= resourceview_data
->drawing
->width
-x
;
1549 drawing
->damage_begin
= 0;
1551 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1553 /* Clear the data request background, but not SAFETY */
1554 rectangle_pixmap(process_list
,
1555 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1557 drawing
->damage_begin
+SAFETY
, 0,
1558 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
1560 gtk_widget_queue_draw(drawing
->drawing_area
);
1562 /* Get new data for the rest. */
1563 drawing_data_request(resourceview_data
->drawing
,
1564 drawing
->damage_begin
, 0,
1565 drawing
->damage_end
- drawing
->damage_begin
,
1566 resourceview_data
->drawing
->height
);
1568 if(ltt_time_compare(*ns
,*os
) == -1
1569 && ltt_time_compare(*os
,new_end
) == -1)
1571 g_info("scrolling near left");
1572 /* Scroll left, keep left part of the screen */
1574 guint width
= resourceview_data
->drawing
->width
;
1575 convert_time_to_pixels(
1581 /* Copy old data to new location */
1582 copy_pixmap_region (process_list
,
1584 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1590 if(drawing
->damage_begin
== drawing
->damage_end
)
1591 drawing
->damage_end
= x
;
1593 drawing
->damage_end
=
1594 resourceview_data
->drawing
->width
;
1596 drawing
->damage_begin
= 0;
1598 rectangle_pixmap (process_list
,
1599 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1601 drawing
->damage_begin
, 0,
1602 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
1605 gtk_widget_queue_draw(drawing
->drawing_area
);
1607 /* Get new data for the rest. */
1608 drawing_data_request(resourceview_data
->drawing
,
1609 drawing
->damage_begin
, 0,
1610 drawing
->damage_end
- drawing
->damage_begin
,
1611 resourceview_data
->drawing
->height
);
1614 if(ltt_time_compare(*ns
,*os
) == 0)
1616 g_info("not scrolling");
1618 g_info("scrolling far");
1619 /* Cannot reuse any part of the screen : far jump */
1622 rectangle_pixmap (process_list
,
1623 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1626 resourceview_data
->drawing
->width
+SAFETY
, // do not overlap
1629 gtk_widget_queue_draw(drawing
->drawing_area
);
1631 drawing
->damage_begin
= 0;
1632 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1634 drawing_data_request(resourceview_data
->drawing
,
1636 resourceview_data
->drawing
->width
,
1637 resourceview_data
->drawing
->height
);
1643 /* Different scale (zoom) */
1646 rectangle_pixmap (process_list
,
1647 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1650 resourceview_data
->drawing
->width
+SAFETY
, // do not overlap
1653 gtk_widget_queue_draw(drawing
->drawing_area
);
1655 drawing
->damage_begin
= 0;
1656 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1658 drawing_data_request(resourceview_data
->drawing
,
1660 resourceview_data
->drawing
->width
,
1661 resourceview_data
->drawing
->height
);
1664 /* Update directly when scrolling */
1665 gdk_window_process_updates(resourceview_data
->drawing
->drawing_area
->window
,
1671 gint
traceset_notify(void *hook_data
, void *call_data
)
1673 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1674 Drawing_t
*drawing
= resourceview_data
->drawing
;
1676 if(unlikely(drawing
->gc
== NULL
)) {
1679 if(drawing
->dotted_gc
== NULL
) {
1683 drawing_clear(resourceview_data
->drawing
);
1684 processlist_clear(resourceview_data
->process_list
);
1685 gtk_widget_set_size_request(
1686 resourceview_data
->drawing
->drawing_area
,
1687 -1, processlist_get_height(resourceview_data
->process_list
));
1688 redraw_notify(resourceview_data
, NULL
);
1690 request_background_data(resourceview_data
);
1695 gint
redraw_notify(void *hook_data
, void *call_data
)
1697 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1698 Drawing_t
*drawing
= resourceview_data
->drawing
;
1699 GtkWidget
*widget
= drawing
->drawing_area
;
1701 drawing
->damage_begin
= 0;
1702 drawing
->damage_end
= drawing
->width
;
1704 /* fun feature, to be separated someday... */
1705 drawing_clear(resourceview_data
->drawing
);
1706 processlist_clear(resourceview_data
->process_list
);
1707 gtk_widget_set_size_request(
1708 resourceview_data
->drawing
->drawing_area
,
1709 -1, processlist_get_height(resourceview_data
->process_list
));
1711 rectangle_pixmap (resourceview_data
->process_list
,
1712 widget
->style
->black_gc
,
1715 drawing
->alloc_width
,
1718 gtk_widget_queue_draw(drawing
->drawing_area
);
1720 if(drawing
->damage_begin
< drawing
->damage_end
)
1722 drawing_data_request(drawing
,
1723 drawing
->damage_begin
,
1725 drawing
->damage_end
-drawing
->damage_begin
,
1734 gint
continue_notify(void *hook_data
, void *call_data
)
1736 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1737 Drawing_t
*drawing
= resourceview_data
->drawing
;
1739 if(drawing
->damage_begin
< drawing
->damage_end
)
1741 drawing_data_request(drawing
,
1742 drawing
->damage_begin
,
1744 drawing
->damage_end
-drawing
->damage_begin
,
1752 gint
update_current_time_hook(void *hook_data
, void *call_data
)
1754 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
1756 LttTime current_time
= *((LttTime
*)call_data
);
1758 TimeWindow time_window
=
1759 lttvwindow_get_time_window(resourceview_data
->tab
);
1761 LttTime time_begin
= time_window
.start_time
;
1762 LttTime width
= time_window
.time_width
;
1765 guint64 time_ll
= ltt_time_to_uint64(width
);
1766 time_ll
= time_ll
>> 1; /* divide by two */
1767 half_width
= ltt_time_from_uint64(time_ll
);
1769 LttTime time_end
= ltt_time_add(time_begin
, width
);
1771 LttvTraceset
* ts
= lttvwindow_get_traceset(resourceview_data
->tab
);
1773 TimeInterval time_span
= lttv_traceset_get_time_span_real(ts
);
1774 LttTime trace_start
= time_span
.start_time
;
1775 LttTime trace_end
= time_span
.end_time
;
1777 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
1778 current_time
.tv_nsec
);
1780 /* If current time is inside time interval, just move the highlight
1783 /* Else, we have to change the time interval. We have to tell it
1784 * to the main window. */
1785 /* The time interval change will take care of placing the current
1786 * time at the center of the visible area, or nearest possible if we are
1787 * at one end of the trace. */
1790 if(ltt_time_compare(current_time
, time_begin
) < 0)
1792 TimeWindow new_time_window
;
1794 if(ltt_time_compare(current_time
,
1795 ltt_time_add(trace_start
,half_width
)) < 0)
1796 time_begin
= trace_start
;
1798 time_begin
= ltt_time_sub(current_time
,half_width
);
1800 new_time_window
.start_time
= time_begin
;
1801 new_time_window
.time_width
= width
;
1802 new_time_window
.time_width_double
= ltt_time_to_double(width
);
1803 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
1805 lttvwindow_report_time_window(resourceview_data
->tab
, new_time_window
);
1807 else if(ltt_time_compare(current_time
, time_end
) > 0)
1809 TimeWindow new_time_window
;
1811 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
1812 time_begin
= ltt_time_sub(trace_end
,width
);
1814 time_begin
= ltt_time_sub(current_time
,half_width
);
1816 new_time_window
.start_time
= time_begin
;
1817 new_time_window
.time_width
= width
;
1818 new_time_window
.time_width_double
= ltt_time_to_double(width
);
1819 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
1821 lttvwindow_report_time_window(resourceview_data
->tab
, new_time_window
);
1824 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
1826 /* Update directly when scrolling */
1827 gdk_window_process_updates(resourceview_data
->drawing
->drawing_area
->window
,
1833 typedef struct _ClosureData
{
1834 EventsRequest
*events_request
;
1839 /* Draw line until end of the screen */
1841 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
1843 ResourceUniqueNumeric
*process_info
= (ResourceUniqueNumeric
*)key
;
1844 HashedResourceData
*hashed_process_data
= (HashedResourceData
*)value
;
1845 ClosureData
*closure_data
= (ClosureData
*)user_data
;
1847 EventsRequest
*events_request
= closure_data
->events_request
;
1848 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
1849 LttvTraceset
*ts
= lttvwindow_get_traceset(resourceview_data
->tab
);
1851 LttTime evtime
= closure_data
->end_time
;
1853 gboolean dodraw
= TRUE
;
1855 if(hashed_process_data
->type
== RV_RESOURCE_MACHINE
)
1859 /* For the process */
1860 /* First, check if the current process is in the state computation
1861 * process list. If it is there, that means we must add it right now and
1862 * draw items from the beginning of the read for it. If it is not
1863 * present, it's a new process and it was not present : it will
1864 * be added after the state update. */
1866 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
1867 #endif //EXTRA_CHECK
1869 LttvTrace
*trace
= lttv_traceset_get(ts
,process_info
->trace_num
);
1870 LttvTraceState
*ts
= trace
->state
;
1872 /* Only draw for processes that are currently in the trace states */
1875 /* Should be alike when background info is ready */
1876 if(resourceview_data
->background_info_waiting
==0)
1877 g_assert(ltt_time_compare(process
->creation_time
,
1878 process_info
->birth
) == 0);
1879 #endif //EXTRA_CHECK
1881 /* Now, the process is in the state hash and our own process hash.
1882 * We definitely can draw the items related to the ending state.
1885 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
1888 TimeWindow time_window
=
1889 lttvwindow_get_time_window(resourceview_data
->tab
);
1892 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1893 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1895 #endif //EXTRA_CHECK
1896 Drawing_t
*drawing
= resourceview_data
->drawing
;
1897 guint width
= drawing
->width
;
1899 guint x
= closure_data
->x_end
;
1901 DrawContext draw_context
;
1903 /* Now create the drawing context that will be used to draw
1904 * items related to the last state. */
1905 draw_context
.drawable
= hashed_process_data
->pixmap
;
1906 draw_context
.gc
= drawing
->gc
;
1907 draw_context
.pango_layout
= drawing
->pango_layout
;
1908 draw_context
.drawinfo
.end
.x
= x
;
1910 draw_context
.drawinfo
.y
.over
= 1;
1911 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1912 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1914 draw_context
.drawinfo
.start
.offset
.over
= 0;
1915 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1916 draw_context
.drawinfo
.start
.offset
.under
= 0;
1917 draw_context
.drawinfo
.end
.offset
.over
= 0;
1918 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1919 draw_context
.drawinfo
.end
.offset
.under
= 0;
1921 /* Jump over draw if we are at the same x position */
1922 if(x
== hashed_process_data
->x
.over
)
1926 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
1928 PropertiesLine prop_line
= prepare_execmode_line(process
);
1929 draw_line((void*)&prop_line
, (void*)&draw_context
);
1931 hashed_process_data
->x
.over
= x
;
1935 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1936 hashed_process_data
->x
.middle_used
)) {
1937 #if 0 /* do not mark closure : not missing information */
1938 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
1939 /* Draw collision indicator */
1940 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1941 gdk_draw_point(drawing
->pixmap
,
1945 hashed_process_data
->x
.middle_marked
= TRUE
;
1950 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1953 PropertiesLine prop_line
;
1954 prop_line
.line_width
= STATE_LINE_WIDTH
;
1955 prop_line
.style
= GDK_LINE_SOLID
;
1956 prop_line
.y
= MIDDLE
;
1957 if(hashed_process_data
->type
== RV_RESOURCE_CPU
)
1958 cpu_set_line_color(&prop_line
, &ts
->cpu_states
[process_info
->id
]);
1959 else if(hashed_process_data
->type
== RV_RESOURCE_IRQ
)
1960 irq_set_line_color(&prop_line
, &ts
->irq_states
[process_info
->id
]);
1961 else if(hashed_process_data
->type
== RV_RESOURCE_SOFT_IRQ
)
1962 soft_irq_set_line_color(&prop_line
, &ts
->soft_irq_states
[process_info
->id
]);
1963 else if(hashed_process_data
->type
== RV_RESOURCE_TRAP
)
1964 trap_set_line_color(&prop_line
, &ts
->trap_states
[process_info
->id
]);
1965 else if(hashed_process_data
->type
== RV_RESOURCE_BDEV
) {
1966 gint devcode_gint
= process_info
->id
;
1967 LttvBdevState
*bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1968 // the lookup may return null; bdev_set_line_color must act appropriately
1969 bdev_set_line_color(&prop_line
, bdev
);
1972 draw_line((void*)&prop_line
, (void*)&draw_context
);
1975 /* become the last x position */
1976 if(likely(x
!= hashed_process_data
->x
.middle
)) {
1977 hashed_process_data
->x
.middle
= x
;
1978 /* but don't use the pixel */
1979 hashed_process_data
->x
.middle_used
= FALSE
;
1981 /* Calculate the next good time */
1982 convert_pixels_to_time(width
, x
+1, time_window
,
1983 &hashed_process_data
->next_good_time
);
1990 int before_chunk(void *hook_data
, void *call_data
)
1992 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1993 LttvTraceset
*ts
= (LttvTraceset
*)call_data
;
1996 /* Deactivate sort */
1997 gtk_tree_sortable_set_sort_column_id(
1998 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
2000 GTK_SORT_ASCENDING
);
2002 drawing_chunk_begin(events_request
, ts
);
2009 * This gets executed just before an events request is executed
2012 int before_request(void *hook_data
, void *call_data
)
2014 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2016 drawing_data_request_begin(events_request
);
2021 void draw_closing_lines(ControlFlowData
*resourceview_data
,
2022 EventsRequest
* events_request
)
2024 LttTime end_time
= events_request
->end_time
;
2025 ClosureData closure_data
;
2026 closure_data
.events_request
= events_request
;
2027 closure_data
.end_time
= end_time
;
2030 TimeWindow time_window
=
2031 lttvwindow_get_time_window(resourceview_data
->tab
);
2032 guint width
= resourceview_data
->drawing
->width
;
2033 convert_time_to_pixels(
2037 &closure_data
.x_end
);
2040 /* Draw last items */
2041 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
2042 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data
, i
), draw_closure
,
2043 (void*)&closure_data
);
2046 /* Request expose */
2047 drawing_request_expose(events_request
, end_time
);
2051 * after request is necessary in addition of after chunk in order to draw
2052 * lines until the end of the screen. after chunk just draws lines until
2059 int after_request(void *hook_data
, void *call_data
)
2062 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2063 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
2065 draw_closing_lines(resourceview_data
, events_request
);
2075 int after_chunk(void *hook_data
, void *call_data
)
2077 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2078 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
2079 LttvTraceset
*ts
= (LttvTraceset
*)call_data
;
2083 ProcessList
*process_list
= resourceview_data
->process_list
;
2085 guint nb_trace
= lttv_traceset_number(ts
);
2087 /* Only execute when called for the first trace's events request */
2088 if(!process_list
->current_hash_data
)
2091 for(i
= 0 ; i
< nb_trace
; i
++) {
2092 g_free(process_list
->current_hash_data
[i
]);
2094 g_free(process_list
->current_hash_data
);
2095 process_list
->current_hash_data
= NULL
;
2096 #ifdef BABEL_CLEANUP
2098 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
2099 else /* end of traceset, or position now out of request : end */
2100 end_time
= events_request
->end_time
;
2102 draw_closing_lines(resourceview_data
, events_request
);
2107 /* after_statedump_end
2109 * @param hook_data ControlFlowData structure of the viewer.
2110 * @param call_data Event context.
2112 * This function adds items to be drawn in a queue for each process.
2115 int before_statedump_end(void *hook_data
, void *call_data
)
2119 event
= (LttvEvent
*) call_data
;
2121 if (strcmp(lttv_traceset_get_name_from_event(event
),"lttng_statedump_end") != 0)
2124 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
2127 LttvTraceState
*ts
= event
->state
;
2132 #ifdef BABEL_CLEANUP
2134 LttvFilter
*filter
= resourceview_data
->filter
;
2135 if(filter
!= NULL
&& filter
->head
!= NULL
)
2136 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
2137 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
2141 LttTime evtime
= lttv_event_get_timestamp(event
);
2143 ClosureData closure_data
;
2144 //TODO ybrosseau 2013-03-27: Fake and event_request.
2145 // We need to change the API of drawing_request_expose to ask
2146 // For and control flow data only.
2147 EventsRequest events_request
;
2148 events_request
.viewer_data
= resourceview_data
;
2149 closure_data
.events_request
= &events_request
;
2150 closure_data
.end_time
= evtime
;
2152 TimeWindow time_window
=
2153 lttvwindow_get_time_window(resourceview_data
->tab
);
2154 guint width
= resourceview_data
->drawing
->width
;
2155 convert_time_to_pixels(
2159 &closure_data
.x_end
);
2161 /* Draw last items */
2163 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
2164 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data
, i
), draw_closure
,
2165 (void*)&closure_data
);
2168 /* Reactivate sort */
2169 gtk_tree_sortable_set_sort_column_id(
2170 GTK_TREE_SORTABLE(resourceview_data
->process_list
->list_store
),
2171 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2172 GTK_SORT_ASCENDING
);
2174 update_index_to_pixmap(resourceview_data
->process_list
);
2175 /* Request a full expose : drawing scrambled */
2176 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
2178 /* Request expose (updates damages zone also) */
2179 drawing_request_expose(&events_request
, evtime
);