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 <ltt/event.h>
65 #include <ltt/trace.h>
67 #include <lttv/lttv.h>
68 #include <lttv/hook.h>
69 #include <lttv/state.h>
70 #include <lttvwindow/lttvwindow.h>
71 #include <lttvwindow/lttvwindowtraces.h>
72 #include <lttvwindow/support.h>
75 #include "eventhooks.h"
77 #include "processlist.h"
81 #define MAX_PATH_LEN 256
82 #define STATE_LINE_WIDTH 6
83 #define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
85 extern GSList
*g_legend_list
;
88 /* Action to do when background computation completed.
90 * Wait for all the awaited computations to be over.
93 static gint
background_ready(void *hook_data
, void *call_data
)
95 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
97 resourceview_data
->background_info_waiting
--;
99 if(resourceview_data
->background_info_waiting
== 0) {
100 g_message("control flow viewer : background computation data ready.");
102 drawing_clear(resourceview_data
->drawing
);
103 processlist_clear(resourceview_data
->process_list
);
104 gtk_widget_set_size_request(
105 resourceview_data
->drawing
->drawing_area
,
106 -1, processlist_get_height(resourceview_data
->process_list
));
107 redraw_notify(resourceview_data
, NULL
);
114 /* Request background computation. Verify if it is in progress or ready first.
115 * Only for each trace in the tab's traceset.
117 static void request_background_data(ControlFlowData
*resourceview_data
)
119 LttvTracesetContext
* tsc
=
120 lttvwindow_get_traceset_context(resourceview_data
->tab
);
121 gint num_traces
= lttv_traceset_number(tsc
->ts
);
124 LttvTraceState
*tstate
;
126 LttvHooks
*background_ready_hook
=
128 lttv_hooks_add(background_ready_hook
, background_ready
, resourceview_data
,
130 resourceview_data
->background_info_waiting
= 0;
132 for(i
=0;i
<num_traces
;i
++) {
133 trace
= lttv_traceset_get(tsc
->ts
, i
);
134 tstate
= LTTV_TRACE_STATE(tsc
->traces
[i
]);
136 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
137 && !tstate
->has_precomputed_states
) {
139 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
141 /* We first remove requests that could have been done for the same
142 * information. Happens when two viewers ask for it before servicing
145 if(!lttvwindowtraces_background_request_find(trace
, "state"))
146 lttvwindowtraces_background_request_queue(
147 main_window_get_widget(resourceview_data
->tab
), trace
, "state");
148 lttvwindowtraces_background_notify_queue(resourceview_data
,
152 background_ready_hook
);
153 resourceview_data
->background_info_waiting
++;
154 } else { /* in progress */
156 lttvwindowtraces_background_notify_current(resourceview_data
,
160 background_ready_hook
);
161 resourceview_data
->background_info_waiting
++;
164 /* Data ready. By its nature, this viewer doesn't need to have
165 * its data ready hook called there, because a background
166 * request is always linked with a redraw.
171 lttv_hooks_destroy(background_ready_hook
);
176 * Event Viewer's constructor hook
178 * This constructor is given as a parameter to the menuitem and toolbar button
179 * registration. It creates the list.
180 * @param tab A pointer to the parent tab.
181 * @return The widget created.
184 h_resourceview(LttvPlugin
*plugin
)
186 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
187 Tab
*tab
= ptab
->tab
;
188 g_info("h_guicontrolflow, %p", tab
);
189 ControlFlowData
*resourceview_data
= resourceview(ptab
);
191 resourceview_data
->tab
= tab
;
193 // Unreg done in the GuiControlFlow_Destructor
194 lttvwindow_register_traceset_notify(tab
,
198 lttvwindow_register_time_window_notify(tab
,
199 update_time_window_hook
,
201 lttvwindow_register_current_time_notify(tab
,
202 update_current_time_hook
,
204 lttvwindow_register_redraw_notify(tab
,
207 lttvwindow_register_continue_notify(tab
,
210 request_background_data(resourceview_data
);
213 return guicontrolflow_get_widget(resourceview_data
) ;
217 void legend_destructor(GtkWindow
*legend
)
219 g_legend_list
= g_slist_remove(g_legend_list
, legend
);
222 /* Create a popup legend */
224 h_legend(LttvPlugin
*plugin
)
226 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
227 Tab
*tab
= ptab
->tab
;
228 g_info("h_legend, %p", tab
);
230 GtkWindow
*legend
= GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL
));
232 g_legend_list
= g_slist_append(
236 g_object_set_data_full(
240 (GDestroyNotify
)legend_destructor
);
242 gtk_window_set_title(legend
, "Control Flow View Legend");
244 GtkWidget
*pixmap
= create_pixmap(GTK_WIDGET(legend
), "lttv-color-list.png");
246 gtk_container_add(GTK_CONTAINER(legend
), GTK_WIDGET(pixmap
));
248 gtk_widget_show(GTK_WIDGET(pixmap
));
249 gtk_widget_show(GTK_WIDGET(legend
));
252 return NULL
; /* This is a popup window */
256 int event_selected_hook(void *hook_data
, void *call_data
)
258 guint
*event_number
= (guint
*) call_data
;
260 g_debug("DEBUG : event selected by main window : %u", *event_number
);
265 static void cpu_set_line_color(PropertiesLine
*prop_line
, LttvCPUState
*s
)
267 GQuark present_state
;
269 if(s
->mode_stack
->len
== 0)
270 present_state
= LTTV_CPU_UNKNOWN
;
272 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
274 if(present_state
== LTTV_CPU_IDLE
) {
275 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IDLE
];
277 else if(present_state
== LTTV_CPU_BUSY
) {
278 prop_line
->color
= drawing_colors_cpu
[COL_CPU_BUSY
];
280 else if(present_state
== LTTV_CPU_IRQ
) {
281 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IRQ
];
283 else if(present_state
== LTTV_CPU_SOFT_IRQ
) {
284 prop_line
->color
= drawing_colors_cpu
[COL_CPU_SOFT_IRQ
];
286 else if(present_state
== LTTV_CPU_TRAP
) {
287 prop_line
->color
= drawing_colors_cpu
[COL_CPU_TRAP
];
289 prop_line
->color
= drawing_colors_cpu
[COL_CPU_UNKNOWN
];
293 static void irq_set_line_color(PropertiesLine
*prop_line
, LttvIRQState
*s
)
295 GQuark present_state
;
296 if(s
->mode_stack
->len
== 0)
297 present_state
= LTTV_IRQ_UNKNOWN
;
299 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
301 if(present_state
== LTTV_IRQ_IDLE
) {
302 prop_line
->color
= drawing_colors_irq
[COL_IRQ_IDLE
];
304 else if(present_state
== LTTV_IRQ_BUSY
) {
305 prop_line
->color
= drawing_colors_irq
[COL_IRQ_BUSY
];
308 prop_line
->color
= drawing_colors_irq
[COL_IRQ_UNKNOWN
];
312 static void soft_irq_set_line_color(PropertiesLine
*prop_line
, LttvSoftIRQState
*s
)
315 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_BUSY
];
317 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_PENDING
];
319 prop_line
->color
= drawing_colors_soft_irq
[COL_SOFT_IRQ_IDLE
];
322 static void trap_set_line_color(PropertiesLine
*prop_line
, LttvTrapState
*s
)
325 prop_line
->color
= drawing_colors_trap
[COL_TRAP_IDLE
];
327 prop_line
->color
= drawing_colors_trap
[COL_TRAP_BUSY
];
330 static void bdev_set_line_color(PropertiesLine
*prop_line
, LttvBdevState
*s
)
332 GQuark present_state
;
333 if(s
== 0 || s
->mode_stack
->len
== 0)
334 present_state
= LTTV_BDEV_UNKNOWN
;
336 present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
338 if(present_state
== LTTV_BDEV_IDLE
) {
339 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_IDLE
];
341 else if(present_state
== LTTV_BDEV_BUSY_READING
) {
342 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_BUSY_READING
];
344 else if(present_state
== LTTV_BDEV_BUSY_WRITING
) {
345 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_BUSY_WRITING
];
348 prop_line
->color
= drawing_colors_bdev
[COL_BDEV_UNKNOWN
];
352 /* before_schedchange_hook
354 * This function basically draw lines and icons. Two types of lines are drawn :
355 * one small (3 pixels?) representing the state of the process and the second
356 * type is thicker (10 pixels?) representing on which CPU a process is running
357 * (and this only in running state).
359 * Extremums of the lines :
360 * x_min : time of the last event context for this process kept in memory.
361 * x_max : time of the current event.
362 * y : middle of the process in the process list. The process is found in the
363 * list, therefore is it's position in pixels.
365 * The choice of lines'color is defined by the context of the last event for this
370 int before_schedchange_hook(void *hook_data
, void *call_data
)
372 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
373 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
374 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
376 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
378 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
379 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
382 e
= ltt_tracefile_get_event(tfc
->tf
);
384 LttTime evtime
= ltt_event_time(e
);
386 /* we are in a schedchange, before the state update. We must draw the
387 * items corresponding to the state before it changes : now is the right
392 pid_out
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
393 // TODO: can't we reenable this? pmf
394 // if(pid_in != 0 && pid_out != 0) {
395 // /* not a transition to/from idle */
399 tfc
->target_pid
= pid_out
;
401 guint cpu
= tfs
->cpu
;
403 guint trace_num
= ts
->parent
.index
;
404 /* Add process to process list (if not present) */
405 HashedResourceData
*hashed_process_data
= NULL
;
407 hashed_process_data
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
409 /* Now, the process is in the state hash and our own process hash.
410 * We definitely can draw the items related to the ending state.
413 if(ltt_time_compare(hashed_process_data
->next_good_time
,
416 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
418 TimeWindow time_window
=
419 lttvwindow_get_time_window(resourceview_data
->tab
);
421 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
422 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
425 Drawing_t
*drawing
= resourceview_data
->drawing
;
426 guint width
= drawing
->width
;
428 convert_time_to_pixels(
434 /* Draw collision indicator */
435 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
436 gdk_draw_point(hashed_process_data
->pixmap
,
439 COLLISION_POSITION(hashed_process_data
->height
));
440 hashed_process_data
->x
.middle_marked
= TRUE
;
443 TimeWindow time_window
=
444 lttvwindow_get_time_window(resourceview_data
->tab
);
446 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
447 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
450 Drawing_t
*drawing
= resourceview_data
->drawing
;
451 guint width
= drawing
->width
;
453 convert_time_to_pixels(
459 /* Jump over draw if we are at the same x position */
460 if(x
== hashed_process_data
->x
.middle
&&
461 hashed_process_data
->x
.middle_used
)
463 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
464 /* Draw collision indicator */
465 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
466 gdk_draw_point(hashed_process_data
->pixmap
,
469 COLLISION_POSITION(hashed_process_data
->height
));
470 hashed_process_data
->x
.middle_marked
= TRUE
;
474 DrawContext draw_context
;
476 /* Now create the drawing context that will be used to draw
477 * items related to the last state. */
478 draw_context
.drawable
= hashed_process_data
->pixmap
;
479 draw_context
.gc
= drawing
->gc
;
480 draw_context
.pango_layout
= drawing
->pango_layout
;
481 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
482 draw_context
.drawinfo
.end
.x
= x
;
484 draw_context
.drawinfo
.y
.over
= 1;
485 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
486 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
488 draw_context
.drawinfo
.start
.offset
.over
= 0;
489 draw_context
.drawinfo
.start
.offset
.middle
= 0;
490 draw_context
.drawinfo
.start
.offset
.under
= 0;
491 draw_context
.drawinfo
.end
.offset
.over
= 0;
492 draw_context
.drawinfo
.end
.offset
.middle
= 0;
493 draw_context
.drawinfo
.end
.offset
.under
= 0;
497 //PropertiesLine prop_line = prepare_s_e_line(process);
498 PropertiesLine prop_line
;
499 prop_line
.line_width
= STATE_LINE_WIDTH
;
500 prop_line
.style
= GDK_LINE_SOLID
;
501 prop_line
.y
= MIDDLE
;
502 cpu_set_line_color(&prop_line
, tfs
->cpu_state
);
503 draw_line((void*)&prop_line
, (void*)&draw_context
);
506 /* become the last x position */
507 hashed_process_data
->x
.middle
= x
;
508 hashed_process_data
->x
.middle_used
= TRUE
;
509 hashed_process_data
->x
.middle_marked
= FALSE
;
511 /* Calculate the next good time */
512 convert_pixels_to_time(width
, x
+1, time_window
,
513 &hashed_process_data
->next_good_time
);
520 /* after_schedchange_hook
522 * The draw after hook is called by the reading API to have a
523 * particular event drawn on the screen.
524 * @param hook_data ControlFlowData structure of the viewer.
525 * @param call_data Event context.
527 * This function adds items to be drawn in a queue for each process.
530 int after_schedchange_hook(void *hook_data
, void *call_data
)
532 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
533 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
534 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
535 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
536 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
537 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
540 e
= ltt_tracefile_get_event(tfc
->tf
);
542 LttvFilter
*filter
= resourceview_data
->filter
;
543 if(filter
!= NULL
&& filter
->head
!= NULL
)
544 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
545 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
548 LttTime evtime
= ltt_event_time(e
);
550 /* Add process to process list (if not present) */
551 LttvProcessState
*process_in
;
552 HashedResourceData
*hashed_process_data_in
= NULL
;
554 ProcessList
*process_list
= resourceview_data
->process_list
;
556 /* Find process pid_in in the list... */
557 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
558 //process_in = tfs->process;
559 guint cpu
= tfs
->cpu
;
560 guint trace_num
= ts
->parent
.index
;
561 process_in
= ts
->running_process
[cpu
];
562 /* It should exist, because we are after the state update. */
564 g_assert(process_in
!= NULL
);
567 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
568 hashed_process_data_in
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
570 /* Set the current process */
571 process_list
->current_hash_data
[trace_num
][process_in
->cpu
] =
572 hashed_process_data_in
;
574 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
577 TimeWindow time_window
=
578 lttvwindow_get_time_window(resourceview_data
->tab
);
581 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
582 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
585 Drawing_t
*drawing
= resourceview_data
->drawing
;
586 guint width
= drawing
->width
;
589 convert_time_to_pixels(
595 if(hashed_process_data_in
->x
.middle
!= new_x
) {
596 hashed_process_data_in
->x
.middle
= new_x
;
597 hashed_process_data_in
->x
.middle_used
= FALSE
;
598 hashed_process_data_in
->x
.middle_marked
= FALSE
;
604 int before_execmode_hook_irq(void *hook_data
, void *call_data
);
605 int before_execmode_hook_soft_irq(void *hook_data
, void *call_data
);
606 int before_execmode_hook_trap(void *hook_data
, void *call_data
);
608 /* before_execmode_hook
610 * This function basically draw lines and icons. Two types of lines are drawn :
611 * one small (3 pixels?) representing the state of the process and the second
612 * type is thicker (10 pixels?) representing on which CPU a process is running
613 * (and this only in running state).
615 * Extremums of the lines :
616 * x_min : time of the last event context for this process kept in memory.
617 * x_max : time of the current event.
618 * y : middle of the process in the process list. The process is found in the
619 * list, therefore is it's position in pixels.
621 * The choice of lines'color is defined by the context of the last event for this
625 int before_execmode_hook(void *hook_data
, void *call_data
)
627 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
628 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
629 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
631 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
633 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
634 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
637 e
= ltt_tracefile_get_event(tfc
->tf
);
639 LttTime evtime
= ltt_event_time(e
);
641 before_execmode_hook_irq(hook_data
, call_data
);
642 before_execmode_hook_soft_irq(hook_data
, call_data
);
643 before_execmode_hook_trap(hook_data
, call_data
);
645 /* we are in a execmode, before the state update. We must draw the
646 * items corresponding to the state before it changes : now is the right
650 guint cpu
= tfs
->cpu
;
652 guint trace_num
= ts
->parent
.index
;
653 LttvProcessState
*process
= ts
->running_process
[cpu
];
654 g_assert(process
!= NULL
);
656 /* Well, the process_out existed : we must get it in the process hash
657 * or add it, and draw its items.
659 /* Add process to process list (if not present) */
660 HashedResourceData
*hashed_process_data
= NULL
;
661 ProcessList
*process_list
= resourceview_data
->process_list
;
663 if(likely(process_list
->current_hash_data
[trace_num
][cpu
] != NULL
)) {
664 hashed_process_data
= process_list
->current_hash_data
[trace_num
][cpu
];
666 hashed_process_data
= resourcelist_obtain_cpu(resourceview_data
, trace_num
, cpu
);
668 /* Set the current process */
669 process_list
->current_hash_data
[trace_num
][process
->cpu
] =
673 /* Now, the process is in the state hash and our own process hash.
674 * We definitely can draw the items related to the ending state.
677 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
680 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
681 TimeWindow time_window
=
682 lttvwindow_get_time_window(resourceview_data
->tab
);
685 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
686 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
689 Drawing_t
*drawing
= resourceview_data
->drawing
;
690 guint width
= drawing
->width
;
692 convert_time_to_pixels(
698 /* Draw collision indicator */
699 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
700 gdk_draw_point(hashed_process_data
->pixmap
,
703 COLLISION_POSITION(hashed_process_data
->height
));
704 hashed_process_data
->x
.middle_marked
= TRUE
;
708 TimeWindow time_window
=
709 lttvwindow_get_time_window(resourceview_data
->tab
);
712 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
713 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
716 Drawing_t
*drawing
= resourceview_data
->drawing
;
717 guint width
= drawing
->width
;
720 convert_time_to_pixels(
727 /* Jump over draw if we are at the same x position */
728 if(unlikely(x
== hashed_process_data
->x
.middle
&&
729 hashed_process_data
->x
.middle_used
))
731 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
732 /* Draw collision indicator */
733 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
734 gdk_draw_point(hashed_process_data
->pixmap
,
737 COLLISION_POSITION(hashed_process_data
->height
));
738 hashed_process_data
->x
.middle_marked
= TRUE
;
744 DrawContext draw_context
;
745 /* Now create the drawing context that will be used to draw
746 * items related to the last state. */
747 draw_context
.drawable
= hashed_process_data
->pixmap
;
748 draw_context
.gc
= drawing
->gc
;
749 draw_context
.pango_layout
= drawing
->pango_layout
;
750 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
751 draw_context
.drawinfo
.end
.x
= x
;
753 draw_context
.drawinfo
.y
.over
= 1;
754 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
755 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
757 draw_context
.drawinfo
.start
.offset
.over
= 0;
758 draw_context
.drawinfo
.start
.offset
.middle
= 0;
759 draw_context
.drawinfo
.start
.offset
.under
= 0;
760 draw_context
.drawinfo
.end
.offset
.over
= 0;
761 draw_context
.drawinfo
.end
.offset
.middle
= 0;
762 draw_context
.drawinfo
.end
.offset
.under
= 0;
766 PropertiesLine prop_line
;
767 prop_line
.line_width
= STATE_LINE_WIDTH
;
768 prop_line
.style
= GDK_LINE_SOLID
;
769 prop_line
.y
= MIDDLE
;
770 cpu_set_line_color(&prop_line
, tfs
->cpu_state
);
771 draw_line((void*)&prop_line
, (void*)&draw_context
);
773 /* become the last x position */
774 hashed_process_data
->x
.middle
= x
;
775 hashed_process_data
->x
.middle_used
= TRUE
;
776 hashed_process_data
->x
.middle_marked
= FALSE
;
778 /* Calculate the next good time */
779 convert_pixels_to_time(width
, x
+1, time_window
,
780 &hashed_process_data
->next_good_time
);
787 int before_execmode_hook_irq(void *hook_data
, void *call_data
)
789 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
790 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
791 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
793 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
795 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
796 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
797 struct marker_info
*minfo
;
800 e
= ltt_tracefile_get_event(tfc
->tf
);
802 LttTime evtime
= ltt_event_time(e
);
804 /* we are in a execmode, before the state update. We must draw the
805 * items corresponding to the state before it changes : now is the right
811 guint cpu
= tfs
->cpu
;
814 * Check for LTT_CHANNEL_KERNEL channel name and event ID
815 * corresponding to LTT_EVENT_IRQ_ENTRY or LTT_EVENT_IRQ_EXIT.
817 if (tfc
->tf
->name
!= LTT_CHANNEL_KERNEL
)
819 minfo
= marker_get_info_from_id(tfc
->tf
->mdata
, e
->event_id
);
820 g_assert(minfo
!= NULL
);
821 if (minfo
->name
== LTT_EVENT_IRQ_ENTRY
) {
822 irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
823 } else if (minfo
->name
== LTT_EVENT_IRQ_EXIT
) {
824 gint len
= ts
->cpu_states
[cpu
].irq_stack
->len
;
826 irq
= g_array_index(ts
->cpu_states
[cpu
].irq_stack
, gint
, len
-1);
834 guint trace_num
= ts
->parent
.index
;
836 /* Well, the process_out existed : we must get it in the process hash
837 * or add it, and draw its items.
839 /* Add process to process list (if not present) */
840 HashedResourceData
*hashed_process_data
= NULL
;
842 hashed_process_data
= resourcelist_obtain_irq(resourceview_data
, trace_num
, irq
);
843 // TODO: fix this, it's ugly and slow:
847 str
= g_strdup_printf("IRQ %" PRIu64
" [%s]", irq
,
848 (char*)g_quark_to_string(ts
->name_tables
->irq_names
[irq
]));
849 name
= g_quark_from_string(str
);
852 gtk_tree_store_set(resourceview_data
->process_list
->list_store
, &hashed_process_data
->y_iter
, NAME_COLUMN
, g_quark_to_string(name
), -1);
854 /* Now, the process is in the state hash and our own process hash.
855 * We definitely can draw the items related to the ending state.
858 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
861 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
862 TimeWindow time_window
=
863 lttvwindow_get_time_window(resourceview_data
->tab
);
866 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
867 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
870 Drawing_t
*drawing
= resourceview_data
->drawing
;
871 guint width
= drawing
->width
;
873 convert_time_to_pixels(
879 /* Draw collision indicator */
880 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
881 gdk_draw_point(hashed_process_data
->pixmap
,
884 COLLISION_POSITION(hashed_process_data
->height
));
885 hashed_process_data
->x
.middle_marked
= TRUE
;
889 TimeWindow time_window
=
890 lttvwindow_get_time_window(resourceview_data
->tab
);
893 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
894 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
897 Drawing_t
*drawing
= resourceview_data
->drawing
;
898 guint width
= drawing
->width
;
901 convert_time_to_pixels(
908 /* Jump over draw if we are at the same x position */
909 if(unlikely(x
== hashed_process_data
->x
.middle
&&
910 hashed_process_data
->x
.middle_used
))
912 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
913 /* Draw collision indicator */
914 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
915 gdk_draw_point(hashed_process_data
->pixmap
,
918 COLLISION_POSITION(hashed_process_data
->height
));
919 hashed_process_data
->x
.middle_marked
= TRUE
;
925 DrawContext draw_context
;
926 /* Now create the drawing context that will be used to draw
927 * items related to the last state. */
928 draw_context
.drawable
= hashed_process_data
->pixmap
;
929 draw_context
.gc
= drawing
->gc
;
930 draw_context
.pango_layout
= drawing
->pango_layout
;
931 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
932 draw_context
.drawinfo
.end
.x
= x
;
934 draw_context
.drawinfo
.y
.over
= 1;
935 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
936 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
938 draw_context
.drawinfo
.start
.offset
.over
= 0;
939 draw_context
.drawinfo
.start
.offset
.middle
= 0;
940 draw_context
.drawinfo
.start
.offset
.under
= 0;
941 draw_context
.drawinfo
.end
.offset
.over
= 0;
942 draw_context
.drawinfo
.end
.offset
.middle
= 0;
943 draw_context
.drawinfo
.end
.offset
.under
= 0;
947 PropertiesLine prop_line
;
948 prop_line
.line_width
= STATE_LINE_WIDTH
;
949 prop_line
.style
= GDK_LINE_SOLID
;
950 prop_line
.y
= MIDDLE
;
951 irq_set_line_color(&prop_line
, &ts
->irq_states
[irq
]);
952 draw_line((void*)&prop_line
, (void*)&draw_context
);
954 /* become the last x position */
955 hashed_process_data
->x
.middle
= x
;
956 hashed_process_data
->x
.middle_used
= TRUE
;
957 hashed_process_data
->x
.middle_marked
= FALSE
;
959 /* Calculate the next good time */
960 convert_pixels_to_time(width
, x
+1, time_window
,
961 &hashed_process_data
->next_good_time
);
968 int before_execmode_hook_soft_irq(void *hook_data
, void *call_data
)
970 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
971 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
972 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
974 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
976 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
977 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
978 struct marker_info
*minfo
;
981 e
= ltt_tracefile_get_event(tfc
->tf
);
983 LttTime evtime
= ltt_event_time(e
);
985 /* we are in a execmode, before the state update. We must draw the
986 * items corresponding to the state before it changes : now is the right
992 guint cpu
= tfs
->cpu
;
995 * Check for LTT_CHANNEL_KERNEL channel name and event ID
996 * corresponding to LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY
997 * or LTT_EVENT_SOFT_IRQ_EXIT.
999 if (tfc
->tf
->name
!= LTT_CHANNEL_KERNEL
)
1001 minfo
= marker_get_info_from_id(tfc
->tf
->mdata
, e
->event_id
);
1002 g_assert(minfo
!= NULL
);
1003 if (minfo
->name
== LTT_EVENT_SOFT_IRQ_RAISE
1004 || minfo
->name
== LTT_EVENT_SOFT_IRQ_ENTRY
) {
1005 softirq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
1006 } else if (minfo
->name
== LTT_EVENT_SOFT_IRQ_EXIT
) {
1007 gint len
= ts
->cpu_states
[cpu
].softirq_stack
->len
;
1009 softirq
= g_array_index(ts
->cpu_states
[cpu
].softirq_stack
, gint
, len
-1);
1017 guint trace_num
= ts
->parent
.index
;
1019 /* Well, the process_out existed : we must get it in the process hash
1020 * or add it, and draw its items.
1022 /* Add process to process list (if not present) */
1023 HashedResourceData
*hashed_process_data
= NULL
;
1025 hashed_process_data
= resourcelist_obtain_soft_irq(resourceview_data
, trace_num
, softirq
);
1027 /* Now, the process is in the state hash and our own process hash.
1028 * We definitely can draw the items related to the ending state.
1031 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1034 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1035 TimeWindow time_window
=
1036 lttvwindow_get_time_window(resourceview_data
->tab
);
1039 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1040 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1042 #endif //EXTRA_CHECK
1043 Drawing_t
*drawing
= resourceview_data
->drawing
;
1044 guint width
= drawing
->width
;
1046 convert_time_to_pixels(
1052 /* Draw collision indicator */
1053 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1054 gdk_draw_point(hashed_process_data
->pixmap
,
1057 COLLISION_POSITION(hashed_process_data
->height
));
1058 hashed_process_data
->x
.middle_marked
= TRUE
;
1062 TimeWindow time_window
=
1063 lttvwindow_get_time_window(resourceview_data
->tab
);
1066 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1067 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1069 #endif //EXTRA_CHECK
1070 Drawing_t
*drawing
= resourceview_data
->drawing
;
1071 guint width
= drawing
->width
;
1074 convert_time_to_pixels(
1081 /* Jump over draw if we are at the same x position */
1082 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1083 hashed_process_data
->x
.middle_used
))
1085 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1086 /* Draw collision indicator */
1087 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1088 gdk_draw_point(hashed_process_data
->pixmap
,
1091 COLLISION_POSITION(hashed_process_data
->height
));
1092 hashed_process_data
->x
.middle_marked
= TRUE
;
1098 DrawContext draw_context
;
1099 /* Now create the drawing context that will be used to draw
1100 * items related to the last state. */
1101 draw_context
.drawable
= hashed_process_data
->pixmap
;
1102 draw_context
.gc
= drawing
->gc
;
1103 draw_context
.pango_layout
= drawing
->pango_layout
;
1104 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1105 draw_context
.drawinfo
.end
.x
= x
;
1107 draw_context
.drawinfo
.y
.over
= 1;
1108 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1109 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1111 draw_context
.drawinfo
.start
.offset
.over
= 0;
1112 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1113 draw_context
.drawinfo
.start
.offset
.under
= 0;
1114 draw_context
.drawinfo
.end
.offset
.over
= 0;
1115 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1116 draw_context
.drawinfo
.end
.offset
.under
= 0;
1120 PropertiesLine prop_line
;
1121 prop_line
.line_width
= STATE_LINE_WIDTH
;
1122 prop_line
.style
= GDK_LINE_SOLID
;
1123 prop_line
.y
= MIDDLE
;
1124 soft_irq_set_line_color(&prop_line
, &ts
->soft_irq_states
[softirq
]);
1125 draw_line((void*)&prop_line
, (void*)&draw_context
);
1127 /* become the last x position */
1128 hashed_process_data
->x
.middle
= x
;
1129 hashed_process_data
->x
.middle_used
= TRUE
;
1130 hashed_process_data
->x
.middle_marked
= FALSE
;
1132 /* Calculate the next good time */
1133 convert_pixels_to_time(width
, x
+1, time_window
,
1134 &hashed_process_data
->next_good_time
);
1141 int before_execmode_hook_trap(void *hook_data
, void *call_data
)
1143 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
1144 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
1145 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
1147 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1149 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1150 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1151 struct marker_info
*minfo
;
1154 e
= ltt_tracefile_get_event(tfc
->tf
);
1156 LttTime evtime
= ltt_event_time(e
);
1158 /* we are in a execmode, before the state update. We must draw the
1159 * items corresponding to the state before it changes : now is the right
1165 guint cpu
= tfs
->cpu
;
1168 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1169 * corresponding to LTT_EVENT_TRAP/PAGE_FAULT_ENTRY or
1170 * LTT_EVENT_TRAP/PAGE_FAULT_EXIT.
1172 if (tfc
->tf
->name
!= LTT_CHANNEL_KERNEL
)
1174 minfo
= marker_get_info_from_id(tfc
->tf
->mdata
, e
->event_id
);
1175 g_assert(minfo
!= NULL
);
1176 if (minfo
->name
== LTT_EVENT_TRAP_ENTRY
1177 || minfo
->name
== LTT_EVENT_PAGE_FAULT_ENTRY
1178 || minfo
->name
== LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
) {
1179 trap
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
1180 } else if (minfo
->name
== LTT_EVENT_TRAP_EXIT
1181 || minfo
->name
== LTT_EVENT_PAGE_FAULT_EXIT
1182 || minfo
->name
== LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
) {
1183 gint len
= ts
->cpu_states
[cpu
].trap_stack
->len
;
1185 trap
= g_array_index(ts
->cpu_states
[cpu
].trap_stack
, gint
, len
-1);
1193 guint trace_num
= ts
->parent
.index
;
1195 /* Well, the process_out existed : we must get it in the process hash
1196 * or add it, and draw its items.
1198 /* Add process to process list (if not present) */
1199 HashedResourceData
*hashed_process_data
= NULL
;
1201 hashed_process_data
= resourcelist_obtain_trap(resourceview_data
, trace_num
, trap
);
1203 /* Now, the process is in the state hash and our own process hash.
1204 * We definitely can draw the items related to the ending state.
1207 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1210 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1211 TimeWindow time_window
=
1212 lttvwindow_get_time_window(resourceview_data
->tab
);
1215 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1216 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1218 #endif //EXTRA_CHECK
1219 Drawing_t
*drawing
= resourceview_data
->drawing
;
1220 guint width
= drawing
->width
;
1222 convert_time_to_pixels(
1228 /* Draw collision indicator */
1229 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1230 gdk_draw_point(hashed_process_data
->pixmap
,
1233 COLLISION_POSITION(hashed_process_data
->height
));
1234 hashed_process_data
->x
.middle_marked
= TRUE
;
1238 TimeWindow time_window
=
1239 lttvwindow_get_time_window(resourceview_data
->tab
);
1242 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1243 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1245 #endif //EXTRA_CHECK
1246 Drawing_t
*drawing
= resourceview_data
->drawing
;
1247 guint width
= drawing
->width
;
1250 convert_time_to_pixels(
1257 /* Jump over draw if we are at the same x position */
1258 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1259 hashed_process_data
->x
.middle_used
))
1261 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1262 /* Draw collision indicator */
1263 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1264 gdk_draw_point(hashed_process_data
->pixmap
,
1267 COLLISION_POSITION(hashed_process_data
->height
));
1268 hashed_process_data
->x
.middle_marked
= TRUE
;
1274 DrawContext draw_context
;
1275 /* Now create the drawing context that will be used to draw
1276 * items related to the last state. */
1277 draw_context
.drawable
= hashed_process_data
->pixmap
;
1278 draw_context
.gc
= drawing
->gc
;
1279 draw_context
.pango_layout
= drawing
->pango_layout
;
1280 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1281 draw_context
.drawinfo
.end
.x
= x
;
1283 draw_context
.drawinfo
.y
.over
= 1;
1284 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1285 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1287 draw_context
.drawinfo
.start
.offset
.over
= 0;
1288 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1289 draw_context
.drawinfo
.start
.offset
.under
= 0;
1290 draw_context
.drawinfo
.end
.offset
.over
= 0;
1291 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1292 draw_context
.drawinfo
.end
.offset
.under
= 0;
1296 PropertiesLine prop_line
;
1297 prop_line
.line_width
= STATE_LINE_WIDTH
;
1298 prop_line
.style
= GDK_LINE_SOLID
;
1299 prop_line
.y
= MIDDLE
;
1300 trap_set_line_color(&prop_line
, &ts
->trap_states
[trap
]);
1301 draw_line((void*)&prop_line
, (void*)&draw_context
);
1303 /* become the last x position */
1304 hashed_process_data
->x
.middle
= x
;
1305 hashed_process_data
->x
.middle_used
= TRUE
;
1306 hashed_process_data
->x
.middle_marked
= FALSE
;
1308 /* Calculate the next good time */
1309 convert_pixels_to_time(width
, x
+1, time_window
,
1310 &hashed_process_data
->next_good_time
);
1318 int before_bdev_event_hook(void *hook_data
, void *call_data
)
1320 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
1321 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
1322 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
1324 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1326 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1329 e
= ltt_tracefile_get_event(tfc
->tf
);
1331 LttTime evtime
= ltt_event_time(e
);
1333 /* we are in a execmode, before the state update. We must draw the
1334 * items corresponding to the state before it changes : now is the right
1339 guint8 major
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
1340 guint8 minor
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
1341 gint devcode_gint
= MKDEV(major
,minor
);
1343 guint trace_num
= ts
->parent
.index
;
1345 LttvBdevState
*bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1346 /* the result of the lookup might be NULL. that's ok, the rest of the function
1347 should understand it was not found and that its state is unknown */
1349 /* Well, the process_out existed : we must get it in the process hash
1350 * or add it, and draw its items.
1352 /* Add process to process list (if not present) */
1353 HashedResourceData
*hashed_process_data
= NULL
;
1354 // LttTime birth = process->creation_time;
1356 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1357 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1359 hashed_process_data
= resourcelist_obtain_bdev(resourceview_data
, trace_num
, devcode_gint
);
1360 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
1361 // hashed_process_data = processlist_get_process_data(process_list,
1367 /* Set the current process */
1368 // process_list->current_hash_data[trace_num][process->cpu] =
1369 // hashed_process_data;
1372 /* Now, the process is in the state hash and our own process hash.
1373 * We definitely can draw the items related to the ending state.
1376 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1379 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1380 TimeWindow time_window
=
1381 lttvwindow_get_time_window(resourceview_data
->tab
);
1384 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1385 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1387 #endif //EXTRA_CHECK
1388 Drawing_t
*drawing
= resourceview_data
->drawing
;
1389 guint width
= drawing
->width
;
1391 convert_time_to_pixels(
1397 /* Draw collision indicator */
1398 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1399 gdk_draw_point(hashed_process_data
->pixmap
,
1402 COLLISION_POSITION(hashed_process_data
->height
));
1403 hashed_process_data
->x
.middle_marked
= TRUE
;
1407 TimeWindow time_window
=
1408 lttvwindow_get_time_window(resourceview_data
->tab
);
1411 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1412 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1414 #endif //EXTRA_CHECK
1415 Drawing_t
*drawing
= resourceview_data
->drawing
;
1416 guint width
= drawing
->width
;
1419 convert_time_to_pixels(
1426 /* Jump over draw if we are at the same x position */
1427 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1428 hashed_process_data
->x
.middle_used
))
1430 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1431 /* Draw collision indicator */
1432 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1433 gdk_draw_point(hashed_process_data
->pixmap
,
1436 COLLISION_POSITION(hashed_process_data
->height
));
1437 hashed_process_data
->x
.middle_marked
= TRUE
;
1443 DrawContext draw_context
;
1444 /* Now create the drawing context that will be used to draw
1445 * items related to the last state. */
1446 draw_context
.drawable
= hashed_process_data
->pixmap
;
1447 draw_context
.gc
= drawing
->gc
;
1448 draw_context
.pango_layout
= drawing
->pango_layout
;
1449 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1450 draw_context
.drawinfo
.end
.x
= x
;
1452 draw_context
.drawinfo
.y
.over
= 1;
1453 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1454 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1456 draw_context
.drawinfo
.start
.offset
.over
= 0;
1457 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1458 draw_context
.drawinfo
.start
.offset
.under
= 0;
1459 draw_context
.drawinfo
.end
.offset
.over
= 0;
1460 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1461 draw_context
.drawinfo
.end
.offset
.under
= 0;
1465 PropertiesLine prop_line
;
1466 prop_line
.line_width
= STATE_LINE_WIDTH
;
1467 prop_line
.style
= GDK_LINE_SOLID
;
1468 prop_line
.y
= MIDDLE
;
1469 bdev_set_line_color(&prop_line
, bdev
);
1470 draw_line((void*)&prop_line
, (void*)&draw_context
);
1472 /* become the last x position */
1473 hashed_process_data
->x
.middle
= x
;
1474 hashed_process_data
->x
.middle_used
= TRUE
;
1475 hashed_process_data
->x
.middle_marked
= FALSE
;
1477 /* Calculate the next good time */
1478 convert_pixels_to_time(width
, x
+1, time_window
,
1479 &hashed_process_data
->next_good_time
);
1486 gint
update_time_window_hook(void *hook_data
, void *call_data
)
1488 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1489 Drawing_t
*drawing
= resourceview_data
->drawing
;
1490 ProcessList
*process_list
= resourceview_data
->process_list
;
1492 const TimeWindowNotifyData
*time_window_nofify_data
=
1493 ((const TimeWindowNotifyData
*)call_data
);
1495 TimeWindow
*old_time_window
=
1496 time_window_nofify_data
->old_time_window
;
1497 TimeWindow
*new_time_window
=
1498 time_window_nofify_data
->new_time_window
;
1500 /* Update the ruler */
1501 drawing_update_ruler(resourceview_data
->drawing
,
1505 /* Two cases : zoom in/out or scrolling */
1507 /* In order to make sure we can reuse the old drawing, the scale must
1508 * be the same and the new time interval being partly located in the
1509 * currently shown time interval. (reuse is only for scrolling)
1512 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1513 old_time_window
->start_time
.tv_sec
,
1514 old_time_window
->start_time
.tv_nsec
,
1515 old_time_window
->time_width
.tv_sec
,
1516 old_time_window
->time_width
.tv_nsec
);
1518 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1519 new_time_window
->start_time
.tv_sec
,
1520 new_time_window
->start_time
.tv_nsec
,
1521 new_time_window
->time_width
.tv_sec
,
1522 new_time_window
->time_width
.tv_nsec
);
1524 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
1525 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
1527 /* Same scale (scrolling) */
1528 g_info("scrolling");
1529 LttTime
*ns
= &new_time_window
->start_time
;
1530 LttTime
*os
= &old_time_window
->start_time
;
1531 LttTime old_end
= old_time_window
->end_time
;
1532 LttTime new_end
= new_time_window
->end_time
;
1534 //if(ns<os+w && os+w<ns+w)
1535 //if(ns<old_end && os<ns)
1536 if(ltt_time_compare(*ns
, old_end
) == -1
1537 && ltt_time_compare(*os
, *ns
) == -1)
1539 g_info("scrolling near right");
1540 /* Scroll right, keep right part of the screen */
1542 guint width
= resourceview_data
->drawing
->width
;
1543 convert_time_to_pixels(
1549 /* Copy old data to new location */
1550 copy_pixmap_region(process_list
,
1552 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1556 resourceview_data
->drawing
->width
-x
+SAFETY
, -1);
1558 if(drawing
->damage_begin
== drawing
->damage_end
)
1559 drawing
->damage_begin
= resourceview_data
->drawing
->width
-x
;
1561 drawing
->damage_begin
= 0;
1563 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1565 /* Clear the data request background, but not SAFETY */
1566 rectangle_pixmap(process_list
,
1567 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1569 drawing
->damage_begin
+SAFETY
, 0,
1570 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
1572 gtk_widget_queue_draw(drawing
->drawing_area
);
1574 /* Get new data for the rest. */
1575 drawing_data_request(resourceview_data
->drawing
,
1576 drawing
->damage_begin
, 0,
1577 drawing
->damage_end
- drawing
->damage_begin
,
1578 resourceview_data
->drawing
->height
);
1580 if(ltt_time_compare(*ns
,*os
) == -1
1581 && ltt_time_compare(*os
,new_end
) == -1)
1583 g_info("scrolling near left");
1584 /* Scroll left, keep left part of the screen */
1586 guint width
= resourceview_data
->drawing
->width
;
1587 convert_time_to_pixels(
1593 /* Copy old data to new location */
1594 copy_pixmap_region (process_list
,
1596 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1602 if(drawing
->damage_begin
== drawing
->damage_end
)
1603 drawing
->damage_end
= x
;
1605 drawing
->damage_end
=
1606 resourceview_data
->drawing
->width
;
1608 drawing
->damage_begin
= 0;
1610 rectangle_pixmap (process_list
,
1611 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1613 drawing
->damage_begin
, 0,
1614 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
1617 gtk_widget_queue_draw(drawing
->drawing_area
);
1619 /* Get new data for the rest. */
1620 drawing_data_request(resourceview_data
->drawing
,
1621 drawing
->damage_begin
, 0,
1622 drawing
->damage_end
- drawing
->damage_begin
,
1623 resourceview_data
->drawing
->height
);
1626 if(ltt_time_compare(*ns
,*os
) == 0)
1628 g_info("not scrolling");
1630 g_info("scrolling far");
1631 /* Cannot reuse any part of the screen : far jump */
1634 rectangle_pixmap (process_list
,
1635 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1638 resourceview_data
->drawing
->width
+SAFETY
, // do not overlap
1641 gtk_widget_queue_draw(drawing
->drawing_area
);
1643 drawing
->damage_begin
= 0;
1644 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1646 drawing_data_request(resourceview_data
->drawing
,
1648 resourceview_data
->drawing
->width
,
1649 resourceview_data
->drawing
->height
);
1655 /* Different scale (zoom) */
1658 rectangle_pixmap (process_list
,
1659 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
1662 resourceview_data
->drawing
->width
+SAFETY
, // do not overlap
1665 gtk_widget_queue_draw(drawing
->drawing_area
);
1667 drawing
->damage_begin
= 0;
1668 drawing
->damage_end
= resourceview_data
->drawing
->width
;
1670 drawing_data_request(resourceview_data
->drawing
,
1672 resourceview_data
->drawing
->width
,
1673 resourceview_data
->drawing
->height
);
1676 /* Update directly when scrolling */
1677 gdk_window_process_updates(resourceview_data
->drawing
->drawing_area
->window
,
1683 gint
traceset_notify(void *hook_data
, void *call_data
)
1685 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1686 Drawing_t
*drawing
= resourceview_data
->drawing
;
1688 if(unlikely(drawing
->gc
== NULL
)) {
1691 if(drawing
->dotted_gc
== NULL
) {
1695 drawing_clear(resourceview_data
->drawing
);
1696 processlist_clear(resourceview_data
->process_list
);
1697 gtk_widget_set_size_request(
1698 resourceview_data
->drawing
->drawing_area
,
1699 -1, processlist_get_height(resourceview_data
->process_list
));
1700 redraw_notify(resourceview_data
, NULL
);
1702 request_background_data(resourceview_data
);
1707 gint
redraw_notify(void *hook_data
, void *call_data
)
1709 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1710 Drawing_t
*drawing
= resourceview_data
->drawing
;
1711 GtkWidget
*widget
= drawing
->drawing_area
;
1713 drawing
->damage_begin
= 0;
1714 drawing
->damage_end
= drawing
->width
;
1716 /* fun feature, to be separated someday... */
1717 drawing_clear(resourceview_data
->drawing
);
1718 processlist_clear(resourceview_data
->process_list
);
1719 gtk_widget_set_size_request(
1720 resourceview_data
->drawing
->drawing_area
,
1721 -1, processlist_get_height(resourceview_data
->process_list
));
1723 rectangle_pixmap (resourceview_data
->process_list
,
1724 widget
->style
->black_gc
,
1727 drawing
->alloc_width
,
1730 gtk_widget_queue_draw(drawing
->drawing_area
);
1732 if(drawing
->damage_begin
< drawing
->damage_end
)
1734 drawing_data_request(drawing
,
1735 drawing
->damage_begin
,
1737 drawing
->damage_end
-drawing
->damage_begin
,
1746 gint
continue_notify(void *hook_data
, void *call_data
)
1748 ControlFlowData
*resourceview_data
= (ControlFlowData
*) hook_data
;
1749 Drawing_t
*drawing
= resourceview_data
->drawing
;
1751 if(drawing
->damage_begin
< drawing
->damage_end
)
1753 drawing_data_request(drawing
,
1754 drawing
->damage_begin
,
1756 drawing
->damage_end
-drawing
->damage_begin
,
1764 gint
update_current_time_hook(void *hook_data
, void *call_data
)
1766 ControlFlowData
*resourceview_data
= (ControlFlowData
*)hook_data
;
1768 LttTime current_time
= *((LttTime
*)call_data
);
1770 TimeWindow time_window
=
1771 lttvwindow_get_time_window(resourceview_data
->tab
);
1773 LttTime time_begin
= time_window
.start_time
;
1774 LttTime width
= time_window
.time_width
;
1777 guint64 time_ll
= ltt_time_to_uint64(width
);
1778 time_ll
= time_ll
>> 1; /* divide by two */
1779 half_width
= ltt_time_from_uint64(time_ll
);
1781 LttTime time_end
= ltt_time_add(time_begin
, width
);
1783 LttvTracesetContext
* tsc
=
1784 lttvwindow_get_traceset_context(resourceview_data
->tab
);
1786 LttTime trace_start
= tsc
->time_span
.start_time
;
1787 LttTime trace_end
= tsc
->time_span
.end_time
;
1789 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
1790 current_time
.tv_nsec
);
1792 /* If current time is inside time interval, just move the highlight
1795 /* Else, we have to change the time interval. We have to tell it
1796 * to the main window. */
1797 /* The time interval change will take care of placing the current
1798 * time at the center of the visible area, or nearest possible if we are
1799 * at one end of the trace. */
1802 if(ltt_time_compare(current_time
, time_begin
) < 0)
1804 TimeWindow new_time_window
;
1806 if(ltt_time_compare(current_time
,
1807 ltt_time_add(trace_start
,half_width
)) < 0)
1808 time_begin
= trace_start
;
1810 time_begin
= ltt_time_sub(current_time
,half_width
);
1812 new_time_window
.start_time
= time_begin
;
1813 new_time_window
.time_width
= width
;
1814 new_time_window
.time_width_double
= ltt_time_to_double(width
);
1815 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
1817 lttvwindow_report_time_window(resourceview_data
->tab
, new_time_window
);
1819 else if(ltt_time_compare(current_time
, time_end
) > 0)
1821 TimeWindow new_time_window
;
1823 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
1824 time_begin
= ltt_time_sub(trace_end
,width
);
1826 time_begin
= ltt_time_sub(current_time
,half_width
);
1828 new_time_window
.start_time
= time_begin
;
1829 new_time_window
.time_width
= width
;
1830 new_time_window
.time_width_double
= ltt_time_to_double(width
);
1831 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
1833 lttvwindow_report_time_window(resourceview_data
->tab
, new_time_window
);
1836 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
1838 /* Update directly when scrolling */
1839 gdk_window_process_updates(resourceview_data
->drawing
->drawing_area
->window
,
1845 typedef struct _ClosureData
{
1846 EventsRequest
*events_request
;
1847 LttvTracesetState
*tss
;
1852 /* Draw line until end of the screen */
1854 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
1856 ResourceUniqueNumeric
*process_info
= (ResourceUniqueNumeric
*)key
;
1857 HashedResourceData
*hashed_process_data
= (HashedResourceData
*)value
;
1858 ClosureData
*closure_data
= (ClosureData
*)user_data
;
1860 EventsRequest
*events_request
= closure_data
->events_request
;
1861 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
1863 LttvTracesetState
*tss
= closure_data
->tss
;
1864 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
1866 LttTime evtime
= closure_data
->end_time
;
1868 gboolean dodraw
= TRUE
;
1870 if(hashed_process_data
->type
== RV_RESOURCE_MACHINE
)
1874 /* For the process */
1875 /* First, check if the current process is in the state computation
1876 * process list. If it is there, that means we must add it right now and
1877 * draw items from the beginning of the read for it. If it is not
1878 * present, it's a new process and it was not present : it will
1879 * be added after the state update. */
1881 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
1882 #endif //EXTRA_CHECK
1883 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
1884 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
1886 /* Only draw for processes that are currently in the trace states */
1889 /* Should be alike when background info is ready */
1890 if(resourceview_data
->background_info_waiting
==0)
1891 g_assert(ltt_time_compare(process
->creation_time
,
1892 process_info
->birth
) == 0);
1893 #endif //EXTRA_CHECK
1895 /* Now, the process is in the state hash and our own process hash.
1896 * We definitely can draw the items related to the ending state.
1899 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
1902 TimeWindow time_window
=
1903 lttvwindow_get_time_window(resourceview_data
->tab
);
1906 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1907 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1909 #endif //EXTRA_CHECK
1910 Drawing_t
*drawing
= resourceview_data
->drawing
;
1911 guint width
= drawing
->width
;
1913 guint x
= closure_data
->x_end
;
1915 DrawContext draw_context
;
1917 /* Now create the drawing context that will be used to draw
1918 * items related to the last state. */
1919 draw_context
.drawable
= hashed_process_data
->pixmap
;
1920 draw_context
.gc
= drawing
->gc
;
1921 draw_context
.pango_layout
= drawing
->pango_layout
;
1922 draw_context
.drawinfo
.end
.x
= x
;
1924 draw_context
.drawinfo
.y
.over
= 1;
1925 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1926 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1928 draw_context
.drawinfo
.start
.offset
.over
= 0;
1929 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1930 draw_context
.drawinfo
.start
.offset
.under
= 0;
1931 draw_context
.drawinfo
.end
.offset
.over
= 0;
1932 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1933 draw_context
.drawinfo
.end
.offset
.under
= 0;
1935 /* Jump over draw if we are at the same x position */
1936 if(x
== hashed_process_data
->x
.over
)
1940 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
1942 PropertiesLine prop_line
= prepare_execmode_line(process
);
1943 draw_line((void*)&prop_line
, (void*)&draw_context
);
1945 hashed_process_data
->x
.over
= x
;
1949 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1950 hashed_process_data
->x
.middle_used
)) {
1951 #if 0 /* do not mark closure : not missing information */
1952 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
1953 /* Draw collision indicator */
1954 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1955 gdk_draw_point(drawing
->pixmap
,
1959 hashed_process_data
->x
.middle_marked
= TRUE
;
1964 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1967 PropertiesLine prop_line
;
1968 prop_line
.line_width
= STATE_LINE_WIDTH
;
1969 prop_line
.style
= GDK_LINE_SOLID
;
1970 prop_line
.y
= MIDDLE
;
1971 if(hashed_process_data
->type
== RV_RESOURCE_CPU
)
1972 cpu_set_line_color(&prop_line
, &ts
->cpu_states
[process_info
->id
]);
1973 else if(hashed_process_data
->type
== RV_RESOURCE_IRQ
)
1974 irq_set_line_color(&prop_line
, &ts
->irq_states
[process_info
->id
]);
1975 else if(hashed_process_data
->type
== RV_RESOURCE_SOFT_IRQ
)
1976 soft_irq_set_line_color(&prop_line
, &ts
->soft_irq_states
[process_info
->id
]);
1977 else if(hashed_process_data
->type
== RV_RESOURCE_TRAP
)
1978 trap_set_line_color(&prop_line
, &ts
->trap_states
[process_info
->id
]);
1979 else if(hashed_process_data
->type
== RV_RESOURCE_BDEV
) {
1980 gint devcode_gint
= process_info
->id
;
1981 LttvBdevState
*bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1982 // the lookup may return null; bdev_set_line_color must act appropriately
1983 bdev_set_line_color(&prop_line
, bdev
);
1986 draw_line((void*)&prop_line
, (void*)&draw_context
);
1989 /* become the last x position */
1990 if(likely(x
!= hashed_process_data
->x
.middle
)) {
1991 hashed_process_data
->x
.middle
= x
;
1992 /* but don't use the pixel */
1993 hashed_process_data
->x
.middle_used
= FALSE
;
1995 /* Calculate the next good time */
1996 convert_pixels_to_time(width
, x
+1, time_window
,
1997 &hashed_process_data
->next_good_time
);
2004 int before_chunk(void *hook_data
, void *call_data
)
2006 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2007 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2009 /* Deactivate sort */
2010 gtk_tree_sortable_set_sort_column_id(
2011 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
2013 GTK_SORT_ASCENDING
);
2015 drawing_chunk_begin(events_request
, tss
);
2022 * This gets executed just before an events request is executed
2025 int before_request(void *hook_data
, void *call_data
)
2027 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2028 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2030 drawing_data_request_begin(events_request
, tss
);
2037 * after request is necessary in addition of after chunk in order to draw
2038 * lines until the end of the screen. after chunk just draws lines until
2045 int after_request(void *hook_data
, void *call_data
)
2048 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2049 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
2050 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2052 LttTime end_time
= events_request
->end_time
;
2054 ClosureData closure_data
;
2055 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2056 closure_data
.tss
= tss
;
2057 closure_data
.end_time
= end_time
;
2059 TimeWindow time_window
=
2060 lttvwindow_get_time_window(resourceview_data
->tab
);
2061 guint width
= resourceview_data
->drawing
->width
;
2062 convert_time_to_pixels(
2066 &closure_data
.x_end
);
2069 /* Draw last items */
2070 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
2071 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data
, i
), draw_closure
,
2072 (void*)&closure_data
);
2075 /* Request expose */
2076 drawing_request_expose(events_request
, tss
, end_time
);
2085 int after_chunk(void *hook_data
, void *call_data
)
2087 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2088 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
2089 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2090 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
2091 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
2094 ProcessList
*process_list
= resourceview_data
->process_list
;
2096 LttvTraceset
*traceset
= tsc
->ts
;
2097 guint nb_trace
= lttv_traceset_number(traceset
);
2099 /* Only execute when called for the first trace's events request */
2100 if(!process_list
->current_hash_data
)
2103 for(i
= 0 ; i
< nb_trace
; i
++) {
2104 g_free(process_list
->current_hash_data
[i
]);
2106 g_free(process_list
->current_hash_data
);
2107 process_list
->current_hash_data
= NULL
;
2110 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
2111 else /* end of traceset, or position now out of request : end */
2112 end_time
= events_request
->end_time
;
2114 ClosureData closure_data
;
2115 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2116 closure_data
.tss
= tss
;
2117 closure_data
.end_time
= end_time
;
2119 TimeWindow time_window
=
2120 lttvwindow_get_time_window(resourceview_data
->tab
);
2121 guint width
= resourceview_data
->drawing
->width
;
2122 convert_time_to_pixels(
2126 &closure_data
.x_end
);
2128 /* Draw last items */
2129 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
2130 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data
, i
), draw_closure
,
2131 (void*)&closure_data
);
2134 /* Reactivate sort */
2135 gtk_tree_sortable_set_sort_column_id(
2136 GTK_TREE_SORTABLE(resourceview_data
->process_list
->list_store
),
2137 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2138 GTK_SORT_ASCENDING
);
2140 update_index_to_pixmap(resourceview_data
->process_list
);
2141 /* Request a full expose : drawing scrambled */
2142 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
2144 /* Request expose (updates damages zone also) */
2145 drawing_request_expose(events_request
, tss
, end_time
);
2150 /* after_statedump_end
2152 * @param hook_data ControlFlowData structure of the viewer.
2153 * @param call_data Event context.
2155 * This function adds items to be drawn in a queue for each process.
2158 int before_statedump_end(void *hook_data
, void *call_data
)
2162 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2163 EventsRequest
*events_request
= (EventsRequest
*)th
->hook_data
;
2164 ControlFlowData
*resourceview_data
= events_request
->viewer_data
;
2166 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2168 LttvTracesetState
*tss
= (LttvTracesetState
*)tfc
->t_context
->ts_context
;
2171 e
= ltt_tracefile_get_event(tfc
->tf
);
2173 LttvFilter
*filter
= resourceview_data
->filter
;
2174 if(filter
!= NULL
&& filter
->head
!= NULL
)
2175 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
2176 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
2179 LttTime evtime
= ltt_event_time(e
);
2181 ClosureData closure_data
;
2182 closure_data
.events_request
= events_request
;
2183 closure_data
.tss
= tss
;
2184 closure_data
.end_time
= evtime
;
2186 TimeWindow time_window
=
2187 lttvwindow_get_time_window(resourceview_data
->tab
);
2188 guint width
= resourceview_data
->drawing
->width
;
2189 convert_time_to_pixels(
2193 &closure_data
.x_end
);
2195 /* Draw last items */
2197 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
2198 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data
, i
), draw_closure
,
2199 (void*)&closure_data
);
2202 /* Reactivate sort */
2203 gtk_tree_sortable_set_sort_column_id(
2204 GTK_TREE_SORTABLE(resourceview_data
->process_list
->list_store
),
2205 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2206 GTK_SORT_ASCENDING
);
2208 update_index_to_pixmap(resourceview_data
->process_list
);
2209 /* Request a full expose : drawing scrambled */
2210 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
2212 /* Request expose (updates damages zone also) */
2213 drawing_request_expose(events_request
, tss
, evtime
);