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
60 //#include <pango/pango.h>
62 #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 4
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
*control_flow_data
= (ControlFlowData
*)hook_data
;
96 LttvTrace
*trace
= (LttvTrace
*)call_data
;
98 control_flow_data
->background_info_waiting
--;
100 if(control_flow_data
->background_info_waiting
== 0) {
101 g_message("control flow viewer : background computation data ready.");
103 drawing_clear(control_flow_data
->drawing
);
104 processlist_clear(control_flow_data
->process_list
);
105 gtk_widget_set_size_request(
106 control_flow_data
->drawing
->drawing_area
,
107 -1, processlist_get_height(control_flow_data
->process_list
));
108 redraw_notify(control_flow_data
, NULL
);
115 /* Request background computation. Verify if it is in progress or ready first.
116 * Only for each trace in the tab's traceset.
118 static void request_background_data(ControlFlowData
*control_flow_data
)
120 LttvTracesetContext
* tsc
=
121 lttvwindow_get_traceset_context(control_flow_data
->tab
);
122 gint num_traces
= lttv_traceset_number(tsc
->ts
);
125 LttvTraceState
*tstate
;
127 LttvHooks
*background_ready_hook
=
129 lttv_hooks_add(background_ready_hook
, background_ready
, control_flow_data
,
131 control_flow_data
->background_info_waiting
= 0;
133 for(i
=0;i
<num_traces
;i
++) {
134 trace
= lttv_traceset_get(tsc
->ts
, i
);
135 tstate
= LTTV_TRACE_STATE(tsc
->traces
[i
]);
137 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
138 && !tstate
->has_precomputed_states
) {
140 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
142 /* We first remove requests that could have been done for the same
143 * information. Happens when two viewers ask for it before servicing
146 if(!lttvwindowtraces_background_request_find(trace
, "state"))
147 lttvwindowtraces_background_request_queue(
148 main_window_get_widget(control_flow_data
->tab
), trace
, "state");
149 lttvwindowtraces_background_notify_queue(control_flow_data
,
153 background_ready_hook
);
154 control_flow_data
->background_info_waiting
++;
155 } else { /* in progress */
157 lttvwindowtraces_background_notify_current(control_flow_data
,
161 background_ready_hook
);
162 control_flow_data
->background_info_waiting
++;
165 /* Data ready. By its nature, this viewer doesn't need to have
166 * its data ready hook called there, because a background
167 * request is always linked with a redraw.
173 lttv_hooks_destroy(background_ready_hook
);
180 * Event Viewer's constructor hook
182 * This constructor is given as a parameter to the menuitem and toolbar button
183 * registration. It creates the list.
184 * @param tab A pointer to the parent tab.
185 * @return The widget created.
188 h_resourceview(LttvPlugin
*plugin
)
190 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
191 Tab
*tab
= ptab
->tab
;
192 g_info("h_guicontrolflow, %p", tab
);
193 ControlFlowData
*control_flow_data
= resourceview(ptab
);
195 control_flow_data
->tab
= tab
;
197 // Unreg done in the GuiControlFlow_Destructor
198 lttvwindow_register_traceset_notify(tab
,
202 lttvwindow_register_time_window_notify(tab
,
203 update_time_window_hook
,
205 lttvwindow_register_current_time_notify(tab
,
206 update_current_time_hook
,
208 lttvwindow_register_redraw_notify(tab
,
211 lttvwindow_register_continue_notify(tab
,
214 request_background_data(control_flow_data
);
217 return guicontrolflow_get_widget(control_flow_data
) ;
221 void legend_destructor(GtkWindow
*legend
)
223 g_legend_list
= g_slist_remove(g_legend_list
, legend
);
226 /* Create a popup legend */
228 h_legend(LttvPlugin
*plugin
)
230 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
231 Tab
*tab
= ptab
->tab
;
232 g_info("h_legend, %p", tab
);
234 GtkWindow
*legend
= GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL
));
236 g_legend_list
= g_slist_append(
240 g_object_set_data_full(
244 (GDestroyNotify
)legend_destructor
);
246 gtk_window_set_title(legend
, "Control Flow View Legend");
248 GtkWidget
*pixmap
= create_pixmap(GTK_WIDGET(legend
), "lttv-color-list.png");
250 // GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixmap(
251 // GDK_PIXMAP(pixmap), NULL));
253 gtk_container_add(GTK_CONTAINER(legend
), GTK_WIDGET(pixmap
));
255 gtk_widget_show(GTK_WIDGET(pixmap
));
256 gtk_widget_show(GTK_WIDGET(legend
));
259 return NULL
; /* This is a popup window */
263 int event_selected_hook(void *hook_data
, void *call_data
)
265 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
266 guint
*event_number
= (guint
*) call_data
;
268 g_debug("DEBUG : event selected by main window : %u", *event_number
);
273 /* Function that selects the color of status&exemode line */
274 static inline PropertiesLine
prepare_s_e_line(LttvProcessState
*process
)
276 PropertiesLine prop_line
;
277 prop_line
.line_width
= STATE_LINE_WIDTH
;
278 prop_line
.style
= GDK_LINE_SOLID
;
279 prop_line
.y
= MIDDLE
;
281 if(process
->state
->s
== LTTV_STATE_RUN
) {
282 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
283 prop_line
.color
= drawing_colors
[COL_RUN_USER_MODE
];
284 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
285 prop_line
.color
= drawing_colors
[COL_RUN_SYSCALL
];
286 else if(process
->state
->t
== LTTV_STATE_TRAP
)
287 prop_line
.color
= drawing_colors
[COL_RUN_TRAP
];
288 else if(process
->state
->t
== LTTV_STATE_IRQ
)
289 prop_line
.color
= drawing_colors
[COL_RUN_IRQ
];
290 else if(process
->state
->t
== LTTV_STATE_SOFT_IRQ
)
291 prop_line
.color
= drawing_colors
[COL_RUN_SOFT_IRQ
];
292 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
293 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
295 g_assert(FALSE
); /* RUNNING MODE UNKNOWN */
296 } else if(process
->state
->s
== LTTV_STATE_WAIT
) {
297 /* We don't show if we wait while in user mode, trap, irq or syscall */
298 prop_line
.color
= drawing_colors
[COL_WAIT
];
299 } else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
) {
300 /* We don't show if we wait for CPU while in user mode, trap, irq
302 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
303 } else if(process
->state
->s
== LTTV_STATE_ZOMBIE
) {
304 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
305 } else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
) {
306 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
307 } else if(process
->state
->s
== LTTV_STATE_EXIT
) {
308 prop_line
.color
= drawing_colors
[COL_EXIT
];
309 } else if(process
->state
->s
== LTTV_STATE_UNNAMED
) {
310 prop_line
.color
= drawing_colors
[COL_UNNAMED
];
312 g_critical("unknown state : %s", g_quark_to_string(process
->state
->s
));
313 g_assert(FALSE
); /* UNKNOWN STATE */
320 static void cpu_set_line_color(PropertiesLine
*prop_line
, LttvCPUState
*s
)
322 GQuark present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
324 if(present_state
== LTTV_CPU_UNKNOWN
) {
325 prop_line
->color
= drawing_colors_cpu
[COL_CPU_UNKNOWN
];
327 else if(present_state
== LTTV_CPU_IDLE
) {
328 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IDLE
];
330 else if(present_state
== LTTV_CPU_BUSY
) {
331 prop_line
->color
= drawing_colors_cpu
[COL_CPU_BUSY
];
333 else if(present_state
== LTTV_CPU_IRQ
) {
334 prop_line
->color
= drawing_colors_cpu
[COL_CPU_IRQ
];
336 else if(present_state
== LTTV_CPU_TRAP
) {
337 prop_line
->color
= drawing_colors_cpu
[COL_CPU_TRAP
];
341 static void irq_set_line_color(PropertiesLine
*prop_line
, LttvIRQState
*s
)
343 GQuark present_state
= ((GQuark
*)s
->mode_stack
->data
)[s
->mode_stack
->len
-1];
345 if(present_state
== LTTV_IRQ_UNKNOWN
) {
346 prop_line
->color
= drawing_colors_irq
[COL_IRQ_UNKNOWN
];
348 else if(present_state
== LTTV_IRQ_IDLE
) {
349 prop_line
->color
= drawing_colors_irq
[COL_IRQ_IDLE
];
351 else if(present_state
== LTTV_IRQ_BUSY
) {
352 prop_line
->color
= drawing_colors_irq
[COL_IRQ_BUSY
];
356 /* before_schedchange_hook
358 * This function basically draw lines and icons. Two types of lines are drawn :
359 * one small (3 pixels?) representing the state of the process and the second
360 * type is thicker (10 pixels?) representing on which CPU a process is running
361 * (and this only in running state).
363 * Extremums of the lines :
364 * x_min : time of the last event context for this process kept in memory.
365 * x_max : time of the current event.
366 * y : middle of the process in the process list. The process is found in the
367 * list, therefore is it's position in pixels.
369 * The choice of lines'color is defined by the context of the last event for this
374 int before_schedchange_hook(void *hook_data
, void *call_data
)
376 before_schedchange_hook_cpu(hook_data
, call_data
);
377 // before_schedchange_hook_irq(hook_data, call_data);
382 int before_schedchange_hook_cpu(void *hook_data
, void *call_data
)
384 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
385 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
386 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
388 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
390 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
391 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
394 e
= ltt_tracefile_get_event(tfc
->tf
);
395 gint target_pid_saved
= tfc
->target_pid
;
397 LttTime evtime
= ltt_event_time(e
);
398 LttvFilter
*filter
= control_flow_data
->filter
;
402 /* we are in a schedchange, before the state update. We must draw the
403 * items corresponding to the state before it changes : now is the right
409 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
410 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
411 // if(pid_in != 0 && pid_out != 0) {
412 // /* not a transition to/from idle */
416 tfc
->target_pid
= pid_out
;
417 // if(!filter || !filter->head ||
418 // lttv_filter_tree_parse(filter->head,e,tfc->tf,
419 // tfc->t_context->t,tfc,NULL,NULL)) {
420 /* For the pid_out */
421 /* First, check if the current process is in the state computation
422 * process list. If it is there, that means we must add it right now and
423 * draw items from the beginning of the read for it. If it is not
424 * present, it's a new process and it was not present : it will
425 * be added after the state update. */
426 guint cpu
= tfs
->cpu
;
429 cpustr
= g_strdup_printf("CPU%u", cpu
);
430 cpuq
= g_quark_from_string(cpustr
);
434 guint trace_num
= ts
->parent
.index
;
435 // LttvProcessState *process = ts->running_process[cpu];
436 /* unknown state, bad current pid */
437 // if(process->pid != pid_out)
438 // process = lttv_state_find_process(ts,
439 // tfs->cpu, pid_out);
441 // if(process != NULL) {
442 /* Well, the process_out existed : we must get it in the process hash
443 * or add it, and draw its items.
445 /* Add process to process list (if not present) */
447 HashedResourceData
*hashed_process_data
= NULL
;
448 ProcessList
*process_list
= control_flow_data
->process_list
;
449 // LttTime birth = process->creation_time;
451 hashed_process_data
= processlist_get_process_data(process_list
, cpuq
, trace_num
);
452 // hashed_process_data = processlist_get_process_data(process_list,
457 if(hashed_process_data
== NULL
)
459 // g_assert(pid_out == 0 || pid_out != process->ppid);
460 /* Process not present */
461 ResourceInfo
*process_info
;
462 Drawing_t
*drawing
= control_flow_data
->drawing
;
463 resourcelist_add(process_list
,
466 cpuq
, //process->name,
471 &hashed_process_data
);
472 gtk_widget_set_size_request(drawing
->drawing_area
,
475 gtk_widget_queue_draw(drawing
->drawing_area
);
479 /* Now, the process is in the state hash and our own process hash.
480 * We definitely can draw the items related to the ending state.
483 if(ltt_time_compare(hashed_process_data
->next_good_time
,
486 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
488 TimeWindow time_window
=
489 lttvwindow_get_time_window(control_flow_data
->tab
);
491 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
492 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
495 Drawing_t
*drawing
= control_flow_data
->drawing
;
496 guint width
= drawing
->width
;
498 convert_time_to_pixels(
504 /* Draw collision indicator */
505 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
506 gdk_draw_point(hashed_process_data
->pixmap
,
509 COLLISION_POSITION(hashed_process_data
->height
));
510 hashed_process_data
->x
.middle_marked
= TRUE
;
513 TimeWindow time_window
=
514 lttvwindow_get_time_window(control_flow_data
->tab
);
516 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
517 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
520 Drawing_t
*drawing
= control_flow_data
->drawing
;
521 guint width
= drawing
->width
;
523 convert_time_to_pixels(
530 /* Jump over draw if we are at the same x position */
531 if(x
== hashed_process_data
->x
.middle
&&
532 hashed_process_data
->x
.middle_used
)
534 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
535 /* Draw collision indicator */
536 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
537 gdk_draw_point(hashed_process_data
->pixmap
,
540 COLLISION_POSITION(hashed_process_data
->height
));
541 hashed_process_data
->x
.middle_marked
= TRUE
;
545 DrawContext draw_context
;
547 /* Now create the drawing context that will be used to draw
548 * items related to the last state. */
549 draw_context
.drawable
= hashed_process_data
->pixmap
;
550 draw_context
.gc
= drawing
->gc
;
551 draw_context
.pango_layout
= drawing
->pango_layout
;
552 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
553 draw_context
.drawinfo
.end
.x
= x
;
555 draw_context
.drawinfo
.y
.over
= 1;
556 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
557 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
559 draw_context
.drawinfo
.start
.offset
.over
= 0;
560 draw_context
.drawinfo
.start
.offset
.middle
= 0;
561 draw_context
.drawinfo
.start
.offset
.under
= 0;
562 draw_context
.drawinfo
.end
.offset
.over
= 0;
563 draw_context
.drawinfo
.end
.offset
.middle
= 0;
564 draw_context
.drawinfo
.end
.offset
.under
= 0;
568 //PropertiesLine prop_line = prepare_s_e_line(process);
569 PropertiesLine prop_line
;
570 prop_line
.line_width
= STATE_LINE_WIDTH
;
571 prop_line
.style
= GDK_LINE_SOLID
;
572 prop_line
.y
= MIDDLE
;
573 cpu_set_line_color(&prop_line
, tfs
->cpu_state
);
574 draw_line((void*)&prop_line
, (void*)&draw_context
);
577 /* become the last x position */
578 hashed_process_data
->x
.middle
= x
;
579 hashed_process_data
->x
.middle_used
= TRUE
;
580 hashed_process_data
->x
.middle_marked
= FALSE
;
582 /* Calculate the next good time */
583 convert_pixels_to_time(width
, x
+1, time_window
,
584 &hashed_process_data
->next_good_time
);
590 // tfc->target_pid = pid_in;
591 // if(!filter || !filter->head ||
592 // lttv_filter_tree_parse(filter->head,e,tfc->tf,
593 // tfc->t_context->t,tfc,NULL,NULL)) {
594 // /* For the pid_in */
595 // /* First, check if the current process is in the state computation
596 // * process list. If it is there, that means we must add it right now and
597 // * draw items from the beginning of the read for it. If it is not
598 // * present, it's a new process and it was not present : it will
599 // * be added after the state update. */
600 // LttvProcessState *process;
601 // process = lttv_state_find_process(ts,
602 // tfs->cpu, pid_in);
603 // guint trace_num = ts->parent.index;
605 // if(process != NULL) {
606 // /* Well, the process existed : we must get it in the process hash
607 // * or add it, and draw its items.
609 // /* Add process to process list (if not present) */
610 // guint pl_height = 0;
611 // HashedResourceData *hashed_process_data = NULL;
612 // ProcessList *process_list = control_flow_data->process_list;
613 // LttTime birth = process->creation_time;
615 // hashed_process_data = processlist_get_process_data(process_list, cpuq);
616 //// hashed_process_data = processlist_get_process_data(process_list,
621 // if(hashed_process_data == NULL)
623 // g_assert(pid_in == 0 || pid_in != process->ppid);
624 // /* Process not present */
625 // ResourceInfo *process_info;
626 // Drawing_t *drawing = control_flow_data->drawing;
627 // resourcelist_add(process_list,
639 // &hashed_process_data);
640 // gtk_widget_set_size_request(drawing->drawing_area,
643 // gtk_widget_queue_draw(drawing->drawing_area);
646 // //We could set the current process and hash here, but will be done
647 // //by after schedchange hook
649 // /* Now, the process is in the state hash and our own process hash.
650 // * We definitely can draw the items related to the ending state.
653 // if(ltt_time_compare(hashed_process_data->next_good_time,
656 // if(hashed_process_data->x.middle_marked == FALSE) {
658 // TimeWindow time_window =
659 // lttvwindow_get_time_window(control_flow_data->tab);
661 // if(ltt_time_compare(evtime, time_window.start_time) == -1
662 // || ltt_time_compare(evtime, time_window.end_time) == 1)
664 //#endif //EXTRA_CHECK
665 // Drawing_t *drawing = control_flow_data->drawing;
666 // guint width = drawing->width;
668 // convert_time_to_pixels(
674 // /* Draw collision indicator */
675 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
676 // gdk_draw_point(hashed_process_data->pixmap,
679 // COLLISION_POSITION(hashed_process_data->height));
680 // hashed_process_data->x.middle_marked = TRUE;
683 // TimeWindow time_window =
684 // lttvwindow_get_time_window(control_flow_data->tab);
686 // if(ltt_time_compare(evtime, time_window.start_time) == -1
687 // || ltt_time_compare(evtime, time_window.end_time) == 1)
689 //#endif //EXTRA_CHECK
690 // Drawing_t *drawing = control_flow_data->drawing;
691 // guint width = drawing->width;
694 // convert_time_to_pixels(
701 // /* Jump over draw if we are at the same x position */
702 // if(x == hashed_process_data->x.middle &&
703 // hashed_process_data->x.middle_used)
705 // if(hashed_process_data->x.middle_marked == FALSE) {
706 // /* Draw collision indicator */
707 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
708 // gdk_draw_point(hashed_process_data->pixmap,
711 // COLLISION_POSITION(hashed_process_data->height));
712 // hashed_process_data->x.middle_marked = TRUE;
716 // DrawContext draw_context;
718 // /* Now create the drawing context that will be used to draw
719 // * items related to the last state. */
720 // draw_context.drawable = hashed_process_data->pixmap;
721 // draw_context.gc = drawing->gc;
722 // draw_context.pango_layout = drawing->pango_layout;
723 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
724 // draw_context.drawinfo.end.x = x;
726 // draw_context.drawinfo.y.over = 1;
727 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
728 // draw_context.drawinfo.y.under = hashed_process_data->height;
730 // draw_context.drawinfo.start.offset.over = 0;
731 // draw_context.drawinfo.start.offset.middle = 0;
732 // draw_context.drawinfo.start.offset.under = 0;
733 // draw_context.drawinfo.end.offset.over = 0;
734 // draw_context.drawinfo.end.offset.middle = 0;
735 // draw_context.drawinfo.end.offset.under = 0;
738 // /* Draw the line */
739 // PropertiesLine prop_line = prepare_s_e_line(process);
740 // draw_line((void*)&prop_line, (void*)&draw_context);
744 // /* become the last x position */
745 // hashed_process_data->x.middle = x;
746 // hashed_process_data->x.middle_used = TRUE;
747 // hashed_process_data->x.middle_marked = FALSE;
749 // /* Calculate the next good time */
750 // convert_pixels_to_time(width, x+1, time_window,
751 // &hashed_process_data->next_good_time);
755 // g_warning("Cannot find pin_in in schedchange %u", pid_in);
757 // tfc->target_pid = target_pid_saved;
765 GString
*string
= g_string_new("");;
766 gboolean field_names
= TRUE
, state
= TRUE
;
768 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
769 g_string_append_printf(string
,"\n");
772 g_string_append_printf(string
, " %s",
773 g_quark_to_string(tfs
->process
->state
->s
));
776 g_info("%s",string
->str
);
778 g_string_free(string
, TRUE
);
780 /* End of text dump */
785 /* after_schedchange_hook
787 * The draw after hook is called by the reading API to have a
788 * particular event drawn on the screen.
789 * @param hook_data ControlFlowData structure of the viewer.
790 * @param call_data Event context.
792 * This function adds items to be drawn in a queue for each process.
795 int after_schedchange_hook(void *hook_data
, void *call_data
)
797 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
798 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
799 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
801 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
803 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
805 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
808 e
= ltt_tracefile_get_event(tfc
->tf
);
810 LttvFilter
*filter
= control_flow_data
->filter
;
811 if(filter
!= NULL
&& filter
->head
!= NULL
)
812 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
813 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
816 LttTime evtime
= ltt_event_time(e
);
820 /* Add process to process list (if not present) */
821 LttvProcessState
*process_in
;
824 HashedResourceData
*hashed_process_data_in
= NULL
;
826 ProcessList
*process_list
= control_flow_data
->process_list
;
831 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
832 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
836 /* Find process pid_in in the list... */
837 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
838 //process_in = tfs->process;
839 guint cpu
= tfs
->cpu
;
842 cpustr
= g_strdup_printf("CPU%u", cpu
);
843 cpuq
= g_quark_from_string(cpustr
);
846 guint trace_num
= ts
->parent
.index
;
847 process_in
= ts
->running_process
[cpu
];
848 /* It should exist, because we are after the state update. */
850 g_assert(process_in
!= NULL
);
852 birth
= process_in
->creation_time
;
854 hashed_process_data_in
= processlist_get_process_data(process_list
, cpuq
, trace_num
);
855 // hashed_process_data_in = processlist_get_process_data(process_list,
860 if(hashed_process_data_in
== NULL
)
862 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
863 ResourceInfo
*process_info
;
864 Drawing_t
*drawing
= control_flow_data
->drawing
;
865 /* Process not present */
866 resourcelist_add(process_list
,
874 &hashed_process_data_in
);
875 gtk_widget_set_size_request(drawing
->drawing_area
,
878 gtk_widget_queue_draw(drawing
->drawing_area
);
880 /* Set the current process */
881 process_list
->current_hash_data
[trace_num
][process_in
->cpu
] =
882 hashed_process_data_in
;
884 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
887 TimeWindow time_window
=
888 lttvwindow_get_time_window(control_flow_data
->tab
);
891 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
892 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
895 Drawing_t
*drawing
= control_flow_data
->drawing
;
896 guint width
= drawing
->width
;
899 convert_time_to_pixels(
905 if(hashed_process_data_in
->x
.middle
!= new_x
) {
906 hashed_process_data_in
->x
.middle
= new_x
;
907 hashed_process_data_in
->x
.middle_used
= FALSE
;
908 hashed_process_data_in
->x
.middle_marked
= FALSE
;
914 /* before_execmode_hook
916 * This function basically draw lines and icons. Two types of lines are drawn :
917 * one small (3 pixels?) representing the state of the process and the second
918 * type is thicker (10 pixels?) representing on which CPU a process is running
919 * (and this only in running state).
921 * Extremums of the lines :
922 * x_min : time of the last event context for this process kept in memory.
923 * x_max : time of the current event.
924 * y : middle of the process in the process list. The process is found in the
925 * list, therefore is it's position in pixels.
927 * The choice of lines'color is defined by the context of the last event for this
931 int before_execmode_hook(void *hook_data
, void *call_data
)
933 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
934 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
935 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
937 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
939 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
940 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
943 e
= ltt_tracefile_get_event(tfc
->tf
);
945 LttTime evtime
= ltt_event_time(e
);
949 before_execmode_hook_irq(hook_data
, call_data
);
951 /* we are in a execmode, before the state update. We must draw the
952 * items corresponding to the state before it changes : now is the right
956 //LttvProcessState *process = tfs->process;
957 guint cpu
= tfs
->cpu
;
960 cpustr
= g_strdup_printf("CPU%u", cpu
);
961 cpuq
= g_quark_from_string(cpustr
);
964 guint trace_num
= ts
->parent
.index
;
965 LttvProcessState
*process
= ts
->running_process
[cpu
];
966 g_assert(process
!= NULL
);
968 // guint pid = process->pid;
970 /* Well, the process_out existed : we must get it in the process hash
971 * or add it, and draw its items.
973 /* Add process to process list (if not present) */
975 HashedResourceData
*hashed_process_data
= NULL
;
976 ProcessList
*process_list
= control_flow_data
->process_list
;
977 LttTime birth
= process
->creation_time
;
979 if(likely(process_list
->current_hash_data
[trace_num
][cpu
] != NULL
)) {
980 hashed_process_data
= process_list
->current_hash_data
[trace_num
][cpu
];
982 hashed_process_data
= processlist_get_process_data(process_list
, cpuq
, trace_num
);
983 // hashed_process_data = processlist_get_process_data(process_list,
988 if(unlikely(hashed_process_data
== NULL
))
990 //g_assert(pid == 0 || pid != process->ppid);
991 ResourceInfo
*process_info
;
992 /* Process not present */
993 Drawing_t
*drawing
= control_flow_data
->drawing
;
994 resourcelist_add(process_list
,
997 cpuq
, //process->name,
1002 &hashed_process_data
);
1003 gtk_widget_set_size_request(drawing
->drawing_area
,
1006 gtk_widget_queue_draw(drawing
->drawing_area
);
1008 /* Set the current process */
1009 process_list
->current_hash_data
[trace_num
][process
->cpu
] =
1010 hashed_process_data
;
1013 /* Now, the process is in the state hash and our own process hash.
1014 * We definitely can draw the items related to the ending state.
1017 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1020 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1021 TimeWindow time_window
=
1022 lttvwindow_get_time_window(control_flow_data
->tab
);
1025 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1026 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1028 #endif //EXTRA_CHECK
1029 Drawing_t
*drawing
= control_flow_data
->drawing
;
1030 guint width
= drawing
->width
;
1032 convert_time_to_pixels(
1038 /* Draw collision indicator */
1039 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1040 gdk_draw_point(hashed_process_data
->pixmap
,
1043 COLLISION_POSITION(hashed_process_data
->height
));
1044 hashed_process_data
->x
.middle_marked
= TRUE
;
1048 TimeWindow time_window
=
1049 lttvwindow_get_time_window(control_flow_data
->tab
);
1052 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1053 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1055 #endif //EXTRA_CHECK
1056 Drawing_t
*drawing
= control_flow_data
->drawing
;
1057 guint width
= drawing
->width
;
1060 convert_time_to_pixels(
1067 /* Jump over draw if we are at the same x position */
1068 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1069 hashed_process_data
->x
.middle_used
))
1071 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1072 /* Draw collision indicator */
1073 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1074 gdk_draw_point(hashed_process_data
->pixmap
,
1077 COLLISION_POSITION(hashed_process_data
->height
));
1078 hashed_process_data
->x
.middle_marked
= TRUE
;
1084 DrawContext draw_context
;
1085 /* Now create the drawing context that will be used to draw
1086 * items related to the last state. */
1087 draw_context
.drawable
= hashed_process_data
->pixmap
;
1088 draw_context
.gc
= drawing
->gc
;
1089 draw_context
.pango_layout
= drawing
->pango_layout
;
1090 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1091 draw_context
.drawinfo
.end
.x
= x
;
1093 draw_context
.drawinfo
.y
.over
= 1;
1094 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1095 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1097 draw_context
.drawinfo
.start
.offset
.over
= 0;
1098 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1099 draw_context
.drawinfo
.start
.offset
.under
= 0;
1100 draw_context
.drawinfo
.end
.offset
.over
= 0;
1101 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1102 draw_context
.drawinfo
.end
.offset
.under
= 0;
1106 PropertiesLine prop_line
;
1107 prop_line
.line_width
= STATE_LINE_WIDTH
;
1108 prop_line
.style
= GDK_LINE_SOLID
;
1109 prop_line
.y
= MIDDLE
;
1110 cpu_set_line_color(&prop_line
, tfs
->cpu_state
);
1111 draw_line((void*)&prop_line
, (void*)&draw_context
);
1113 /* become the last x position */
1114 hashed_process_data
->x
.middle
= x
;
1115 hashed_process_data
->x
.middle_used
= TRUE
;
1116 hashed_process_data
->x
.middle_marked
= FALSE
;
1118 /* Calculate the next good time */
1119 convert_pixels_to_time(width
, x
+1, time_window
,
1120 &hashed_process_data
->next_good_time
);
1127 int before_execmode_hook_irq(void *hook_data
, void *call_data
)
1129 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1130 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1131 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1133 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1135 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1136 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1139 e
= ltt_tracefile_get_event(tfc
->tf
);
1141 LttTime evtime
= ltt_event_time(e
);
1145 /* we are in a execmode, before the state update. We must draw the
1146 * items corresponding to the state before it changes : now is the right
1152 guint cpu
= tfs
->cpu
;
1154 LttFacility
*ev_facility
= ltt_event_facility(e
);
1155 if(ltt_facility_name(ev_facility
) != LTT_FACILITY_KERNEL
)
1157 guint8 ev_id_entry
= ltt_eventtype_id(ltt_facility_eventtype_get_by_name(ev_facility
, LTT_EVENT_IRQ_ENTRY
));
1158 guint8 ev_id_exit
= ltt_eventtype_id(ltt_facility_eventtype_get_by_name(ev_facility
, LTT_EVENT_IRQ_EXIT
));
1159 if(ltt_facility_name(ev_facility
) == LTT_FACILITY_KERNEL
&&
1160 ev_id_entry
== ltt_event_eventtype_id(e
)) {
1161 irq
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1163 else if(ltt_facility_name(ev_facility
) == LTT_FACILITY_KERNEL
&&
1164 ev_id_exit
== ltt_event_eventtype_id(e
)) {
1165 irq
= ts
->cpu_states
[cpu
].last_irq
;
1173 irqstr
= g_strdup_printf("IRQ %u", irq
);
1174 resourceq
= g_quark_from_string(irqstr
);
1177 guint trace_num
= ts
->parent
.index
;
1179 // guint pid = process->pid;
1181 /* Well, the process_out existed : we must get it in the process hash
1182 * or add it, and draw its items.
1184 /* Add process to process list (if not present) */
1185 guint pl_height
= 0;
1186 HashedResourceData
*hashed_process_data
= NULL
;
1187 ProcessList
*process_list
= control_flow_data
->process_list
;
1188 // LttTime birth = process->creation_time;
1190 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1191 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1193 hashed_process_data
= processlist_get_process_data(process_list
, resourceq
, trace_num
);
1194 // hashed_process_data = processlist_get_process_data(process_list,
1199 if(unlikely(hashed_process_data
== NULL
))
1201 //g_assert(pid == 0 || pid != process->ppid);
1202 ResourceInfo
*process_info
;
1203 /* Process not present */
1204 Drawing_t
*drawing
= control_flow_data
->drawing
;
1205 resourcelist_add(process_list
,
1208 resourceq
, //process->name,
1213 &hashed_process_data
);
1214 gtk_widget_set_size_request(drawing
->drawing_area
,
1217 gtk_widget_queue_draw(drawing
->drawing_area
);
1219 /* Set the current process */
1220 // process_list->current_hash_data[trace_num][process->cpu] =
1221 // hashed_process_data;
1224 /* Now, the process is in the state hash and our own process hash.
1225 * We definitely can draw the items related to the ending state.
1228 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
1231 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1232 TimeWindow time_window
=
1233 lttvwindow_get_time_window(control_flow_data
->tab
);
1236 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1237 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1239 #endif //EXTRA_CHECK
1240 Drawing_t
*drawing
= control_flow_data
->drawing
;
1241 guint width
= drawing
->width
;
1243 convert_time_to_pixels(
1249 /* Draw collision indicator */
1250 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1251 gdk_draw_point(hashed_process_data
->pixmap
,
1254 COLLISION_POSITION(hashed_process_data
->height
));
1255 hashed_process_data
->x
.middle_marked
= TRUE
;
1259 TimeWindow time_window
=
1260 lttvwindow_get_time_window(control_flow_data
->tab
);
1263 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1264 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1266 #endif //EXTRA_CHECK
1267 Drawing_t
*drawing
= control_flow_data
->drawing
;
1268 guint width
= drawing
->width
;
1271 convert_time_to_pixels(
1278 /* Jump over draw if we are at the same x position */
1279 if(unlikely(x
== hashed_process_data
->x
.middle
&&
1280 hashed_process_data
->x
.middle_used
))
1282 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
1283 /* Draw collision indicator */
1284 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
1285 gdk_draw_point(hashed_process_data
->pixmap
,
1288 COLLISION_POSITION(hashed_process_data
->height
));
1289 hashed_process_data
->x
.middle_marked
= TRUE
;
1295 DrawContext draw_context
;
1296 /* Now create the drawing context that will be used to draw
1297 * items related to the last state. */
1298 draw_context
.drawable
= hashed_process_data
->pixmap
;
1299 draw_context
.gc
= drawing
->gc
;
1300 draw_context
.pango_layout
= drawing
->pango_layout
;
1301 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
1302 draw_context
.drawinfo
.end
.x
= x
;
1304 draw_context
.drawinfo
.y
.over
= 1;
1305 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
1306 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
1308 draw_context
.drawinfo
.start
.offset
.over
= 0;
1309 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1310 draw_context
.drawinfo
.start
.offset
.under
= 0;
1311 draw_context
.drawinfo
.end
.offset
.over
= 0;
1312 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1313 draw_context
.drawinfo
.end
.offset
.under
= 0;
1317 PropertiesLine prop_line
;
1318 prop_line
.line_width
= STATE_LINE_WIDTH
;
1319 prop_line
.style
= GDK_LINE_SOLID
;
1320 prop_line
.y
= MIDDLE
;
1321 irq_set_line_color(&prop_line
, &ts
->irq_states
[irq
]);
1322 draw_line((void*)&prop_line
, (void*)&draw_context
);
1324 /* become the last x position */
1325 hashed_process_data
->x
.middle
= x
;
1326 hashed_process_data
->x
.middle_used
= TRUE
;
1327 hashed_process_data
->x
.middle_marked
= FALSE
;
1329 /* Calculate the next good time */
1330 convert_pixels_to_time(width
, x
+1, time_window
,
1331 &hashed_process_data
->next_good_time
);
1338 /* before_process_exit_hook
1340 * Draw lines for process event.
1342 * @param hook_data ControlFlowData structure of the viewer.
1343 * @param call_data Event context.
1345 * This function adds items to be drawn in a queue for each process.
1349 //int before_process_exit_hook(void *hook_data, void *call_data)
1351 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1352 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1354 // ControlFlowData *control_flow_data = events_request->viewer_data;
1356 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1358 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1360 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1363 // e = ltt_tracefile_get_event(tfc->tf);
1365 // LttvFilter *filter = control_flow_data->filter;
1366 // if(filter != NULL && filter->head != NULL)
1367 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1368 // tfc->t_context->t,tfc,NULL,NULL))
1371 // LttTime evtime = ltt_event_time(e);
1373 // /* Add process to process list (if not present) */
1374 // //LttvProcessState *process = tfs->process;
1375 // guint cpu = tfs->cpu;
1376 // guint trace_num = ts->parent.index;
1377 // LttvProcessState *process = ts->running_process[cpu];
1378 // guint pid = process->pid;
1380 // guint pl_height = 0;
1381 // HashedResourceData *hashed_process_data = NULL;
1383 // ProcessList *process_list = control_flow_data->process_list;
1385 // g_assert(process != NULL);
1387 // birth = process->creation_time;
1389 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1390 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1392 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1393 //// hashed_process_data = processlist_get_process_data(process_list,
1398 // if(unlikely(hashed_process_data == NULL))
1400 // g_assert(pid == 0 || pid != process->ppid);
1401 // /* Process not present */
1402 // Drawing_t *drawing = control_flow_data->drawing;
1403 // ResourceInfo *process_info;
1404 // processlist_add(process_list,
1416 // &hashed_process_data);
1417 // gtk_widget_set_size_request(drawing->drawing_area,
1420 // gtk_widget_queue_draw(drawing->drawing_area);
1424 // /* Now, the process is in the state hash and our own process hash.
1425 // * We definitely can draw the items related to the ending state.
1428 // if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1431 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1432 // TimeWindow time_window =
1433 // lttvwindow_get_time_window(control_flow_data->tab);
1435 //#ifdef EXTRA_CHECK
1436 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1437 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1439 //#endif //EXTRA_CHECK
1440 // Drawing_t *drawing = control_flow_data->drawing;
1441 // guint width = drawing->width;
1443 // convert_time_to_pixels(
1449 // /* Draw collision indicator */
1450 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1451 // gdk_draw_point(hashed_process_data->pixmap,
1454 // COLLISION_POSITION(hashed_process_data->height));
1455 // hashed_process_data->x.middle_marked = TRUE;
1458 // TimeWindow time_window =
1459 // lttvwindow_get_time_window(control_flow_data->tab);
1461 //#ifdef EXTRA_CHECK
1462 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1463 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1465 //#endif //EXTRA_CHECK
1466 // Drawing_t *drawing = control_flow_data->drawing;
1467 // guint width = drawing->width;
1470 // convert_time_to_pixels(
1477 // /* Jump over draw if we are at the same x position */
1478 // if(unlikely(x == hashed_process_data->x.middle &&
1479 // hashed_process_data->x.middle_used))
1481 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1482 // /* Draw collision indicator */
1483 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1484 // gdk_draw_point(hashed_process_data->pixmap,
1487 // COLLISION_POSITION(hashed_process_data->height));
1488 // hashed_process_data->x.middle_marked = TRUE;
1492 // DrawContext draw_context;
1494 // /* Now create the drawing context that will be used to draw
1495 // * items related to the last state. */
1496 // draw_context.drawable = hashed_process_data->pixmap;
1497 // draw_context.gc = drawing->gc;
1498 // draw_context.pango_layout = drawing->pango_layout;
1499 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1500 // draw_context.drawinfo.end.x = x;
1502 // draw_context.drawinfo.y.over = 1;
1503 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1504 // draw_context.drawinfo.y.under = hashed_process_data->height;
1506 // draw_context.drawinfo.start.offset.over = 0;
1507 // draw_context.drawinfo.start.offset.middle = 0;
1508 // draw_context.drawinfo.start.offset.under = 0;
1509 // draw_context.drawinfo.end.offset.over = 0;
1510 // draw_context.drawinfo.end.offset.middle = 0;
1511 // draw_context.drawinfo.end.offset.under = 0;
1514 // /* Draw the line */
1515 // PropertiesLine prop_line = prepare_s_e_line(process);
1516 // draw_line((void*)&prop_line, (void*)&draw_context);
1519 // /* become the last x position */
1520 // hashed_process_data->x.middle = x;
1521 // hashed_process_data->x.middle_used = TRUE;
1522 // hashed_process_data->x.middle_marked = FALSE;
1524 // /* Calculate the next good time */
1525 // convert_pixels_to_time(width, x+1, time_window,
1526 // &hashed_process_data->next_good_time);
1535 /* before_process_release_hook
1537 * Draw lines for process event.
1539 * @param hook_data ControlFlowData structure of the viewer.
1540 * @param call_data Event context.
1542 * This function adds items to be drawn in a queue for each process.
1546 //int before_process_release_hook(void *hook_data, void *call_data)
1548 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1549 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1551 // ControlFlowData *control_flow_data = events_request->viewer_data;
1553 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1555 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1557 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1560 // e = ltt_tracefile_get_event(tfc->tf);
1562 // LttvFilter *filter = control_flow_data->filter;
1563 // if(filter != NULL && filter->head != NULL)
1564 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1565 // tfc->t_context->t,tfc,NULL,NULL))
1568 // LttTime evtime = ltt_event_time(e);
1570 // guint trace_num = ts->parent.index;
1574 // pid = ltt_event_get_long_unsigned(e, thf->f1);
1577 // /* Add process to process list (if not present) */
1578 // /* Don't care about the process if it's not in the state hash already :
1579 // * that means a process that has never done anything in the trace and
1580 // * unknown suddently gets destroyed : no state meaningful to show. */
1581 // LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
1583 // if(process != NULL) {
1585 // guint pl_height = 0;
1586 // HashedResourceData *hashed_process_data = NULL;
1588 // ProcessList *process_list = control_flow_data->process_list;
1590 // birth = process->creation_time;
1592 // /* Cannot use current process : this event happens on another process,
1593 // * action done by the parent. */
1594 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1595 //// hashed_process_data = processlist_get_process_data(process_list,
1600 // if(unlikely(hashed_process_data == NULL))
1602 // g_assert(pid == 0 || pid != process->ppid);
1603 // /* Process not present */
1604 // Drawing_t *drawing = control_flow_data->drawing;
1605 // ResourceInfo *process_info;
1606 // processlist_add(process_list,
1618 // &hashed_process_data);
1619 // gtk_widget_set_size_request(drawing->drawing_area,
1622 // gtk_widget_queue_draw(drawing->drawing_area);
1625 // /* Now, the process is in the state hash and our own process hash.
1626 // * We definitely can draw the items related to the ending state.
1629 // if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1632 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1633 // TimeWindow time_window =
1634 // lttvwindow_get_time_window(control_flow_data->tab);
1636 //#ifdef EXTRA_CHECK
1637 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1638 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1640 //#endif //EXTRA_CHECK
1641 // Drawing_t *drawing = control_flow_data->drawing;
1642 // guint width = drawing->width;
1644 // convert_time_to_pixels(
1650 // /* Draw collision indicator */
1651 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1652 // gdk_draw_point(hashed_process_data->pixmap,
1655 // COLLISION_POSITION(hashed_process_data->height));
1656 // hashed_process_data->x.middle_marked = TRUE;
1659 // TimeWindow time_window =
1660 // lttvwindow_get_time_window(control_flow_data->tab);
1662 //#ifdef EXTRA_CHECK
1663 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1664 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1666 //#endif //EXTRA_CHECK
1667 // Drawing_t *drawing = control_flow_data->drawing;
1668 // guint width = drawing->width;
1671 // convert_time_to_pixels(
1678 // /* Jump over draw if we are at the same x position */
1679 // if(unlikely(x == hashed_process_data->x.middle &&
1680 // hashed_process_data->x.middle_used))
1682 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1683 // /* Draw collision indicator */
1684 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1685 // gdk_draw_point(hashed_process_data->pixmap,
1688 // COLLISION_POSITION(hashed_process_data->height));
1689 // hashed_process_data->x.middle_marked = TRUE;
1693 // DrawContext draw_context;
1695 // /* Now create the drawing context that will be used to draw
1696 // * items related to the last state. */
1697 // draw_context.drawable = hashed_process_data->pixmap;
1698 // draw_context.gc = drawing->gc;
1699 // draw_context.pango_layout = drawing->pango_layout;
1700 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1701 // draw_context.drawinfo.end.x = x;
1703 // draw_context.drawinfo.y.over = 1;
1704 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1705 // draw_context.drawinfo.y.under = hashed_process_data->height;
1707 // draw_context.drawinfo.start.offset.over = 0;
1708 // draw_context.drawinfo.start.offset.middle = 0;
1709 // draw_context.drawinfo.start.offset.under = 0;
1710 // draw_context.drawinfo.end.offset.over = 0;
1711 // draw_context.drawinfo.end.offset.middle = 0;
1712 // draw_context.drawinfo.end.offset.under = 0;
1715 // /* Draw the line */
1716 // PropertiesLine prop_line = prepare_s_e_line(process);
1717 // draw_line((void*)&prop_line, (void*)&draw_context);
1720 // /* become the last x position */
1721 // hashed_process_data->x.middle = x;
1722 // hashed_process_data->x.middle_used = TRUE;
1723 // hashed_process_data->x.middle_marked = FALSE;
1725 // /* Calculate the next good time */
1726 // convert_pixels_to_time(width, x+1, time_window,
1727 // &hashed_process_data->next_good_time);
1735 /* after_process_fork_hook
1737 * Create the processlist entry for the child process. Put the last
1738 * position in x at the current time value.
1740 * @param hook_data ControlFlowData structure of the viewer.
1741 * @param call_data Event context.
1743 * This function adds items to be drawn in a queue for each process.
1746 //int after_process_fork_hook(void *hook_data, void *call_data)
1748 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1749 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1750 // ControlFlowData *control_flow_data = events_request->viewer_data;
1752 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1754 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1756 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1759 // e = ltt_tracefile_get_event(tfc->tf);
1761 // LttvFilter *filter = control_flow_data->filter;
1762 // if(filter != NULL && filter->head != NULL)
1763 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1764 // tfc->t_context->t,tfc,NULL,NULL))
1767 // LttTime evtime = ltt_event_time(e);
1771 // child_pid = ltt_event_get_long_unsigned(e, thf->f2);
1774 // /* Add process to process list (if not present) */
1775 // LttvProcessState *process_child;
1777 // guint pl_height = 0;
1778 // HashedResourceData *hashed_process_data_child = NULL;
1780 // ProcessList *process_list = control_flow_data->process_list;
1782 // /* Find child in the list... */
1783 // process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
1784 // /* It should exist, because we are after the state update. */
1785 // g_assert(process_child != NULL);
1787 // birth = process_child->creation_time;
1788 // guint trace_num = ts->parent.index;
1790 // /* Cannot use current process, because this action is done by the parent
1791 // * on its child. */
1792 // hashed_process_data_child = processlist_get_process_data(process_list, "CPU0");
1793 //// hashed_process_data_child = processlist_get_process_data(process_list,
1795 //// process_child->cpu,
1798 // if(likely(hashed_process_data_child == NULL))
1800 // g_assert(child_pid == 0 || child_pid != process_child->ppid);
1801 // /* Process not present */
1802 // Drawing_t *drawing = control_flow_data->drawing;
1803 // ResourceInfo *process_info;
1804 // processlist_add(process_list,
1807 // process_child->tgid,
1808 // process_child->cpu,
1809 // process_child->ppid,
1812 // process_child->name,
1813 // process_child->brand,
1816 // &hashed_process_data_child);
1817 // gtk_widget_set_size_request(drawing->drawing_area,
1820 // gtk_widget_queue_draw(drawing->drawing_area);
1822 // processlist_set_ppid(process_list, process_child->ppid,
1823 // hashed_process_data_child);
1824 // processlist_set_tgid(process_list, process_child->tgid,
1825 // hashed_process_data_child);
1829 // if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1832 // TimeWindow time_window =
1833 // lttvwindow_get_time_window(control_flow_data->tab);
1835 //#ifdef EXTRA_CHECK
1836 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1837 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1839 //#endif //EXTRA_CHECK
1840 // Drawing_t *drawing = control_flow_data->drawing;
1841 // guint width = drawing->width;
1843 // convert_time_to_pixels(
1849 // if(likely(hashed_process_data_child->x.over != new_x)) {
1850 // hashed_process_data_child->x.over = new_x;
1851 // hashed_process_data_child->x.over_used = FALSE;
1852 // hashed_process_data_child->x.over_marked = FALSE;
1854 // if(likely(hashed_process_data_child->x.middle != new_x)) {
1855 // hashed_process_data_child->x.middle = new_x;
1856 // hashed_process_data_child->x.middle_used = FALSE;
1857 // hashed_process_data_child->x.middle_marked = FALSE;
1859 // if(likely(hashed_process_data_child->x.under != new_x)) {
1860 // hashed_process_data_child->x.under = new_x;
1861 // hashed_process_data_child->x.under_used = FALSE;
1862 // hashed_process_data_child->x.under_marked = FALSE;
1870 /* after_process_exit_hook
1872 * Create the processlist entry for the child process. Put the last
1873 * position in x at the current time value.
1875 * @param hook_data ControlFlowData structure of the viewer.
1876 * @param call_data Event context.
1878 * This function adds items to be drawn in a queue for each process.
1881 //int after_process_exit_hook(void *hook_data, void *call_data)
1883 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1884 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1885 // ControlFlowData *control_flow_data = events_request->viewer_data;
1887 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1889 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1891 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1894 // e = ltt_tracefile_get_event(tfc->tf);
1896 // LttvFilter *filter = control_flow_data->filter;
1897 // if(filter != NULL && filter->head != NULL)
1898 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1899 // tfc->t_context->t,tfc,NULL,NULL))
1902 // LttTime evtime = ltt_event_time(e);
1904 // /* Add process to process list (if not present) */
1905 // //LttvProcessState *process = tfs->process;
1906 // guint cpu = tfs->cpu;
1907 // guint trace_num = ts->parent.index;
1908 // LttvProcessState *process = ts->running_process[cpu];
1910 // /* It should exist, because we are after the state update. */
1911 // g_assert(process != NULL);
1913 // guint pid = process->pid;
1915 // guint pl_height = 0;
1916 // HashedResourceData *hashed_process_data = NULL;
1918 // ProcessList *process_list = control_flow_data->process_list;
1920 // birth = process->creation_time;
1922 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1923 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1925 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1926 //// hashed_process_data = processlist_get_process_data(process_list,
1931 // if(unlikely(hashed_process_data == NULL))
1933 // g_assert(pid == 0 || pid != process->ppid);
1934 // /* Process not present */
1935 // Drawing_t *drawing = control_flow_data->drawing;
1936 // ResourceInfo *process_info;
1937 // processlist_add(process_list,
1949 // &hashed_process_data);
1950 // gtk_widget_set_size_request(drawing->drawing_area,
1953 // gtk_widget_queue_draw(drawing->drawing_area);
1956 // /* Set the current process */
1957 // process_list->current_hash_data[trace_num][process->cpu] =
1958 // hashed_process_data;
1961 // if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1964 // TimeWindow time_window =
1965 // lttvwindow_get_time_window(control_flow_data->tab);
1967 //#ifdef EXTRA_CHECK
1968 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1969 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1971 //#endif //EXTRA_CHECK
1972 // Drawing_t *drawing = control_flow_data->drawing;
1973 // guint width = drawing->width;
1975 // convert_time_to_pixels(
1980 // if(unlikely(hashed_process_data->x.middle != new_x)) {
1981 // hashed_process_data->x.middle = new_x;
1982 // hashed_process_data->x.middle_used = FALSE;
1983 // hashed_process_data->x.middle_marked = FALSE;
1991 /* Get the filename of the process to print */
1992 //int after_fs_exec_hook(void *hook_data, void *call_data)
1994 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1995 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1996 // ControlFlowData *control_flow_data = events_request->viewer_data;
1998 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2000 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2002 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2005 // e = ltt_tracefile_get_event(tfc->tf);
2007 // LttvFilter *filter = control_flow_data->filter;
2008 // if(filter != NULL && filter->head != NULL)
2009 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2010 // tfc->t_context->t,tfc,NULL,NULL))
2013 // guint cpu = tfs->cpu;
2014 // guint trace_num = ts->parent.index;
2015 // LttvProcessState *process = ts->running_process[cpu];
2016 // g_assert(process != NULL);
2018 // guint pid = process->pid;
2020 // /* Well, the process_out existed : we must get it in the process hash
2021 // * or add it, and draw its items.
2023 // /* Add process to process list (if not present) */
2024 // guint pl_height = 0;
2025 // HashedResourceData *hashed_process_data = NULL;
2026 // ProcessList *process_list = control_flow_data->process_list;
2027 // LttTime birth = process->creation_time;
2029 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
2030 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2032 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
2033 //// hashed_process_data = processlist_get_process_data(process_list,
2038 // if(unlikely(hashed_process_data == NULL))
2040 // g_assert(pid == 0 || pid != process->ppid);
2041 // ResourceInfo *process_info;
2042 // /* Process not present */
2043 // Drawing_t *drawing = control_flow_data->drawing;
2044 // processlist_add(process_list,
2056 // &hashed_process_data);
2057 // gtk_widget_set_size_request(drawing->drawing_area,
2060 // gtk_widget_queue_draw(drawing->drawing_area);
2062 // /* Set the current process */
2063 // process_list->current_hash_data[trace_num][process->cpu] =
2064 // hashed_process_data;
2067 // processlist_set_name(process_list, process->name, hashed_process_data);
2073 /* Get the filename of the process to print */
2074 //int after_user_generic_thread_brand_hook(void *hook_data, void *call_data)
2076 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2077 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2078 // ControlFlowData *control_flow_data = events_request->viewer_data;
2080 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2082 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2084 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2087 // e = ltt_tracefile_get_event(tfc->tf);
2089 // LttvFilter *filter = control_flow_data->filter;
2090 // if(filter != NULL && filter->head != NULL)
2091 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2092 // tfc->t_context->t,tfc,NULL,NULL))
2095 // guint cpu = tfs->cpu;
2096 // guint trace_num = ts->parent.index;
2097 // LttvProcessState *process = ts->running_process[cpu];
2098 // g_assert(process != NULL);
2100 // guint pid = process->pid;
2102 // /* Well, the process_out existed : we must get it in the process hash
2103 // * or add it, and draw its items.
2105 // /* Add process to process list (if not present) */
2106 // guint pl_height = 0;
2107 // HashedResourceData *hashed_process_data = NULL;
2108 // ProcessList *process_list = control_flow_data->process_list;
2109 // LttTime birth = process->creation_time;
2111 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
2112 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2114 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
2115 //// hashed_process_data = processlist_get_process_data(process_list,
2120 // if(unlikely(hashed_process_data == NULL))
2122 // g_assert(pid == 0 || pid != process->ppid);
2123 // ResourceInfo *process_info;
2124 // /* Process not present */
2125 // Drawing_t *drawing = control_flow_data->drawing;
2126 // processlist_add(process_list,
2138 // &hashed_process_data);
2139 // gtk_widget_set_size_request(drawing->drawing_area,
2142 // gtk_widget_queue_draw(drawing->drawing_area);
2144 // /* Set the current process */
2145 // process_list->current_hash_data[trace_num][process->cpu] =
2146 // hashed_process_data;
2149 // processlist_set_brand(process_list, process->brand, hashed_process_data);
2156 /* after_event_enum_process_hook
2158 * Create the processlist entry for the child process. Put the last
2159 * position in x at the current time value.
2161 * @param hook_data ControlFlowData structure of the viewer.
2162 * @param call_data Event context.
2164 * This function adds items to be drawn in a queue for each process.
2167 //int after_event_enum_process_hook(void *hook_data, void *call_data)
2169 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2170 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2171 // ControlFlowData *control_flow_data = events_request->viewer_data;
2173 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2175 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2177 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2179 // guint first_cpu, nb_cpus, cpu;
2182 // e = ltt_tracefile_get_event(tfc->tf);
2184 // LttvFilter *filter = control_flow_data->filter;
2185 // if(filter != NULL && filter->head != NULL)
2186 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2187 // tfc->t_context->t,tfc,NULL,NULL))
2190 // LttTime evtime = ltt_event_time(e);
2192 // /* Add process to process list (if not present) */
2193 // LttvProcessState *process_in;
2195 // guint pl_height = 0;
2196 // HashedResourceData *hashed_process_data_in = NULL;
2198 // ProcessList *process_list = control_flow_data->process_list;
2199 // guint trace_num = ts->parent.index;
2203 // pid_in = ltt_event_get_long_unsigned(e, thf->f1);
2206 // if(pid_in == 0) {
2208 // nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
2210 // first_cpu = ANY_CPU;
2211 // nb_cpus = ANY_CPU+1;
2214 // for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
2215 // /* Find process pid_in in the list... */
2216 // process_in = lttv_state_find_process(ts, cpu, pid_in);
2217 // //process_in = tfs->process;
2218 // //guint cpu = tfs->cpu;
2219 // //guint trace_num = ts->parent.index;
2220 // //process_in = ts->running_process[cpu];
2221 // /* It should exist, because we are after the state update. */
2222 // #ifdef EXTRA_CHECK
2223 // //g_assert(process_in != NULL);
2224 // #endif //EXTRA_CHECK
2225 // birth = process_in->creation_time;
2227 // hashed_process_data_in = processlist_get_process_data(process_list, "CPU0");
2228 //// hashed_process_data_in = processlist_get_process_data(process_list,
2230 //// process_in->cpu,
2233 // if(hashed_process_data_in == NULL)
2235 // if(pid_in != 0 && pid_in == process_in->ppid)
2236 // g_critical("TEST %u , %u", pid_in, process_in->ppid);
2237 // g_assert(pid_in == 0 || pid_in != process_in->ppid);
2238 // ResourceInfo *process_info;
2239 // Drawing_t *drawing = control_flow_data->drawing;
2240 // /* Process not present */
2241 // processlist_add(process_list,
2244 // process_in->tgid,
2246 // process_in->ppid,
2249 // process_in->name,
2250 // process_in->brand,
2253 // &hashed_process_data_in);
2254 // gtk_widget_set_size_request(drawing->drawing_area,
2257 // gtk_widget_queue_draw(drawing->drawing_area);
2259 // processlist_set_name(process_list, process_in->name,
2260 // hashed_process_data_in);
2261 // processlist_set_ppid(process_list, process_in->ppid,
2262 // hashed_process_data_in);
2263 // processlist_set_tgid(process_list, process_in->tgid,
2264 // hashed_process_data_in);
2271 gint
update_time_window_hook(void *hook_data
, void *call_data
)
2273 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2274 Drawing_t
*drawing
= control_flow_data
->drawing
;
2275 ProcessList
*process_list
= control_flow_data
->process_list
;
2277 const TimeWindowNotifyData
*time_window_nofify_data
=
2278 ((const TimeWindowNotifyData
*)call_data
);
2280 TimeWindow
*old_time_window
=
2281 time_window_nofify_data
->old_time_window
;
2282 TimeWindow
*new_time_window
=
2283 time_window_nofify_data
->new_time_window
;
2285 /* Update the ruler */
2286 drawing_update_ruler(control_flow_data
->drawing
,
2290 /* Two cases : zoom in/out or scrolling */
2292 /* In order to make sure we can reuse the old drawing, the scale must
2293 * be the same and the new time interval being partly located in the
2294 * currently shown time interval. (reuse is only for scrolling)
2297 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
2298 old_time_window
->start_time
.tv_sec
,
2299 old_time_window
->start_time
.tv_nsec
,
2300 old_time_window
->time_width
.tv_sec
,
2301 old_time_window
->time_width
.tv_nsec
);
2303 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
2304 new_time_window
->start_time
.tv_sec
,
2305 new_time_window
->start_time
.tv_nsec
,
2306 new_time_window
->time_width
.tv_sec
,
2307 new_time_window
->time_width
.tv_nsec
);
2309 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
2310 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
2312 /* Same scale (scrolling) */
2313 g_info("scrolling");
2314 LttTime
*ns
= &new_time_window
->start_time
;
2315 LttTime
*nw
= &new_time_window
->time_width
;
2316 LttTime
*os
= &old_time_window
->start_time
;
2317 LttTime
*ow
= &old_time_window
->time_width
;
2318 LttTime old_end
= old_time_window
->end_time
;
2319 LttTime new_end
= new_time_window
->end_time
;
2321 //if(ns<os+w && os+w<ns+w)
2322 //if(ns<old_end && os<ns)
2323 if(ltt_time_compare(*ns
, old_end
) == -1
2324 && ltt_time_compare(*os
, *ns
) == -1)
2326 g_info("scrolling near right");
2327 /* Scroll right, keep right part of the screen */
2329 guint width
= control_flow_data
->drawing
->width
;
2330 convert_time_to_pixels(
2336 /* Copy old data to new location */
2337 copy_pixmap_region(process_list
,
2339 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2343 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
2345 if(drawing
->damage_begin
== drawing
->damage_end
)
2346 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
2348 drawing
->damage_begin
= 0;
2350 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2352 /* Clear the data request background, but not SAFETY */
2353 rectangle_pixmap(process_list
,
2354 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2356 drawing
->damage_begin
+SAFETY
, 0,
2357 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2359 gtk_widget_queue_draw(drawing
->drawing_area
);
2360 //gtk_widget_queue_draw_area (drawing->drawing_area,
2362 // control_flow_data->drawing->width,
2363 // control_flow_data->drawing->height);
2365 /* Get new data for the rest. */
2366 drawing_data_request(control_flow_data
->drawing
,
2367 drawing
->damage_begin
, 0,
2368 drawing
->damage_end
- drawing
->damage_begin
,
2369 control_flow_data
->drawing
->height
);
2372 //if(ns<os && os<ns+w)
2373 //if(ns<os && os<new_end)
2374 if(ltt_time_compare(*ns
,*os
) == -1
2375 && ltt_time_compare(*os
,new_end
) == -1)
2377 g_info("scrolling near left");
2378 /* Scroll left, keep left part of the screen */
2380 guint width
= control_flow_data
->drawing
->width
;
2381 convert_time_to_pixels(
2387 /* Copy old data to new location */
2388 copy_pixmap_region (process_list
,
2390 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2396 if(drawing
->damage_begin
== drawing
->damage_end
)
2397 drawing
->damage_end
= x
;
2399 drawing
->damage_end
=
2400 control_flow_data
->drawing
->width
;
2402 drawing
->damage_begin
= 0;
2404 rectangle_pixmap (process_list
,
2405 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2407 drawing
->damage_begin
, 0,
2408 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2411 gtk_widget_queue_draw(drawing
->drawing_area
);
2412 //gtk_widget_queue_draw_area (drawing->drawing_area,
2414 // control_flow_data->drawing->width,
2415 // control_flow_data->drawing->height);
2418 /* Get new data for the rest. */
2419 drawing_data_request(control_flow_data
->drawing
,
2420 drawing
->damage_begin
, 0,
2421 drawing
->damage_end
- drawing
->damage_begin
,
2422 control_flow_data
->drawing
->height
);
2425 if(ltt_time_compare(*ns
,*os
) == 0)
2427 g_info("not scrolling");
2429 g_info("scrolling far");
2430 /* Cannot reuse any part of the screen : far jump */
2433 rectangle_pixmap (process_list
,
2434 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2437 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2440 //gtk_widget_queue_draw_area (drawing->drawing_area,
2442 // control_flow_data->drawing->width,
2443 // control_flow_data->drawing->height);
2444 gtk_widget_queue_draw(drawing
->drawing_area
);
2446 drawing
->damage_begin
= 0;
2447 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2449 drawing_data_request(control_flow_data
->drawing
,
2451 control_flow_data
->drawing
->width
,
2452 control_flow_data
->drawing
->height
);
2458 /* Different scale (zoom) */
2461 rectangle_pixmap (process_list
,
2462 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2465 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2468 //gtk_widget_queue_draw_area (drawing->drawing_area,
2470 // control_flow_data->drawing->width,
2471 // control_flow_data->drawing->height);
2472 gtk_widget_queue_draw(drawing
->drawing_area
);
2474 drawing
->damage_begin
= 0;
2475 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2477 drawing_data_request(control_flow_data
->drawing
,
2479 control_flow_data
->drawing
->width
,
2480 control_flow_data
->drawing
->height
);
2483 /* Update directly when scrolling */
2484 gdk_window_process_updates(control_flow_data
->drawing
->drawing_area
->window
,
2490 gint
traceset_notify(void *hook_data
, void *call_data
)
2492 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2493 Drawing_t
*drawing
= control_flow_data
->drawing
;
2495 if(unlikely(drawing
->gc
== NULL
)) {
2498 if(drawing
->dotted_gc
== NULL
) {
2502 drawing_clear(control_flow_data
->drawing
);
2503 processlist_clear(control_flow_data
->process_list
);
2504 gtk_widget_set_size_request(
2505 control_flow_data
->drawing
->drawing_area
,
2506 -1, processlist_get_height(control_flow_data
->process_list
));
2507 redraw_notify(control_flow_data
, NULL
);
2509 request_background_data(control_flow_data
);
2514 gint
redraw_notify(void *hook_data
, void *call_data
)
2516 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2517 Drawing_t
*drawing
= control_flow_data
->drawing
;
2518 GtkWidget
*widget
= drawing
->drawing_area
;
2520 drawing
->damage_begin
= 0;
2521 drawing
->damage_end
= drawing
->width
;
2523 /* fun feature, to be separated someday... */
2524 drawing_clear(control_flow_data
->drawing
);
2525 processlist_clear(control_flow_data
->process_list
);
2526 gtk_widget_set_size_request(
2527 control_flow_data
->drawing
->drawing_area
,
2528 -1, processlist_get_height(control_flow_data
->process_list
));
2530 rectangle_pixmap (control_flow_data
->process_list
,
2531 widget
->style
->black_gc
,
2534 drawing
->alloc_width
,
2537 gtk_widget_queue_draw(drawing
->drawing_area
);
2539 if(drawing
->damage_begin
< drawing
->damage_end
)
2541 drawing_data_request(drawing
,
2542 drawing
->damage_begin
,
2544 drawing
->damage_end
-drawing
->damage_begin
,
2548 //gtk_widget_queue_draw_area(drawing->drawing_area,
2551 // drawing->height);
2557 gint
continue_notify(void *hook_data
, void *call_data
)
2559 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2560 Drawing_t
*drawing
= control_flow_data
->drawing
;
2562 //g_assert(widget->allocation.width == drawing->damage_end);
2564 if(drawing
->damage_begin
< drawing
->damage_end
)
2566 drawing_data_request(drawing
,
2567 drawing
->damage_begin
,
2569 drawing
->damage_end
-drawing
->damage_begin
,
2577 gint
update_current_time_hook(void *hook_data
, void *call_data
)
2579 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
2580 Drawing_t
*drawing
= control_flow_data
->drawing
;
2582 LttTime current_time
= *((LttTime
*)call_data
);
2584 TimeWindow time_window
=
2585 lttvwindow_get_time_window(control_flow_data
->tab
);
2587 LttTime time_begin
= time_window
.start_time
;
2588 LttTime width
= time_window
.time_width
;
2591 guint64 time_ll
= ltt_time_to_uint64(width
);
2592 time_ll
= time_ll
>> 1; /* divide by two */
2593 half_width
= ltt_time_from_uint64(time_ll
);
2595 LttTime time_end
= ltt_time_add(time_begin
, width
);
2597 LttvTracesetContext
* tsc
=
2598 lttvwindow_get_traceset_context(control_flow_data
->tab
);
2600 LttTime trace_start
= tsc
->time_span
.start_time
;
2601 LttTime trace_end
= tsc
->time_span
.end_time
;
2603 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
2604 current_time
.tv_nsec
);
2608 /* If current time is inside time interval, just move the highlight
2611 /* Else, we have to change the time interval. We have to tell it
2612 * to the main window. */
2613 /* The time interval change will take care of placing the current
2614 * time at the center of the visible area, or nearest possible if we are
2615 * at one end of the trace. */
2618 if(ltt_time_compare(current_time
, time_begin
) < 0)
2620 TimeWindow new_time_window
;
2622 if(ltt_time_compare(current_time
,
2623 ltt_time_add(trace_start
,half_width
)) < 0)
2624 time_begin
= trace_start
;
2626 time_begin
= ltt_time_sub(current_time
,half_width
);
2628 new_time_window
.start_time
= time_begin
;
2629 new_time_window
.time_width
= width
;
2630 new_time_window
.time_width_double
= ltt_time_to_double(width
);
2631 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
2633 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2635 else if(ltt_time_compare(current_time
, time_end
) > 0)
2637 TimeWindow new_time_window
;
2639 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
2640 time_begin
= ltt_time_sub(trace_end
,width
);
2642 time_begin
= ltt_time_sub(current_time
,half_width
);
2644 new_time_window
.start_time
= time_begin
;
2645 new_time_window
.time_width
= width
;
2646 new_time_window
.time_width_double
= ltt_time_to_double(width
);
2647 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
2649 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2652 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
2654 /* Update directly when scrolling */
2655 gdk_window_process_updates(control_flow_data
->drawing
->drawing_area
->window
,
2661 typedef struct _ClosureData
{
2662 EventsRequest
*events_request
;
2663 LttvTracesetState
*tss
;
2668 /* Draw line until end of the screen */
2670 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
2672 ResourceInfo
*process_info
= (ResourceInfo
*)key
;
2673 HashedResourceData
*hashed_process_data
= (HashedResourceData
*)value
;
2674 ClosureData
*closure_data
= (ClosureData
*)user_data
;
2676 EventsRequest
*events_request
= closure_data
->events_request
;
2677 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2679 LttvTracesetState
*tss
= closure_data
->tss
;
2680 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
2682 LttTime evtime
= closure_data
->end_time
;
2684 gboolean dodraw
= TRUE
;
2687 /* For the process */
2688 /* First, check if the current process is in the state computation
2689 * process list. If it is there, that means we must add it right now and
2690 * draw items from the beginning of the read for it. If it is not
2691 * present, it's a new process and it was not present : it will
2692 * be added after the state update. */
2694 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
2695 #endif //EXTRA_CHECK
2696 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
2697 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
2700 //FIXME : optimize data structures.
2701 LttvTracefileState
*tfs
;
2702 LttvTracefileContext
*tfc
;
2704 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
2705 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
2706 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
2707 && tfs
->cpu
== process_info
->cpu
)
2711 g_assert(i
<tc
->tracefiles
->len
);
2712 tfs
= LTTV_TRACEFILE_STATE(tfc
);
2714 // LttvTracefileState *tfs =
2715 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
2716 // tracefiles[process_info->cpu];
2718 // LttvProcessState *process;
2719 // process = lttv_state_find_process(ts, process_info->cpu,
2720 // process_info->pid);
2722 // if(unlikely(process != NULL)) {
2724 // LttvFilter *filter = control_flow_data->filter;
2725 // if(filter != NULL && filter->head != NULL)
2726 // if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
2727 // tc->t,NULL,process,tc))
2730 /* Only draw for processes that are currently in the trace states */
2732 ProcessList
*process_list
= control_flow_data
->process_list
;
2734 /* Should be alike when background info is ready */
2735 if(control_flow_data
->background_info_waiting
==0)
2736 g_assert(ltt_time_compare(process
->creation_time
,
2737 process_info
->birth
) == 0);
2738 #endif //EXTRA_CHECK
2740 /* Now, the process is in the state hash and our own process hash.
2741 * We definitely can draw the items related to the ending state.
2744 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2747 TimeWindow time_window
=
2748 lttvwindow_get_time_window(control_flow_data
->tab
);
2751 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2752 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2754 #endif //EXTRA_CHECK
2755 Drawing_t
*drawing
= control_flow_data
->drawing
;
2756 guint width
= drawing
->width
;
2758 guint x
= closure_data
->x_end
;
2760 DrawContext draw_context
;
2762 /* Now create the drawing context that will be used to draw
2763 * items related to the last state. */
2764 draw_context
.drawable
= hashed_process_data
->pixmap
;
2765 draw_context
.gc
= drawing
->gc
;
2766 draw_context
.pango_layout
= drawing
->pango_layout
;
2767 draw_context
.drawinfo
.end
.x
= x
;
2769 draw_context
.drawinfo
.y
.over
= 1;
2770 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2771 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2773 draw_context
.drawinfo
.start
.offset
.over
= 0;
2774 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2775 draw_context
.drawinfo
.start
.offset
.under
= 0;
2776 draw_context
.drawinfo
.end
.offset
.over
= 0;
2777 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2778 draw_context
.drawinfo
.end
.offset
.under
= 0;
2780 /* Jump over draw if we are at the same x position */
2781 if(x
== hashed_process_data
->x
.over
)
2785 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
2787 PropertiesLine prop_line
= prepare_execmode_line(process
);
2788 draw_line((void*)&prop_line
, (void*)&draw_context
);
2790 hashed_process_data
->x
.over
= x
;
2794 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2795 hashed_process_data
->x
.middle_used
)) {
2796 #if 0 /* do not mark closure : not missing information */
2797 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
2798 /* Draw collision indicator */
2799 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2800 gdk_draw_point(drawing
->pixmap
,
2804 hashed_process_data
->x
.middle_marked
= TRUE
;
2809 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2812 PropertiesLine prop_line
;
2813 prop_line
.line_width
= STATE_LINE_WIDTH
;
2814 prop_line
.style
= GDK_LINE_SOLID
;
2815 prop_line
.y
= MIDDLE
;
2816 if(process_info
->type
== 0)
2817 cpu_set_line_color(&prop_line
, &ts
->cpu_states
[process_info
->id
]);
2818 else if(process_info
->type
== 1)
2819 irq_set_line_color(&prop_line
, &ts
->irq_states
[process_info
->id
]);
2821 draw_line((void*)&prop_line
, (void*)&draw_context
);
2824 /* become the last x position */
2825 if(likely(x
!= hashed_process_data
->x
.middle
)) {
2826 hashed_process_data
->x
.middle
= x
;
2827 /* but don't use the pixel */
2828 hashed_process_data
->x
.middle_used
= FALSE
;
2830 /* Calculate the next good time */
2831 convert_pixels_to_time(width
, x
+1, time_window
,
2832 &hashed_process_data
->next_good_time
);
2841 int before_chunk(void *hook_data
, void *call_data
)
2843 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2844 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2845 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
2847 /* Desactivate sort */
2848 gtk_tree_sortable_set_sort_column_id(
2849 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
2851 GTK_SORT_ASCENDING
);
2853 drawing_chunk_begin(events_request
, tss
);
2858 int before_request(void *hook_data
, void *call_data
)
2860 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2861 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2863 drawing_data_request_begin(events_request
, tss
);
2870 * after request is necessary in addition of after chunk in order to draw
2871 * lines until the end of the screen. after chunk just draws lines until
2878 // TODO pmf: reenable this
2879 int after_request(void *hook_data
, void *call_data
)
2881 // EventsRequest *events_request = (EventsRequest*)hook_data;
2882 // ControlFlowData *control_flow_data = events_request->viewer_data;
2883 // LttvTracesetState *tss = (LttvTracesetState*)call_data;
2885 // ProcessList *process_list = control_flow_data->process_list;
2886 // LttTime end_time = events_request->end_time;
2888 // ClosureData closure_data;
2889 // closure_data.events_request = (EventsRequest*)hook_data;
2890 // closure_data.tss = tss;
2891 // closure_data.end_time = end_time;
2893 // TimeWindow time_window =
2894 // lttvwindow_get_time_window(control_flow_data->tab);
2895 // guint width = control_flow_data->drawing->width;
2896 // convert_time_to_pixels(
2900 // &closure_data.x_end);
2903 // /* Draw last items */
2904 // g_hash_table_foreach(process_list->process_hash, draw_closure,
2905 // (void*)&closure_data);
2908 // /* Request expose */
2909 // drawing_request_expose(events_request, tss, end_time);
2918 int after_chunk(void *hook_data
, void *call_data
)
2920 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2921 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2922 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2923 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
2924 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
2927 ProcessList
*process_list
= control_flow_data
->process_list
;
2929 LttvTraceset
*traceset
= tsc
->ts
;
2930 guint nb_trace
= lttv_traceset_number(traceset
);
2932 /* Only execute when called for the first trace's events request */
2933 if(!process_list
->current_hash_data
) return;
2935 for(i
= 0 ; i
< nb_trace
; i
++) {
2936 g_free(process_list
->current_hash_data
[i
]);
2938 g_free(process_list
->current_hash_data
);
2939 process_list
->current_hash_data
= NULL
;
2942 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
2943 else /* end of traceset, or position now out of request : end */
2944 end_time
= events_request
->end_time
;
2946 ClosureData closure_data
;
2947 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2948 closure_data
.tss
= tss
;
2949 closure_data
.end_time
= end_time
;
2951 TimeWindow time_window
=
2952 lttvwindow_get_time_window(control_flow_data
->tab
);
2953 guint width
= control_flow_data
->drawing
->width
;
2954 convert_time_to_pixels(
2958 &closure_data
.x_end
);
2960 /* Draw last items */
2961 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2962 (void*)&closure_data
);
2964 /* Reactivate sort */
2965 gtk_tree_sortable_set_sort_column_id(
2966 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
2967 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2968 GTK_SORT_ASCENDING
);
2970 update_index_to_pixmap(control_flow_data
->process_list
);
2971 /* Request a full expose : drawing scrambled */
2972 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
2974 /* Request expose (updates damages zone also) */
2975 drawing_request_expose(events_request
, tss
, end_time
);
2980 /* after_statedump_end
2982 * @param hook_data ControlFlowData structure of the viewer.
2983 * @param call_data Event context.
2985 * This function adds items to be drawn in a queue for each process.
2988 int before_statedump_end(void *hook_data
, void *call_data
)
2990 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2991 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2992 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2994 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2996 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2998 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3000 LttvTracesetState
*tss
= (LttvTracesetState
*)tfc
->t_context
->ts_context
;
3001 ProcessList
*process_list
= control_flow_data
->process_list
;
3004 e
= ltt_tracefile_get_event(tfc
->tf
);
3006 LttvFilter
*filter
= control_flow_data
->filter
;
3007 if(filter
!= NULL
&& filter
->head
!= NULL
)
3008 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
3009 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
3012 LttTime evtime
= ltt_event_time(e
);
3014 ClosureData closure_data
;
3015 closure_data
.events_request
= events_request
;
3016 closure_data
.tss
= tss
;
3017 closure_data
.end_time
= evtime
;
3019 TimeWindow time_window
=
3020 lttvwindow_get_time_window(control_flow_data
->tab
);
3021 guint width
= control_flow_data
->drawing
->width
;
3022 convert_time_to_pixels(
3026 &closure_data
.x_end
);
3028 /* Draw last items */
3029 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
3030 (void*)&closure_data
);
3032 /* Reactivate sort */
3033 gtk_tree_sortable_set_sort_column_id(
3034 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
3035 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
3036 GTK_SORT_ASCENDING
);
3038 update_index_to_pixmap(control_flow_data
->process_list
);
3039 /* Request a full expose : drawing scrambled */
3040 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
3042 /* Request expose (updates damages zone also) */
3043 drawing_request_expose(events_request
, tss
, evtime
);