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
83 extern GSList
*g_legend_list
;
86 typedef struct _ProcessAddClosure
{
91 static void process_add(gpointer key
,
95 LttvProcessState
*process
= (LttvProcessState
*)value
;
96 ProcessAddClosure
*closure
= (ProcessAddClosure
*)user_data
;
97 ControlFlowData
*control_flow_data
= closure
->cfd
;
98 guint trace_num
= closure
->trace_num
;
100 /* Add process to process list (if not present) */
103 guint y
= 0, height
= 0, pl_height
= 0;
105 ProcessList
*process_list
= control_flow_data
->process_list
;
108 birth
= process
->creation_time
;
109 const gchar
*name
= g_quark_to_string(process
->name
);
110 HashedProcessData
*hashed_process_data
= NULL
;
112 if(processlist_get_process_pixels(process_list
,
118 &hashed_process_data
) == 1)
120 /* Process not present */
121 processlist_add(process_list
,
127 &hashed_process_data
);
128 processlist_get_process_pixels(process_list
,
134 &hashed_process_data
);
135 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
141 /* Action to do when background computation completed.
143 * Wait for all the awaited computations to be over.
146 gint
background_ready(void *hook_data
, void *call_data
)
148 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
149 LttvTrace
*trace
= (LttvTrace
*)call_data
;
151 control_flow_data
->background_info_waiting
--;
153 if(control_flow_data
->background_info_waiting
== 0) {
154 g_debug("control flow viewer : background computation data ready.");
156 drawing_clear(control_flow_data
->drawing
);
157 processlist_clear(control_flow_data
->process_list
);
158 gtk_widget_set_size_request(
159 control_flow_data
->drawing
->drawing_area
,
160 -1, processlist_get_height(control_flow_data
->process_list
));
161 redraw_notify(control_flow_data
, NULL
);
168 /* Request background computation. Verify if it is in progress or ready first.
169 * Only for each trace in the tab's traceset.
171 void request_background_data(ControlFlowData
*control_flow_data
)
173 LttvTracesetContext
* tsc
=
174 lttvwindow_get_traceset_context(control_flow_data
->tab
);
175 gint num_traces
= lttv_traceset_number(tsc
->ts
);
179 LttvHooks
*background_ready_hook
=
181 lttv_hooks_add(background_ready_hook
, background_ready
, control_flow_data
,
183 control_flow_data
->background_info_waiting
= 0;
185 for(i
=0;i
<num_traces
;i
++) {
186 trace
= lttv_traceset_get(tsc
->ts
, i
);
188 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
) {
190 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
192 /* We first remove requests that could have been done for the same
193 * information. Happens when two viewers ask for it before servicing
196 lttvwindowtraces_background_request_remove(trace
, "state");
197 lttvwindowtraces_background_request_queue(trace
,
199 lttvwindowtraces_background_notify_queue(control_flow_data
,
203 background_ready_hook
);
204 control_flow_data
->background_info_waiting
++;
205 } else { /* in progress */
207 lttvwindowtraces_background_notify_current(control_flow_data
,
211 background_ready_hook
);
212 control_flow_data
->background_info_waiting
++;
215 /* Data ready. Be its nature, this viewer doesn't need to have
216 * its data ready hook called htere, because a background
217 * request is always linked with a redraw.
223 lttv_hooks_destroy(background_ready_hook
);
230 * Event Viewer's constructor hook
232 * This constructor is given as a parameter to the menuitem and toolbar button
233 * registration. It creates the list.
234 * @param tab A pointer to the parent tab.
235 * @return The widget created.
238 h_guicontrolflow(Tab
*tab
)
240 g_info("h_guicontrolflow, %p", tab
);
241 ControlFlowData
*control_flow_data
= guicontrolflow() ;
243 control_flow_data
->tab
= tab
;
245 // Unreg done in the GuiControlFlow_Destructor
246 lttvwindow_register_traceset_notify(tab
,
250 lttvwindow_register_time_window_notify(tab
,
251 update_time_window_hook
,
253 lttvwindow_register_current_time_notify(tab
,
254 update_current_time_hook
,
256 lttvwindow_register_redraw_notify(tab
,
259 lttvwindow_register_continue_notify(tab
,
262 request_background_data(control_flow_data
);
265 return guicontrolflow_get_widget(control_flow_data
) ;
269 void legend_destructor(GtkWindow
*legend
)
271 g_legend_list
= g_slist_remove(g_legend_list
, legend
);
274 /* Create a popup legend */
278 g_info("h_legend, %p", tab
);
280 GtkWindow
*legend
= GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL
));
282 g_legend_list
= g_slist_append(
286 g_object_set_data_full(
290 (GDestroyNotify
)legend_destructor
);
292 gtk_window_set_title(legend
, "Control Flow View Legend");
294 GtkWidget
*pixmap
= create_pixmap(GTK_WIDGET(legend
), "lttv-color-list.png");
296 // GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixmap(
297 // GDK_PIXMAP(pixmap), NULL));
299 gtk_container_add(GTK_CONTAINER(legend
), GTK_WIDGET(pixmap
));
301 gtk_widget_show(GTK_WIDGET(pixmap
));
302 gtk_widget_show(GTK_WIDGET(legend
));
305 return NULL
; /* This is a popup window */
309 int event_selected_hook(void *hook_data
, void *call_data
)
311 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
312 guint
*event_number
= (guint
*) call_data
;
314 g_debug("DEBUG : event selected by main window : %u", *event_number
);
319 /* Function that selects the color of status&exemode line */
320 static inline PropertiesLine
prepare_s_e_line(LttvProcessState
*process
)
322 PropertiesLine prop_line
;
323 prop_line
.line_width
= 2;
324 prop_line
.style
= GDK_LINE_SOLID
;
325 prop_line
.y
= MIDDLE
;
326 //GdkColormap *colormap = gdk_colormap_get_system();
328 if(process
->state
->s
== LTTV_STATE_RUN
) {
329 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
330 prop_line
.color
= drawing_colors
[COL_RUN_USER_MODE
];
331 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
332 prop_line
.color
= drawing_colors
[COL_RUN_SYSCALL
];
333 else if(process
->state
->t
== LTTV_STATE_TRAP
)
334 prop_line
.color
= drawing_colors
[COL_RUN_TRAP
];
335 else if(process
->state
->t
== LTTV_STATE_IRQ
)
336 prop_line
.color
= drawing_colors
[COL_RUN_IRQ
];
337 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
338 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
340 g_assert(FALSE
); /* RUNNING MODE UNKNOWN */
341 } else if(process
->state
->s
== LTTV_STATE_WAIT
) {
342 /* We don't show if we wait while in user mode, trap, irq or syscall */
343 prop_line
.color
= drawing_colors
[COL_WAIT
];
344 } else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
) {
345 /* We don't show if we wait for CPU while in user mode, trap, irq
347 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
348 } else if(process
->state
->s
== LTTV_STATE_ZOMBIE
) {
349 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
350 } else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
) {
351 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
352 } else if(process
->state
->s
== LTTV_STATE_EXIT
) {
353 prop_line
.color
= drawing_colors
[COL_EXIT
];
354 } else if(process
->state
->s
== LTTV_STATE_UNNAMED
) {
355 prop_line
.color
= drawing_colors
[COL_UNNAMED
];
357 g_assert(FALSE
); /* UNKNOWN STATE */
364 static inline PropertiesLine
prepare_status_line(LttvProcessState
*process
)
366 PropertiesLine prop_line
;
367 prop_line
.line_width
= 2;
368 prop_line
.style
= GDK_LINE_SOLID
;
369 prop_line
.y
= MIDDLE
;
370 //GdkColormap *colormap = gdk_colormap_get_system();
372 g_debug("prepare_status_line for state : %s",
373 g_quark_to_string(process
->state
->s
));
375 /* color of line : status of the process */
376 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
377 prop_line
.color
= drawing_colors
[COL_WHITE
];
378 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
379 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
380 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
381 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
382 else if(process
->state
->s
== LTTV_STATE_EXIT
)
383 prop_line
.color
= drawing_colors
[COL_EXIT
];
384 else if(process
->state
->s
== LTTV_STATE_ZOMBIE
)
385 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
386 else if(process
->state
->s
== LTTV_STATE_WAIT
)
387 prop_line
.color
= drawing_colors
[COL_WAIT
];
388 else if(process
->state
->s
== LTTV_STATE_RUN
)
389 prop_line
.color
= drawing_colors
[COL_RUN
];
391 prop_line
.color
= drawing_colors
[COL_WHITE
];
393 //gdk_colormap_alloc_color(colormap,
404 /* before_schedchange_hook
406 * This function basically draw lines and icons. Two types of lines are drawn :
407 * one small (3 pixels?) representing the state of the process and the second
408 * type is thicker (10 pixels?) representing on which CPU a process is running
409 * (and this only in running state).
411 * Extremums of the lines :
412 * x_min : time of the last event context for this process kept in memory.
413 * x_max : time of the current event.
414 * y : middle of the process in the process list. The process is found in the
415 * list, therefore is it's position in pixels.
417 * The choice of lines'color is defined by the context of the last event for this
422 int before_schedchange_hook(void *hook_data
, void *call_data
)
424 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
425 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
426 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
428 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
430 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
431 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
434 e
= ltt_tracefile_get_event(tfc
->tf
);
436 LttTime evtime
= ltt_event_time(e
);
438 /* we are in a schedchange, before the state update. We must draw the
439 * items corresponding to the state before it changes : now is the right
446 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
447 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
451 /* For the pid_out */
452 /* First, check if the current process is in the state computation
453 * process list. If it is there, that means we must add it right now and
454 * draw items from the beginning of the read for it. If it is not
455 * present, it's a new process and it was not present : it will
456 * be added after the state update. */
457 guint cpu
= ltt_tracefile_num(tfc
->tf
);
458 LttvProcessState
*process
= ts
->running_process
[cpu
];
459 /* unknown state, bad current pid */
460 if(process
->pid
!= pid_out
)
461 process
= lttv_state_find_process(ts
,
462 ltt_tracefile_num(tfc
->tf
), pid_out
);
464 if(process
!= NULL
) {
465 /* Well, the process_out existed : we must get it in the process hash
466 * or add it, and draw its items.
468 /* Add process to process list (if not present) */
470 HashedProcessData
*hashed_process_data
= NULL
;
471 ProcessList
*process_list
= control_flow_data
->process_list
;
472 LttTime birth
= process
->creation_time
;
474 hashed_process_data
= processlist_get_process_data(process_list
,
478 tfc
->t_context
->index
);
479 if(hashed_process_data
== NULL
)
481 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
482 /* Process not present */
483 ProcessInfo
*process_info
;
484 Drawing_t
*drawing
= control_flow_data
->drawing
;
485 processlist_add(process_list
,
491 tfc
->t_context
->index
,
495 &hashed_process_data
);
496 gtk_widget_set_size_request(drawing
->drawing_area
,
499 gtk_widget_queue_draw(drawing
->drawing_area
);
503 /* Now, the process is in the state hash and our own process hash.
504 * We definitely can draw the items related to the ending state.
507 if(ltt_time_compare(hashed_process_data
->next_good_time
,
510 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
512 TimeWindow time_window
=
513 lttvwindow_get_time_window(control_flow_data
->tab
);
515 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
516 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
519 Drawing_t
*drawing
= control_flow_data
->drawing
;
520 guint width
= drawing
->width
;
522 convert_time_to_pixels(
528 /* Draw collision indicator */
529 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
530 gdk_draw_point(hashed_process_data
->pixmap
,
533 (hashed_process_data
->height
/2)-3);
534 hashed_process_data
->x
.middle_marked
= TRUE
;
537 TimeWindow time_window
=
538 lttvwindow_get_time_window(control_flow_data
->tab
);
540 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
541 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
544 Drawing_t
*drawing
= control_flow_data
->drawing
;
545 guint width
= drawing
->width
;
547 convert_time_to_pixels(
554 /* Jump over draw if we are at the same x position */
555 if(x
== hashed_process_data
->x
.middle
&&
556 hashed_process_data
->x
.middle_used
)
558 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
559 /* Draw collision indicator */
560 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
561 gdk_draw_point(hashed_process_data
->pixmap
,
564 (hashed_process_data
->height
/2)-3);
565 hashed_process_data
->x
.middle_marked
= TRUE
;
569 DrawContext draw_context
;
571 /* Now create the drawing context that will be used to draw
572 * items related to the last state. */
573 draw_context
.drawable
= hashed_process_data
->pixmap
;
574 draw_context
.gc
= drawing
->gc
;
575 draw_context
.pango_layout
= drawing
->pango_layout
;
576 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
577 draw_context
.drawinfo
.end
.x
= x
;
579 draw_context
.drawinfo
.y
.over
= 1;
580 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
581 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
583 draw_context
.drawinfo
.start
.offset
.over
= 0;
584 draw_context
.drawinfo
.start
.offset
.middle
= 0;
585 draw_context
.drawinfo
.start
.offset
.under
= 0;
586 draw_context
.drawinfo
.end
.offset
.over
= 0;
587 draw_context
.drawinfo
.end
.offset
.middle
= 0;
588 draw_context
.drawinfo
.end
.offset
.under
= 0;
592 PropertiesLine prop_line
= prepare_s_e_line(process
);
593 draw_line((void*)&prop_line
, (void*)&draw_context
);
596 /* become the last x position */
597 hashed_process_data
->x
.middle
= x
;
598 hashed_process_data
->x
.middle_used
= TRUE
;
599 hashed_process_data
->x
.middle_marked
= FALSE
;
601 /* Calculate the next good time */
602 convert_pixels_to_time(width
, x
+1, time_window
,
603 &hashed_process_data
->next_good_time
);
611 /* First, check if the current process is in the state computation
612 * process list. If it is there, that means we must add it right now and
613 * draw items from the beginning of the read for it. If it is not
614 * present, it's a new process and it was not present : it will
615 * be added after the state update. */
616 LttvProcessState
*process
;
617 process
= lttv_state_find_process(ts
,
618 ltt_tracefile_num(tfc
->tf
), pid_in
);
620 if(process
!= NULL
) {
621 /* Well, the process existed : we must get it in the process hash
622 * or add it, and draw its items.
624 /* Add process to process list (if not present) */
626 HashedProcessData
*hashed_process_data
= NULL
;
627 ProcessList
*process_list
= control_flow_data
->process_list
;
628 LttTime birth
= process
->creation_time
;
630 hashed_process_data
= processlist_get_process_data(process_list
,
634 tfc
->t_context
->index
);
635 if(hashed_process_data
== NULL
)
637 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
638 /* Process not present */
639 ProcessInfo
*process_info
;
640 Drawing_t
*drawing
= control_flow_data
->drawing
;
641 processlist_add(process_list
,
647 tfc
->t_context
->index
,
651 &hashed_process_data
);
652 gtk_widget_set_size_request(drawing
->drawing_area
,
655 gtk_widget_queue_draw(drawing
->drawing_area
);
658 //We could set the current process and hash here, but will be done
659 //by after schedchange hook
661 /* Now, the process is in the state hash and our own process hash.
662 * We definitely can draw the items related to the ending state.
665 if(ltt_time_compare(hashed_process_data
->next_good_time
,
668 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
670 TimeWindow time_window
=
671 lttvwindow_get_time_window(control_flow_data
->tab
);
673 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
674 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
677 Drawing_t
*drawing
= control_flow_data
->drawing
;
678 guint width
= drawing
->width
;
680 convert_time_to_pixels(
686 /* Draw collision indicator */
687 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
688 gdk_draw_point(hashed_process_data
->pixmap
,
691 (hashed_process_data
->height
/2)-3);
692 hashed_process_data
->x
.middle_marked
= TRUE
;
695 TimeWindow time_window
=
696 lttvwindow_get_time_window(control_flow_data
->tab
);
698 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
699 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
702 Drawing_t
*drawing
= control_flow_data
->drawing
;
703 guint width
= drawing
->width
;
706 convert_time_to_pixels(
713 /* Jump over draw if we are at the same x position */
714 if(x
== hashed_process_data
->x
.middle
&&
715 hashed_process_data
->x
.middle_used
)
717 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
718 /* Draw collision indicator */
719 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
720 gdk_draw_point(hashed_process_data
->pixmap
,
723 (hashed_process_data
->height
/2)-3);
724 hashed_process_data
->x
.middle_marked
= TRUE
;
728 DrawContext draw_context
;
730 /* Now create the drawing context that will be used to draw
731 * items related to the last state. */
732 draw_context
.drawable
= hashed_process_data
->pixmap
;
733 draw_context
.gc
= drawing
->gc
;
734 draw_context
.pango_layout
= drawing
->pango_layout
;
735 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
736 draw_context
.drawinfo
.end
.x
= x
;
738 draw_context
.drawinfo
.y
.over
= 1;
739 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
740 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
742 draw_context
.drawinfo
.start
.offset
.over
= 0;
743 draw_context
.drawinfo
.start
.offset
.middle
= 0;
744 draw_context
.drawinfo
.start
.offset
.under
= 0;
745 draw_context
.drawinfo
.end
.offset
.over
= 0;
746 draw_context
.drawinfo
.end
.offset
.middle
= 0;
747 draw_context
.drawinfo
.end
.offset
.under
= 0;
751 PropertiesLine prop_line
= prepare_s_e_line(process
);
752 draw_line((void*)&prop_line
, (void*)&draw_context
);
756 /* become the last x position */
757 hashed_process_data
->x
.middle
= x
;
758 hashed_process_data
->x
.middle_used
= TRUE
;
759 hashed_process_data
->x
.middle_marked
= FALSE
;
761 /* Calculate the next good time */
762 convert_pixels_to_time(width
, x
+1, time_window
,
763 &hashed_process_data
->next_good_time
);
772 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
773 ControlFlowData
*control_flow_data
=
774 (ControlFlowData
*)events_request
->viewer_data
;
775 Tab
*tab
= control_flow_data
->tab
;
777 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
779 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
780 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
785 LttTime evtime
= ltt_event_time(e
);
786 TimeWindow time_window
=
787 lttvwindow_get_time_window(tab
);
789 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
791 //if(time < time_beg || time > time_end) return;
792 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
793 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
796 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
798 g_debug("schedchange!");
800 /* Add process to process list (if not present) and get drawing "y" from
801 * process position */
802 guint pid_out
, pid_in
;
803 LttvProcessState
*process_out
, *process_in
;
805 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
807 ProcessList
*process_list
= control_flow_data
->process_list
;
810 LttField
*f
= ltt_event_field(e
);
812 element
= ltt_field_member(f
,0);
813 pid_out
= ltt_event_get_long_unsigned(e
,element
);
814 element
= ltt_field_member(f
,1);
815 pid_in
= ltt_event_get_long_unsigned(e
,element
);
816 g_debug("out : %u in : %u", pid_out
, pid_in
);
819 /* Find process pid_out in the list... */
820 process_out
= lttv_state_find_process(tfs
, pid_out
);
821 if(process_out
== NULL
) return 0;
822 g_debug("out : %s",g_quark_to_string(process_out
->state
->s
));
824 birth
= process_out
->creation_time
;
825 const gchar
*name
= g_quark_to_string(process_out
->name
);
826 HashedProcessData
*hashed_process_data_out
= NULL
;
828 if(processlist_get_process_pixels(process_list
,
831 tfc
->t_context
->index
,
834 &hashed_process_data_out
) == 1)
836 /* Process not present */
837 processlist_add(process_list
,
840 tfc
->t_context
->index
,
843 &hashed_process_data_out
);
844 g_assert(processlist_get_process_pixels(process_list
,
847 tfc
->t_context
->index
,
850 &hashed_process_data_out
)==0);
851 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
855 /* Find process pid_in in the list... */
856 process_in
= lttv_state_find_process(tfs
, pid_in
);
857 if(process_in
== NULL
) return 0;
858 g_debug("in : %s",g_quark_to_string(process_in
->state
->s
));
860 birth
= process_in
->creation_time
;
861 name
= g_quark_to_string(process_in
->name
);
862 HashedProcessData
*hashed_process_data_in
= NULL
;
864 if(processlist_get_process_pixels(process_list
,
867 tfc
->t_context
->index
,
870 &hashed_process_data_in
) == 1)
872 /* Process not present */
873 processlist_add(process_list
,
876 tfc
->t_context
->index
,
879 &hashed_process_data_in
);
880 processlist_get_process_pixels(process_list
,
883 tfc
->t_context
->index
,
886 &hashed_process_data_in
);
888 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
893 /* Find pixels corresponding to time of the event. If the time does
894 * not fit in the window, show a warning, not supposed to happend. */
896 guint width
= control_flow_data
->drawing
->width
;
898 LttTime time
= ltt_event_time(e
);
900 LttTime window_end
= time_window
.time_window
.end_time
;
902 convert_time_to_pixels(
907 //assert(x <= width);
909 /* draw what represents the event for outgoing process. */
911 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
912 draw_context_out
->current
->modify_over
->x
= x
;
913 draw_context_out
->current
->modify_under
->x
= x
;
914 draw_context_out
->current
->modify_over
->y
= y_out
;
915 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
916 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
917 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
918 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
919 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
920 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
921 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
922 //draw_context_out->gc = widget->style->black_gc;
924 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
925 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
927 /* Draw the line/background of the out process */
928 if(draw_context_out
->previous
->middle
->x
== -1)
930 draw_context_out
->previous
->over
->x
=
931 control_flow_data
->drawing
->damage_begin
;
932 draw_context_out
->previous
->middle
->x
=
933 control_flow_data
->drawing
->damage_begin
;
934 draw_context_out
->previous
->under
->x
=
935 control_flow_data
->drawing
->damage_begin
;
936 g_debug("out middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
939 draw_context_out
->current
->middle
->x
= x
;
940 draw_context_out
->current
->over
->x
= x
;
941 draw_context_out
->current
->under
->x
= x
;
942 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
943 draw_context_out
->current
->over
->y
= y_out
;
944 draw_context_out
->current
->under
->y
= y_out
+ height
;
945 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
946 draw_context_out
->previous
->over
->y
= y_out
;
947 draw_context_out
->previous
->under
->y
= y_out
+ height
;
949 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
950 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
952 if(process_out
->state
->s
== LTTV_STATE_RUN
)
954 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
955 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
956 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
958 PropertiesBG prop_bg
;
959 prop_bg
.color
= g_new(GdkColor
,1);
961 switch(ltt_tracefile_num(tfc
->tf
)) {
963 prop_bg
.color
->red
= 0x1515;
964 prop_bg
.color
->green
= 0x1515;
965 prop_bg
.color
->blue
= 0x8c8c;
968 prop_bg
.color
->red
= 0x4e4e;
969 prop_bg
.color
->green
= 0xa9a9;
970 prop_bg
.color
->blue
= 0xa4a4;
973 prop_bg
.color
->red
= 0x7a7a;
974 prop_bg
.color
->green
= 0x4a4a;
975 prop_bg
.color
->blue
= 0x8b8b;
978 prop_bg
.color
->red
= 0x8080;
979 prop_bg
.color
->green
= 0x7777;
980 prop_bg
.color
->blue
= 0x4747;
983 prop_bg
.color
->red
= 0xe7e7;
984 prop_bg
.color
->green
= 0xe7e7;
985 prop_bg
.color
->blue
= 0xe7e7;
988 g_debug("calling from draw_event");
989 draw_bg((void*)&prop_bg
, (void*)draw_context_out
);
990 g_free(prop_bg
.color
);
991 //gdk_gc_unref(draw_context_out->gc);
994 draw_context_out
->gc
= widget
->style
->black_gc
;
996 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
997 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
998 PropertiesText prop_text_out
;
999 prop_text_out
.foreground
= &colorfg_out
;
1000 prop_text_out
.background
= &colorbg_out
;
1001 prop_text_out
.size
= 6;
1002 prop_text_out
.position
= OVER
;
1004 /* color of text : status of the process */
1005 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1007 prop_text_out
.foreground
->red
= 0xffff;
1008 prop_text_out
.foreground
->green
= 0xffff;
1009 prop_text_out
.foreground
->blue
= 0xffff;
1011 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1013 prop_text_out
.foreground
->red
= 0x0fff;
1014 prop_text_out
.foreground
->green
= 0xffff;
1015 prop_text_out
.foreground
->blue
= 0xfff0;
1017 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1019 prop_text_out
.foreground
->red
= 0xffff;
1020 prop_text_out
.foreground
->green
= 0xffff;
1021 prop_text_out
.foreground
->blue
= 0x0000;
1023 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1025 prop_text_out
.foreground
->red
= 0xffff;
1026 prop_text_out
.foreground
->green
= 0x0000;
1027 prop_text_out
.foreground
->blue
= 0xffff;
1029 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1031 prop_text_out
.foreground
->red
= 0xffff;
1032 prop_text_out
.foreground
->green
= 0x0000;
1033 prop_text_out
.foreground
->blue
= 0x0000;
1035 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1037 prop_text_out
.foreground
->red
= 0x0000;
1038 prop_text_out
.foreground
->green
= 0xffff;
1039 prop_text_out
.foreground
->blue
= 0x0000;
1043 prop_text_out
.foreground
->red
= 0xffff;
1044 prop_text_out
.foreground
->green
= 0xffff;
1045 prop_text_out
.foreground
->blue
= 0xffff;
1049 /* Print status of the process : U, WF, WC, E, W, R */
1050 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1051 prop_text_out
.text
= "U->";
1052 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1053 prop_text_out
.text
= "WF->";
1054 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1055 prop_text_out
.text
= "WC->";
1056 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1057 prop_text_out
.text
= "E->";
1058 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1059 prop_text_out
.text
= "W->";
1060 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1061 prop_text_out
.text
= "R->";
1063 prop_text_out
.text
= "U";
1065 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1066 //gdk_gc_unref(draw_context_out->gc);
1068 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1069 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1070 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
1072 PropertiesLine prop_line_out
;
1073 prop_line_out
.color
= g_new(GdkColor
,1);
1074 prop_line_out
.line_width
= 2;
1075 prop_line_out
.style
= GDK_LINE_SOLID
;
1076 prop_line_out
.position
= MIDDLE
;
1078 g_debug("out state : %s", g_quark_to_string(process_out
->state
->s
));
1080 /* color of line : status of the process */
1081 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1083 prop_line_out
.color
->red
= 0xffff;
1084 prop_line_out
.color
->green
= 0xffff;
1085 prop_line_out
.color
->blue
= 0xffff;
1087 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1089 prop_line_out
.color
->red
= 0x0fff;
1090 prop_line_out
.color
->green
= 0xffff;
1091 prop_line_out
.color
->blue
= 0xfff0;
1093 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1095 prop_line_out
.color
->red
= 0xffff;
1096 prop_line_out
.color
->green
= 0xffff;
1097 prop_line_out
.color
->blue
= 0x0000;
1099 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1101 prop_line_out
.color
->red
= 0xffff;
1102 prop_line_out
.color
->green
= 0x0000;
1103 prop_line_out
.color
->blue
= 0xffff;
1105 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1107 prop_line_out
.color
->red
= 0xffff;
1108 prop_line_out
.color
->green
= 0x0000;
1109 prop_line_out
.color
->blue
= 0x0000;
1111 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1113 prop_line_out
.color
->red
= 0x0000;
1114 prop_line_out
.color
->green
= 0xffff;
1115 prop_line_out
.color
->blue
= 0x0000;
1119 prop_line_out
.color
->red
= 0xffff;
1120 prop_line_out
.color
->green
= 0xffff;
1121 prop_line_out
.color
->blue
= 0xffff;
1124 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
1125 g_free(prop_line_out
.color
);
1126 //gdk_gc_unref(draw_context_out->gc);
1127 /* Note : finishing line will have to be added when trace read over. */
1129 /* Finally, update the drawing context of the pid_in. */
1131 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1132 draw_context_in
->current
->modify_over
->x
= x
;
1133 draw_context_in
->current
->modify_under
->x
= x
;
1134 draw_context_in
->current
->modify_over
->y
= y_in
;
1135 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1136 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1137 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1138 widget
= control_flow_data
->drawing
->drawing_area
;
1139 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1140 //draw_context_in->gc = widget->style->black_gc;
1141 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1142 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1144 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1145 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1147 /* Draw the line/bg of the in process */
1148 if(draw_context_in
->previous
->middle
->x
== -1)
1150 draw_context_in
->previous
->over
->x
=
1151 control_flow_data
->drawing
->damage_begin
;
1152 draw_context_in
->previous
->middle
->x
=
1153 control_flow_data
->drawing
->damage_begin
;
1154 draw_context_in
->previous
->under
->x
=
1155 control_flow_data
->drawing
->damage_begin
;
1157 g_debug("in middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
1161 draw_context_in
->current
->middle
->x
= x
;
1162 draw_context_in
->current
->over
->x
= x
;
1163 draw_context_in
->current
->under
->x
= x
;
1164 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
1165 draw_context_in
->current
->over
->y
= y_in
;
1166 draw_context_in
->current
->under
->y
= y_in
+ height
;
1167 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
1168 draw_context_in
->previous
->over
->y
= y_in
;
1169 draw_context_in
->previous
->under
->y
= y_in
+ height
;
1171 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1172 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1175 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1177 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1178 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1179 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1181 PropertiesBG prop_bg
;
1182 prop_bg
.color
= g_new(GdkColor
,1);
1184 switcht(ltt_tracefile_num(tfc
->tf
)) {
1186 prop_bg
.color
->red
= 0x1515;
1187 prop_bg
.color
->green
= 0x1515;
1188 prop_bg
.color
->blue
= 0x8c8c;
1191 prop_bg
.color
->red
= 0x4e4e;
1192 prop_bg
.color
->green
= 0xa9a9;
1193 prop_bg
.color
->blue
= 0xa4a4;
1196 prop_bg
.color
->red
= 0x7a7a;
1197 prop_bg
.color
->green
= 0x4a4a;
1198 prop_bg
.color
->blue
= 0x8b8b;
1201 prop_bg
.color
->red
= 0x8080;
1202 prop_bg
.color
->green
= 0x7777;
1203 prop_bg
.color
->blue
= 0x4747;
1206 prop_bg
.color
->red
= 0xe7e7;
1207 prop_bg
.color
->green
= 0xe7e7;
1208 prop_bg
.color
->blue
= 0xe7e7;
1212 draw_bg((void*)&prop_bg
, (void*)draw_context_in
);
1213 g_free(prop_bg
.color
);
1214 //gdk_gc_unref(draw_context_in->gc);
1217 draw_context_in
->gc
= widget
->style
->black_gc
;
1219 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1220 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1221 PropertiesText prop_text_in
;
1222 prop_text_in
.foreground
= &colorfg_in
;
1223 prop_text_in
.background
= &colorbg_in
;
1224 prop_text_in
.size
= 6;
1225 prop_text_in
.position
= OVER
;
1227 g_debug("in state : %s", g_quark_to_string(process_in
->state
->s
));
1228 /* foreground of text : status of the process */
1229 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1231 prop_text_in
.foreground
->red
= 0xffff;
1232 prop_text_in
.foreground
->green
= 0xffff;
1233 prop_text_in
.foreground
->blue
= 0xffff;
1235 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1237 prop_text_in
.foreground
->red
= 0x0fff;
1238 prop_text_in
.foreground
->green
= 0xffff;
1239 prop_text_in
.foreground
->blue
= 0xfff0;
1241 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1243 prop_text_in
.foreground
->red
= 0xffff;
1244 prop_text_in
.foreground
->green
= 0xffff;
1245 prop_text_in
.foreground
->blue
= 0x0000;
1247 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1249 prop_text_in
.foreground
->red
= 0xffff;
1250 prop_text_in
.foreground
->green
= 0x0000;
1251 prop_text_in
.foreground
->blue
= 0xffff;
1253 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1255 prop_text_in
.foreground
->red
= 0xffff;
1256 prop_text_in
.foreground
->green
= 0x0000;
1257 prop_text_in
.foreground
->blue
= 0x0000;
1259 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1261 prop_text_in
.foreground
->red
= 0x0000;
1262 prop_text_in
.foreground
->green
= 0xffff;
1263 prop_text_in
.foreground
->blue
= 0x0000;
1267 prop_text_in
.foreground
->red
= 0xffff;
1268 prop_text_in
.foreground
->green
= 0xffff;
1269 prop_text_in
.foreground
->blue
= 0xffff;
1274 /* Print status of the process : U, WF, WC, E, W, R */
1275 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1276 prop_text_in
.text
= "U->";
1277 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1278 prop_text_in
.text
= "WF->";
1279 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1280 prop_text_in
.text
= "WC->";
1281 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1282 prop_text_in
.text
= "E->";
1283 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1284 prop_text_in
.text
= "W->";
1285 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1286 prop_text_in
.text
= "R->";
1288 prop_text_in
.text
= "U";
1290 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1291 //gdk_gc_unref(draw_context_in->gc);
1293 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1294 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1295 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1297 PropertiesLine prop_line_in
;
1298 prop_line_in
.color
= g_new(GdkColor
,1);
1299 prop_line_in
.line_width
= 2;
1300 prop_line_in
.style
= GDK_LINE_SOLID
;
1301 prop_line_in
.position
= MIDDLE
;
1303 /* color of line : status of the process */
1304 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1306 prop_line_in
.color
->red
= 0xffff;
1307 prop_line_in
.color
->green
= 0xffff;
1308 prop_line_in
.color
->blue
= 0xffff;
1310 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1312 prop_line_in
.color
->red
= 0x0fff;
1313 prop_line_in
.color
->green
= 0xffff;
1314 prop_line_in
.color
->blue
= 0xfff0;
1316 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1318 prop_line_in
.color
->red
= 0xffff;
1319 prop_line_in
.color
->green
= 0xffff;
1320 prop_line_in
.color
->blue
= 0x0000;
1322 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1324 prop_line_in
.color
->red
= 0xffff;
1325 prop_line_in
.color
->green
= 0x0000;
1326 prop_line_in
.color
->blue
= 0xffff;
1328 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1330 prop_line_in
.color
->red
= 0xffff;
1331 prop_line_in
.color
->green
= 0x0000;
1332 prop_line_in
.color
->blue
= 0x0000;
1334 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1336 prop_line_in
.color
->red
= 0x0000;
1337 prop_line_in
.color
->green
= 0xffff;
1338 prop_line_in
.color
->blue
= 0x0000;
1342 prop_line_in
.color
->red
= 0xffff;
1343 prop_line_in
.color
->green
= 0xffff;
1344 prop_line_in
.color
->blue
= 0xffff;
1347 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
1348 g_free(prop_line_in
.color
);
1349 //gdk_gc_unref(draw_context_in->gc);
1359 GString
*string
= g_string_new("");;
1360 gboolean field_names
= TRUE
, state
= TRUE
;
1362 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
1363 g_string_append_printf(string
,"\n");
1366 g_string_append_printf(string
, " %s",
1367 g_quark_to_string(tfs
->process
->state
->s
));
1370 g_info("%s",string
->str
);
1372 g_string_free(string
, TRUE
);
1374 /* End of text dump */
1379 /* after_schedchange_hook
1381 * The draw after hook is called by the reading API to have a
1382 * particular event drawn on the screen.
1383 * @param hook_data ControlFlowData structure of the viewer.
1384 * @param call_data Event context.
1386 * This function adds items to be drawn in a queue for each process.
1389 int after_schedchange_hook(void *hook_data
, void *call_data
)
1391 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1392 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1393 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1395 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1397 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1399 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1402 e
= ltt_tracefile_get_event(tfc
->tf
);
1404 LttTime evtime
= ltt_event_time(e
);
1406 /* Add process to process list (if not present) */
1407 LttvProcessState
*process_in
;
1409 guint pl_height
= 0;
1410 HashedProcessData
*hashed_process_data_in
= NULL
;
1412 ProcessList
*process_list
= control_flow_data
->process_list
;
1417 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1418 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
1422 /* Find process pid_in in the list... */
1423 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
1424 //process_in = tfs->process;
1425 guint cpu
= ltt_tracefile_num(tfc
->tf
);
1426 process_in
= ts
->running_process
[cpu
];
1427 /* It should exist, because we are after the state update. */
1429 g_assert(process_in
!= NULL
);
1430 #endif //EXTRA_CHECK
1431 birth
= process_in
->creation_time
;
1433 hashed_process_data_in
= processlist_get_process_data(process_list
,
1437 tfc
->t_context
->index
);
1438 if(hashed_process_data_in
== NULL
)
1440 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1441 ProcessInfo
*process_info
;
1442 Drawing_t
*drawing
= control_flow_data
->drawing
;
1443 /* Process not present */
1444 processlist_add(process_list
,
1450 tfc
->t_context
->index
,
1454 &hashed_process_data_in
);
1455 gtk_widget_set_size_request(drawing
->drawing_area
,
1458 gtk_widget_queue_draw(drawing
->drawing_area
);
1460 /* Set the current process */
1461 process_list
->current_hash_data
[process_in
->cpu
] =
1462 hashed_process_data_in
;
1464 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
1467 TimeWindow time_window
=
1468 lttvwindow_get_time_window(control_flow_data
->tab
);
1471 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1472 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1474 #endif //EXTRA_CHECK
1475 Drawing_t
*drawing
= control_flow_data
->drawing
;
1476 guint width
= drawing
->width
;
1479 convert_time_to_pixels(
1485 if(hashed_process_data_in
->x
.middle
!= new_x
) {
1486 hashed_process_data_in
->x
.middle
= new_x
;
1487 hashed_process_data_in
->x
.middle_used
= FALSE
;
1488 hashed_process_data_in
->x
.middle_marked
= FALSE
;
1498 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1499 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1501 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1503 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1504 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1510 LttTime evtime
= ltt_event_time(e
);
1511 TimeWindow time_window
=
1512 lttvwindow_get_time_window(control_flow_data
->tab
);
1514 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
1516 //if(time < time_beg || time > time_end) return;
1517 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1518 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1522 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1524 g_debug("schedchange!");
1526 /* Add process to process list (if not present) and get drawing "y" from
1527 * process position */
1528 guint pid_out
, pid_in
;
1529 LttvProcessState
*process_out
, *process_in
;
1531 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1533 ProcessList
*process_list
= control_flow_data
->process_list
;
1536 LttField
*f
= ltt_event_field(e
);
1538 element
= ltt_field_member(f
,0);
1539 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1540 element
= ltt_field_member(f
,1);
1541 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1542 //g_debug("out : %u in : %u", pid_out, pid_in);
1545 /* Find process pid_out in the list... */
1546 process_out
= lttv_state_find_process(tfs
, pid_out
);
1547 if(process_out
== NULL
) return 0;
1548 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1550 birth
= process_out
->creation_time
;
1551 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1552 HashedProcessData
*hashed_process_data_out
= NULL
;
1554 if(processlist_get_process_pixels(process_list
,
1557 tfc
->t_context
->index
,
1560 &hashed_process_data_out
) == 1)
1562 /* Process not present */
1563 processlist_add(process_list
,
1566 tfc
->t_context
->index
,
1569 &hashed_process_data_out
);
1570 processlist_get_process_pixels(process_list
,
1573 tfc
->t_context
->index
,
1576 &hashed_process_data_out
);
1577 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1582 /* Find process pid_in in the list... */
1583 process_in
= lttv_state_find_process(tfs
, pid_in
);
1584 if(process_in
== NULL
) return 0;
1585 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1587 birth
= process_in
->creation_time
;
1588 name
= strdup(g_quark_to_string(process_in
->name
));
1589 HashedProcessData
*hashed_process_data_in
= NULL
;
1591 if(processlist_get_process_pixels(process_list
,
1594 tfc
->t_context
->index
,
1597 &hashed_process_data_in
) == 1)
1599 /* Process not present */
1600 processlist_add(process_list
,
1603 tfc
->t_context
->index
,
1606 &hashed_process_data_in
);
1607 processlist_get_process_pixels(process_list
,
1610 tfc
->t_context
->index
,
1613 &hashed_process_data_in
);
1615 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1620 /* Find pixels corresponding to time of the event. If the time does
1621 * not fit in the window, show a warning, not supposed to happend. */
1623 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1625 //LttTime time = ltt_event_time(e);
1627 //LttTime window_end = time_window->time_window.end_time;
1630 //convert_time_to_pixels(
1636 //assert(x <= width);
1638 /* draw what represents the event for outgoing process. */
1640 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1641 //draw_context_out->current->modify_over->x = x;
1642 draw_context_out
->current
->modify_over
->y
= y_out
;
1643 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1644 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1645 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1646 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1647 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1649 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1650 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1652 /*if(process_out->state->s == LTTV_STATE_RUN)
1654 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1655 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1656 PropertiesBG prop_bg;
1657 prop_bg.color = g_new(GdkColor,1);
1659 prop_bg.color->red = 0xffff;
1660 prop_bg.color->green = 0xffff;
1661 prop_bg.color->blue = 0xffff;
1663 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1664 g_free(prop_bg.color);
1665 gdk_gc_unref(draw_context_out->gc);
1668 draw_context_out
->gc
= widget
->style
->black_gc
;
1670 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1671 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1672 PropertiesText prop_text_out
;
1673 prop_text_out
.foreground
= &colorfg_out
;
1674 prop_text_out
.background
= &colorbg_out
;
1675 prop_text_out
.size
= 6;
1676 prop_text_out
.position
= OVER
;
1678 /* color of text : status of the process */
1679 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1681 prop_text_out
.foreground
->red
= 0xffff;
1682 prop_text_out
.foreground
->green
= 0xffff;
1683 prop_text_out
.foreground
->blue
= 0xffff;
1685 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1687 prop_text_out
.foreground
->red
= 0x0fff;
1688 prop_text_out
.foreground
->green
= 0xffff;
1689 prop_text_out
.foreground
->blue
= 0xfff0;
1691 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1693 prop_text_out
.foreground
->red
= 0xffff;
1694 prop_text_out
.foreground
->green
= 0xffff;
1695 prop_text_out
.foreground
->blue
= 0x0000;
1697 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1699 prop_text_out
.foreground
->red
= 0xffff;
1700 prop_text_out
.foreground
->green
= 0x0000;
1701 prop_text_out
.foreground
->blue
= 0xffff;
1703 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1705 prop_text_out
.foreground
->red
= 0xffff;
1706 prop_text_out
.foreground
->green
= 0x0000;
1707 prop_text_out
.foreground
->blue
= 0x0000;
1709 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1711 prop_text_out
.foreground
->red
= 0x0000;
1712 prop_text_out
.foreground
->green
= 0xffff;
1713 prop_text_out
.foreground
->blue
= 0x0000;
1717 prop_text_out
.foreground
->red
= 0xffff;
1718 prop_text_out
.foreground
->green
= 0xffff;
1719 prop_text_out
.foreground
->blue
= 0xffff;
1722 /* Print status of the process : U, WF, WC, E, W, R */
1723 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1724 prop_text_out
.text
= "U";
1725 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1726 prop_text_out
.text
= "WF";
1727 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1728 prop_text_out
.text
= "WC";
1729 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1730 prop_text_out
.text
= "E";
1731 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1732 prop_text_out
.text
= "W";
1733 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1734 prop_text_out
.text
= "R";
1736 prop_text_out
.text
= "U";
1738 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1740 //gdk_gc_unref(draw_context_out->gc);
1742 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1743 draw_context_out
->current
->over
->y
= y_out
;
1744 draw_context_out
->current
->under
->y
= y_out
+height
;
1745 draw_context_out
->current
->status
= process_out
->state
->s
;
1747 /* for pid_out : remove previous, Prev = current, new current (default) */
1748 g_free(draw_context_out
->previous
->modify_under
);
1749 g_free(draw_context_out
->previous
->modify_middle
);
1750 g_free(draw_context_out
->previous
->modify_over
);
1751 g_free(draw_context_out
->previous
->under
);
1752 g_free(draw_context_out
->previous
->middle
);
1753 g_free(draw_context_out
->previous
->over
);
1754 g_free(draw_context_out
->previous
);
1756 draw_context_out
->previous
= draw_context_out
->current
;
1758 draw_context_out
->current
= g_new(DrawInfo
,1);
1759 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1760 draw_context_out
->current
->over
->x
= -1;
1761 draw_context_out
->current
->over
->y
= -1;
1762 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1763 draw_context_out
->current
->middle
->x
= -1;
1764 draw_context_out
->current
->middle
->y
= -1;
1765 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1766 draw_context_out
->current
->under
->x
= -1;
1767 draw_context_out
->current
->under
->y
= -1;
1768 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1769 draw_context_out
->current
->modify_over
->x
= -1;
1770 draw_context_out
->current
->modify_over
->y
= -1;
1771 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1772 draw_context_out
->current
->modify_middle
->x
= -1;
1773 draw_context_out
->current
->modify_middle
->y
= -1;
1774 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1775 draw_context_out
->current
->modify_under
->x
= -1;
1776 draw_context_out
->current
->modify_under
->y
= -1;
1777 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1779 /* Finally, update the drawing context of the pid_in. */
1781 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1782 //draw_context_in->current->modify_over->x = x;
1783 draw_context_in
->current
->modify_over
->y
= y_in
;
1784 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1785 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1786 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1787 widget
= control_flow_data
->drawing
->drawing_area
;
1788 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1790 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1791 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1793 /*if(process_in->state->s == LTTV_STATE_RUN)
1795 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1796 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1797 PropertiesBG prop_bg;
1798 prop_bg.color = g_new(GdkColor,1);
1800 prop_bg.color->red = 0xffff;
1801 prop_bg.color->green = 0xffff;
1802 prop_bg.color->blue = 0xffff;
1804 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1805 g_free(prop_bg.color);
1806 gdk_gc_unref(draw_context_in->gc);
1809 draw_context_in
->gc
= widget
->style
->black_gc
;
1811 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1812 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1813 PropertiesText prop_text_in
;
1814 prop_text_in
.foreground
= &colorfg_in
;
1815 prop_text_in
.background
= &colorbg_in
;
1816 prop_text_in
.size
= 6;
1817 prop_text_in
.position
= OVER
;
1819 /* foreground of text : status of the process */
1820 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1822 prop_text_in
.foreground
->red
= 0xffff;
1823 prop_text_in
.foreground
->green
= 0xffff;
1824 prop_text_in
.foreground
->blue
= 0xffff;
1826 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1828 prop_text_in
.foreground
->red
= 0x0fff;
1829 prop_text_in
.foreground
->green
= 0xffff;
1830 prop_text_in
.foreground
->blue
= 0xfff0;
1832 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1834 prop_text_in
.foreground
->red
= 0xffff;
1835 prop_text_in
.foreground
->green
= 0xffff;
1836 prop_text_in
.foreground
->blue
= 0x0000;
1838 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1840 prop_text_in
.foreground
->red
= 0xffff;
1841 prop_text_in
.foreground
->green
= 0x0000;
1842 prop_text_in
.foreground
->blue
= 0xffff;
1844 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1846 prop_text_in
.foreground
->red
= 0xffff;
1847 prop_text_in
.foreground
->green
= 0x0000;
1848 prop_text_in
.foreground
->blue
= 0x0000;
1850 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1852 prop_text_in
.foreground
->red
= 0x0000;
1853 prop_text_in
.foreground
->green
= 0xffff;
1854 prop_text_in
.foreground
->blue
= 0x0000;
1858 prop_text_in
.foreground
->red
= 0xffff;
1859 prop_text_in
.foreground
->green
= 0xffff;
1860 prop_text_in
.foreground
->blue
= 0xffff;
1864 /* Print status of the process : U, WF, WC, E, W, R */
1865 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1866 prop_text_in
.text
= "U";
1867 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1868 prop_text_in
.text
= "WF";
1869 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1870 prop_text_in
.text
= "WC";
1871 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1872 prop_text_in
.text
= "E";
1873 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1874 prop_text_in
.text
= "W";
1875 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1876 prop_text_in
.text
= "R";
1878 prop_text_in
.text
= "U";
1880 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1883 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1886 prop_text_in
.foreground
= &colorfg_in
;
1887 prop_text_in
.background
= &colorbg_in
;
1888 prop_text_in
.foreground
->red
= 0xffff;
1889 prop_text_in
.foreground
->green
= 0xffff;
1890 prop_text_in
.foreground
->blue
= 0xffff;
1891 prop_text_in
.size
= 6;
1892 prop_text_in
.position
= UNDER
;
1894 prop_text_in
.text
= g_new(gchar
, 260);
1895 strcpy(prop_text_in
.text
, "CPU ");
1896 snprintf(tmp
, 255, "%u", ltt_tracefile_num(tfc
->tf
));
1897 strcat(prop_text_in
.text
, tmp
);
1899 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1900 g_free(prop_text_in
.text
);
1904 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1905 draw_context_in
->current
->over
->y
= y_in
;
1906 draw_context_in
->current
->under
->y
= y_in
+height
;
1907 draw_context_in
->current
->status
= process_in
->state
->s
;
1909 /* for pid_in : remove previous, Prev = current, new current (default) */
1910 g_free(draw_context_in
->previous
->modify_under
);
1911 g_free(draw_context_in
->previous
->modify_middle
);
1912 g_free(draw_context_in
->previous
->modify_over
);
1913 g_free(draw_context_in
->previous
->under
);
1914 g_free(draw_context_in
->previous
->middle
);
1915 g_free(draw_context_in
->previous
->over
);
1916 g_free(draw_context_in
->previous
);
1918 draw_context_in
->previous
= draw_context_in
->current
;
1920 draw_context_in
->current
= g_new(DrawInfo
,1);
1921 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1922 draw_context_in
->current
->over
->x
= -1;
1923 draw_context_in
->current
->over
->y
= -1;
1924 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1925 draw_context_in
->current
->middle
->x
= -1;
1926 draw_context_in
->current
->middle
->y
= -1;
1927 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1928 draw_context_in
->current
->under
->x
= -1;
1929 draw_context_in
->current
->under
->y
= -1;
1930 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1931 draw_context_in
->current
->modify_over
->x
= -1;
1932 draw_context_in
->current
->modify_over
->y
= -1;
1933 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1934 draw_context_in
->current
->modify_middle
->x
= -1;
1935 draw_context_in
->current
->modify_middle
->y
= -1;
1936 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1937 draw_context_in
->current
->modify_under
->x
= -1;
1938 draw_context_in
->current
->modify_under
->y
= -1;
1939 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1948 static inline PropertiesLine
prepare_execmode_line(LttvProcessState
*process
)
1950 PropertiesLine prop_line
;
1951 prop_line
.line_width
= 1;
1952 prop_line
.style
= GDK_LINE_SOLID
;
1954 //GdkColormap *colormap = gdk_colormap_get_system();
1956 /* color of line : execution mode of the process */
1957 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
1958 prop_line
.color
= drawing_colors
[COL_USER_MODE
];
1959 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
1960 prop_line
.color
= drawing_colors
[COL_SYSCALL
];
1961 else if(process
->state
->t
== LTTV_STATE_TRAP
)
1962 prop_line
.color
= drawing_colors
[COL_TRAP
];
1963 else if(process
->state
->t
== LTTV_STATE_IRQ
)
1964 prop_line
.color
= drawing_colors
[COL_IRQ
];
1965 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
1966 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
1968 prop_line
.color
= drawing_colors
[COL_WHITE
];
1970 //gdk_colormap_alloc_color(colormap,
1981 /* before_execmode_hook
1983 * This function basically draw lines and icons. Two types of lines are drawn :
1984 * one small (3 pixels?) representing the state of the process and the second
1985 * type is thicker (10 pixels?) representing on which CPU a process is running
1986 * (and this only in running state).
1988 * Extremums of the lines :
1989 * x_min : time of the last event context for this process kept in memory.
1990 * x_max : time of the current event.
1991 * y : middle of the process in the process list. The process is found in the
1992 * list, therefore is it's position in pixels.
1994 * The choice of lines'color is defined by the context of the last event for this
1999 int before_execmode_hook(void *hook_data
, void *call_data
)
2001 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2002 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2003 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2005 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2007 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2009 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2012 e
= ltt_tracefile_get_event(tfc
->tf
);
2014 LttTime evtime
= ltt_event_time(e
);
2016 /* we are in a execmode, before the state update. We must draw the
2017 * items corresponding to the state before it changes : now is the right
2021 //LttvProcessState *process = tfs->process;
2022 guint cpu
= ltt_tracefile_num(tfc
->tf
);
2023 LttvProcessState
*process
= ts
->running_process
[cpu
];
2024 g_assert(process
!= NULL
);
2026 guint pid
= process
->pid
;
2028 /* Well, the process_out existed : we must get it in the process hash
2029 * or add it, and draw its items.
2031 /* Add process to process list (if not present) */
2032 guint pl_height
= 0;
2033 HashedProcessData
*hashed_process_data
= NULL
;
2034 ProcessList
*process_list
= control_flow_data
->process_list
;
2035 LttTime birth
= process
->creation_time
;
2037 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
2038 hashed_process_data
= process_list
->current_hash_data
[cpu
];
2040 hashed_process_data
= processlist_get_process_data(process_list
,
2044 tfc
->t_context
->index
);
2045 if(unlikely(hashed_process_data
== NULL
))
2047 g_assert(pid
== 0 || pid
!= process
->ppid
);
2048 ProcessInfo
*process_info
;
2049 /* Process not present */
2050 Drawing_t
*drawing
= control_flow_data
->drawing
;
2051 processlist_add(process_list
,
2057 tfc
->t_context
->index
,
2061 &hashed_process_data
);
2062 gtk_widget_set_size_request(drawing
->drawing_area
,
2065 gtk_widget_queue_draw(drawing
->drawing_area
);
2067 /* Set the current process */
2068 process_list
->current_hash_data
[process
->cpu
] =
2069 hashed_process_data
;
2072 /* Now, the process is in the state hash and our own process hash.
2073 * We definitely can draw the items related to the ending state.
2076 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2079 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2080 TimeWindow time_window
=
2081 lttvwindow_get_time_window(control_flow_data
->tab
);
2084 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2085 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2087 #endif //EXTRA_CHECK
2088 Drawing_t
*drawing
= control_flow_data
->drawing
;
2089 guint width
= drawing
->width
;
2091 convert_time_to_pixels(
2097 /* Draw collision indicator */
2098 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2099 gdk_draw_point(hashed_process_data
->pixmap
,
2102 (hashed_process_data
->height
/2)-3);
2103 hashed_process_data
->x
.middle_marked
= TRUE
;
2106 TimeWindow time_window
=
2107 lttvwindow_get_time_window(control_flow_data
->tab
);
2110 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2111 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2113 #endif //EXTRA_CHECK
2114 Drawing_t
*drawing
= control_flow_data
->drawing
;
2115 guint width
= drawing
->width
;
2118 convert_time_to_pixels(
2125 /* Jump over draw if we are at the same x position */
2126 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2127 hashed_process_data
->x
.middle_used
))
2129 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2130 /* Draw collision indicator */
2131 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2132 gdk_draw_point(hashed_process_data
->pixmap
,
2135 (hashed_process_data
->height
/2)-3);
2136 hashed_process_data
->x
.middle_marked
= TRUE
;
2141 DrawContext draw_context
;
2142 /* Now create the drawing context that will be used to draw
2143 * items related to the last state. */
2144 draw_context
.drawable
= hashed_process_data
->pixmap
;
2145 draw_context
.gc
= drawing
->gc
;
2146 draw_context
.pango_layout
= drawing
->pango_layout
;
2147 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2148 draw_context
.drawinfo
.end
.x
= x
;
2150 draw_context
.drawinfo
.y
.over
= 1;
2151 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2152 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2154 draw_context
.drawinfo
.start
.offset
.over
= 0;
2155 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2156 draw_context
.drawinfo
.start
.offset
.under
= 0;
2157 draw_context
.drawinfo
.end
.offset
.over
= 0;
2158 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2159 draw_context
.drawinfo
.end
.offset
.under
= 0;
2163 PropertiesLine prop_line
= prepare_s_e_line(process
);
2164 draw_line((void*)&prop_line
, (void*)&draw_context
);
2167 /* become the last x position */
2168 hashed_process_data
->x
.middle
= x
;
2169 hashed_process_data
->x
.middle_used
= TRUE
;
2170 hashed_process_data
->x
.middle_marked
= FALSE
;
2172 /* Calculate the next good time */
2173 convert_pixels_to_time(width
, x
+1, time_window
,
2174 &hashed_process_data
->next_good_time
);
2181 /* after_execmode_hook
2183 * The draw after hook is called by the reading API to have a
2184 * particular event drawn on the screen.
2185 * @param hook_data ControlFlowData structure of the viewer.
2186 * @param call_data Event context.
2188 * This function adds items to be drawn in a queue for each process.
2192 int after_execmode_hook(void *hook_data
, void *call_data
)
2194 /**************** DOES NOTHING!! *************/
2195 /* hook desactivated in drawing.c */
2199 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2200 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2201 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2203 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2205 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2208 e
= ltt_tracefile_get_event(tfc
->tf
);
2210 LttTime evtime
= ltt_event_time(e
);
2212 /* Add process to process list (if not present) */
2213 LttvProcessState
*process
;
2215 guint pl_height
= 0;
2216 HashedProcessData
*hashed_process_data
= NULL
;
2218 ProcessList
*process_list
= control_flow_data
->process_list
;
2220 /* Find process pid_in in the list... */
2221 process
= tfs
->process
;
2222 /* It should exist, because we are after the state update. */
2223 g_assert(process
!= NULL
);
2225 guint pid
= process
->pid
;
2227 birth
= process
->creation_time
;
2229 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
2230 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
2232 hashed_process_data
= processlist_get_process_data(process_list
,
2234 process
->last_cpu_index
,
2236 tfc
->t_context
->index
);
2237 if(unlikely(hashed_process_data
== NULL
))
2239 g_assert(pid
== 0 || pid
!= process
->ppid
);
2240 /* Process not present */
2241 Drawing_t
*drawing
= control_flow_data
->drawing
;
2242 const gchar
*name
= g_quark_to_string(process
->name
);
2243 ProcessInfo
*process_info
;
2244 processlist_add(process_list
,
2247 process
->last_cpu_index
,
2250 tfc
->t_context
->index
,
2254 &hashed_process_data
);
2255 gtk_widget_set_size_request(drawing
->drawing_area
,
2258 gtk_widget_queue_draw(drawing
->drawing_area
);
2260 /* Set the current process */
2261 process_list
->current_hash_data
[process
->last_cpu_index
] =
2262 hashed_process_data
;
2265 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2268 TimeWindow time_window
=
2269 lttvwindow_get_time_window(control_flow_data
->tab
);
2272 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2273 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2275 #endif //EXTRA_CHECK
2276 Drawing_t
*drawing
= control_flow_data
->drawing
;
2277 guint width
= drawing
->width
;
2280 convert_time_to_pixels(
2286 if(hashed_process_data
->x
.middle
!= new_x
) {
2287 hashed_process_data
->x
.middle
= new_x
;
2288 hashed_process_data
->x
.middle_used
= FALSE
;
2289 hashed_process_data
->x
.middle_marked
= FALSE
;
2298 /* before_process_exit_hook
2300 * Draw lines for process event.
2302 * @param hook_data ControlFlowData structure of the viewer.
2303 * @param call_data Event context.
2305 * This function adds items to be drawn in a queue for each process.
2310 int before_process_exit_hook(void *hook_data
, void *call_data
)
2312 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2313 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2315 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2317 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2319 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2321 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2324 e
= ltt_tracefile_get_event(tfc
->tf
);
2326 LttTime evtime
= ltt_event_time(e
);
2328 /* Add process to process list (if not present) */
2329 //LttvProcessState *process = tfs->process;
2330 guint cpu
= ltt_tracefile_num(tfc
->tf
);
2331 LttvProcessState
*process
= ts
->running_process
[cpu
];
2332 guint pid
= process
->pid
;
2334 guint pl_height
= 0;
2335 HashedProcessData
*hashed_process_data
= NULL
;
2337 ProcessList
*process_list
= control_flow_data
->process_list
;
2339 g_assert(process
!= NULL
);
2341 birth
= process
->creation_time
;
2343 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
2344 hashed_process_data
= process_list
->current_hash_data
[cpu
];
2346 hashed_process_data
= processlist_get_process_data(process_list
,
2350 tfc
->t_context
->index
);
2351 if(unlikely(hashed_process_data
== NULL
))
2353 g_assert(pid
== 0 || pid
!= process
->ppid
);
2354 /* Process not present */
2355 Drawing_t
*drawing
= control_flow_data
->drawing
;
2356 ProcessInfo
*process_info
;
2357 processlist_add(process_list
,
2363 tfc
->t_context
->index
,
2367 &hashed_process_data
);
2368 gtk_widget_set_size_request(drawing
->drawing_area
,
2371 gtk_widget_queue_draw(drawing
->drawing_area
);
2375 /* Now, the process is in the state hash and our own process hash.
2376 * We definitely can draw the items related to the ending state.
2379 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2382 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2383 TimeWindow time_window
=
2384 lttvwindow_get_time_window(control_flow_data
->tab
);
2387 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2388 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2390 #endif //EXTRA_CHECK
2391 Drawing_t
*drawing
= control_flow_data
->drawing
;
2392 guint width
= drawing
->width
;
2394 convert_time_to_pixels(
2400 /* Draw collision indicator */
2401 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2402 gdk_draw_point(hashed_process_data
->pixmap
,
2405 (hashed_process_data
->height
/2)-3);
2406 hashed_process_data
->x
.middle_marked
= TRUE
;
2409 TimeWindow time_window
=
2410 lttvwindow_get_time_window(control_flow_data
->tab
);
2413 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2414 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2416 #endif //EXTRA_CHECK
2417 Drawing_t
*drawing
= control_flow_data
->drawing
;
2418 guint width
= drawing
->width
;
2421 convert_time_to_pixels(
2428 /* Jump over draw if we are at the same x position */
2429 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2430 hashed_process_data
->x
.middle_used
))
2432 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2433 /* Draw collision indicator */
2434 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2435 gdk_draw_point(hashed_process_data
->pixmap
,
2438 (hashed_process_data
->height
/2)-3);
2439 hashed_process_data
->x
.middle_marked
= TRUE
;
2443 DrawContext draw_context
;
2445 /* Now create the drawing context that will be used to draw
2446 * items related to the last state. */
2447 draw_context
.drawable
= hashed_process_data
->pixmap
;
2448 draw_context
.gc
= drawing
->gc
;
2449 draw_context
.pango_layout
= drawing
->pango_layout
;
2450 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2451 draw_context
.drawinfo
.end
.x
= x
;
2453 draw_context
.drawinfo
.y
.over
= 1;
2454 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2455 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2457 draw_context
.drawinfo
.start
.offset
.over
= 0;
2458 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2459 draw_context
.drawinfo
.start
.offset
.under
= 0;
2460 draw_context
.drawinfo
.end
.offset
.over
= 0;
2461 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2462 draw_context
.drawinfo
.end
.offset
.under
= 0;
2466 PropertiesLine prop_line
= prepare_s_e_line(process
);
2467 draw_line((void*)&prop_line
, (void*)&draw_context
);
2470 /* become the last x position */
2471 hashed_process_data
->x
.middle
= x
;
2472 hashed_process_data
->x
.middle_used
= TRUE
;
2473 hashed_process_data
->x
.middle_marked
= FALSE
;
2475 /* Calculate the next good time */
2476 convert_pixels_to_time(width
, x
+1, time_window
,
2477 &hashed_process_data
->next_good_time
);
2487 /* before_process_release_hook
2489 * Draw lines for process event.
2491 * @param hook_data ControlFlowData structure of the viewer.
2492 * @param call_data Event context.
2494 * This function adds items to be drawn in a queue for each process.
2499 int before_process_release_hook(void *hook_data
, void *call_data
)
2501 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2502 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2504 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2506 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2508 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2510 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2513 e
= ltt_tracefile_get_event(tfc
->tf
);
2515 LttTime evtime
= ltt_event_time(e
);
2520 pid
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2523 /* Add process to process list (if not present) */
2524 /* Don't care about the process if it's not in the state hash already :
2525 * that means a process that has never done anything in the trace and
2526 * unknown suddently gets destroyed : no state meaningful to show. */
2527 LttvProcessState
*process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2529 if(process
!= NULL
) {
2531 guint pl_height
= 0;
2532 HashedProcessData
*hashed_process_data
= NULL
;
2534 ProcessList
*process_list
= control_flow_data
->process_list
;
2536 birth
= process
->creation_time
;
2538 /* Cannot use current process : this event happens on another process,
2539 * action done by the parent. */
2540 hashed_process_data
= processlist_get_process_data(process_list
,
2544 tfc
->t_context
->index
);
2545 if(unlikely(hashed_process_data
== NULL
))
2547 g_assert(pid
== 0 || pid
!= process
->ppid
);
2548 /* Process not present */
2549 Drawing_t
*drawing
= control_flow_data
->drawing
;
2550 ProcessInfo
*process_info
;
2551 processlist_add(process_list
,
2557 tfc
->t_context
->index
,
2561 &hashed_process_data
);
2562 gtk_widget_set_size_request(drawing
->drawing_area
,
2565 gtk_widget_queue_draw(drawing
->drawing_area
);
2568 /* Now, the process is in the state hash and our own process hash.
2569 * We definitely can draw the items related to the ending state.
2572 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2575 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2576 TimeWindow time_window
=
2577 lttvwindow_get_time_window(control_flow_data
->tab
);
2580 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2581 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2583 #endif //EXTRA_CHECK
2584 Drawing_t
*drawing
= control_flow_data
->drawing
;
2585 guint width
= drawing
->width
;
2587 convert_time_to_pixels(
2593 /* Draw collision indicator */
2594 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2595 gdk_draw_point(hashed_process_data
->pixmap
,
2598 (hashed_process_data
->height
/2)-3);
2599 hashed_process_data
->x
.middle_marked
= TRUE
;
2602 TimeWindow time_window
=
2603 lttvwindow_get_time_window(control_flow_data
->tab
);
2606 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2607 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2609 #endif //EXTRA_CHECK
2610 Drawing_t
*drawing
= control_flow_data
->drawing
;
2611 guint width
= drawing
->width
;
2614 convert_time_to_pixels(
2621 /* Jump over draw if we are at the same x position */
2622 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2623 hashed_process_data
->x
.middle_used
))
2625 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2626 /* Draw collision indicator */
2627 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2628 gdk_draw_point(hashed_process_data
->pixmap
,
2631 (hashed_process_data
->height
/2)-3);
2632 hashed_process_data
->x
.middle_marked
= TRUE
;
2636 DrawContext draw_context
;
2638 /* Now create the drawing context that will be used to draw
2639 * items related to the last state. */
2640 draw_context
.drawable
= hashed_process_data
->pixmap
;
2641 draw_context
.gc
= drawing
->gc
;
2642 draw_context
.pango_layout
= drawing
->pango_layout
;
2643 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2644 draw_context
.drawinfo
.end
.x
= x
;
2646 draw_context
.drawinfo
.y
.over
= 1;
2647 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2648 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2650 draw_context
.drawinfo
.start
.offset
.over
= 0;
2651 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2652 draw_context
.drawinfo
.start
.offset
.under
= 0;
2653 draw_context
.drawinfo
.end
.offset
.over
= 0;
2654 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2655 draw_context
.drawinfo
.end
.offset
.under
= 0;
2659 PropertiesLine prop_line
= prepare_s_e_line(process
);
2660 draw_line((void*)&prop_line
, (void*)&draw_context
);
2663 /* become the last x position */
2664 hashed_process_data
->x
.middle
= x
;
2665 hashed_process_data
->x
.middle_used
= TRUE
;
2666 hashed_process_data
->x
.middle_marked
= FALSE
;
2668 /* Calculate the next good time */
2669 convert_pixels_to_time(width
, x
+1, time_window
,
2670 &hashed_process_data
->next_good_time
);
2686 /* before_process_hook
2688 * Draw lines for process event.
2690 * @param hook_data ControlFlowData structure of the viewer.
2691 * @param call_data Event context.
2693 * This function adds items to be drawn in a queue for each process.
2696 int before_process_hook(void *hook_data
, void *call_data
)
2698 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2699 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2700 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2702 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2704 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2707 e
= ltt_tracefile_get_event(tfc
->tf
);
2709 LttTime evtime
= ltt_event_time(e
);
2713 LttField
*f
= ltt_event_field(e
);
2715 element
= ltt_field_member(f
,0);
2716 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2719 if(sub_id
== 3) { /* exit */
2721 /* Add process to process list (if not present) */
2722 LttvProcessState
*process
= tfs
->process
;
2723 guint pid
= process
->pid
;
2725 guint pl_height
= 0;
2726 HashedProcessData
*hashed_process_data
= NULL
;
2728 ProcessList
*process_list
= control_flow_data
->process_list
;
2730 g_assert(process
!= NULL
);
2732 birth
= process
->creation_time
;
2734 if(likely(process_list
->current_hash_data
[tfc
->index
] != NULL
)) {
2735 hashed_process_data
= process_list
->current_hash_data
[tfc
->index
];
2737 hashed_process_data
= processlist_get_process_data(process_list
,
2739 process
->last_cpu_index
,
2741 tfc
->t_context
->index
);
2742 if(unlikely(hashed_process_data
== NULL
))
2744 g_assert(pid
== 0 || pid
!= process
->ppid
);
2745 /* Process not present */
2746 Drawing_t
*drawing
= control_flow_data
->drawing
;
2747 const gchar
*name
= g_quark_to_string(process
->name
);
2748 ProcessInfo
*process_info
;
2749 processlist_add(process_list
,
2752 process
->last_cpu_index
,
2755 tfc
->t_context
->index
,
2759 &hashed_process_data
);
2760 gtk_widget_set_size_request(drawing
->drawing_area
,
2763 gtk_widget_queue_draw(drawing
->drawing_area
);
2767 /* Now, the process is in the state hash and our own process hash.
2768 * We definitely can draw the items related to the ending state.
2771 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2774 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2775 TimeWindow time_window
=
2776 lttvwindow_get_time_window(control_flow_data
->tab
);
2779 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2780 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2782 #endif //EXTRA_CHECK
2783 Drawing_t
*drawing
= control_flow_data
->drawing
;
2784 guint width
= drawing
->width
;
2786 convert_time_to_pixels(
2792 /* Draw collision indicator */
2793 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2794 gdk_draw_point(hashed_process_data
->pixmap
,
2797 (hashed_process_data
->height
/2)-3);
2798 hashed_process_data
->x
.middle_marked
= TRUE
;
2801 TimeWindow time_window
=
2802 lttvwindow_get_time_window(control_flow_data
->tab
);
2805 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2806 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2808 #endif //EXTRA_CHECK
2809 Drawing_t
*drawing
= control_flow_data
->drawing
;
2810 guint width
= drawing
->width
;
2813 convert_time_to_pixels(
2820 /* Jump over draw if we are at the same x position */
2821 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2822 hashed_process_data
->x
.middle_used
))
2824 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2825 /* Draw collision indicator */
2826 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2827 gdk_draw_point(hashed_process_data
->pixmap
,
2830 (hashed_process_data
->height
/2)-3);
2831 hashed_process_data
->x
.middle_marked
= TRUE
;
2835 DrawContext draw_context
;
2837 /* Now create the drawing context that will be used to draw
2838 * items related to the last state. */
2839 draw_context
.drawable
= hashed_process_data
->pixmap
;
2840 draw_context
.gc
= drawing
->gc
;
2841 draw_context
.pango_layout
= drawing
->pango_layout
;
2842 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2843 draw_context
.drawinfo
.end
.x
= x
;
2845 draw_context
.drawinfo
.y
.over
= 1;
2846 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2847 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2849 draw_context
.drawinfo
.start
.offset
.over
= 0;
2850 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2851 draw_context
.drawinfo
.start
.offset
.under
= 0;
2852 draw_context
.drawinfo
.end
.offset
.over
= 0;
2853 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2854 draw_context
.drawinfo
.end
.offset
.under
= 0;
2858 PropertiesLine prop_line
= prepare_s_e_line(process
);
2859 draw_line((void*)&prop_line
, (void*)&draw_context
);
2862 /* become the last x position */
2863 hashed_process_data
->x
.middle
= x
;
2864 hashed_process_data
->x
.middle_used
= TRUE
;
2865 hashed_process_data
->x
.middle_marked
= FALSE
;
2867 /* Calculate the next good time */
2868 convert_pixels_to_time(width
, x
+1, time_window
,
2869 &hashed_process_data
->next_good_time
);
2873 } else if(sub_id
== 7) /* release */ {
2877 LttField
*f
= ltt_event_field(e
);
2879 element
= ltt_field_member(f
,1);
2880 pid
= ltt_event_get_long_unsigned(e
,element
);
2883 /* Add process to process list (if not present) */
2884 /* Don't care about the process if it's not in the state hash already :
2885 * that means a process that has never done anything in the trace and
2886 * unknown suddently gets destroyed : no state meaningful to show. */
2887 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
2889 if(process
!= NULL
) {
2891 guint pl_height
= 0;
2892 HashedProcessData
*hashed_process_data
= NULL
;
2894 ProcessList
*process_list
= control_flow_data
->process_list
;
2896 birth
= process
->creation_time
;
2898 /* Cannot use current process : this event happens on another process,
2899 * action done by the parent. */
2900 hashed_process_data
= processlist_get_process_data(process_list
,
2902 process
->last_cpu_index
,
2904 tfc
->t_context
->index
);
2905 if(unlikely(hashed_process_data
== NULL
))
2907 g_assert(pid
== 0 || pid
!= process
->ppid
);
2908 /* Process not present */
2909 Drawing_t
*drawing
= control_flow_data
->drawing
;
2910 ProcessInfo
*process_info
;
2911 processlist_add(process_list
,
2914 process
->last_cpu_index
,
2917 tfc
->t_context
->index
,
2921 &hashed_process_data
);
2922 gtk_widget_set_size_request(drawing
->drawing_area
,
2925 gtk_widget_queue_draw(drawing
->drawing_area
);
2928 /* Now, the process is in the state hash and our own process hash.
2929 * We definitely can draw the items related to the ending state.
2932 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2935 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2936 TimeWindow time_window
=
2937 lttvwindow_get_time_window(control_flow_data
->tab
);
2940 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2941 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2943 #endif //EXTRA_CHECK
2944 Drawing_t
*drawing
= control_flow_data
->drawing
;
2945 guint width
= drawing
->width
;
2947 convert_time_to_pixels(
2953 /* Draw collision indicator */
2954 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2955 gdk_draw_point(hashed_process_data
->pixmap
,
2958 (hashed_process_data
->height
/2)-3);
2959 hashed_process_data
->x
.middle_marked
= TRUE
;
2962 TimeWindow time_window
=
2963 lttvwindow_get_time_window(control_flow_data
->tab
);
2966 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2967 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2969 #endif //EXTRA_CHECK
2970 Drawing_t
*drawing
= control_flow_data
->drawing
;
2971 guint width
= drawing
->width
;
2974 convert_time_to_pixels(
2981 /* Jump over draw if we are at the same x position */
2982 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2983 hashed_process_data
->x
.middle_used
))
2985 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2986 /* Draw collision indicator */
2987 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2988 gdk_draw_point(hashed_process_data
->pixmap
,
2991 (hashed_process_data
->height
/2)-3);
2992 hashed_process_data
->x
.middle_marked
= TRUE
;
2996 DrawContext draw_context
;
2998 /* Now create the drawing context that will be used to draw
2999 * items related to the last state. */
3000 draw_context
.drawable
= hashed_process_data
->pixmap
;
3001 draw_context
.gc
= drawing
->gc
;
3002 draw_context
.pango_layout
= drawing
->pango_layout
;
3003 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
3004 draw_context
.drawinfo
.end
.x
= x
;
3006 draw_context
.drawinfo
.y
.over
= 1;
3007 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
3008 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
3010 draw_context
.drawinfo
.start
.offset
.over
= 0;
3011 draw_context
.drawinfo
.start
.offset
.middle
= 0;
3012 draw_context
.drawinfo
.start
.offset
.under
= 0;
3013 draw_context
.drawinfo
.end
.offset
.over
= 0;
3014 draw_context
.drawinfo
.end
.offset
.middle
= 0;
3015 draw_context
.drawinfo
.end
.offset
.under
= 0;
3019 PropertiesLine prop_line
= prepare_s_e_line(process
);
3020 draw_line((void*)&prop_line
, (void*)&draw_context
);
3023 /* become the last x position */
3024 hashed_process_data
->x
.middle
= x
;
3025 hashed_process_data
->x
.middle_used
= TRUE
;
3026 hashed_process_data
->x
.middle_marked
= FALSE
;
3028 /* Calculate the next good time */
3029 convert_pixels_to_time(width
, x
+1, time_window
,
3030 &hashed_process_data
->next_good_time
);
3044 /* after_process_fork_hook
3046 * Create the processlist entry for the child process. Put the last
3047 * position in x at the current time value.
3049 * @param hook_data ControlFlowData structure of the viewer.
3050 * @param call_data Event context.
3052 * This function adds items to be drawn in a queue for each process.
3055 int after_process_fork_hook(void *hook_data
, void *call_data
)
3057 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3058 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3059 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3061 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3063 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3065 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3068 e
= ltt_tracefile_get_event(tfc
->tf
);
3070 LttTime evtime
= ltt_event_time(e
);
3074 child_pid
= ltt_event_get_long_unsigned(e
, thf
->f2
);
3077 /* Add process to process list (if not present) */
3078 LttvProcessState
*process_child
;
3080 guint pl_height
= 0;
3081 HashedProcessData
*hashed_process_data_child
= NULL
;
3083 ProcessList
*process_list
= control_flow_data
->process_list
;
3085 /* Find child in the list... */
3086 process_child
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3087 /* It should exist, because we are after the state update. */
3088 g_assert(process_child
!= NULL
);
3090 birth
= process_child
->creation_time
;
3092 /* Cannot use current process, because this action is done by the parent
3094 hashed_process_data_child
= processlist_get_process_data(process_list
,
3098 tfc
->t_context
->index
);
3099 if(likely(hashed_process_data_child
== NULL
))
3101 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3102 /* Process not present */
3103 Drawing_t
*drawing
= control_flow_data
->drawing
;
3104 ProcessInfo
*process_info
;
3105 processlist_add(process_list
,
3109 process_child
->ppid
,
3111 tfc
->t_context
->index
,
3112 process_child
->name
,
3115 &hashed_process_data_child
);
3116 gtk_widget_set_size_request(drawing
->drawing_area
,
3119 gtk_widget_queue_draw(drawing
->drawing_area
);
3123 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3126 TimeWindow time_window
=
3127 lttvwindow_get_time_window(control_flow_data
->tab
);
3130 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3131 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3133 #endif //EXTRA_CHECK
3134 Drawing_t
*drawing
= control_flow_data
->drawing
;
3135 guint width
= drawing
->width
;
3137 convert_time_to_pixels(
3143 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3144 hashed_process_data_child
->x
.over
= new_x
;
3145 hashed_process_data_child
->x
.over_used
= FALSE
;
3146 hashed_process_data_child
->x
.over_marked
= FALSE
;
3148 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3149 hashed_process_data_child
->x
.middle
= new_x
;
3150 hashed_process_data_child
->x
.middle_used
= FALSE
;
3151 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3153 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3154 hashed_process_data_child
->x
.under
= new_x
;
3155 hashed_process_data_child
->x
.under_used
= FALSE
;
3156 hashed_process_data_child
->x
.under_marked
= FALSE
;
3164 /* after_process_exit_hook
3166 * Create the processlist entry for the child process. Put the last
3167 * position in x at the current time value.
3169 * @param hook_data ControlFlowData structure of the viewer.
3170 * @param call_data Event context.
3172 * This function adds items to be drawn in a queue for each process.
3175 int after_process_exit_hook(void *hook_data
, void *call_data
)
3177 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3178 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3179 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3181 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3183 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3185 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3188 e
= ltt_tracefile_get_event(tfc
->tf
);
3190 LttTime evtime
= ltt_event_time(e
);
3192 /* Add process to process list (if not present) */
3193 //LttvProcessState *process = tfs->process;
3194 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3195 LttvProcessState
*process
= ts
->running_process
[cpu
];
3197 /* It should exist, because we are after the state update. */
3198 g_assert(process
!= NULL
);
3200 guint pid
= process
->pid
;
3202 guint pl_height
= 0;
3203 HashedProcessData
*hashed_process_data
= NULL
;
3205 ProcessList
*process_list
= control_flow_data
->process_list
;
3207 birth
= process
->creation_time
;
3209 if(likely(process_list
->current_hash_data
[cpu
] != NULL
) ){
3210 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3212 hashed_process_data
= processlist_get_process_data(process_list
,
3216 tfc
->t_context
->index
);
3217 if(unlikely(hashed_process_data
== NULL
))
3219 g_assert(pid
== 0 || pid
!= process
->ppid
);
3220 /* Process not present */
3221 Drawing_t
*drawing
= control_flow_data
->drawing
;
3222 ProcessInfo
*process_info
;
3223 processlist_add(process_list
,
3229 tfc
->t_context
->index
,
3233 &hashed_process_data
);
3234 gtk_widget_set_size_request(drawing
->drawing_area
,
3237 gtk_widget_queue_draw(drawing
->drawing_area
);
3240 /* Set the current process */
3241 process_list
->current_hash_data
[process
->cpu
] =
3242 hashed_process_data
;
3245 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3248 TimeWindow time_window
=
3249 lttvwindow_get_time_window(control_flow_data
->tab
);
3252 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3253 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3255 #endif //EXTRA_CHECK
3256 Drawing_t
*drawing
= control_flow_data
->drawing
;
3257 guint width
= drawing
->width
;
3259 convert_time_to_pixels(
3264 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3265 hashed_process_data
->x
.middle
= new_x
;
3266 hashed_process_data
->x
.middle_used
= FALSE
;
3267 hashed_process_data
->x
.middle_marked
= FALSE
;
3277 /* after_process_hook
3279 * Create the processlist entry for the child process. Put the last
3280 * position in x at the current time value.
3282 * @param hook_data ControlFlowData structure of the viewer.
3283 * @param call_data Event context.
3285 * This function adds items to be drawn in a queue for each process.
3288 int after_process_hook(void *hook_data
, void *call_data
)
3290 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3291 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3292 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3294 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3296 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3299 e
= ltt_tracefile_get_event(tfc
->tf
);
3301 LttTime evtime
= ltt_event_time(e
);
3306 LttField
*f
= ltt_event_field(e
);
3308 element
= ltt_field_member(f
,0);
3309 sub_id
= ltt_event_get_long_unsigned(e
,element
);
3310 element
= ltt_field_member(f
,1);
3311 param1
= ltt_event_get_long_unsigned(e
,element
);
3314 if(sub_id
== 2) { /* fork */
3316 guint child_pid
= param1
;
3317 /* Add process to process list (if not present) */
3318 LttvProcessState
*process_child
;
3320 guint pl_height
= 0;
3321 HashedProcessData
*hashed_process_data_child
= NULL
;
3323 ProcessList
*process_list
= control_flow_data
->process_list
;
3325 /* Find child in the list... */
3326 process_child
= lttv_state_find_process(tfs
, child_pid
);
3327 /* It should exist, because we are after the state update. */
3328 g_assert(process_child
!= NULL
);
3330 birth
= process_child
->creation_time
;
3332 /* Cannot use current process, because this action is done by the parent
3334 hashed_process_data_child
= processlist_get_process_data(process_list
,
3336 process_child
->last_cpu_index
,
3338 tfc
->t_context
->index
);
3339 if(likely(hashed_process_data_child
== NULL
))
3341 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3342 /* Process not present */
3343 Drawing_t
*drawing
= control_flow_data
->drawing
;
3344 const gchar
*name
= g_quark_to_string(process_child
->name
);
3345 ProcessInfo
*process_info
;
3346 processlist_add(process_list
,
3349 process_child
->last_cpu_index
,
3350 process_child
->ppid
,
3352 tfc
->t_context
->index
,
3356 &hashed_process_data_child
);
3357 gtk_widget_set_size_request(drawing
->drawing_area
,
3360 gtk_widget_queue_draw(drawing
->drawing_area
);
3364 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3367 TimeWindow time_window
=
3368 lttvwindow_get_time_window(control_flow_data
->tab
);
3371 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3372 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3374 #endif //EXTRA_CHECK
3375 Drawing_t
*drawing
= control_flow_data
->drawing
;
3376 guint width
= drawing
->width
;
3378 convert_time_to_pixels(
3384 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3385 hashed_process_data_child
->x
.over
= new_x
;
3386 hashed_process_data_child
->x
.over_used
= FALSE
;
3387 hashed_process_data_child
->x
.over_marked
= FALSE
;
3389 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3390 hashed_process_data_child
->x
.middle
= new_x
;
3391 hashed_process_data_child
->x
.middle_used
= FALSE
;
3392 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3394 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3395 hashed_process_data_child
->x
.under
= new_x
;
3396 hashed_process_data_child
->x
.under_used
= FALSE
;
3397 hashed_process_data_child
->x
.under_marked
= FALSE
;
3401 } else if(sub_id
== 3) { /* exit */
3403 /* Add process to process list (if not present) */
3404 LttvProcessState
*process
= tfs
->process
;
3405 guint pid
= process
->pid
;
3407 guint pl_height
= 0;
3408 HashedProcessData
*hashed_process_data
= NULL
;
3410 ProcessList
*process_list
= control_flow_data
->process_list
;
3412 /* It should exist, because we are after the state update. */
3413 g_assert(process
!= NULL
);
3415 birth
= process
->creation_time
;
3417 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
) ){
3418 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
3420 hashed_process_data
= processlist_get_process_data(process_list
,
3422 process
->last_cpu_index
,
3424 tfc
->t_context
->index
);
3425 if(unlikely(hashed_process_data
== NULL
))
3427 g_assert(pid
== 0 || pid
!= process
->ppid
);
3428 /* Process not present */
3429 Drawing_t
*drawing
= control_flow_data
->drawing
;
3430 const gchar
*name
= g_quark_to_string(process
->name
);
3431 ProcessInfo
*process_info
;
3432 processlist_add(process_list
,
3435 process
->last_cpu_index
,
3438 tfc
->t_context
->index
,
3442 &hashed_process_data
);
3443 gtk_widget_set_size_request(drawing
->drawing_area
,
3446 gtk_widget_queue_draw(drawing
->drawing_area
);
3449 /* Set the current process */
3450 process_list
->current_hash_data
[process
->last_cpu_index
] =
3451 hashed_process_data
;
3454 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3457 TimeWindow time_window
=
3458 lttvwindow_get_time_window(control_flow_data
->tab
);
3461 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3462 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3464 #endif //EXTRA_CHECK
3465 Drawing_t
*drawing
= control_flow_data
->drawing
;
3466 guint width
= drawing
->width
;
3468 convert_time_to_pixels(
3473 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3474 hashed_process_data
->x
.middle
= new_x
;
3475 hashed_process_data
->x
.middle_used
= FALSE
;
3476 hashed_process_data
->x
.middle_marked
= FALSE
;
3486 /* Get the filename of the process to print */
3487 int after_fs_exec_hook(void *hook_data
, void *call_data
)
3489 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3490 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3491 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3493 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3495 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3497 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3499 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3500 LttvProcessState
*process
= ts
->running_process
[cpu
];
3501 g_assert(process
!= NULL
);
3503 guint pid
= process
->pid
;
3505 /* Well, the process_out existed : we must get it in the process hash
3506 * or add it, and draw its items.
3508 /* Add process to process list (if not present) */
3509 guint pl_height
= 0;
3510 HashedProcessData
*hashed_process_data
= NULL
;
3511 ProcessList
*process_list
= control_flow_data
->process_list
;
3512 LttTime birth
= process
->creation_time
;
3514 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
3515 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3517 hashed_process_data
= processlist_get_process_data(process_list
,
3521 tfc
->t_context
->index
);
3522 if(unlikely(hashed_process_data
== NULL
))
3524 g_assert(pid
== 0 || pid
!= process
->ppid
);
3525 ProcessInfo
*process_info
;
3526 /* Process not present */
3527 Drawing_t
*drawing
= control_flow_data
->drawing
;
3528 processlist_add(process_list
,
3534 tfc
->t_context
->index
,
3538 &hashed_process_data
);
3539 gtk_widget_set_size_request(drawing
->drawing_area
,
3542 gtk_widget_queue_draw(drawing
->drawing_area
);
3544 /* Set the current process */
3545 process_list
->current_hash_data
[process
->cpu
] =
3546 hashed_process_data
;
3549 processlist_set_name(process_list
, process
->name
, hashed_process_data
);
3558 gint
update_time_window_hook(void *hook_data
, void *call_data
)
3560 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3561 Drawing_t
*drawing
= control_flow_data
->drawing
;
3562 ProcessList
*process_list
= control_flow_data
->process_list
;
3564 const TimeWindowNotifyData
*time_window_nofify_data
=
3565 ((const TimeWindowNotifyData
*)call_data
);
3567 TimeWindow
*old_time_window
=
3568 time_window_nofify_data
->old_time_window
;
3569 TimeWindow
*new_time_window
=
3570 time_window_nofify_data
->new_time_window
;
3572 /* Update the ruler */
3573 drawing_update_ruler(control_flow_data
->drawing
,
3577 /* Two cases : zoom in/out or scrolling */
3579 /* In order to make sure we can reuse the old drawing, the scale must
3580 * be the same and the new time interval being partly located in the
3581 * currently shown time interval. (reuse is only for scrolling)
3584 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3585 old_time_window
->start_time
.tv_sec
,
3586 old_time_window
->start_time
.tv_nsec
,
3587 old_time_window
->time_width
.tv_sec
,
3588 old_time_window
->time_width
.tv_nsec
);
3590 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3591 new_time_window
->start_time
.tv_sec
,
3592 new_time_window
->start_time
.tv_nsec
,
3593 new_time_window
->time_width
.tv_sec
,
3594 new_time_window
->time_width
.tv_nsec
);
3596 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
3597 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
3599 /* Same scale (scrolling) */
3600 g_info("scrolling");
3601 LttTime
*ns
= &new_time_window
->start_time
;
3602 LttTime
*nw
= &new_time_window
->time_width
;
3603 LttTime
*os
= &old_time_window
->start_time
;
3604 LttTime
*ow
= &old_time_window
->time_width
;
3605 LttTime old_end
= old_time_window
->end_time
;
3606 LttTime new_end
= new_time_window
->end_time
;
3608 //if(ns<os+w && os+w<ns+w)
3609 //if(ns<old_end && os<ns)
3610 if(ltt_time_compare(*ns
, old_end
) == -1
3611 && ltt_time_compare(*os
, *ns
) == -1)
3613 g_info("scrolling near right");
3614 /* Scroll right, keep right part of the screen */
3616 guint width
= control_flow_data
->drawing
->width
;
3617 convert_time_to_pixels(
3623 /* Copy old data to new location */
3624 copy_pixmap_region(process_list
,
3626 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3630 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
3632 if(drawing
->damage_begin
== drawing
->damage_end
)
3633 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
3635 drawing
->damage_begin
= 0;
3637 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3639 /* Clear the data request background, but not SAFETY */
3640 rectangle_pixmap(process_list
,
3641 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3643 drawing
->damage_begin
+SAFETY
, 0,
3644 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3646 gtk_widget_queue_draw(drawing
->drawing_area
);
3647 //gtk_widget_queue_draw_area (drawing->drawing_area,
3649 // control_flow_data->drawing->width,
3650 // control_flow_data->drawing->height);
3652 /* Get new data for the rest. */
3653 drawing_data_request(control_flow_data
->drawing
,
3654 drawing
->damage_begin
, 0,
3655 drawing
->damage_end
- drawing
->damage_begin
,
3656 control_flow_data
->drawing
->height
);
3659 //if(ns<os && os<ns+w)
3660 //if(ns<os && os<new_end)
3661 if(ltt_time_compare(*ns
,*os
) == -1
3662 && ltt_time_compare(*os
,new_end
) == -1)
3664 g_info("scrolling near left");
3665 /* Scroll left, keep left part of the screen */
3667 guint width
= control_flow_data
->drawing
->width
;
3668 convert_time_to_pixels(
3674 /* Copy old data to new location */
3675 copy_pixmap_region (process_list
,
3677 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3683 if(drawing
->damage_begin
== drawing
->damage_end
)
3684 drawing
->damage_end
= x
;
3686 drawing
->damage_end
=
3687 control_flow_data
->drawing
->width
;
3689 drawing
->damage_begin
= 0;
3691 rectangle_pixmap (process_list
,
3692 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3694 drawing
->damage_begin
, 0,
3695 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3698 gtk_widget_queue_draw(drawing
->drawing_area
);
3699 //gtk_widget_queue_draw_area (drawing->drawing_area,
3701 // control_flow_data->drawing->width,
3702 // control_flow_data->drawing->height);
3705 /* Get new data for the rest. */
3706 drawing_data_request(control_flow_data
->drawing
,
3707 drawing
->damage_begin
, 0,
3708 drawing
->damage_end
- drawing
->damage_begin
,
3709 control_flow_data
->drawing
->height
);
3712 if(ltt_time_compare(*ns
,*os
) == 0)
3714 g_info("not scrolling");
3716 g_info("scrolling far");
3717 /* Cannot reuse any part of the screen : far jump */
3720 rectangle_pixmap (process_list
,
3721 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3724 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3727 //gtk_widget_queue_draw_area (drawing->drawing_area,
3729 // control_flow_data->drawing->width,
3730 // control_flow_data->drawing->height);
3731 gtk_widget_queue_draw(drawing
->drawing_area
);
3733 drawing
->damage_begin
= 0;
3734 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3736 drawing_data_request(control_flow_data
->drawing
,
3738 control_flow_data
->drawing
->width
,
3739 control_flow_data
->drawing
->height
);
3745 /* Different scale (zoom) */
3748 rectangle_pixmap (process_list
,
3749 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3752 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3755 //gtk_widget_queue_draw_area (drawing->drawing_area,
3757 // control_flow_data->drawing->width,
3758 // control_flow_data->drawing->height);
3759 gtk_widget_queue_draw(drawing
->drawing_area
);
3761 drawing
->damage_begin
= 0;
3762 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3764 drawing_data_request(control_flow_data
->drawing
,
3766 control_flow_data
->drawing
->width
,
3767 control_flow_data
->drawing
->height
);
3775 gint
traceset_notify(void *hook_data
, void *call_data
)
3777 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3778 Drawing_t
*drawing
= control_flow_data
->drawing
;
3781 drawing_clear(control_flow_data
->drawing
);
3782 processlist_clear(control_flow_data
->process_list
);
3783 gtk_widget_set_size_request(
3784 control_flow_data
->drawing
->drawing_area
,
3785 -1, processlist_get_height(control_flow_data
->process_list
));
3786 redraw_notify(control_flow_data
, NULL
);
3788 request_background_data(control_flow_data
);
3793 gint
redraw_notify(void *hook_data
, void *call_data
)
3795 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3796 Drawing_t
*drawing
= control_flow_data
->drawing
;
3797 GtkWidget
*widget
= drawing
->drawing_area
;
3799 drawing
->damage_begin
= 0;
3800 drawing
->damage_end
= drawing
->width
;
3802 /* fun feature, to be separated someday... */
3803 drawing_clear(control_flow_data
->drawing
);
3804 processlist_clear(control_flow_data
->process_list
);
3805 gtk_widget_set_size_request(
3806 control_flow_data
->drawing
->drawing_area
,
3807 -1, processlist_get_height(control_flow_data
->process_list
));
3809 rectangle_pixmap (control_flow_data
->process_list
,
3810 widget
->style
->black_gc
,
3813 drawing
->alloc_width
,
3816 gtk_widget_queue_draw(drawing
->drawing_area
);
3818 if(drawing
->damage_begin
< drawing
->damage_end
)
3820 drawing_data_request(drawing
,
3821 drawing
->damage_begin
,
3823 drawing
->damage_end
-drawing
->damage_begin
,
3827 //gtk_widget_queue_draw_area(drawing->drawing_area,
3830 // drawing->height);
3836 gint
continue_notify(void *hook_data
, void *call_data
)
3838 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3839 Drawing_t
*drawing
= control_flow_data
->drawing
;
3841 //g_assert(widget->allocation.width == drawing->damage_end);
3843 if(drawing
->damage_begin
< drawing
->damage_end
)
3845 drawing_data_request(drawing
,
3846 drawing
->damage_begin
,
3848 drawing
->damage_end
-drawing
->damage_begin
,
3856 gint
update_current_time_hook(void *hook_data
, void *call_data
)
3858 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
3859 Drawing_t
*drawing
= control_flow_data
->drawing
;
3861 LttTime current_time
= *((LttTime
*)call_data
);
3863 TimeWindow time_window
=
3864 lttvwindow_get_time_window(control_flow_data
->tab
);
3866 LttTime time_begin
= time_window
.start_time
;
3867 LttTime width
= time_window
.time_width
;
3870 guint64 time_ll
= ltt_time_to_uint64(width
);
3871 time_ll
= time_ll
>> 1; /* divide by two */
3872 half_width
= ltt_time_from_uint64(time_ll
);
3874 LttTime time_end
= ltt_time_add(time_begin
, width
);
3876 LttvTracesetContext
* tsc
=
3877 lttvwindow_get_traceset_context(control_flow_data
->tab
);
3879 LttTime trace_start
= tsc
->time_span
.start_time
;
3880 LttTime trace_end
= tsc
->time_span
.end_time
;
3882 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
3883 current_time
.tv_nsec
);
3887 /* If current time is inside time interval, just move the highlight
3890 /* Else, we have to change the time interval. We have to tell it
3891 * to the main window. */
3892 /* The time interval change will take care of placing the current
3893 * time at the center of the visible area, or nearest possible if we are
3894 * at one end of the trace. */
3897 if(ltt_time_compare(current_time
, time_begin
) < 0)
3899 TimeWindow new_time_window
;
3901 if(ltt_time_compare(current_time
,
3902 ltt_time_add(trace_start
,half_width
)) < 0)
3903 time_begin
= trace_start
;
3905 time_begin
= ltt_time_sub(current_time
,half_width
);
3907 new_time_window
.start_time
= time_begin
;
3908 new_time_window
.time_width
= width
;
3909 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3910 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3912 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3914 else if(ltt_time_compare(current_time
, time_end
) > 0)
3916 TimeWindow new_time_window
;
3918 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
3919 time_begin
= ltt_time_sub(trace_end
,width
);
3921 time_begin
= ltt_time_sub(current_time
,half_width
);
3923 new_time_window
.start_time
= time_begin
;
3924 new_time_window
.time_width
= width
;
3925 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3926 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3928 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3931 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
3937 typedef struct _ClosureData
{
3938 EventsRequest
*events_request
;
3939 LttvTracesetState
*tss
;
3945 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
3947 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
3948 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
3949 ClosureData
*closure_data
= (ClosureData
*)user_data
;
3951 EventsRequest
*events_request
= closure_data
->events_request
;
3952 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3954 LttvTracesetState
*tss
= closure_data
->tss
;
3955 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
3957 LttTime evtime
= closure_data
->end_time
;
3960 /* For the process */
3961 /* First, check if the current process is in the state computation
3962 * process list. If it is there, that means we must add it right now and
3963 * draw items from the beginning of the read for it. If it is not
3964 * present, it's a new process and it was not present : it will
3965 * be added after the state update. */
3967 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
3968 #endif //EXTRA_CHECK
3969 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
3970 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
3973 //FIXME : optimize data structures.
3974 LttvTracefileState
*tfs
;
3975 LttvTracefileContext
*tfc
;
3977 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
3978 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
3979 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
3980 && ltt_tracefile_num(tfc
->tf
) == process_info
->cpu
)
3984 g_assert(i
<tc
->tracefiles
->len
);
3985 tfs
= LTTV_TRACEFILE_STATE(tfc
);
3987 // LttvTracefileState *tfs =
3988 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3989 // tracefiles[process_info->cpu];
3991 LttvProcessState
*process
;
3992 process
= lttv_state_find_process(ts
, process_info
->cpu
,
3995 if(unlikely(process
!= NULL
)) {
3997 /* Only draw for processes that are currently in the trace states */
3999 ProcessList
*process_list
= control_flow_data
->process_list
;
4001 /* Should be alike when background info is ready */
4002 if(control_flow_data
->background_info_waiting
==0)
4003 g_assert(ltt_time_compare(process
->creation_time
,
4004 process_info
->birth
) == 0);
4005 #endif //EXTRA_CHECK
4007 /* Now, the process is in the state hash and our own process hash.
4008 * We definitely can draw the items related to the ending state.
4011 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
4014 TimeWindow time_window
=
4015 lttvwindow_get_time_window(control_flow_data
->tab
);
4018 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
4019 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
4021 #endif //EXTRA_CHECK
4022 Drawing_t
*drawing
= control_flow_data
->drawing
;
4023 guint width
= drawing
->width
;
4025 guint x
= closure_data
->x_end
;
4027 DrawContext draw_context
;
4029 /* Now create the drawing context that will be used to draw
4030 * items related to the last state. */
4031 draw_context
.drawable
= hashed_process_data
->pixmap
;
4032 draw_context
.gc
= drawing
->gc
;
4033 draw_context
.pango_layout
= drawing
->pango_layout
;
4034 draw_context
.drawinfo
.end
.x
= x
;
4036 draw_context
.drawinfo
.y
.over
= 1;
4037 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
4038 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
4040 draw_context
.drawinfo
.start
.offset
.over
= 0;
4041 draw_context
.drawinfo
.start
.offset
.middle
= 0;
4042 draw_context
.drawinfo
.start
.offset
.under
= 0;
4043 draw_context
.drawinfo
.end
.offset
.over
= 0;
4044 draw_context
.drawinfo
.end
.offset
.middle
= 0;
4045 draw_context
.drawinfo
.end
.offset
.under
= 0;
4047 /* Jump over draw if we are at the same x position */
4048 if(x
== hashed_process_data
->x
.over
)
4052 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
4054 PropertiesLine prop_line
= prepare_execmode_line(process
);
4055 draw_line((void*)&prop_line
, (void*)&draw_context
);
4057 hashed_process_data
->x
.over
= x
;
4061 if(unlikely(x
== hashed_process_data
->x
.middle
&&
4062 hashed_process_data
->x
.middle_used
)) {
4063 #if 0 /* do not mark closure : not missing information */
4064 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
4065 /* Draw collision indicator */
4066 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
4067 gdk_draw_point(drawing
->pixmap
,
4071 hashed_process_data
->x
.middle_marked
= TRUE
;
4076 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
4078 PropertiesLine prop_line
= prepare_s_e_line(process
);
4079 draw_line((void*)&prop_line
, (void*)&draw_context
);
4081 /* become the last x position */
4082 if(likely(x
!= hashed_process_data
->x
.middle
)) {
4083 hashed_process_data
->x
.middle
= x
;
4084 /* but don't use the pixel */
4085 hashed_process_data
->x
.middle_used
= FALSE
;
4087 /* Calculate the next good time */
4088 convert_pixels_to_time(width
, x
+1, time_window
,
4089 &hashed_process_data
->next_good_time
);
4098 int before_chunk(void *hook_data
, void *call_data
)
4100 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4101 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4102 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
4104 /* Desactivate sort */
4105 gtk_tree_sortable_set_sort_column_id(
4106 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
4108 GTK_SORT_ASCENDING
);
4110 drawing_chunk_begin(events_request
, tss
);
4115 int before_request(void *hook_data
, void *call_data
)
4117 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4118 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4120 drawing_data_request_begin(events_request
, tss
);
4127 * after request is necessary in addition of after chunk in order to draw
4128 * lines until the end of the screen. after chunk just draws lines until
4135 int after_request(void *hook_data
, void *call_data
)
4137 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4138 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4139 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4141 ProcessList
*process_list
= control_flow_data
->process_list
;
4142 LttTime end_time
= events_request
->end_time
;
4144 ClosureData closure_data
;
4145 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4146 closure_data
.tss
= tss
;
4147 closure_data
.end_time
= end_time
;
4149 TimeWindow time_window
=
4150 lttvwindow_get_time_window(control_flow_data
->tab
);
4151 guint width
= control_flow_data
->drawing
->width
;
4152 convert_time_to_pixels(
4156 &closure_data
.x_end
);
4159 /* Draw last items */
4160 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4161 (void*)&closure_data
);
4164 /* Request expose */
4165 drawing_request_expose(events_request
, tss
, end_time
);
4174 int after_chunk(void *hook_data
, void *call_data
)
4176 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4177 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4178 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4179 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
4180 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
4183 ProcessList
*process_list
= control_flow_data
->process_list
;
4185 g_free(process_list
->current_hash_data
);
4186 process_list
->current_hash_data
= NULL
;
4189 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
4190 else /* end of traceset, or position now out of request : end */
4191 end_time
= events_request
->end_time
;
4193 ClosureData closure_data
;
4194 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4195 closure_data
.tss
= tss
;
4196 closure_data
.end_time
= end_time
;
4198 TimeWindow time_window
=
4199 lttvwindow_get_time_window(control_flow_data
->tab
);
4200 guint width
= control_flow_data
->drawing
->width
;
4201 convert_time_to_pixels(
4205 &closure_data
.x_end
);
4207 /* Draw last items */
4208 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4209 (void*)&closure_data
);
4211 /* Reactivate sort */
4212 gtk_tree_sortable_set_sort_column_id(
4213 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
4214 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
4215 GTK_SORT_ASCENDING
);
4217 update_index_to_pixmap(control_flow_data
->process_list
);
4218 /* Request a full expose : drawing scrambled */
4219 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
4221 /* Request expose (updates damages zone also) */
4222 drawing_request_expose(events_request
, tss
, end_time
);