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 */
321 /* before_schedchange_hook
323 * This function basically draw lines and icons. Two types of lines are drawn :
324 * one small (3 pixels?) representing the state of the process and the second
325 * type is thicker (10 pixels?) representing on which CPU a process is running
326 * (and this only in running state).
328 * Extremums of the lines :
329 * x_min : time of the last event context for this process kept in memory.
330 * x_max : time of the current event.
331 * y : middle of the process in the process list. The process is found in the
332 * list, therefore is it's position in pixels.
334 * The choice of lines'color is defined by the context of the last event for this
339 int before_schedchange_hook(void *hook_data
, void *call_data
)
341 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
342 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
343 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
345 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
347 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
348 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
351 e
= ltt_tracefile_get_event(tfc
->tf
);
352 gint target_pid_saved
= tfc
->target_pid
;
354 LttTime evtime
= ltt_event_time(e
);
355 LttvFilter
*filter
= control_flow_data
->filter
;
359 /* we are in a schedchange, before the state update. We must draw the
360 * items corresponding to the state before it changes : now is the right
366 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
367 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
368 // if(pid_in != 0 && pid_out != 0) {
369 // /* not a transition to/from idle */
373 tfc
->target_pid
= pid_out
;
374 // if(!filter || !filter->head ||
375 // lttv_filter_tree_parse(filter->head,e,tfc->tf,
376 // tfc->t_context->t,tfc,NULL,NULL)) {
377 /* For the pid_out */
378 /* First, check if the current process is in the state computation
379 * process list. If it is there, that means we must add it right now and
380 * draw items from the beginning of the read for it. If it is not
381 * present, it's a new process and it was not present : it will
382 * be added after the state update. */
383 guint cpu
= tfs
->cpu
;
386 cpustr
= g_strdup_printf("CPU%u", cpu
);
387 cpuq
= g_quark_from_string(cpustr
);
391 guint trace_num
= ts
->parent
.index
;
392 // LttvProcessState *process = ts->running_process[cpu];
393 /* unknown state, bad current pid */
394 // if(process->pid != pid_out)
395 // process = lttv_state_find_process(ts,
396 // tfs->cpu, pid_out);
398 // if(process != NULL) {
399 /* Well, the process_out existed : we must get it in the process hash
400 * or add it, and draw its items.
402 /* Add process to process list (if not present) */
404 HashedResourceData
*hashed_process_data
= NULL
;
405 ProcessList
*process_list
= control_flow_data
->process_list
;
406 // LttTime birth = process->creation_time;
408 hashed_process_data
= processlist_get_process_data(process_list
, cpuq
, trace_num
);
409 // hashed_process_data = processlist_get_process_data(process_list,
414 if(hashed_process_data
== NULL
)
416 // g_assert(pid_out == 0 || pid_out != process->ppid);
417 /* Process not present */
418 ResourceInfo
*process_info
;
419 Drawing_t
*drawing
= control_flow_data
->drawing
;
420 resourcelist_add(process_list
,
423 cpuq
, //process->name,
428 &hashed_process_data
);
429 gtk_widget_set_size_request(drawing
->drawing_area
,
432 gtk_widget_queue_draw(drawing
->drawing_area
);
436 /* Now, the process is in the state hash and our own process hash.
437 * We definitely can draw the items related to the ending state.
440 if(ltt_time_compare(hashed_process_data
->next_good_time
,
443 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
445 TimeWindow time_window
=
446 lttvwindow_get_time_window(control_flow_data
->tab
);
448 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
449 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
452 Drawing_t
*drawing
= control_flow_data
->drawing
;
453 guint width
= drawing
->width
;
455 convert_time_to_pixels(
461 /* Draw collision indicator */
462 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
463 gdk_draw_point(hashed_process_data
->pixmap
,
466 COLLISION_POSITION(hashed_process_data
->height
));
467 hashed_process_data
->x
.middle_marked
= TRUE
;
470 TimeWindow time_window
=
471 lttvwindow_get_time_window(control_flow_data
->tab
);
473 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
474 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
477 Drawing_t
*drawing
= control_flow_data
->drawing
;
478 guint width
= drawing
->width
;
480 convert_time_to_pixels(
487 /* Jump over draw if we are at the same x position */
488 if(x
== hashed_process_data
->x
.middle
&&
489 hashed_process_data
->x
.middle_used
)
491 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
492 /* Draw collision indicator */
493 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
494 gdk_draw_point(hashed_process_data
->pixmap
,
497 COLLISION_POSITION(hashed_process_data
->height
));
498 hashed_process_data
->x
.middle_marked
= TRUE
;
502 DrawContext draw_context
;
504 /* Now create the drawing context that will be used to draw
505 * items related to the last state. */
506 draw_context
.drawable
= hashed_process_data
->pixmap
;
507 draw_context
.gc
= drawing
->gc
;
508 draw_context
.pango_layout
= drawing
->pango_layout
;
509 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
510 draw_context
.drawinfo
.end
.x
= x
;
512 draw_context
.drawinfo
.y
.over
= 1;
513 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
514 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
516 draw_context
.drawinfo
.start
.offset
.over
= 0;
517 draw_context
.drawinfo
.start
.offset
.middle
= 0;
518 draw_context
.drawinfo
.start
.offset
.under
= 0;
519 draw_context
.drawinfo
.end
.offset
.over
= 0;
520 draw_context
.drawinfo
.end
.offset
.middle
= 0;
521 draw_context
.drawinfo
.end
.offset
.under
= 0;
525 //PropertiesLine prop_line = prepare_s_e_line(process);
526 PropertiesLine prop_line
;
527 prop_line
.line_width
= STATE_LINE_WIDTH
;
528 prop_line
.style
= GDK_LINE_SOLID
;
529 prop_line
.y
= MIDDLE
;
531 if(tfs
->cpu_state
->present_state
== LTTV_CPU_IDLE
) {
532 prop_line
.color
= drawing_colors_cpu
[COL_CPU_IDLE
];
535 prop_line
.color
= drawing_colors_cpu
[COL_CPU_BUSY
];
538 draw_line((void*)&prop_line
, (void*)&draw_context
);
541 /* become the last x position */
542 hashed_process_data
->x
.middle
= x
;
543 hashed_process_data
->x
.middle_used
= TRUE
;
544 hashed_process_data
->x
.middle_marked
= FALSE
;
546 /* Calculate the next good time */
547 convert_pixels_to_time(width
, x
+1, time_window
,
548 &hashed_process_data
->next_good_time
);
554 // tfc->target_pid = pid_in;
555 // if(!filter || !filter->head ||
556 // lttv_filter_tree_parse(filter->head,e,tfc->tf,
557 // tfc->t_context->t,tfc,NULL,NULL)) {
558 // /* For the pid_in */
559 // /* First, check if the current process is in the state computation
560 // * process list. If it is there, that means we must add it right now and
561 // * draw items from the beginning of the read for it. If it is not
562 // * present, it's a new process and it was not present : it will
563 // * be added after the state update. */
564 // LttvProcessState *process;
565 // process = lttv_state_find_process(ts,
566 // tfs->cpu, pid_in);
567 // guint trace_num = ts->parent.index;
569 // if(process != NULL) {
570 // /* Well, the process existed : we must get it in the process hash
571 // * or add it, and draw its items.
573 // /* Add process to process list (if not present) */
574 // guint pl_height = 0;
575 // HashedResourceData *hashed_process_data = NULL;
576 // ProcessList *process_list = control_flow_data->process_list;
577 // LttTime birth = process->creation_time;
579 // hashed_process_data = processlist_get_process_data(process_list, cpuq);
580 //// hashed_process_data = processlist_get_process_data(process_list,
585 // if(hashed_process_data == NULL)
587 // g_assert(pid_in == 0 || pid_in != process->ppid);
588 // /* Process not present */
589 // ResourceInfo *process_info;
590 // Drawing_t *drawing = control_flow_data->drawing;
591 // resourcelist_add(process_list,
603 // &hashed_process_data);
604 // gtk_widget_set_size_request(drawing->drawing_area,
607 // gtk_widget_queue_draw(drawing->drawing_area);
610 // //We could set the current process and hash here, but will be done
611 // //by after schedchange hook
613 // /* Now, the process is in the state hash and our own process hash.
614 // * We definitely can draw the items related to the ending state.
617 // if(ltt_time_compare(hashed_process_data->next_good_time,
620 // if(hashed_process_data->x.middle_marked == FALSE) {
622 // TimeWindow time_window =
623 // lttvwindow_get_time_window(control_flow_data->tab);
625 // if(ltt_time_compare(evtime, time_window.start_time) == -1
626 // || ltt_time_compare(evtime, time_window.end_time) == 1)
628 //#endif //EXTRA_CHECK
629 // Drawing_t *drawing = control_flow_data->drawing;
630 // guint width = drawing->width;
632 // convert_time_to_pixels(
638 // /* Draw collision indicator */
639 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
640 // gdk_draw_point(hashed_process_data->pixmap,
643 // COLLISION_POSITION(hashed_process_data->height));
644 // hashed_process_data->x.middle_marked = TRUE;
647 // TimeWindow time_window =
648 // lttvwindow_get_time_window(control_flow_data->tab);
650 // if(ltt_time_compare(evtime, time_window.start_time) == -1
651 // || ltt_time_compare(evtime, time_window.end_time) == 1)
653 //#endif //EXTRA_CHECK
654 // Drawing_t *drawing = control_flow_data->drawing;
655 // guint width = drawing->width;
658 // convert_time_to_pixels(
665 // /* Jump over draw if we are at the same x position */
666 // if(x == hashed_process_data->x.middle &&
667 // hashed_process_data->x.middle_used)
669 // if(hashed_process_data->x.middle_marked == FALSE) {
670 // /* Draw collision indicator */
671 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
672 // gdk_draw_point(hashed_process_data->pixmap,
675 // COLLISION_POSITION(hashed_process_data->height));
676 // hashed_process_data->x.middle_marked = TRUE;
680 // DrawContext draw_context;
682 // /* Now create the drawing context that will be used to draw
683 // * items related to the last state. */
684 // draw_context.drawable = hashed_process_data->pixmap;
685 // draw_context.gc = drawing->gc;
686 // draw_context.pango_layout = drawing->pango_layout;
687 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
688 // draw_context.drawinfo.end.x = x;
690 // draw_context.drawinfo.y.over = 1;
691 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
692 // draw_context.drawinfo.y.under = hashed_process_data->height;
694 // draw_context.drawinfo.start.offset.over = 0;
695 // draw_context.drawinfo.start.offset.middle = 0;
696 // draw_context.drawinfo.start.offset.under = 0;
697 // draw_context.drawinfo.end.offset.over = 0;
698 // draw_context.drawinfo.end.offset.middle = 0;
699 // draw_context.drawinfo.end.offset.under = 0;
702 // /* Draw the line */
703 // PropertiesLine prop_line = prepare_s_e_line(process);
704 // draw_line((void*)&prop_line, (void*)&draw_context);
708 // /* become the last x position */
709 // hashed_process_data->x.middle = x;
710 // hashed_process_data->x.middle_used = TRUE;
711 // hashed_process_data->x.middle_marked = FALSE;
713 // /* Calculate the next good time */
714 // convert_pixels_to_time(width, x+1, time_window,
715 // &hashed_process_data->next_good_time);
719 // g_warning("Cannot find pin_in in schedchange %u", pid_in);
721 // tfc->target_pid = target_pid_saved;
729 GString
*string
= g_string_new("");;
730 gboolean field_names
= TRUE
, state
= TRUE
;
732 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
733 g_string_append_printf(string
,"\n");
736 g_string_append_printf(string
, " %s",
737 g_quark_to_string(tfs
->process
->state
->s
));
740 g_info("%s",string
->str
);
742 g_string_free(string
, TRUE
);
744 /* End of text dump */
749 /* after_schedchange_hook
751 * The draw after hook is called by the reading API to have a
752 * particular event drawn on the screen.
753 * @param hook_data ControlFlowData structure of the viewer.
754 * @param call_data Event context.
756 * This function adds items to be drawn in a queue for each process.
759 int after_schedchange_hook(void *hook_data
, void *call_data
)
761 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
762 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
763 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
765 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
767 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
769 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
772 e
= ltt_tracefile_get_event(tfc
->tf
);
774 LttvFilter
*filter
= control_flow_data
->filter
;
775 if(filter
!= NULL
&& filter
->head
!= NULL
)
776 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
777 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
780 LttTime evtime
= ltt_event_time(e
);
784 /* Add process to process list (if not present) */
785 LttvProcessState
*process_in
;
788 HashedResourceData
*hashed_process_data_in
= NULL
;
790 ProcessList
*process_list
= control_flow_data
->process_list
;
795 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
796 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
800 /* Find process pid_in in the list... */
801 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
802 //process_in = tfs->process;
803 guint cpu
= tfs
->cpu
;
806 cpustr
= g_strdup_printf("CPU%u", cpu
);
807 cpuq
= g_quark_from_string(cpustr
);
810 guint trace_num
= ts
->parent
.index
;
811 process_in
= ts
->running_process
[cpu
];
812 /* It should exist, because we are after the state update. */
814 g_assert(process_in
!= NULL
);
816 birth
= process_in
->creation_time
;
818 hashed_process_data_in
= processlist_get_process_data(process_list
, cpuq
, trace_num
);
819 // hashed_process_data_in = processlist_get_process_data(process_list,
824 if(hashed_process_data_in
== NULL
)
826 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
827 ResourceInfo
*process_info
;
828 Drawing_t
*drawing
= control_flow_data
->drawing
;
829 /* Process not present */
830 resourcelist_add(process_list
,
838 &hashed_process_data_in
);
839 gtk_widget_set_size_request(drawing
->drawing_area
,
842 gtk_widget_queue_draw(drawing
->drawing_area
);
844 /* Set the current process */
845 process_list
->current_hash_data
[trace_num
][process_in
->cpu
] =
846 hashed_process_data_in
;
848 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
851 TimeWindow time_window
=
852 lttvwindow_get_time_window(control_flow_data
->tab
);
855 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
856 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
859 Drawing_t
*drawing
= control_flow_data
->drawing
;
860 guint width
= drawing
->width
;
863 convert_time_to_pixels(
869 if(hashed_process_data_in
->x
.middle
!= new_x
) {
870 hashed_process_data_in
->x
.middle
= new_x
;
871 hashed_process_data_in
->x
.middle_used
= FALSE
;
872 hashed_process_data_in
->x
.middle_marked
= FALSE
;
878 /* before_execmode_hook
880 * This function basically draw lines and icons. Two types of lines are drawn :
881 * one small (3 pixels?) representing the state of the process and the second
882 * type is thicker (10 pixels?) representing on which CPU a process is running
883 * (and this only in running state).
885 * Extremums of the lines :
886 * x_min : time of the last event context for this process kept in memory.
887 * x_max : time of the current event.
888 * y : middle of the process in the process list. The process is found in the
889 * list, therefore is it's position in pixels.
891 * The choice of lines'color is defined by the context of the last event for this
895 //int before_execmode_hook(void *hook_data, void *call_data)
897 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
898 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
899 // ControlFlowData *control_flow_data = events_request->viewer_data;
901 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
903 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
905 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
908 // e = ltt_tracefile_get_event(tfc->tf);
910 // LttvFilter *filter = control_flow_data->filter;
911 // if(filter != NULL && filter->head != NULL)
912 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
913 // tfc->t_context->t,tfc,NULL,NULL))
916 // LttTime evtime = ltt_event_time(e);
918 // /* we are in a execmode, before the state update. We must draw the
919 // * items corresponding to the state before it changes : now is the right
923 // //LttvProcessState *process = tfs->process;
924 // guint cpu = tfs->cpu;
925 // guint trace_num = ts->parent.index;
926 // LttvProcessState *process = ts->running_process[cpu];
927 // g_assert(process != NULL);
929 // guint pid = process->pid;
931 // /* Well, the process_out existed : we must get it in the process hash
932 // * or add it, and draw its items.
934 // /* Add process to process list (if not present) */
935 // guint pl_height = 0;
936 // HashedResourceData *hashed_process_data = NULL;
937 // ProcessList *process_list = control_flow_data->process_list;
938 // LttTime birth = process->creation_time;
940 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
941 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
943 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
944 //// hashed_process_data = processlist_get_process_data(process_list,
949 // if(unlikely(hashed_process_data == NULL))
951 // g_assert(pid == 0 || pid != process->ppid);
952 // ResourceInfo *process_info;
953 // /* Process not present */
954 // Drawing_t *drawing = control_flow_data->drawing;
955 // processlist_add(process_list,
967 // &hashed_process_data);
968 // gtk_widget_set_size_request(drawing->drawing_area,
971 // gtk_widget_queue_draw(drawing->drawing_area);
973 // /* Set the current process */
974 // process_list->current_hash_data[trace_num][process->cpu] =
975 // hashed_process_data;
978 // /* Now, the process is in the state hash and our own process hash.
979 // * We definitely can draw the items related to the ending state.
982 // if(likely(ltt_time_compare(hashed_process_data->next_good_time,
985 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
986 // TimeWindow time_window =
987 // lttvwindow_get_time_window(control_flow_data->tab);
990 // if(ltt_time_compare(evtime, time_window.start_time) == -1
991 // || ltt_time_compare(evtime, time_window.end_time) == 1)
993 //#endif //EXTRA_CHECK
994 // Drawing_t *drawing = control_flow_data->drawing;
995 // guint width = drawing->width;
997 // convert_time_to_pixels(
1003 // /* Draw collision indicator */
1004 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1005 // gdk_draw_point(hashed_process_data->pixmap,
1008 // COLLISION_POSITION(hashed_process_data->height));
1009 // hashed_process_data->x.middle_marked = TRUE;
1012 // TimeWindow time_window =
1013 // lttvwindow_get_time_window(control_flow_data->tab);
1015 //#ifdef EXTRA_CHECK
1016 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1017 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1019 //#endif //EXTRA_CHECK
1020 // Drawing_t *drawing = control_flow_data->drawing;
1021 // guint width = drawing->width;
1024 // convert_time_to_pixels(
1031 // /* Jump over draw if we are at the same x position */
1032 // if(unlikely(x == hashed_process_data->x.middle &&
1033 // hashed_process_data->x.middle_used))
1035 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1036 // /* Draw collision indicator */
1037 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1038 // gdk_draw_point(hashed_process_data->pixmap,
1041 // COLLISION_POSITION(hashed_process_data->height));
1042 // hashed_process_data->x.middle_marked = TRUE;
1047 // DrawContext draw_context;
1048 // /* Now create the drawing context that will be used to draw
1049 // * items related to the last state. */
1050 // draw_context.drawable = hashed_process_data->pixmap;
1051 // draw_context.gc = drawing->gc;
1052 // draw_context.pango_layout = drawing->pango_layout;
1053 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1054 // draw_context.drawinfo.end.x = x;
1056 // draw_context.drawinfo.y.over = 1;
1057 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1058 // draw_context.drawinfo.y.under = hashed_process_data->height;
1060 // draw_context.drawinfo.start.offset.over = 0;
1061 // draw_context.drawinfo.start.offset.middle = 0;
1062 // draw_context.drawinfo.start.offset.under = 0;
1063 // draw_context.drawinfo.end.offset.over = 0;
1064 // draw_context.drawinfo.end.offset.middle = 0;
1065 // draw_context.drawinfo.end.offset.under = 0;
1068 // /* Draw the line */
1069 // PropertiesLine prop_line = prepare_s_e_line(process);
1070 // draw_line((void*)&prop_line, (void*)&draw_context);
1073 // /* become the last x position */
1074 // hashed_process_data->x.middle = x;
1075 // hashed_process_data->x.middle_used = TRUE;
1076 // hashed_process_data->x.middle_marked = FALSE;
1078 // /* Calculate the next good time */
1079 // convert_pixels_to_time(width, x+1, time_window,
1080 // &hashed_process_data->next_good_time);
1087 /* before_process_exit_hook
1089 * Draw lines for process event.
1091 * @param hook_data ControlFlowData structure of the viewer.
1092 * @param call_data Event context.
1094 * This function adds items to be drawn in a queue for each process.
1098 //int before_process_exit_hook(void *hook_data, void *call_data)
1100 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1101 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1103 // ControlFlowData *control_flow_data = events_request->viewer_data;
1105 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1107 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1109 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1112 // e = ltt_tracefile_get_event(tfc->tf);
1114 // LttvFilter *filter = control_flow_data->filter;
1115 // if(filter != NULL && filter->head != NULL)
1116 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1117 // tfc->t_context->t,tfc,NULL,NULL))
1120 // LttTime evtime = ltt_event_time(e);
1122 // /* Add process to process list (if not present) */
1123 // //LttvProcessState *process = tfs->process;
1124 // guint cpu = tfs->cpu;
1125 // guint trace_num = ts->parent.index;
1126 // LttvProcessState *process = ts->running_process[cpu];
1127 // guint pid = process->pid;
1129 // guint pl_height = 0;
1130 // HashedResourceData *hashed_process_data = NULL;
1132 // ProcessList *process_list = control_flow_data->process_list;
1134 // g_assert(process != NULL);
1136 // birth = process->creation_time;
1138 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1139 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1141 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1142 //// hashed_process_data = processlist_get_process_data(process_list,
1147 // if(unlikely(hashed_process_data == NULL))
1149 // g_assert(pid == 0 || pid != process->ppid);
1150 // /* Process not present */
1151 // Drawing_t *drawing = control_flow_data->drawing;
1152 // ResourceInfo *process_info;
1153 // processlist_add(process_list,
1165 // &hashed_process_data);
1166 // gtk_widget_set_size_request(drawing->drawing_area,
1169 // gtk_widget_queue_draw(drawing->drawing_area);
1173 // /* Now, the process is in the state hash and our own process hash.
1174 // * We definitely can draw the items related to the ending state.
1177 // if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1180 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1181 // TimeWindow time_window =
1182 // lttvwindow_get_time_window(control_flow_data->tab);
1184 //#ifdef EXTRA_CHECK
1185 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1186 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1188 //#endif //EXTRA_CHECK
1189 // Drawing_t *drawing = control_flow_data->drawing;
1190 // guint width = drawing->width;
1192 // convert_time_to_pixels(
1198 // /* Draw collision indicator */
1199 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1200 // gdk_draw_point(hashed_process_data->pixmap,
1203 // COLLISION_POSITION(hashed_process_data->height));
1204 // hashed_process_data->x.middle_marked = TRUE;
1207 // TimeWindow time_window =
1208 // lttvwindow_get_time_window(control_flow_data->tab);
1210 //#ifdef EXTRA_CHECK
1211 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1212 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1214 //#endif //EXTRA_CHECK
1215 // Drawing_t *drawing = control_flow_data->drawing;
1216 // guint width = drawing->width;
1219 // convert_time_to_pixels(
1226 // /* Jump over draw if we are at the same x position */
1227 // if(unlikely(x == hashed_process_data->x.middle &&
1228 // hashed_process_data->x.middle_used))
1230 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1231 // /* Draw collision indicator */
1232 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1233 // gdk_draw_point(hashed_process_data->pixmap,
1236 // COLLISION_POSITION(hashed_process_data->height));
1237 // hashed_process_data->x.middle_marked = TRUE;
1241 // DrawContext draw_context;
1243 // /* Now create the drawing context that will be used to draw
1244 // * items related to the last state. */
1245 // draw_context.drawable = hashed_process_data->pixmap;
1246 // draw_context.gc = drawing->gc;
1247 // draw_context.pango_layout = drawing->pango_layout;
1248 // draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1249 // draw_context.drawinfo.end.x = x;
1251 // draw_context.drawinfo.y.over = 1;
1252 // draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1253 // draw_context.drawinfo.y.under = hashed_process_data->height;
1255 // draw_context.drawinfo.start.offset.over = 0;
1256 // draw_context.drawinfo.start.offset.middle = 0;
1257 // draw_context.drawinfo.start.offset.under = 0;
1258 // draw_context.drawinfo.end.offset.over = 0;
1259 // draw_context.drawinfo.end.offset.middle = 0;
1260 // draw_context.drawinfo.end.offset.under = 0;
1263 // /* Draw the line */
1264 // PropertiesLine prop_line = prepare_s_e_line(process);
1265 // draw_line((void*)&prop_line, (void*)&draw_context);
1268 // /* become the last x position */
1269 // hashed_process_data->x.middle = x;
1270 // hashed_process_data->x.middle_used = TRUE;
1271 // hashed_process_data->x.middle_marked = FALSE;
1273 // /* Calculate the next good time */
1274 // convert_pixels_to_time(width, x+1, time_window,
1275 // &hashed_process_data->next_good_time);
1284 /* before_process_release_hook
1286 * Draw lines for process event.
1288 * @param hook_data ControlFlowData structure of the viewer.
1289 * @param call_data Event context.
1291 * This function adds items to be drawn in a queue for each process.
1295 //int before_process_release_hook(void *hook_data, void *call_data)
1297 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1298 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1300 // ControlFlowData *control_flow_data = events_request->viewer_data;
1302 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1304 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1306 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1309 // e = ltt_tracefile_get_event(tfc->tf);
1311 // LttvFilter *filter = control_flow_data->filter;
1312 // if(filter != NULL && filter->head != NULL)
1313 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1314 // tfc->t_context->t,tfc,NULL,NULL))
1317 // LttTime evtime = ltt_event_time(e);
1319 // guint trace_num = ts->parent.index;
1323 // pid = ltt_event_get_long_unsigned(e, thf->f1);
1326 // /* Add process to process list (if not present) */
1327 // /* Don't care about the process if it's not in the state hash already :
1328 // * that means a process that has never done anything in the trace and
1329 // * unknown suddently gets destroyed : no state meaningful to show. */
1330 // LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
1332 // if(process != NULL) {
1334 // guint pl_height = 0;
1335 // HashedResourceData *hashed_process_data = NULL;
1337 // ProcessList *process_list = control_flow_data->process_list;
1339 // birth = process->creation_time;
1341 // /* Cannot use current process : this event happens on another process,
1342 // * action done by the parent. */
1343 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1344 //// hashed_process_data = processlist_get_process_data(process_list,
1349 // if(unlikely(hashed_process_data == NULL))
1351 // g_assert(pid == 0 || pid != process->ppid);
1352 // /* Process not present */
1353 // Drawing_t *drawing = control_flow_data->drawing;
1354 // ResourceInfo *process_info;
1355 // processlist_add(process_list,
1367 // &hashed_process_data);
1368 // gtk_widget_set_size_request(drawing->drawing_area,
1371 // gtk_widget_queue_draw(drawing->drawing_area);
1374 // /* Now, the process is in the state hash and our own process hash.
1375 // * We definitely can draw the items related to the ending state.
1378 // if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1381 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1382 // TimeWindow time_window =
1383 // lttvwindow_get_time_window(control_flow_data->tab);
1385 //#ifdef EXTRA_CHECK
1386 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1387 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1389 //#endif //EXTRA_CHECK
1390 // Drawing_t *drawing = control_flow_data->drawing;
1391 // guint width = drawing->width;
1393 // convert_time_to_pixels(
1399 // /* Draw collision indicator */
1400 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1401 // gdk_draw_point(hashed_process_data->pixmap,
1404 // COLLISION_POSITION(hashed_process_data->height));
1405 // hashed_process_data->x.middle_marked = TRUE;
1408 // TimeWindow time_window =
1409 // lttvwindow_get_time_window(control_flow_data->tab);
1411 //#ifdef EXTRA_CHECK
1412 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1413 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1415 //#endif //EXTRA_CHECK
1416 // Drawing_t *drawing = control_flow_data->drawing;
1417 // guint width = drawing->width;
1420 // convert_time_to_pixels(
1427 // /* Jump over draw if we are at the same x position */
1428 // if(unlikely(x == hashed_process_data->x.middle &&
1429 // hashed_process_data->x.middle_used))
1431 // if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1432 // /* Draw collision indicator */
1433 // gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1434 // gdk_draw_point(hashed_process_data->pixmap,
1437 // COLLISION_POSITION(hashed_process_data->height));
1438 // hashed_process_data->x.middle_marked = TRUE;
1442 // 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;
1464 // /* Draw the line */
1465 // PropertiesLine prop_line = prepare_s_e_line(process);
1466 // draw_line((void*)&prop_line, (void*)&draw_context);
1469 // /* become the last x position */
1470 // hashed_process_data->x.middle = x;
1471 // hashed_process_data->x.middle_used = TRUE;
1472 // hashed_process_data->x.middle_marked = FALSE;
1474 // /* Calculate the next good time */
1475 // convert_pixels_to_time(width, x+1, time_window,
1476 // &hashed_process_data->next_good_time);
1484 /* after_process_fork_hook
1486 * Create the processlist entry for the child process. Put the last
1487 * position in x at the current time value.
1489 * @param hook_data ControlFlowData structure of the viewer.
1490 * @param call_data Event context.
1492 * This function adds items to be drawn in a queue for each process.
1495 //int after_process_fork_hook(void *hook_data, void *call_data)
1497 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1498 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1499 // ControlFlowData *control_flow_data = events_request->viewer_data;
1501 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1503 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1505 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1508 // e = ltt_tracefile_get_event(tfc->tf);
1510 // LttvFilter *filter = control_flow_data->filter;
1511 // if(filter != NULL && filter->head != NULL)
1512 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1513 // tfc->t_context->t,tfc,NULL,NULL))
1516 // LttTime evtime = ltt_event_time(e);
1520 // child_pid = ltt_event_get_long_unsigned(e, thf->f2);
1523 // /* Add process to process list (if not present) */
1524 // LttvProcessState *process_child;
1526 // guint pl_height = 0;
1527 // HashedResourceData *hashed_process_data_child = NULL;
1529 // ProcessList *process_list = control_flow_data->process_list;
1531 // /* Find child in the list... */
1532 // process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
1533 // /* It should exist, because we are after the state update. */
1534 // g_assert(process_child != NULL);
1536 // birth = process_child->creation_time;
1537 // guint trace_num = ts->parent.index;
1539 // /* Cannot use current process, because this action is done by the parent
1540 // * on its child. */
1541 // hashed_process_data_child = processlist_get_process_data(process_list, "CPU0");
1542 //// hashed_process_data_child = processlist_get_process_data(process_list,
1544 //// process_child->cpu,
1547 // if(likely(hashed_process_data_child == NULL))
1549 // g_assert(child_pid == 0 || child_pid != process_child->ppid);
1550 // /* Process not present */
1551 // Drawing_t *drawing = control_flow_data->drawing;
1552 // ResourceInfo *process_info;
1553 // processlist_add(process_list,
1556 // process_child->tgid,
1557 // process_child->cpu,
1558 // process_child->ppid,
1561 // process_child->name,
1562 // process_child->brand,
1565 // &hashed_process_data_child);
1566 // gtk_widget_set_size_request(drawing->drawing_area,
1569 // gtk_widget_queue_draw(drawing->drawing_area);
1571 // processlist_set_ppid(process_list, process_child->ppid,
1572 // hashed_process_data_child);
1573 // processlist_set_tgid(process_list, process_child->tgid,
1574 // hashed_process_data_child);
1578 // if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1581 // TimeWindow time_window =
1582 // lttvwindow_get_time_window(control_flow_data->tab);
1584 //#ifdef EXTRA_CHECK
1585 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1586 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1588 //#endif //EXTRA_CHECK
1589 // Drawing_t *drawing = control_flow_data->drawing;
1590 // guint width = drawing->width;
1592 // convert_time_to_pixels(
1598 // if(likely(hashed_process_data_child->x.over != new_x)) {
1599 // hashed_process_data_child->x.over = new_x;
1600 // hashed_process_data_child->x.over_used = FALSE;
1601 // hashed_process_data_child->x.over_marked = FALSE;
1603 // if(likely(hashed_process_data_child->x.middle != new_x)) {
1604 // hashed_process_data_child->x.middle = new_x;
1605 // hashed_process_data_child->x.middle_used = FALSE;
1606 // hashed_process_data_child->x.middle_marked = FALSE;
1608 // if(likely(hashed_process_data_child->x.under != new_x)) {
1609 // hashed_process_data_child->x.under = new_x;
1610 // hashed_process_data_child->x.under_used = FALSE;
1611 // hashed_process_data_child->x.under_marked = FALSE;
1619 /* after_process_exit_hook
1621 * Create the processlist entry for the child process. Put the last
1622 * position in x at the current time value.
1624 * @param hook_data ControlFlowData structure of the viewer.
1625 * @param call_data Event context.
1627 * This function adds items to be drawn in a queue for each process.
1630 //int after_process_exit_hook(void *hook_data, void *call_data)
1632 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1633 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1634 // ControlFlowData *control_flow_data = events_request->viewer_data;
1636 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1638 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1640 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1643 // e = ltt_tracefile_get_event(tfc->tf);
1645 // LttvFilter *filter = control_flow_data->filter;
1646 // if(filter != NULL && filter->head != NULL)
1647 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1648 // tfc->t_context->t,tfc,NULL,NULL))
1651 // LttTime evtime = ltt_event_time(e);
1653 // /* Add process to process list (if not present) */
1654 // //LttvProcessState *process = tfs->process;
1655 // guint cpu = tfs->cpu;
1656 // guint trace_num = ts->parent.index;
1657 // LttvProcessState *process = ts->running_process[cpu];
1659 // /* It should exist, because we are after the state update. */
1660 // g_assert(process != NULL);
1662 // guint pid = process->pid;
1664 // guint pl_height = 0;
1665 // HashedResourceData *hashed_process_data = NULL;
1667 // ProcessList *process_list = control_flow_data->process_list;
1669 // birth = process->creation_time;
1671 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1672 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1674 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1675 //// hashed_process_data = processlist_get_process_data(process_list,
1680 // if(unlikely(hashed_process_data == NULL))
1682 // g_assert(pid == 0 || pid != process->ppid);
1683 // /* Process not present */
1684 // Drawing_t *drawing = control_flow_data->drawing;
1685 // ResourceInfo *process_info;
1686 // processlist_add(process_list,
1698 // &hashed_process_data);
1699 // gtk_widget_set_size_request(drawing->drawing_area,
1702 // gtk_widget_queue_draw(drawing->drawing_area);
1705 // /* Set the current process */
1706 // process_list->current_hash_data[trace_num][process->cpu] =
1707 // hashed_process_data;
1710 // if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1713 // TimeWindow time_window =
1714 // lttvwindow_get_time_window(control_flow_data->tab);
1716 //#ifdef EXTRA_CHECK
1717 // if(ltt_time_compare(evtime, time_window.start_time) == -1
1718 // || ltt_time_compare(evtime, time_window.end_time) == 1)
1720 //#endif //EXTRA_CHECK
1721 // Drawing_t *drawing = control_flow_data->drawing;
1722 // guint width = drawing->width;
1724 // convert_time_to_pixels(
1729 // if(unlikely(hashed_process_data->x.middle != new_x)) {
1730 // hashed_process_data->x.middle = new_x;
1731 // hashed_process_data->x.middle_used = FALSE;
1732 // hashed_process_data->x.middle_marked = FALSE;
1740 /* Get the filename of the process to print */
1741 //int after_fs_exec_hook(void *hook_data, void *call_data)
1743 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1744 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1745 // ControlFlowData *control_flow_data = events_request->viewer_data;
1747 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1749 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1751 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1754 // e = ltt_tracefile_get_event(tfc->tf);
1756 // LttvFilter *filter = control_flow_data->filter;
1757 // if(filter != NULL && filter->head != NULL)
1758 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1759 // tfc->t_context->t,tfc,NULL,NULL))
1762 // guint cpu = tfs->cpu;
1763 // guint trace_num = ts->parent.index;
1764 // LttvProcessState *process = ts->running_process[cpu];
1765 // g_assert(process != NULL);
1767 // guint pid = process->pid;
1769 // /* Well, the process_out existed : we must get it in the process hash
1770 // * or add it, and draw its items.
1772 // /* Add process to process list (if not present) */
1773 // guint pl_height = 0;
1774 // HashedResourceData *hashed_process_data = NULL;
1775 // ProcessList *process_list = control_flow_data->process_list;
1776 // LttTime birth = process->creation_time;
1778 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1779 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1781 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1782 //// hashed_process_data = processlist_get_process_data(process_list,
1787 // if(unlikely(hashed_process_data == NULL))
1789 // g_assert(pid == 0 || pid != process->ppid);
1790 // ResourceInfo *process_info;
1791 // /* Process not present */
1792 // Drawing_t *drawing = control_flow_data->drawing;
1793 // processlist_add(process_list,
1805 // &hashed_process_data);
1806 // gtk_widget_set_size_request(drawing->drawing_area,
1809 // gtk_widget_queue_draw(drawing->drawing_area);
1811 // /* Set the current process */
1812 // process_list->current_hash_data[trace_num][process->cpu] =
1813 // hashed_process_data;
1816 // processlist_set_name(process_list, process->name, hashed_process_data);
1822 /* Get the filename of the process to print */
1823 //int after_user_generic_thread_brand_hook(void *hook_data, void *call_data)
1825 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1826 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1827 // ControlFlowData *control_flow_data = events_request->viewer_data;
1829 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1831 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1833 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1836 // e = ltt_tracefile_get_event(tfc->tf);
1838 // LttvFilter *filter = control_flow_data->filter;
1839 // if(filter != NULL && filter->head != NULL)
1840 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1841 // tfc->t_context->t,tfc,NULL,NULL))
1844 // guint cpu = tfs->cpu;
1845 // guint trace_num = ts->parent.index;
1846 // LttvProcessState *process = ts->running_process[cpu];
1847 // g_assert(process != NULL);
1849 // guint pid = process->pid;
1851 // /* Well, the process_out existed : we must get it in the process hash
1852 // * or add it, and draw its items.
1854 // /* Add process to process list (if not present) */
1855 // guint pl_height = 0;
1856 // HashedResourceData *hashed_process_data = NULL;
1857 // ProcessList *process_list = control_flow_data->process_list;
1858 // LttTime birth = process->creation_time;
1860 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1861 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1863 // hashed_process_data = processlist_get_process_data(process_list, "CPU0");
1864 //// hashed_process_data = processlist_get_process_data(process_list,
1869 // if(unlikely(hashed_process_data == NULL))
1871 // g_assert(pid == 0 || pid != process->ppid);
1872 // ResourceInfo *process_info;
1873 // /* Process not present */
1874 // Drawing_t *drawing = control_flow_data->drawing;
1875 // processlist_add(process_list,
1887 // &hashed_process_data);
1888 // gtk_widget_set_size_request(drawing->drawing_area,
1891 // gtk_widget_queue_draw(drawing->drawing_area);
1893 // /* Set the current process */
1894 // process_list->current_hash_data[trace_num][process->cpu] =
1895 // hashed_process_data;
1898 // processlist_set_brand(process_list, process->brand, hashed_process_data);
1905 /* after_event_enum_process_hook
1907 * Create the processlist entry for the child process. Put the last
1908 * position in x at the current time value.
1910 * @param hook_data ControlFlowData structure of the viewer.
1911 * @param call_data Event context.
1913 * This function adds items to be drawn in a queue for each process.
1916 //int after_event_enum_process_hook(void *hook_data, void *call_data)
1918 // LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1919 // EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1920 // ControlFlowData *control_flow_data = events_request->viewer_data;
1922 // LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1924 // LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1926 // LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1928 // guint first_cpu, nb_cpus, cpu;
1931 // e = ltt_tracefile_get_event(tfc->tf);
1933 // LttvFilter *filter = control_flow_data->filter;
1934 // if(filter != NULL && filter->head != NULL)
1935 // if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1936 // tfc->t_context->t,tfc,NULL,NULL))
1939 // LttTime evtime = ltt_event_time(e);
1941 // /* Add process to process list (if not present) */
1942 // LttvProcessState *process_in;
1944 // guint pl_height = 0;
1945 // HashedResourceData *hashed_process_data_in = NULL;
1947 // ProcessList *process_list = control_flow_data->process_list;
1948 // guint trace_num = ts->parent.index;
1952 // pid_in = ltt_event_get_long_unsigned(e, thf->f1);
1955 // if(pid_in == 0) {
1957 // nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1959 // first_cpu = ANY_CPU;
1960 // nb_cpus = ANY_CPU+1;
1963 // for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
1964 // /* Find process pid_in in the list... */
1965 // process_in = lttv_state_find_process(ts, cpu, pid_in);
1966 // //process_in = tfs->process;
1967 // //guint cpu = tfs->cpu;
1968 // //guint trace_num = ts->parent.index;
1969 // //process_in = ts->running_process[cpu];
1970 // /* It should exist, because we are after the state update. */
1971 // #ifdef EXTRA_CHECK
1972 // //g_assert(process_in != NULL);
1973 // #endif //EXTRA_CHECK
1974 // birth = process_in->creation_time;
1976 // hashed_process_data_in = processlist_get_process_data(process_list, "CPU0");
1977 //// hashed_process_data_in = processlist_get_process_data(process_list,
1979 //// process_in->cpu,
1982 // if(hashed_process_data_in == NULL)
1984 // if(pid_in != 0 && pid_in == process_in->ppid)
1985 // g_critical("TEST %u , %u", pid_in, process_in->ppid);
1986 // g_assert(pid_in == 0 || pid_in != process_in->ppid);
1987 // ResourceInfo *process_info;
1988 // Drawing_t *drawing = control_flow_data->drawing;
1989 // /* Process not present */
1990 // processlist_add(process_list,
1993 // process_in->tgid,
1995 // process_in->ppid,
1998 // process_in->name,
1999 // process_in->brand,
2002 // &hashed_process_data_in);
2003 // gtk_widget_set_size_request(drawing->drawing_area,
2006 // gtk_widget_queue_draw(drawing->drawing_area);
2008 // processlist_set_name(process_list, process_in->name,
2009 // hashed_process_data_in);
2010 // processlist_set_ppid(process_list, process_in->ppid,
2011 // hashed_process_data_in);
2012 // processlist_set_tgid(process_list, process_in->tgid,
2013 // hashed_process_data_in);
2020 gint
update_time_window_hook(void *hook_data
, void *call_data
)
2022 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2023 Drawing_t
*drawing
= control_flow_data
->drawing
;
2024 ProcessList
*process_list
= control_flow_data
->process_list
;
2026 const TimeWindowNotifyData
*time_window_nofify_data
=
2027 ((const TimeWindowNotifyData
*)call_data
);
2029 TimeWindow
*old_time_window
=
2030 time_window_nofify_data
->old_time_window
;
2031 TimeWindow
*new_time_window
=
2032 time_window_nofify_data
->new_time_window
;
2034 /* Update the ruler */
2035 drawing_update_ruler(control_flow_data
->drawing
,
2039 /* Two cases : zoom in/out or scrolling */
2041 /* In order to make sure we can reuse the old drawing, the scale must
2042 * be the same and the new time interval being partly located in the
2043 * currently shown time interval. (reuse is only for scrolling)
2046 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
2047 old_time_window
->start_time
.tv_sec
,
2048 old_time_window
->start_time
.tv_nsec
,
2049 old_time_window
->time_width
.tv_sec
,
2050 old_time_window
->time_width
.tv_nsec
);
2052 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
2053 new_time_window
->start_time
.tv_sec
,
2054 new_time_window
->start_time
.tv_nsec
,
2055 new_time_window
->time_width
.tv_sec
,
2056 new_time_window
->time_width
.tv_nsec
);
2058 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
2059 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
2061 /* Same scale (scrolling) */
2062 g_info("scrolling");
2063 LttTime
*ns
= &new_time_window
->start_time
;
2064 LttTime
*nw
= &new_time_window
->time_width
;
2065 LttTime
*os
= &old_time_window
->start_time
;
2066 LttTime
*ow
= &old_time_window
->time_width
;
2067 LttTime old_end
= old_time_window
->end_time
;
2068 LttTime new_end
= new_time_window
->end_time
;
2070 //if(ns<os+w && os+w<ns+w)
2071 //if(ns<old_end && os<ns)
2072 if(ltt_time_compare(*ns
, old_end
) == -1
2073 && ltt_time_compare(*os
, *ns
) == -1)
2075 g_info("scrolling near right");
2076 /* Scroll right, keep right part of the screen */
2078 guint width
= control_flow_data
->drawing
->width
;
2079 convert_time_to_pixels(
2085 /* Copy old data to new location */
2086 copy_pixmap_region(process_list
,
2088 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2092 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
2094 if(drawing
->damage_begin
== drawing
->damage_end
)
2095 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
2097 drawing
->damage_begin
= 0;
2099 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2101 /* Clear the data request background, but not SAFETY */
2102 rectangle_pixmap(process_list
,
2103 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2105 drawing
->damage_begin
+SAFETY
, 0,
2106 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2108 gtk_widget_queue_draw(drawing
->drawing_area
);
2109 //gtk_widget_queue_draw_area (drawing->drawing_area,
2111 // control_flow_data->drawing->width,
2112 // control_flow_data->drawing->height);
2114 /* Get new data for the rest. */
2115 drawing_data_request(control_flow_data
->drawing
,
2116 drawing
->damage_begin
, 0,
2117 drawing
->damage_end
- drawing
->damage_begin
,
2118 control_flow_data
->drawing
->height
);
2121 //if(ns<os && os<ns+w)
2122 //if(ns<os && os<new_end)
2123 if(ltt_time_compare(*ns
,*os
) == -1
2124 && ltt_time_compare(*os
,new_end
) == -1)
2126 g_info("scrolling near left");
2127 /* Scroll left, keep left part of the screen */
2129 guint width
= control_flow_data
->drawing
->width
;
2130 convert_time_to_pixels(
2136 /* Copy old data to new location */
2137 copy_pixmap_region (process_list
,
2139 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2145 if(drawing
->damage_begin
== drawing
->damage_end
)
2146 drawing
->damage_end
= x
;
2148 drawing
->damage_end
=
2149 control_flow_data
->drawing
->width
;
2151 drawing
->damage_begin
= 0;
2153 rectangle_pixmap (process_list
,
2154 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2156 drawing
->damage_begin
, 0,
2157 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2160 gtk_widget_queue_draw(drawing
->drawing_area
);
2161 //gtk_widget_queue_draw_area (drawing->drawing_area,
2163 // control_flow_data->drawing->width,
2164 // control_flow_data->drawing->height);
2167 /* Get new data for the rest. */
2168 drawing_data_request(control_flow_data
->drawing
,
2169 drawing
->damage_begin
, 0,
2170 drawing
->damage_end
- drawing
->damage_begin
,
2171 control_flow_data
->drawing
->height
);
2174 if(ltt_time_compare(*ns
,*os
) == 0)
2176 g_info("not scrolling");
2178 g_info("scrolling far");
2179 /* Cannot reuse any part of the screen : far jump */
2182 rectangle_pixmap (process_list
,
2183 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2186 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2189 //gtk_widget_queue_draw_area (drawing->drawing_area,
2191 // control_flow_data->drawing->width,
2192 // control_flow_data->drawing->height);
2193 gtk_widget_queue_draw(drawing
->drawing_area
);
2195 drawing
->damage_begin
= 0;
2196 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2198 drawing_data_request(control_flow_data
->drawing
,
2200 control_flow_data
->drawing
->width
,
2201 control_flow_data
->drawing
->height
);
2207 /* Different scale (zoom) */
2210 rectangle_pixmap (process_list
,
2211 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2214 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2217 //gtk_widget_queue_draw_area (drawing->drawing_area,
2219 // control_flow_data->drawing->width,
2220 // control_flow_data->drawing->height);
2221 gtk_widget_queue_draw(drawing
->drawing_area
);
2223 drawing
->damage_begin
= 0;
2224 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2226 drawing_data_request(control_flow_data
->drawing
,
2228 control_flow_data
->drawing
->width
,
2229 control_flow_data
->drawing
->height
);
2232 /* Update directly when scrolling */
2233 gdk_window_process_updates(control_flow_data
->drawing
->drawing_area
->window
,
2239 gint
traceset_notify(void *hook_data
, void *call_data
)
2241 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2242 Drawing_t
*drawing
= control_flow_data
->drawing
;
2244 if(unlikely(drawing
->gc
== NULL
)) {
2247 if(drawing
->dotted_gc
== NULL
) {
2251 drawing_clear(control_flow_data
->drawing
);
2252 processlist_clear(control_flow_data
->process_list
);
2253 gtk_widget_set_size_request(
2254 control_flow_data
->drawing
->drawing_area
,
2255 -1, processlist_get_height(control_flow_data
->process_list
));
2256 redraw_notify(control_flow_data
, NULL
);
2258 request_background_data(control_flow_data
);
2263 gint
redraw_notify(void *hook_data
, void *call_data
)
2265 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2266 Drawing_t
*drawing
= control_flow_data
->drawing
;
2267 GtkWidget
*widget
= drawing
->drawing_area
;
2269 drawing
->damage_begin
= 0;
2270 drawing
->damage_end
= drawing
->width
;
2272 /* fun feature, to be separated someday... */
2273 drawing_clear(control_flow_data
->drawing
);
2274 processlist_clear(control_flow_data
->process_list
);
2275 gtk_widget_set_size_request(
2276 control_flow_data
->drawing
->drawing_area
,
2277 -1, processlist_get_height(control_flow_data
->process_list
));
2279 rectangle_pixmap (control_flow_data
->process_list
,
2280 widget
->style
->black_gc
,
2283 drawing
->alloc_width
,
2286 gtk_widget_queue_draw(drawing
->drawing_area
);
2288 if(drawing
->damage_begin
< drawing
->damage_end
)
2290 drawing_data_request(drawing
,
2291 drawing
->damage_begin
,
2293 drawing
->damage_end
-drawing
->damage_begin
,
2297 //gtk_widget_queue_draw_area(drawing->drawing_area,
2300 // drawing->height);
2306 gint
continue_notify(void *hook_data
, void *call_data
)
2308 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2309 Drawing_t
*drawing
= control_flow_data
->drawing
;
2311 //g_assert(widget->allocation.width == drawing->damage_end);
2313 if(drawing
->damage_begin
< drawing
->damage_end
)
2315 drawing_data_request(drawing
,
2316 drawing
->damage_begin
,
2318 drawing
->damage_end
-drawing
->damage_begin
,
2326 gint
update_current_time_hook(void *hook_data
, void *call_data
)
2328 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
2329 Drawing_t
*drawing
= control_flow_data
->drawing
;
2331 LttTime current_time
= *((LttTime
*)call_data
);
2333 TimeWindow time_window
=
2334 lttvwindow_get_time_window(control_flow_data
->tab
);
2336 LttTime time_begin
= time_window
.start_time
;
2337 LttTime width
= time_window
.time_width
;
2340 guint64 time_ll
= ltt_time_to_uint64(width
);
2341 time_ll
= time_ll
>> 1; /* divide by two */
2342 half_width
= ltt_time_from_uint64(time_ll
);
2344 LttTime time_end
= ltt_time_add(time_begin
, width
);
2346 LttvTracesetContext
* tsc
=
2347 lttvwindow_get_traceset_context(control_flow_data
->tab
);
2349 LttTime trace_start
= tsc
->time_span
.start_time
;
2350 LttTime trace_end
= tsc
->time_span
.end_time
;
2352 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
2353 current_time
.tv_nsec
);
2357 /* If current time is inside time interval, just move the highlight
2360 /* Else, we have to change the time interval. We have to tell it
2361 * to the main window. */
2362 /* The time interval change will take care of placing the current
2363 * time at the center of the visible area, or nearest possible if we are
2364 * at one end of the trace. */
2367 if(ltt_time_compare(current_time
, time_begin
) < 0)
2369 TimeWindow new_time_window
;
2371 if(ltt_time_compare(current_time
,
2372 ltt_time_add(trace_start
,half_width
)) < 0)
2373 time_begin
= trace_start
;
2375 time_begin
= ltt_time_sub(current_time
,half_width
);
2377 new_time_window
.start_time
= time_begin
;
2378 new_time_window
.time_width
= width
;
2379 new_time_window
.time_width_double
= ltt_time_to_double(width
);
2380 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
2382 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2384 else if(ltt_time_compare(current_time
, time_end
) > 0)
2386 TimeWindow new_time_window
;
2388 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
2389 time_begin
= ltt_time_sub(trace_end
,width
);
2391 time_begin
= ltt_time_sub(current_time
,half_width
);
2393 new_time_window
.start_time
= time_begin
;
2394 new_time_window
.time_width
= width
;
2395 new_time_window
.time_width_double
= ltt_time_to_double(width
);
2396 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
2398 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2401 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
2403 /* Update directly when scrolling */
2404 gdk_window_process_updates(control_flow_data
->drawing
->drawing_area
->window
,
2410 typedef struct _ClosureData
{
2411 EventsRequest
*events_request
;
2412 LttvTracesetState
*tss
;
2417 /* Draw line until end of the screen */
2419 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
2421 ResourceInfo
*process_info
= (ResourceInfo
*)key
;
2422 HashedResourceData
*hashed_process_data
= (HashedResourceData
*)value
;
2423 ClosureData
*closure_data
= (ClosureData
*)user_data
;
2425 EventsRequest
*events_request
= closure_data
->events_request
;
2426 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2428 LttvTracesetState
*tss
= closure_data
->tss
;
2429 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
2431 LttTime evtime
= closure_data
->end_time
;
2433 gboolean dodraw
= TRUE
;
2436 /* For the process */
2437 /* First, check if the current process is in the state computation
2438 * process list. If it is there, that means we must add it right now and
2439 * draw items from the beginning of the read for it. If it is not
2440 * present, it's a new process and it was not present : it will
2441 * be added after the state update. */
2443 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
2444 #endif //EXTRA_CHECK
2445 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
2446 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
2449 //FIXME : optimize data structures.
2450 LttvTracefileState
*tfs
;
2451 LttvTracefileContext
*tfc
;
2453 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
2454 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
2455 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
2456 && tfs
->cpu
== process_info
->cpu
)
2460 g_assert(i
<tc
->tracefiles
->len
);
2461 tfs
= LTTV_TRACEFILE_STATE(tfc
);
2463 // LttvTracefileState *tfs =
2464 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
2465 // tracefiles[process_info->cpu];
2467 // LttvProcessState *process;
2468 // process = lttv_state_find_process(ts, process_info->cpu,
2469 // process_info->pid);
2471 // if(unlikely(process != NULL)) {
2473 // LttvFilter *filter = control_flow_data->filter;
2474 // if(filter != NULL && filter->head != NULL)
2475 // if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
2476 // tc->t,NULL,process,tc))
2479 /* Only draw for processes that are currently in the trace states */
2481 ProcessList
*process_list
= control_flow_data
->process_list
;
2483 /* Should be alike when background info is ready */
2484 if(control_flow_data
->background_info_waiting
==0)
2485 g_assert(ltt_time_compare(process
->creation_time
,
2486 process_info
->birth
) == 0);
2487 #endif //EXTRA_CHECK
2489 /* Now, the process is in the state hash and our own process hash.
2490 * We definitely can draw the items related to the ending state.
2493 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2496 TimeWindow time_window
=
2497 lttvwindow_get_time_window(control_flow_data
->tab
);
2500 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2501 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2503 #endif //EXTRA_CHECK
2504 Drawing_t
*drawing
= control_flow_data
->drawing
;
2505 guint width
= drawing
->width
;
2507 guint x
= closure_data
->x_end
;
2509 DrawContext draw_context
;
2511 /* Now create the drawing context that will be used to draw
2512 * items related to the last state. */
2513 draw_context
.drawable
= hashed_process_data
->pixmap
;
2514 draw_context
.gc
= drawing
->gc
;
2515 draw_context
.pango_layout
= drawing
->pango_layout
;
2516 draw_context
.drawinfo
.end
.x
= x
;
2518 draw_context
.drawinfo
.y
.over
= 1;
2519 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2520 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2522 draw_context
.drawinfo
.start
.offset
.over
= 0;
2523 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2524 draw_context
.drawinfo
.start
.offset
.under
= 0;
2525 draw_context
.drawinfo
.end
.offset
.over
= 0;
2526 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2527 draw_context
.drawinfo
.end
.offset
.under
= 0;
2529 /* Jump over draw if we are at the same x position */
2530 if(x
== hashed_process_data
->x
.over
)
2534 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
2536 PropertiesLine prop_line
= prepare_execmode_line(process
);
2537 draw_line((void*)&prop_line
, (void*)&draw_context
);
2539 hashed_process_data
->x
.over
= x
;
2543 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2544 hashed_process_data
->x
.middle_used
)) {
2545 #if 0 /* do not mark closure : not missing information */
2546 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
2547 /* Draw collision indicator */
2548 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2549 gdk_draw_point(drawing
->pixmap
,
2553 hashed_process_data
->x
.middle_marked
= TRUE
;
2558 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2561 // PropertiesLine prop_line = prepare_s_e_line(process);
2562 PropertiesLine prop_line
;
2563 prop_line
.line_width
= STATE_LINE_WIDTH
;
2564 prop_line
.style
= GDK_LINE_SOLID
;
2565 prop_line
.y
= MIDDLE
;
2566 /* if(pid_out == 0) {
2567 prop_line.color = drawing_colors_cpu[COL_IDLE];
2570 prop_line.color = drawing_colors_cpu[COL_BUSY];
2573 //prop_line.color = drawing_colors_cpu[COL_CPU_UNKNOWN];
2574 if(ts
->cpu_states
[process_info
->id
].present_state
== LTTV_CPU_IDLE
) {
2575 prop_line
.color
= drawing_colors_cpu
[COL_CPU_IDLE
];
2578 prop_line
.color
= drawing_colors_cpu
[COL_CPU_BUSY
];
2581 draw_line((void*)&prop_line
, (void*)&draw_context
);
2584 /* become the last x position */
2585 if(likely(x
!= hashed_process_data
->x
.middle
)) {
2586 hashed_process_data
->x
.middle
= x
;
2587 /* but don't use the pixel */
2588 hashed_process_data
->x
.middle_used
= FALSE
;
2590 /* Calculate the next good time */
2591 convert_pixels_to_time(width
, x
+1, time_window
,
2592 &hashed_process_data
->next_good_time
);
2601 int before_chunk(void *hook_data
, void *call_data
)
2603 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2604 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2605 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
2607 /* Desactivate sort */
2608 gtk_tree_sortable_set_sort_column_id(
2609 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
2611 GTK_SORT_ASCENDING
);
2613 drawing_chunk_begin(events_request
, tss
);
2618 int before_request(void *hook_data
, void *call_data
)
2620 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2621 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2623 drawing_data_request_begin(events_request
, tss
);
2630 * after request is necessary in addition of after chunk in order to draw
2631 * lines until the end of the screen. after chunk just draws lines until
2638 // TODO pmf: reenable this
2639 int after_request(void *hook_data
, void *call_data
)
2641 // EventsRequest *events_request = (EventsRequest*)hook_data;
2642 // ControlFlowData *control_flow_data = events_request->viewer_data;
2643 // LttvTracesetState *tss = (LttvTracesetState*)call_data;
2645 // ProcessList *process_list = control_flow_data->process_list;
2646 // LttTime end_time = events_request->end_time;
2648 // ClosureData closure_data;
2649 // closure_data.events_request = (EventsRequest*)hook_data;
2650 // closure_data.tss = tss;
2651 // closure_data.end_time = end_time;
2653 // TimeWindow time_window =
2654 // lttvwindow_get_time_window(control_flow_data->tab);
2655 // guint width = control_flow_data->drawing->width;
2656 // convert_time_to_pixels(
2660 // &closure_data.x_end);
2663 // /* Draw last items */
2664 // g_hash_table_foreach(process_list->process_hash, draw_closure,
2665 // (void*)&closure_data);
2668 // /* Request expose */
2669 // drawing_request_expose(events_request, tss, end_time);
2678 int after_chunk(void *hook_data
, void *call_data
)
2680 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2681 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2682 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
2683 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
2684 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
2687 ProcessList
*process_list
= control_flow_data
->process_list
;
2689 LttvTraceset
*traceset
= tsc
->ts
;
2690 guint nb_trace
= lttv_traceset_number(traceset
);
2692 /* Only execute when called for the first trace's events request */
2693 if(!process_list
->current_hash_data
) return;
2695 for(i
= 0 ; i
< nb_trace
; i
++) {
2696 g_free(process_list
->current_hash_data
[i
]);
2698 g_free(process_list
->current_hash_data
);
2699 process_list
->current_hash_data
= NULL
;
2702 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
2703 else /* end of traceset, or position now out of request : end */
2704 end_time
= events_request
->end_time
;
2706 ClosureData closure_data
;
2707 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2708 closure_data
.tss
= tss
;
2709 closure_data
.end_time
= end_time
;
2711 TimeWindow time_window
=
2712 lttvwindow_get_time_window(control_flow_data
->tab
);
2713 guint width
= control_flow_data
->drawing
->width
;
2714 convert_time_to_pixels(
2718 &closure_data
.x_end
);
2720 /* Draw last items */
2721 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2722 (void*)&closure_data
);
2724 /* Reactivate sort */
2725 gtk_tree_sortable_set_sort_column_id(
2726 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
2727 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2728 GTK_SORT_ASCENDING
);
2730 update_index_to_pixmap(control_flow_data
->process_list
);
2731 /* Request a full expose : drawing scrambled */
2732 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
2734 /* Request expose (updates damages zone also) */
2735 drawing_request_expose(events_request
, tss
, end_time
);
2740 /* after_statedump_end
2742 * @param hook_data ControlFlowData structure of the viewer.
2743 * @param call_data Event context.
2745 * This function adds items to be drawn in a queue for each process.
2748 int before_statedump_end(void *hook_data
, void *call_data
)
2750 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2751 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2752 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2754 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2756 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2758 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2760 LttvTracesetState
*tss
= (LttvTracesetState
*)tfc
->t_context
->ts_context
;
2761 ProcessList
*process_list
= control_flow_data
->process_list
;
2764 e
= ltt_tracefile_get_event(tfc
->tf
);
2766 LttvFilter
*filter
= control_flow_data
->filter
;
2767 if(filter
!= NULL
&& filter
->head
!= NULL
)
2768 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
2769 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
2772 LttTime evtime
= ltt_event_time(e
);
2774 ClosureData closure_data
;
2775 closure_data
.events_request
= events_request
;
2776 closure_data
.tss
= tss
;
2777 closure_data
.end_time
= evtime
;
2779 TimeWindow time_window
=
2780 lttvwindow_get_time_window(control_flow_data
->tab
);
2781 guint width
= control_flow_data
->drawing
->width
;
2782 convert_time_to_pixels(
2786 &closure_data
.x_end
);
2788 /* Draw last items */
2789 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2790 (void*)&closure_data
);
2792 /* Reactivate sort */
2793 gtk_tree_sortable_set_sort_column_id(
2794 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
2795 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
2796 GTK_SORT_ASCENDING
);
2798 update_index_to_pixmap(control_flow_data
->process_list
);
2799 /* Request a full expose : drawing scrambled */
2800 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
2802 /* Request expose (updates damages zone also) */
2803 drawing_request_expose(events_request
, tss
, evtime
);