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
49 //#define PANGO_ENABLE_BACKEND
57 //#include <pango/pango.h>
59 #include <ltt/event.h>
63 #include <lttv/lttv.h>
64 #include <lttv/hook.h>
65 #include <lttv/state.h>
66 #include <lttvwindow/lttvwindow.h>
67 #include <lttvwindow/lttvwindowtraces.h>
70 #include "eventhooks.h"
72 #include "processlist.h"
74 #include "cfv-private.h"
77 #define MAX_PATH_LEN 256
81 typedef struct _ProcessAddClosure
{
86 static void process_add(gpointer key
,
90 LttvProcessState
*process
= (LttvProcessState
*)value
;
91 ProcessAddClosure
*closure
= (ProcessAddClosure
*)user_data
;
92 ControlFlowData
*control_flow_data
= closure
->cfd
;
93 guint trace_num
= closure
->trace_num
;
95 /* Add process to process list (if not present) */
98 guint y
= 0, height
= 0, pl_height
= 0;
100 ProcessList
*process_list
=
101 guicontrolflow_get_process_list(control_flow_data
);
104 birth
= process
->creation_time
;
105 const gchar
*name
= g_quark_to_string(process
->name
);
106 HashedProcessData
*hashed_process_data
= NULL
;
108 if(processlist_get_process_pixels(process_list
,
114 &hashed_process_data
) == 1)
116 /* Process not present */
117 processlist_add(process_list
,
123 &hashed_process_data
);
124 processlist_get_process_pixels(process_list
,
130 &hashed_process_data
);
131 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
137 /* Action to do when background computation completed.
139 * Wait for all the awaited computations to be over.
142 gint
background_ready(void *hook_data
, void *call_data
)
144 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
145 LttvTrace
*trace
= (LttvTrace
*)call_data
;
146 LttvTracesetContext
*tsc
=
147 lttvwindow_get_traceset_context(control_flow_data
->tab
);
149 control_flow_data
->background_info_waiting
--;
151 if(control_flow_data
->background_info_waiting
== 0) {
152 g_debug("control flow viewer : background computation data ready.");
154 drawing_clear(control_flow_data
->drawing
);
155 processlist_clear(control_flow_data
->process_list
);
156 redraw_notify(control_flow_data
, NULL
);
163 /* Request background computation. Verify if it is in progress or ready first.
164 * Only for each trace in the tab's traceset.
166 void request_background_data(ControlFlowData
*control_flow_data
)
168 LttvTracesetContext
* tsc
=
169 lttvwindow_get_traceset_context(control_flow_data
->tab
);
170 gint num_traces
= lttv_traceset_number(tsc
->ts
);
174 LttvHooks
*background_ready_hook
=
176 lttv_hooks_add(background_ready_hook
, background_ready
, control_flow_data
,
178 control_flow_data
->background_info_waiting
= 0;
180 for(i
=0;i
<num_traces
;i
++) {
181 trace
= lttv_traceset_get(tsc
->ts
, i
);
183 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
) {
185 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
187 /* We first remove requests that could have been done for the same
188 * information. Happens when two viewers ask for it before servicing
191 lttvwindowtraces_background_request_remove(trace
, "state");
192 lttvwindowtraces_background_request_queue(trace
,
194 lttvwindowtraces_background_notify_queue(control_flow_data
,
198 background_ready_hook
);
199 control_flow_data
->background_info_waiting
++;
200 } else { /* in progress */
202 lttvwindowtraces_background_notify_current(control_flow_data
,
206 background_ready_hook
);
207 control_flow_data
->background_info_waiting
++;
212 lttv_hooks_destroy(background_ready_hook
);
219 * Event Viewer's constructor hook
221 * This constructor is given as a parameter to the menuitem and toolbar button
222 * registration. It creates the list.
223 * @param tab A pointer to the parent tab.
224 * @return The widget created.
227 h_guicontrolflow(Tab
*tab
)
229 g_info("h_guicontrolflow, %p", tab
);
230 ControlFlowData
*control_flow_data
= guicontrolflow() ;
232 control_flow_data
->tab
= tab
;
234 //g_debug("time width2 : %u",time_window->time_width);
235 // Unreg done in the GuiControlFlow_Destructor
236 lttvwindow_register_traceset_notify(tab
,
240 lttvwindow_register_time_window_notify(tab
,
241 update_time_window_hook
,
243 lttvwindow_register_current_time_notify(tab
,
244 update_current_time_hook
,
246 lttvwindow_register_redraw_notify(tab
,
249 lttvwindow_register_continue_notify(tab
,
252 request_background_data(control_flow_data
);
255 return guicontrolflow_get_widget(control_flow_data
) ;
259 int event_selected_hook(void *hook_data
, void *call_data
)
261 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
262 guint
*event_number
= (guint
*) call_data
;
264 g_debug("DEBUG : event selected by main window : %u", *event_number
);
269 static __inline PropertiesLine
prepare_status_line(LttvProcessState
*process
)
271 PropertiesLine prop_line
;
272 prop_line
.line_width
= 2;
273 prop_line
.style
= GDK_LINE_SOLID
;
274 prop_line
.y
= MIDDLE
;
275 //GdkColormap *colormap = gdk_colormap_get_system();
277 g_debug("prepare_status_line for state : %s", g_quark_to_string(process
->state
->s
));
279 /* color of line : status of the process */
280 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
281 prop_line
.color
= drawing_colors
[COL_WHITE
];
282 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
283 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
284 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
285 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
286 else if(process
->state
->s
== LTTV_STATE_ZOMBIE
)
287 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
288 else if(process
->state
->s
== LTTV_STATE_WAIT
)
289 prop_line
.color
= drawing_colors
[COL_WAIT
];
290 else if(process
->state
->s
== LTTV_STATE_RUN
)
291 prop_line
.color
= drawing_colors
[COL_RUN
];
293 prop_line
.color
= drawing_colors
[COL_WHITE
];
295 //gdk_colormap_alloc_color(colormap,
306 /* before_schedchange_hook
308 * This function basically draw lines and icons. Two types of lines are drawn :
309 * one small (3 pixels?) representing the state of the process and the second
310 * type is thicker (10 pixels?) representing on which CPU a process is running
311 * (and this only in running state).
313 * Extremums of the lines :
314 * x_min : time of the last event context for this process kept in memory.
315 * x_max : time of the current event.
316 * y : middle of the process in the process list. The process is found in the
317 * list, therefore is it's position in pixels.
319 * The choice of lines'color is defined by the context of the last event for this
324 int before_schedchange_hook(void *hook_data
, void *call_data
)
326 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
327 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
328 Drawing_t
*drawing
= control_flow_data
->drawing
;
330 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
332 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
333 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
338 LttTime evtime
= ltt_event_time(e
);
339 TimeWindow time_window
=
340 lttvwindow_get_time_window(control_flow_data
->tab
);
342 LttTime end_time
= ltt_time_add(time_window
.start_time
,
343 time_window
.time_width
);
345 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
346 || ltt_time_compare(evtime
, end_time
) == 1)
349 guint width
= drawing
->width
;
351 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0) {
353 /* we are in a schedchange, before the state update. We must draw the
354 * items corresponding to the state before it changes : now is the right
361 LttField
*f
= ltt_event_field(e
);
363 element
= ltt_field_member(f
,0);
364 pid_out
= ltt_event_get_long_unsigned(e
,element
);
365 element
= ltt_field_member(f
,1);
366 pid_in
= ltt_event_get_long_unsigned(e
,element
);
367 g_debug("out : %u in : %u", pid_out
, pid_in
);
371 /* For the pid_out */
372 /* First, check if the current process is in the state computation
373 * process list. If it is there, that means we must add it right now and
374 * draw items from the beginning of the read for it. If it is not
375 * present, it's a new process and it was not present : it will
376 * be added after the state update. */
377 LttvProcessState
*process
;
378 process
= lttv_state_find_process(tfs
, pid_out
);
380 if(process
!= NULL
) {
381 /* Well, the process_out existed : we must get it in the process hash
382 * or add it, and draw its items.
384 /* Add process to process list (if not present) */
385 guint y
= 0, height
= 0, pl_height
= 0;
386 HashedProcessData
*hashed_process_data
= NULL
;
387 ProcessList
*process_list
=
388 guicontrolflow_get_process_list(control_flow_data
);
389 LttTime birth
= process
->creation_time
;
390 const gchar
*name
= g_quark_to_string(process
->name
);
392 if(processlist_get_process_pixels(process_list
,
396 tfc
->t_context
->index
,
399 &hashed_process_data
) == 1)
401 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
402 /* Process not present */
403 processlist_add(process_list
,
408 tfc
->t_context
->index
,
411 &hashed_process_data
);
412 processlist_get_process_pixels(process_list
,
416 tfc
->t_context
->index
,
419 &hashed_process_data
);
420 drawing_insert_square( drawing
, y
, height
);
423 /* Now, the process is in the state hash and our own process hash.
424 * We definitely can draw the items related to the ending state.
427 /* Check if the x position is unset. In can have been left unset by
428 * a draw closure from a after chunk hook. This should never happen,
429 * because it must be set by before chunk hook to the damage_begin
432 g_assert(hashed_process_data
->x
!= -1);
435 DrawContext draw_context
;
437 convert_time_to_pixels(
438 time_window
.start_time
,
444 /* Now create the drawing context that will be used to draw
445 * items related to the last state. */
446 draw_context
.drawable
= drawing
->pixmap
;
447 draw_context
.gc
= drawing
->gc
;
448 draw_context
.pango_layout
= drawing
->pango_layout
;
449 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
;
450 draw_context
.drawinfo
.end
.x
= x
;
452 draw_context
.drawinfo
.y
.over
= y
;
453 draw_context
.drawinfo
.y
.middle
= y
+(height
/4);
454 draw_context
.drawinfo
.y
.under
= y
+(height
/2)+2;
456 draw_context
.drawinfo
.start
.offset
.over
= 0;
457 draw_context
.drawinfo
.start
.offset
.middle
= 0;
458 draw_context
.drawinfo
.start
.offset
.under
= 0;
459 draw_context
.drawinfo
.end
.offset
.over
= 0;
460 draw_context
.drawinfo
.end
.offset
.middle
= 0;
461 draw_context
.drawinfo
.end
.offset
.under
= 0;
465 PropertiesLine prop_line
= prepare_status_line(process
);
466 draw_line((void*)&prop_line
, (void*)&draw_context
);
469 /* become the last x position */
470 hashed_process_data
->x
= x
;
477 /* First, check if the current process is in the state computation
478 * process list. If it is there, that means we must add it right now and
479 * draw items from the beginning of the read for it. If it is not
480 * present, it's a new process and it was not present : it will
481 * be added after the state update. */
482 LttvProcessState
*process
;
483 process
= lttv_state_find_process(tfs
, pid_in
);
485 if(process
!= NULL
) {
486 /* Well, the process_out existed : we must get it in the process hash
487 * or add it, and draw its items.
489 /* Add process to process list (if not present) */
490 guint y
= 0, height
= 0, pl_height
= 0;
491 HashedProcessData
*hashed_process_data
= NULL
;
492 ProcessList
*process_list
=
493 guicontrolflow_get_process_list(control_flow_data
);
494 LttTime birth
= process
->creation_time
;
495 const gchar
*name
= g_quark_to_string(process
->name
);
497 if(processlist_get_process_pixels(process_list
,
501 tfc
->t_context
->index
,
504 &hashed_process_data
) == 1)
506 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
507 /* Process not present */
508 processlist_add(process_list
,
513 tfc
->t_context
->index
,
516 &hashed_process_data
);
517 processlist_get_process_pixels(process_list
,
521 tfc
->t_context
->index
,
524 &hashed_process_data
);
525 drawing_insert_square( drawing
, y
, height
);
528 /* Now, the process is in the state hash and our own process hash.
529 * We definitely can draw the items related to the ending state.
532 /* Check if the x position is unset. In can have been left unset by
533 * a draw closure from a after chunk hook. This should never happen,
534 * because it must be set by before chunk hook to the damage_begin
537 g_assert(hashed_process_data
->x
!= -1);
540 DrawContext draw_context
;
542 convert_time_to_pixels(
543 time_window
.start_time
,
549 /* Now create the drawing context that will be used to draw
550 * items related to the last state. */
551 draw_context
.drawable
= drawing
->pixmap
;
552 draw_context
.gc
= drawing
->gc
;
553 draw_context
.pango_layout
= drawing
->pango_layout
;
554 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
;
555 draw_context
.drawinfo
.end
.x
= x
;
557 draw_context
.drawinfo
.y
.over
= y
;
558 draw_context
.drawinfo
.y
.middle
= y
+(height
/4);
559 draw_context
.drawinfo
.y
.under
= y
+(height
/2)+2;
561 draw_context
.drawinfo
.start
.offset
.over
= 0;
562 draw_context
.drawinfo
.start
.offset
.middle
= 0;
563 draw_context
.drawinfo
.start
.offset
.under
= 0;
564 draw_context
.drawinfo
.end
.offset
.over
= 0;
565 draw_context
.drawinfo
.end
.offset
.middle
= 0;
566 draw_context
.drawinfo
.end
.offset
.under
= 0;
570 PropertiesLine prop_line
= prepare_status_line(process
);
571 draw_line((void*)&prop_line
, (void*)&draw_context
);
575 /* become the last x position */
576 hashed_process_data
->x
= x
;
581 ltt_eventtype_name(ltt_event_eventtype(e
)),"process") == 0) {
582 /* We are in a fork or exit event */
592 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
593 ControlFlowData
*control_flow_data
=
594 (ControlFlowData
*)events_request
->viewer_data
;
595 Tab
*tab
= control_flow_data
->tab
;
597 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
599 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
600 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
605 LttTime evtime
= ltt_event_time(e
);
606 TimeWindow time_window
=
607 lttvwindow_get_time_window(tab
);
609 LttTime end_time
= ltt_time_add(time_window
.start_time
,
610 time_window
.time_width
);
611 //if(time < time_beg || time > time_end) return;
612 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
613 || ltt_time_compare(evtime
, end_time
) == 1)
616 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
618 g_debug("schedchange!");
620 /* Add process to process list (if not present) and get drawing "y" from
621 * process position */
622 guint pid_out
, pid_in
;
623 LttvProcessState
*process_out
, *process_in
;
625 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
627 ProcessList
*process_list
=
628 guicontrolflow_get_process_list(control_flow_data
);
631 LttField
*f
= ltt_event_field(e
);
633 element
= ltt_field_member(f
,0);
634 pid_out
= ltt_event_get_long_unsigned(e
,element
);
635 element
= ltt_field_member(f
,1);
636 pid_in
= ltt_event_get_long_unsigned(e
,element
);
637 g_debug("out : %u in : %u", pid_out
, pid_in
);
640 /* Find process pid_out in the list... */
641 process_out
= lttv_state_find_process(tfs
, pid_out
);
642 if(process_out
== NULL
) return 0;
643 g_debug("out : %s",g_quark_to_string(process_out
->state
->s
));
645 birth
= process_out
->creation_time
;
646 const gchar
*name
= g_quark_to_string(process_out
->name
);
647 HashedProcessData
*hashed_process_data_out
= NULL
;
649 if(processlist_get_process_pixels(process_list
,
652 tfc
->t_context
->index
,
655 &hashed_process_data_out
) == 1)
657 /* Process not present */
658 processlist_add(process_list
,
661 tfc
->t_context
->index
,
664 &hashed_process_data_out
);
665 g_assert(processlist_get_process_pixels(process_list
,
668 tfc
->t_context
->index
,
671 &hashed_process_data_out
)==0);
672 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
676 /* Find process pid_in in the list... */
677 process_in
= lttv_state_find_process(tfs
, pid_in
);
678 if(process_in
== NULL
) return 0;
679 g_debug("in : %s",g_quark_to_string(process_in
->state
->s
));
681 birth
= process_in
->creation_time
;
682 name
= g_quark_to_string(process_in
->name
);
683 HashedProcessData
*hashed_process_data_in
= NULL
;
685 if(processlist_get_process_pixels(process_list
,
688 tfc
->t_context
->index
,
691 &hashed_process_data_in
) == 1)
693 /* Process not present */
694 processlist_add(process_list
,
697 tfc
->t_context
->index
,
700 &hashed_process_data_in
);
701 processlist_get_process_pixels(process_list
,
704 tfc
->t_context
->index
,
707 &hashed_process_data_in
);
709 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
714 /* Find pixels corresponding to time of the event. If the time does
715 * not fit in the window, show a warning, not supposed to happend. */
717 guint width
= control_flow_data
->drawing
->width
;
719 LttTime time
= ltt_event_time(e
);
721 LttTime window_end
= ltt_time_add(time_window
.time_width
,
722 time_window
.start_time
);
725 convert_time_to_pixels(
726 time_window
.start_time
,
731 //assert(x <= width);
733 /* draw what represents the event for outgoing process. */
735 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
736 draw_context_out
->current
->modify_over
->x
= x
;
737 draw_context_out
->current
->modify_under
->x
= x
;
738 draw_context_out
->current
->modify_over
->y
= y_out
;
739 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
740 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
741 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
742 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
743 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
744 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
745 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
746 //draw_context_out->gc = widget->style->black_gc;
748 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
749 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
751 /* Draw the line/background of the out process */
752 if(draw_context_out
->previous
->middle
->x
== -1)
754 draw_context_out
->previous
->over
->x
=
755 control_flow_data
->drawing
->damage_begin
;
756 draw_context_out
->previous
->middle
->x
=
757 control_flow_data
->drawing
->damage_begin
;
758 draw_context_out
->previous
->under
->x
=
759 control_flow_data
->drawing
->damage_begin
;
761 g_debug("out middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
764 draw_context_out
->current
->middle
->x
= x
;
765 draw_context_out
->current
->over
->x
= x
;
766 draw_context_out
->current
->under
->x
= x
;
767 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
768 draw_context_out
->current
->over
->y
= y_out
;
769 draw_context_out
->current
->under
->y
= y_out
+ height
;
770 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
771 draw_context_out
->previous
->over
->y
= y_out
;
772 draw_context_out
->previous
->under
->y
= y_out
+ height
;
774 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
775 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
777 if(process_out
->state
->s
== LTTV_STATE_RUN
)
779 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
780 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
781 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
783 PropertiesBG prop_bg
;
784 prop_bg
.color
= g_new(GdkColor
,1);
788 prop_bg
.color
->red
= 0x1515;
789 prop_bg
.color
->green
= 0x1515;
790 prop_bg
.color
->blue
= 0x8c8c;
793 prop_bg
.color
->red
= 0x4e4e;
794 prop_bg
.color
->green
= 0xa9a9;
795 prop_bg
.color
->blue
= 0xa4a4;
798 prop_bg
.color
->red
= 0x7a7a;
799 prop_bg
.color
->green
= 0x4a4a;
800 prop_bg
.color
->blue
= 0x8b8b;
803 prop_bg
.color
->red
= 0x8080;
804 prop_bg
.color
->green
= 0x7777;
805 prop_bg
.color
->blue
= 0x4747;
808 prop_bg
.color
->red
= 0xe7e7;
809 prop_bg
.color
->green
= 0xe7e7;
810 prop_bg
.color
->blue
= 0xe7e7;
813 g_debug("calling from draw_event");
814 draw_bg((void*)&prop_bg
, (void*)draw_context_out
);
815 g_free(prop_bg
.color
);
816 //gdk_gc_unref(draw_context_out->gc);
819 draw_context_out
->gc
= widget
->style
->black_gc
;
821 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
822 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
823 PropertiesText prop_text_out
;
824 prop_text_out
.foreground
= &colorfg_out
;
825 prop_text_out
.background
= &colorbg_out
;
826 prop_text_out
.size
= 6;
827 prop_text_out
.position
= OVER
;
829 /* color of text : status of the process */
830 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
832 prop_text_out
.foreground
->red
= 0xffff;
833 prop_text_out
.foreground
->green
= 0xffff;
834 prop_text_out
.foreground
->blue
= 0xffff;
836 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
838 prop_text_out
.foreground
->red
= 0x0fff;
839 prop_text_out
.foreground
->green
= 0xffff;
840 prop_text_out
.foreground
->blue
= 0xfff0;
842 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
844 prop_text_out
.foreground
->red
= 0xffff;
845 prop_text_out
.foreground
->green
= 0xffff;
846 prop_text_out
.foreground
->blue
= 0x0000;
848 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
850 prop_text_out
.foreground
->red
= 0xffff;
851 prop_text_out
.foreground
->green
= 0x0000;
852 prop_text_out
.foreground
->blue
= 0xffff;
854 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
856 prop_text_out
.foreground
->red
= 0xffff;
857 prop_text_out
.foreground
->green
= 0x0000;
858 prop_text_out
.foreground
->blue
= 0x0000;
860 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
862 prop_text_out
.foreground
->red
= 0x0000;
863 prop_text_out
.foreground
->green
= 0xffff;
864 prop_text_out
.foreground
->blue
= 0x0000;
868 prop_text_out
.foreground
->red
= 0xffff;
869 prop_text_out
.foreground
->green
= 0xffff;
870 prop_text_out
.foreground
->blue
= 0xffff;
874 /* Print status of the process : U, WF, WC, E, W, R */
875 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
876 prop_text_out
.text
= "U->";
877 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
878 prop_text_out
.text
= "WF->";
879 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
880 prop_text_out
.text
= "WC->";
881 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
882 prop_text_out
.text
= "E->";
883 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
884 prop_text_out
.text
= "W->";
885 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
886 prop_text_out
.text
= "R->";
888 prop_text_out
.text
= "U";
890 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
891 //gdk_gc_unref(draw_context_out->gc);
893 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
894 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
895 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
897 PropertiesLine prop_line_out
;
898 prop_line_out
.color
= g_new(GdkColor
,1);
899 prop_line_out
.line_width
= 2;
900 prop_line_out
.style
= GDK_LINE_SOLID
;
901 prop_line_out
.position
= MIDDLE
;
903 g_debug("out state : %s", g_quark_to_string(process_out
->state
->s
));
905 /* color of line : status of the process */
906 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
908 prop_line_out
.color
->red
= 0xffff;
909 prop_line_out
.color
->green
= 0xffff;
910 prop_line_out
.color
->blue
= 0xffff;
912 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
914 prop_line_out
.color
->red
= 0x0fff;
915 prop_line_out
.color
->green
= 0xffff;
916 prop_line_out
.color
->blue
= 0xfff0;
918 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
920 prop_line_out
.color
->red
= 0xffff;
921 prop_line_out
.color
->green
= 0xffff;
922 prop_line_out
.color
->blue
= 0x0000;
924 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
926 prop_line_out
.color
->red
= 0xffff;
927 prop_line_out
.color
->green
= 0x0000;
928 prop_line_out
.color
->blue
= 0xffff;
930 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
932 prop_line_out
.color
->red
= 0xffff;
933 prop_line_out
.color
->green
= 0x0000;
934 prop_line_out
.color
->blue
= 0x0000;
936 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
938 prop_line_out
.color
->red
= 0x0000;
939 prop_line_out
.color
->green
= 0xffff;
940 prop_line_out
.color
->blue
= 0x0000;
944 prop_line_out
.color
->red
= 0xffff;
945 prop_line_out
.color
->green
= 0xffff;
946 prop_line_out
.color
->blue
= 0xffff;
949 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
950 g_free(prop_line_out
.color
);
951 //gdk_gc_unref(draw_context_out->gc);
952 /* Note : finishing line will have to be added when trace read over. */
954 /* Finally, update the drawing context of the pid_in. */
956 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
957 draw_context_in
->current
->modify_over
->x
= x
;
958 draw_context_in
->current
->modify_under
->x
= x
;
959 draw_context_in
->current
->modify_over
->y
= y_in
;
960 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
961 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
962 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
963 widget
= control_flow_data
->drawing
->drawing_area
;
964 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
965 //draw_context_in->gc = widget->style->black_gc;
966 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
967 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
969 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
970 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
972 /* Draw the line/bg of the in process */
973 if(draw_context_in
->previous
->middle
->x
== -1)
975 draw_context_in
->previous
->over
->x
=
976 control_flow_data
->drawing
->damage_begin
;
977 draw_context_in
->previous
->middle
->x
=
978 control_flow_data
->drawing
->damage_begin
;
979 draw_context_in
->previous
->under
->x
=
980 control_flow_data
->drawing
->damage_begin
;
982 g_debug("in middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
986 draw_context_in
->current
->middle
->x
= x
;
987 draw_context_in
->current
->over
->x
= x
;
988 draw_context_in
->current
->under
->x
= x
;
989 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
990 draw_context_in
->current
->over
->y
= y_in
;
991 draw_context_in
->current
->under
->y
= y_in
+ height
;
992 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
993 draw_context_in
->previous
->over
->y
= y_in
;
994 draw_context_in
->previous
->under
->y
= y_in
+ height
;
996 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
997 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1000 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1002 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1003 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1004 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1006 PropertiesBG prop_bg
;
1007 prop_bg
.color
= g_new(GdkColor
,1);
1009 switch(tfc
->index
) {
1011 prop_bg
.color
->red
= 0x1515;
1012 prop_bg
.color
->green
= 0x1515;
1013 prop_bg
.color
->blue
= 0x8c8c;
1016 prop_bg
.color
->red
= 0x4e4e;
1017 prop_bg
.color
->green
= 0xa9a9;
1018 prop_bg
.color
->blue
= 0xa4a4;
1021 prop_bg
.color
->red
= 0x7a7a;
1022 prop_bg
.color
->green
= 0x4a4a;
1023 prop_bg
.color
->blue
= 0x8b8b;
1026 prop_bg
.color
->red
= 0x8080;
1027 prop_bg
.color
->green
= 0x7777;
1028 prop_bg
.color
->blue
= 0x4747;
1031 prop_bg
.color
->red
= 0xe7e7;
1032 prop_bg
.color
->green
= 0xe7e7;
1033 prop_bg
.color
->blue
= 0xe7e7;
1037 draw_bg((void*)&prop_bg
, (void*)draw_context_in
);
1038 g_free(prop_bg
.color
);
1039 //gdk_gc_unref(draw_context_in->gc);
1042 draw_context_in
->gc
= widget
->style
->black_gc
;
1044 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1045 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1046 PropertiesText prop_text_in
;
1047 prop_text_in
.foreground
= &colorfg_in
;
1048 prop_text_in
.background
= &colorbg_in
;
1049 prop_text_in
.size
= 6;
1050 prop_text_in
.position
= OVER
;
1052 g_debug("in state : %s", g_quark_to_string(process_in
->state
->s
));
1053 /* foreground of text : status of the process */
1054 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1056 prop_text_in
.foreground
->red
= 0xffff;
1057 prop_text_in
.foreground
->green
= 0xffff;
1058 prop_text_in
.foreground
->blue
= 0xffff;
1060 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1062 prop_text_in
.foreground
->red
= 0x0fff;
1063 prop_text_in
.foreground
->green
= 0xffff;
1064 prop_text_in
.foreground
->blue
= 0xfff0;
1066 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1068 prop_text_in
.foreground
->red
= 0xffff;
1069 prop_text_in
.foreground
->green
= 0xffff;
1070 prop_text_in
.foreground
->blue
= 0x0000;
1072 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1074 prop_text_in
.foreground
->red
= 0xffff;
1075 prop_text_in
.foreground
->green
= 0x0000;
1076 prop_text_in
.foreground
->blue
= 0xffff;
1078 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1080 prop_text_in
.foreground
->red
= 0xffff;
1081 prop_text_in
.foreground
->green
= 0x0000;
1082 prop_text_in
.foreground
->blue
= 0x0000;
1084 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1086 prop_text_in
.foreground
->red
= 0x0000;
1087 prop_text_in
.foreground
->green
= 0xffff;
1088 prop_text_in
.foreground
->blue
= 0x0000;
1092 prop_text_in
.foreground
->red
= 0xffff;
1093 prop_text_in
.foreground
->green
= 0xffff;
1094 prop_text_in
.foreground
->blue
= 0xffff;
1099 /* Print status of the process : U, WF, WC, E, W, R */
1100 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1101 prop_text_in
.text
= "U->";
1102 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1103 prop_text_in
.text
= "WF->";
1104 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1105 prop_text_in
.text
= "WC->";
1106 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1107 prop_text_in
.text
= "E->";
1108 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1109 prop_text_in
.text
= "W->";
1110 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1111 prop_text_in
.text
= "R->";
1113 prop_text_in
.text
= "U";
1115 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1116 //gdk_gc_unref(draw_context_in->gc);
1118 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1119 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1120 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1122 PropertiesLine prop_line_in
;
1123 prop_line_in
.color
= g_new(GdkColor
,1);
1124 prop_line_in
.line_width
= 2;
1125 prop_line_in
.style
= GDK_LINE_SOLID
;
1126 prop_line_in
.position
= MIDDLE
;
1128 /* color of line : status of the process */
1129 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1131 prop_line_in
.color
->red
= 0xffff;
1132 prop_line_in
.color
->green
= 0xffff;
1133 prop_line_in
.color
->blue
= 0xffff;
1135 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1137 prop_line_in
.color
->red
= 0x0fff;
1138 prop_line_in
.color
->green
= 0xffff;
1139 prop_line_in
.color
->blue
= 0xfff0;
1141 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1143 prop_line_in
.color
->red
= 0xffff;
1144 prop_line_in
.color
->green
= 0xffff;
1145 prop_line_in
.color
->blue
= 0x0000;
1147 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1149 prop_line_in
.color
->red
= 0xffff;
1150 prop_line_in
.color
->green
= 0x0000;
1151 prop_line_in
.color
->blue
= 0xffff;
1153 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1155 prop_line_in
.color
->red
= 0xffff;
1156 prop_line_in
.color
->green
= 0x0000;
1157 prop_line_in
.color
->blue
= 0x0000;
1159 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1161 prop_line_in
.color
->red
= 0x0000;
1162 prop_line_in
.color
->green
= 0xffff;
1163 prop_line_in
.color
->blue
= 0x0000;
1167 prop_line_in
.color
->red
= 0xffff;
1168 prop_line_in
.color
->green
= 0xffff;
1169 prop_line_in
.color
->blue
= 0xffff;
1172 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
1173 g_free(prop_line_in
.color
);
1174 //gdk_gc_unref(draw_context_in->gc);
1184 GString
*string
= g_string_new("");;
1185 gboolean field_names
= TRUE
, state
= TRUE
;
1187 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
1188 g_string_append_printf(string
,"\n");
1191 g_string_append_printf(string
, " %s",
1192 g_quark_to_string(tfs
->process
->state
->s
));
1195 g_info("%s",string
->str
);
1197 g_string_free(string
, TRUE
);
1199 /* End of text dump */
1204 /* after_schedchange_hook
1206 * The draw after hook is called by the reading API to have a
1207 * particular event drawn on the screen.
1208 * @param hook_data ControlFlowData structure of the viewer.
1209 * @param call_data Event context.
1211 * This function adds items to be drawn in a queue for each process.
1214 int after_schedchange_hook(void *hook_data
, void *call_data
)
1216 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1217 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1219 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1221 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1222 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1227 LttTime evtime
= ltt_event_time(e
);
1228 TimeWindow time_window
=
1229 lttvwindow_get_time_window(control_flow_data
->tab
);
1231 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1232 time_window
.time_width
);
1234 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1235 || ltt_time_compare(evtime
, end_time
) == 1)
1238 guint width
= control_flow_data
->drawing
->width
;
1240 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0) {
1242 g_debug("schedchange!");
1245 /* Add process to process list (if not present) */
1246 LttvProcessState
*process_out
, *process_in
;
1248 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1249 HashedProcessData
*hashed_process_data_in
= NULL
;
1251 ProcessList
*process_list
=
1252 guicontrolflow_get_process_list(control_flow_data
);
1257 LttField
*f
= ltt_event_field(e
);
1259 element
= ltt_field_member(f
,0);
1260 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1261 element
= ltt_field_member(f
,1);
1262 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1263 g_debug("out : %u in : %u", pid_out
, pid_in
);
1267 /* Find process pid_in in the list... */
1268 process_in
= lttv_state_find_process(tfs
, pid_in
);
1269 /* It should exist, because we are after the state update. */
1270 g_assert(process_in
!= NULL
);
1272 birth
= process_in
->creation_time
;
1273 const gchar
*name
= g_quark_to_string(process_in
->name
);
1275 if(processlist_get_process_pixels(process_list
,
1277 process_in
->last_cpu
,
1279 tfc
->t_context
->index
,
1282 &hashed_process_data_in
) == 1)
1284 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1285 /* Process not present */
1286 processlist_add(process_list
,
1288 process_in
->last_cpu
,
1291 tfc
->t_context
->index
,
1294 &hashed_process_data_in
);
1295 processlist_get_process_pixels(process_list
,
1297 process_in
->last_cpu
,
1299 tfc
->t_context
->index
,
1302 &hashed_process_data_in
);
1303 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1306 convert_time_to_pixels(
1307 time_window
.start_time
,
1311 &hashed_process_data_in
->x
);
1319 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1320 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1322 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1324 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1325 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1331 LttTime evtime
= ltt_event_time(e
);
1332 TimeWindow time_window
=
1333 lttvwindow_get_time_window(control_flow_data
->tab
);
1335 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1336 time_window
.time_width
);
1337 //if(time < time_beg || time > time_end) return;
1338 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1339 || ltt_time_compare(evtime
, end_time
) == 1)
1343 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1345 g_debug("schedchange!");
1347 /* Add process to process list (if not present) and get drawing "y" from
1348 * process position */
1349 guint pid_out
, pid_in
;
1350 LttvProcessState
*process_out
, *process_in
;
1352 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1354 ProcessList
*process_list
=
1355 guicontrolflow_get_process_list(control_flow_data
);
1358 LttField
*f
= ltt_event_field(e
);
1360 element
= ltt_field_member(f
,0);
1361 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1362 element
= ltt_field_member(f
,1);
1363 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1364 //g_debug("out : %u in : %u", pid_out, pid_in);
1367 /* Find process pid_out in the list... */
1368 process_out
= lttv_state_find_process(tfs
, pid_out
);
1369 if(process_out
== NULL
) return 0;
1370 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1372 birth
= process_out
->creation_time
;
1373 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1374 HashedProcessData
*hashed_process_data_out
= NULL
;
1376 if(processlist_get_process_pixels(process_list
,
1379 tfc
->t_context
->index
,
1382 &hashed_process_data_out
) == 1)
1384 /* Process not present */
1385 processlist_add(process_list
,
1388 tfc
->t_context
->index
,
1391 &hashed_process_data_out
);
1392 processlist_get_process_pixels(process_list
,
1395 tfc
->t_context
->index
,
1398 &hashed_process_data_out
);
1399 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1404 /* Find process pid_in in the list... */
1405 process_in
= lttv_state_find_process(tfs
, pid_in
);
1406 if(process_in
== NULL
) return 0;
1407 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1409 birth
= process_in
->creation_time
;
1410 name
= strdup(g_quark_to_string(process_in
->name
));
1411 HashedProcessData
*hashed_process_data_in
= NULL
;
1413 if(processlist_get_process_pixels(process_list
,
1416 tfc
->t_context
->index
,
1419 &hashed_process_data_in
) == 1)
1421 /* Process not present */
1422 processlist_add(process_list
,
1425 tfc
->t_context
->index
,
1428 &hashed_process_data_in
);
1429 processlist_get_process_pixels(process_list
,
1432 tfc
->t_context
->index
,
1435 &hashed_process_data_in
);
1437 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1442 /* Find pixels corresponding to time of the event. If the time does
1443 * not fit in the window, show a warning, not supposed to happend. */
1445 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1447 //LttTime time = ltt_event_time(e);
1449 //LttTime window_end = ltt_time_add(time_window->time_width,
1450 // time_window->start_time);
1453 //convert_time_to_pixels(
1454 // time_window->start_time,
1460 //assert(x <= width);
1462 /* draw what represents the event for outgoing process. */
1464 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1465 //draw_context_out->current->modify_over->x = x;
1466 draw_context_out
->current
->modify_over
->y
= y_out
;
1467 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1468 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1469 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1470 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1471 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1473 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1474 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1476 /*if(process_out->state->s == LTTV_STATE_RUN)
1478 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1479 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1480 PropertiesBG prop_bg;
1481 prop_bg.color = g_new(GdkColor,1);
1483 prop_bg.color->red = 0xffff;
1484 prop_bg.color->green = 0xffff;
1485 prop_bg.color->blue = 0xffff;
1487 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1488 g_free(prop_bg.color);
1489 gdk_gc_unref(draw_context_out->gc);
1492 draw_context_out
->gc
= widget
->style
->black_gc
;
1494 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1495 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1496 PropertiesText prop_text_out
;
1497 prop_text_out
.foreground
= &colorfg_out
;
1498 prop_text_out
.background
= &colorbg_out
;
1499 prop_text_out
.size
= 6;
1500 prop_text_out
.position
= OVER
;
1502 /* color of text : status of the process */
1503 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1505 prop_text_out
.foreground
->red
= 0xffff;
1506 prop_text_out
.foreground
->green
= 0xffff;
1507 prop_text_out
.foreground
->blue
= 0xffff;
1509 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1511 prop_text_out
.foreground
->red
= 0x0fff;
1512 prop_text_out
.foreground
->green
= 0xffff;
1513 prop_text_out
.foreground
->blue
= 0xfff0;
1515 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1517 prop_text_out
.foreground
->red
= 0xffff;
1518 prop_text_out
.foreground
->green
= 0xffff;
1519 prop_text_out
.foreground
->blue
= 0x0000;
1521 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1523 prop_text_out
.foreground
->red
= 0xffff;
1524 prop_text_out
.foreground
->green
= 0x0000;
1525 prop_text_out
.foreground
->blue
= 0xffff;
1527 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1529 prop_text_out
.foreground
->red
= 0xffff;
1530 prop_text_out
.foreground
->green
= 0x0000;
1531 prop_text_out
.foreground
->blue
= 0x0000;
1533 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1535 prop_text_out
.foreground
->red
= 0x0000;
1536 prop_text_out
.foreground
->green
= 0xffff;
1537 prop_text_out
.foreground
->blue
= 0x0000;
1541 prop_text_out
.foreground
->red
= 0xffff;
1542 prop_text_out
.foreground
->green
= 0xffff;
1543 prop_text_out
.foreground
->blue
= 0xffff;
1546 /* Print status of the process : U, WF, WC, E, W, R */
1547 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1548 prop_text_out
.text
= "U";
1549 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1550 prop_text_out
.text
= "WF";
1551 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1552 prop_text_out
.text
= "WC";
1553 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1554 prop_text_out
.text
= "E";
1555 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1556 prop_text_out
.text
= "W";
1557 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1558 prop_text_out
.text
= "R";
1560 prop_text_out
.text
= "U";
1562 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1564 //gdk_gc_unref(draw_context_out->gc);
1566 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1567 draw_context_out
->current
->over
->y
= y_out
;
1568 draw_context_out
->current
->under
->y
= y_out
+height
;
1569 draw_context_out
->current
->status
= process_out
->state
->s
;
1571 /* for pid_out : remove previous, Prev = current, new current (default) */
1572 g_free(draw_context_out
->previous
->modify_under
);
1573 g_free(draw_context_out
->previous
->modify_middle
);
1574 g_free(draw_context_out
->previous
->modify_over
);
1575 g_free(draw_context_out
->previous
->under
);
1576 g_free(draw_context_out
->previous
->middle
);
1577 g_free(draw_context_out
->previous
->over
);
1578 g_free(draw_context_out
->previous
);
1580 draw_context_out
->previous
= draw_context_out
->current
;
1582 draw_context_out
->current
= g_new(DrawInfo
,1);
1583 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1584 draw_context_out
->current
->over
->x
= -1;
1585 draw_context_out
->current
->over
->y
= -1;
1586 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1587 draw_context_out
->current
->middle
->x
= -1;
1588 draw_context_out
->current
->middle
->y
= -1;
1589 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1590 draw_context_out
->current
->under
->x
= -1;
1591 draw_context_out
->current
->under
->y
= -1;
1592 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1593 draw_context_out
->current
->modify_over
->x
= -1;
1594 draw_context_out
->current
->modify_over
->y
= -1;
1595 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1596 draw_context_out
->current
->modify_middle
->x
= -1;
1597 draw_context_out
->current
->modify_middle
->y
= -1;
1598 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1599 draw_context_out
->current
->modify_under
->x
= -1;
1600 draw_context_out
->current
->modify_under
->y
= -1;
1601 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1603 /* Finally, update the drawing context of the pid_in. */
1605 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1606 //draw_context_in->current->modify_over->x = x;
1607 draw_context_in
->current
->modify_over
->y
= y_in
;
1608 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1609 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1610 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1611 widget
= control_flow_data
->drawing
->drawing_area
;
1612 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1614 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1615 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1617 /*if(process_in->state->s == LTTV_STATE_RUN)
1619 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1620 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1621 PropertiesBG prop_bg;
1622 prop_bg.color = g_new(GdkColor,1);
1624 prop_bg.color->red = 0xffff;
1625 prop_bg.color->green = 0xffff;
1626 prop_bg.color->blue = 0xffff;
1628 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1629 g_free(prop_bg.color);
1630 gdk_gc_unref(draw_context_in->gc);
1633 draw_context_in
->gc
= widget
->style
->black_gc
;
1635 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1636 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1637 PropertiesText prop_text_in
;
1638 prop_text_in
.foreground
= &colorfg_in
;
1639 prop_text_in
.background
= &colorbg_in
;
1640 prop_text_in
.size
= 6;
1641 prop_text_in
.position
= OVER
;
1643 /* foreground of text : status of the process */
1644 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1646 prop_text_in
.foreground
->red
= 0xffff;
1647 prop_text_in
.foreground
->green
= 0xffff;
1648 prop_text_in
.foreground
->blue
= 0xffff;
1650 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1652 prop_text_in
.foreground
->red
= 0x0fff;
1653 prop_text_in
.foreground
->green
= 0xffff;
1654 prop_text_in
.foreground
->blue
= 0xfff0;
1656 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1658 prop_text_in
.foreground
->red
= 0xffff;
1659 prop_text_in
.foreground
->green
= 0xffff;
1660 prop_text_in
.foreground
->blue
= 0x0000;
1662 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1664 prop_text_in
.foreground
->red
= 0xffff;
1665 prop_text_in
.foreground
->green
= 0x0000;
1666 prop_text_in
.foreground
->blue
= 0xffff;
1668 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1670 prop_text_in
.foreground
->red
= 0xffff;
1671 prop_text_in
.foreground
->green
= 0x0000;
1672 prop_text_in
.foreground
->blue
= 0x0000;
1674 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1676 prop_text_in
.foreground
->red
= 0x0000;
1677 prop_text_in
.foreground
->green
= 0xffff;
1678 prop_text_in
.foreground
->blue
= 0x0000;
1682 prop_text_in
.foreground
->red
= 0xffff;
1683 prop_text_in
.foreground
->green
= 0xffff;
1684 prop_text_in
.foreground
->blue
= 0xffff;
1688 /* Print status of the process : U, WF, WC, E, W, R */
1689 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1690 prop_text_in
.text
= "U";
1691 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1692 prop_text_in
.text
= "WF";
1693 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1694 prop_text_in
.text
= "WC";
1695 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1696 prop_text_in
.text
= "E";
1697 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1698 prop_text_in
.text
= "W";
1699 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1700 prop_text_in
.text
= "R";
1702 prop_text_in
.text
= "U";
1704 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1707 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1710 prop_text_in
.foreground
= &colorfg_in
;
1711 prop_text_in
.background
= &colorbg_in
;
1712 prop_text_in
.foreground
->red
= 0xffff;
1713 prop_text_in
.foreground
->green
= 0xffff;
1714 prop_text_in
.foreground
->blue
= 0xffff;
1715 prop_text_in
.size
= 6;
1716 prop_text_in
.position
= UNDER
;
1718 prop_text_in
.text
= g_new(gchar
, 260);
1719 strcpy(prop_text_in
.text
, "CPU ");
1720 snprintf(tmp
, 255, "%u", tfc
->index
);
1721 strcat(prop_text_in
.text
, tmp
);
1723 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1724 g_free(prop_text_in
.text
);
1728 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1729 draw_context_in
->current
->over
->y
= y_in
;
1730 draw_context_in
->current
->under
->y
= y_in
+height
;
1731 draw_context_in
->current
->status
= process_in
->state
->s
;
1733 /* for pid_in : remove previous, Prev = current, new current (default) */
1734 g_free(draw_context_in
->previous
->modify_under
);
1735 g_free(draw_context_in
->previous
->modify_middle
);
1736 g_free(draw_context_in
->previous
->modify_over
);
1737 g_free(draw_context_in
->previous
->under
);
1738 g_free(draw_context_in
->previous
->middle
);
1739 g_free(draw_context_in
->previous
->over
);
1740 g_free(draw_context_in
->previous
);
1742 draw_context_in
->previous
= draw_context_in
->current
;
1744 draw_context_in
->current
= g_new(DrawInfo
,1);
1745 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1746 draw_context_in
->current
->over
->x
= -1;
1747 draw_context_in
->current
->over
->y
= -1;
1748 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1749 draw_context_in
->current
->middle
->x
= -1;
1750 draw_context_in
->current
->middle
->y
= -1;
1751 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1752 draw_context_in
->current
->under
->x
= -1;
1753 draw_context_in
->current
->under
->y
= -1;
1754 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1755 draw_context_in
->current
->modify_over
->x
= -1;
1756 draw_context_in
->current
->modify_over
->y
= -1;
1757 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1758 draw_context_in
->current
->modify_middle
->x
= -1;
1759 draw_context_in
->current
->modify_middle
->y
= -1;
1760 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1761 draw_context_in
->current
->modify_under
->x
= -1;
1762 draw_context_in
->current
->modify_under
->y
= -1;
1763 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1773 * Create the processlist entry for the child process. Put the last
1774 * position in x at the current time value.
1776 * @param hook_data ControlFlowData structure of the viewer.
1777 * @param call_data Event context.
1779 * This function adds items to be drawn in a queue for each process.
1782 int after_fork_hook(void *hook_data
, void *call_data
)
1784 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1785 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1787 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1789 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1790 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1795 LttTime evtime
= ltt_event_time(e
);
1796 TimeWindow time_window
=
1797 lttvwindow_get_time_window(control_flow_data
->tab
);
1799 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1800 time_window
.time_width
);
1802 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1803 || ltt_time_compare(evtime
, end_time
) == 1)
1806 guint width
= control_flow_data
->drawing
->width
;
1808 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"process") == 0) {
1813 LttField
*f
= ltt_event_field(e
);
1815 element
= ltt_field_member(f
,0);
1816 sub_id
= ltt_event_get_long_unsigned(e
,element
);
1817 element
= ltt_field_member(f
,1);
1818 child_pid
= ltt_event_get_long_unsigned(e
,element
);
1821 if(sub_id
== 2) { /* fork */
1823 /* Add process to process list (if not present) */
1824 LttvProcessState
*process_child
;
1826 guint y_child
= 0, height
= 0, pl_height
= 0;
1827 HashedProcessData
*hashed_process_data_child
= NULL
;
1829 ProcessList
*process_list
=
1830 guicontrolflow_get_process_list(control_flow_data
);
1833 /* Find child in the list... */
1834 process_child
= lttv_state_find_process(tfs
, child_pid
);
1835 /* It should exist, because we are after the state update. */
1836 g_assert(process_child
!= NULL
);
1838 birth
= process_child
->creation_time
;
1839 const gchar
*name
= g_quark_to_string(process_child
->name
);
1841 if(processlist_get_process_pixels(process_list
,
1843 process_child
->last_cpu
,
1845 tfc
->t_context
->index
,
1848 &hashed_process_data_child
) == 1)
1850 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
1851 /* Process not present */
1852 processlist_add(process_list
,
1854 process_child
->last_cpu
,
1855 process_child
->ppid
,
1857 tfc
->t_context
->index
,
1860 &hashed_process_data_child
);
1861 processlist_get_process_pixels(process_list
,
1863 process_child
->last_cpu
,
1865 tfc
->t_context
->index
,
1868 &hashed_process_data_child
);
1869 drawing_insert_square( control_flow_data
->drawing
, y_child
, height
);
1872 convert_time_to_pixels(
1873 time_window
.start_time
,
1877 &hashed_process_data_child
->x
);
1885 gint
update_time_window_hook(void *hook_data
, void *call_data
)
1887 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
1888 Drawing_t
*drawing
= control_flow_data
->drawing
;
1890 const TimeWindowNotifyData
*time_window_nofify_data
=
1891 ((const TimeWindowNotifyData
*)call_data
);
1893 TimeWindow
*old_time_window
=
1894 time_window_nofify_data
->old_time_window
;
1895 TimeWindow
*new_time_window
=
1896 time_window_nofify_data
->new_time_window
;
1898 /* Update the ruler */
1899 drawing_update_ruler(control_flow_data
->drawing
,
1903 /* Two cases : zoom in/out or scrolling */
1905 /* In order to make sure we can reuse the old drawing, the scale must
1906 * be the same and the new time interval being partly located in the
1907 * currently shown time interval. (reuse is only for scrolling)
1910 g_info("Old time window HOOK : %u, %u to %u, %u",
1911 old_time_window
->start_time
.tv_sec
,
1912 old_time_window
->start_time
.tv_nsec
,
1913 old_time_window
->time_width
.tv_sec
,
1914 old_time_window
->time_width
.tv_nsec
);
1916 g_info("New time window HOOK : %u, %u to %u, %u",
1917 new_time_window
->start_time
.tv_sec
,
1918 new_time_window
->start_time
.tv_nsec
,
1919 new_time_window
->time_width
.tv_sec
,
1920 new_time_window
->time_width
.tv_nsec
);
1922 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
1923 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
1925 /* Same scale (scrolling) */
1926 g_info("scrolling");
1927 LttTime
*ns
= &new_time_window
->start_time
;
1928 LttTime
*os
= &old_time_window
->start_time
;
1929 LttTime old_end
= ltt_time_add(old_time_window
->start_time
,
1930 old_time_window
->time_width
);
1931 LttTime new_end
= ltt_time_add(new_time_window
->start_time
,
1932 new_time_window
->time_width
);
1934 //if(ns<os+w && os+w<ns+w)
1935 //if(ns<old_end && os<ns)
1936 if(ltt_time_compare(*ns
, old_end
) == -1
1937 && ltt_time_compare(*os
, *ns
) == -1)
1939 g_info("scrolling near right");
1940 /* Scroll right, keep right part of the screen */
1942 guint width
= control_flow_data
->drawing
->width
;
1943 convert_time_to_pixels(
1950 /* Copy old data to new location */
1951 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
1952 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
1953 control_flow_data
->drawing
->pixmap
,
1956 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
1958 if(drawing
->damage_begin
== drawing
->damage_end
)
1959 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
1961 drawing
->damage_begin
= 0;
1963 drawing
->damage_end
= control_flow_data
->drawing
->width
;
1965 /* Clear the data request background, but not SAFETY */
1966 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
1967 //control_flow_data->drawing->drawing_area->style->black_gc,
1968 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
1970 drawing
->damage_begin
+SAFETY
, 0,
1971 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
1972 control_flow_data
->drawing
->height
);
1974 gtk_widget_queue_draw_area (drawing
->drawing_area
,
1976 control_flow_data
->drawing
->width
,
1977 control_flow_data
->drawing
->height
);
1979 /* Get new data for the rest. */
1980 drawing_data_request(control_flow_data
->drawing
,
1981 &control_flow_data
->drawing
->pixmap
,
1982 drawing
->damage_begin
, 0,
1983 drawing
->damage_end
- drawing
->damage_begin
,
1984 control_flow_data
->drawing
->height
);
1987 //if(ns<os && os<ns+w)
1988 //if(ns<os && os<new_end)
1989 if(ltt_time_compare(*ns
,*os
) == -1
1990 && ltt_time_compare(*os
,new_end
) == -1)
1992 g_info("scrolling near left");
1993 /* Scroll left, keep left part of the screen */
1995 guint width
= control_flow_data
->drawing
->width
;
1996 convert_time_to_pixels(
2004 /* Copy old data to new location */
2005 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
2006 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2007 control_flow_data
->drawing
->pixmap
,
2012 if(drawing
->damage_begin
== drawing
->damage_end
)
2013 drawing
->damage_end
= x
;
2015 drawing
->damage_end
=
2016 control_flow_data
->drawing
->width
;
2018 drawing
->damage_begin
= 0;
2020 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2021 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2023 drawing
->damage_begin
, 0,
2024 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2025 control_flow_data
->drawing
->height
);
2027 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2029 control_flow_data
->drawing
->width
,
2030 control_flow_data
->drawing
->height
);
2033 /* Get new data for the rest. */
2034 drawing_data_request(control_flow_data
->drawing
,
2035 &control_flow_data
->drawing
->pixmap
,
2036 drawing
->damage_begin
, 0,
2037 drawing
->damage_end
- drawing
->damage_begin
,
2038 control_flow_data
->drawing
->height
);
2041 if(ltt_time_compare(*ns
,*os
) == 0)
2043 g_info("not scrolling");
2045 g_info("scrolling far");
2046 /* Cannot reuse any part of the screen : far jump */
2049 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2050 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2053 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2054 control_flow_data
->drawing
->height
);
2056 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2058 control_flow_data
->drawing
->width
,
2059 control_flow_data
->drawing
->height
);
2061 drawing
->damage_begin
= 0;
2062 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2064 drawing_data_request(control_flow_data
->drawing
,
2065 &control_flow_data
->drawing
->pixmap
,
2067 control_flow_data
->drawing
->width
,
2068 control_flow_data
->drawing
->height
);
2074 /* Different scale (zoom) */
2077 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2078 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2081 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2082 control_flow_data
->drawing
->height
);
2084 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2086 control_flow_data
->drawing
->width
,
2087 control_flow_data
->drawing
->height
);
2089 drawing
->damage_begin
= 0;
2090 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2092 drawing_data_request(control_flow_data
->drawing
,
2093 &control_flow_data
->drawing
->pixmap
,
2095 control_flow_data
->drawing
->width
,
2096 control_flow_data
->drawing
->height
);
2104 gint
traceset_notify(void *hook_data
, void *call_data
)
2106 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2107 Drawing_t
*drawing
= control_flow_data
->drawing
;
2108 GtkWidget
*widget
= drawing
->drawing_area
;
2111 drawing_clear(control_flow_data
->drawing
);
2112 processlist_clear(control_flow_data
->process_list
);
2113 redraw_notify(control_flow_data
, NULL
);
2115 request_background_data(control_flow_data
);
2117 drawing
->damage_begin
= 0;
2118 drawing
->damage_end
= drawing
->width
;
2119 if(drawing
->damage_begin
< drawing
->damage_end
)
2121 drawing_data_request(drawing
,
2123 drawing
->damage_begin
,
2125 drawing
->damage_end
-drawing
->damage_begin
,
2129 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2138 gint
redraw_notify(void *hook_data
, void *call_data
)
2140 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2141 Drawing_t
*drawing
= control_flow_data
->drawing
;
2142 GtkWidget
*widget
= drawing
->drawing_area
;
2144 drawing
->damage_begin
= 0;
2145 drawing
->damage_end
= drawing
->width
;
2149 gdk_draw_rectangle (drawing
->pixmap
,
2150 widget
->style
->black_gc
,
2153 drawing
->width
+SAFETY
,
2157 if(drawing
->damage_begin
< drawing
->damage_end
)
2159 drawing_data_request(drawing
,
2161 drawing
->damage_begin
,
2163 drawing
->damage_end
-drawing
->damage_begin
,
2167 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2177 gint
continue_notify(void *hook_data
, void *call_data
)
2179 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2180 Drawing_t
*drawing
= control_flow_data
->drawing
;
2181 GtkWidget
*widget
= drawing
->drawing_area
;
2183 //g_assert(widget->allocation.width == drawing->damage_end);
2185 if(drawing
->damage_begin
< drawing
->damage_end
)
2187 drawing_data_request(drawing
,
2189 drawing
->damage_begin
,
2191 drawing
->damage_end
-drawing
->damage_begin
,
2199 gint
update_current_time_hook(void *hook_data
, void *call_data
)
2201 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
2202 Drawing_t
*drawing
= control_flow_data
->drawing
;
2204 LttTime current_time
= *((LttTime
*)call_data
);
2206 TimeWindow time_window
=
2207 lttvwindow_get_time_window(control_flow_data
->tab
);
2209 LttTime time_begin
= time_window
.start_time
;
2210 LttTime width
= time_window
.time_width
;
2211 LttTime half_width
= ltt_time_div(width
,2.0);
2212 LttTime time_end
= ltt_time_add(time_begin
, width
);
2214 LttvTracesetContext
* tsc
=
2215 lttvwindow_get_traceset_context(control_flow_data
->tab
);
2217 LttTime trace_start
= tsc
->time_span
.start_time
;
2218 LttTime trace_end
= tsc
->time_span
.end_time
;
2220 g_info("New current time HOOK : %u, %u", current_time
.tv_sec
,
2221 current_time
.tv_nsec
);
2225 /* If current time is inside time interval, just move the highlight
2228 /* Else, we have to change the time interval. We have to tell it
2229 * to the main window. */
2230 /* The time interval change will take care of placing the current
2231 * time at the center of the visible area, or nearest possible if we are
2232 * at one end of the trace. */
2235 if(ltt_time_compare(current_time
, time_begin
) == -1)
2237 TimeWindow new_time_window
;
2239 if(ltt_time_compare(current_time
,
2240 ltt_time_add(trace_start
,half_width
)) == -1)
2241 time_begin
= trace_start
;
2243 time_begin
= ltt_time_sub(current_time
,half_width
);
2245 new_time_window
.start_time
= time_begin
;
2246 new_time_window
.time_width
= width
;
2248 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2250 else if(ltt_time_compare(current_time
, time_end
) == 1)
2252 TimeWindow new_time_window
;
2254 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) == 1)
2255 time_begin
= ltt_time_sub(trace_end
,width
);
2257 time_begin
= ltt_time_sub(current_time
,half_width
);
2259 new_time_window
.start_time
= time_begin
;
2260 new_time_window
.time_width
= width
;
2262 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2265 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2266 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2274 typedef struct _ClosureData
{
2275 EventsRequest
*events_request
;
2276 LttvTracesetState
*tss
;
2281 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
2283 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
2284 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
2285 ClosureData
*closure_data
= (ClosureData
*)user_data
;
2287 EventsRequest
*events_request
= closure_data
->events_request
;
2288 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2289 Drawing_t
*drawing
= control_flow_data
->drawing
;
2291 LttvTracesetState
*tss
= closure_data
->tss
;
2292 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)closure_data
->tss
;
2294 LttTime evtime
= closure_data
->end_time
;
2295 TimeWindow time_window
=
2296 lttvwindow_get_time_window(control_flow_data
->tab
);
2298 LttTime end_time
= ltt_time_add(time_window
.start_time
,
2299 time_window
.time_width
);
2301 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2302 || ltt_time_compare(evtime
, end_time
) == 1)
2305 guint width
= drawing
->width
;
2308 /* For the process */
2309 /* First, check if the current process is in the state computation
2310 * process list. If it is there, that means we must add it right now and
2311 * draw items from the beginning of the read for it. If it is not
2312 * present, it's a new process and it was not present : it will
2313 * be added after the state update. */
2314 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
2316 /* tracefiles[0] is ok here, because we draw for every PID, and
2317 * assume CPU 0 for PID 0 //FIXME */
2318 LttvTracefileState
*tfs
=
2319 (LttvTracefileState
*)tsc
->traces
[process_info
->trace_num
]->tracefiles
[0];
2321 LttvProcessState
*process
;
2322 process
= lttv_state_find_process(tfs
,
2325 if(process
!= NULL
) {
2327 /* Only draw for processes that are currently in the trace states */
2329 guint y
= 0, height
= 0, pl_height
= 0;
2330 ProcessList
*process_list
=
2331 guicontrolflow_get_process_list(control_flow_data
);
2332 LttTime birth
= process_info
->birth
;
2334 /* Should be alike when background info is ready */
2335 if(control_flow_data
->background_info_waiting
==0)
2336 g_assert(ltt_time_compare(process
->creation_time
,
2337 process_info
->birth
) == 0);
2338 const gchar
*name
= g_quark_to_string(process
->name
);
2340 /* process HAS to be present */
2341 g_assert(processlist_get_process_pixels(process_list
,
2345 process_info
->trace_num
,
2348 &hashed_process_data
) != 1);
2350 /* Now, the process is in the state hash and our own process hash.
2351 * We definitely can draw the items related to the ending state.
2354 /* Check if the x position is unset. In can have been left unset by
2355 * a draw closure from a after chunk hook. This should never happen,
2356 * because it must be set by before chunk hook to the damage_begin
2359 g_assert(hashed_process_data
->x
!= -1);
2362 DrawContext draw_context
;
2364 convert_time_to_pixels(
2365 time_window
.start_time
,
2371 /* Now create the drawing context that will be used to draw
2372 * items related to the last state. */
2373 draw_context
.drawable
= drawing
->pixmap
;
2374 draw_context
.gc
= drawing
->gc
;
2375 draw_context
.pango_layout
= drawing
->pango_layout
;
2376 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
;
2377 draw_context
.drawinfo
.end
.x
= x
;
2379 draw_context
.drawinfo
.y
.over
= y
;
2380 draw_context
.drawinfo
.y
.middle
= y
+(height
/4);
2381 draw_context
.drawinfo
.y
.under
= y
+(height
/2)+2;
2383 draw_context
.drawinfo
.start
.offset
.over
= 0;
2384 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2385 draw_context
.drawinfo
.start
.offset
.under
= 0;
2386 draw_context
.drawinfo
.end
.offset
.over
= 0;
2387 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2388 draw_context
.drawinfo
.end
.offset
.under
= 0;
2392 PropertiesLine prop_line
= prepare_status_line(process
);
2393 draw_line((void*)&prop_line
, (void*)&draw_context
);
2397 /* special case LTTV_STATE_WAIT : CPU is unknown. */
2399 /* become the last x position */
2400 hashed_process_data
->x
= x
;
2407 int before_chunk(void *hook_data
, void *call_data
)
2409 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2410 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2412 drawing_chunk_begin(events_request
, tss
);
2417 int before_request(void *hook_data
, void *call_data
)
2419 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2420 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2422 drawing_data_request_begin(events_request
, tss
);
2429 * after request is necessary in addition of after chunk in order to draw
2430 * lines until the end of the screen. after chunk just draws lines until
2437 int after_request(void *hook_data
, void *call_data
)
2439 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2440 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2441 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2442 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(call_data
);
2444 ProcessList
*process_list
=
2445 guicontrolflow_get_process_list(control_flow_data
);
2446 LttTime end_time
= events_request
->end_time
;
2448 ClosureData closure_data
;
2449 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2450 closure_data
.tss
= tss
;
2451 closure_data
.end_time
= end_time
;
2453 /* Draw last items */
2454 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2455 (void*)&closure_data
);
2457 /* Request expose */
2458 drawing_request_expose(events_request
, tss
, end_time
);
2467 int after_chunk(void *hook_data
, void *call_data
)
2469 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2470 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2471 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2472 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(call_data
);
2473 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
2476 ProcessList
*process_list
=
2477 guicontrolflow_get_process_list(control_flow_data
);
2480 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
2481 else /* end of traceset, or position now out of request : end */
2482 end_time
= events_request
->end_time
;
2484 ClosureData closure_data
;
2485 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2486 closure_data
.tss
= tss
;
2487 closure_data
.end_time
= end_time
;
2489 /* Draw last items */
2490 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2491 (void*)&closure_data
);
2493 /* Request expose */
2494 drawing_request_expose(events_request
, tss
, end_time
);