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
++;
210 /* Data ready. Be its nature, this viewer doesn't need to have
211 * its data ready hook called htere, because a background
212 * request is always linked with a redraw.
218 lttv_hooks_destroy(background_ready_hook
);
225 * Event Viewer's constructor hook
227 * This constructor is given as a parameter to the menuitem and toolbar button
228 * registration. It creates the list.
229 * @param tab A pointer to the parent tab.
230 * @return The widget created.
233 h_guicontrolflow(Tab
*tab
)
235 g_info("h_guicontrolflow, %p", tab
);
236 ControlFlowData
*control_flow_data
= guicontrolflow() ;
238 control_flow_data
->tab
= tab
;
240 //g_debug("time width2 : %u",time_window->time_width);
241 // Unreg done in the GuiControlFlow_Destructor
242 lttvwindow_register_traceset_notify(tab
,
246 lttvwindow_register_time_window_notify(tab
,
247 update_time_window_hook
,
249 lttvwindow_register_current_time_notify(tab
,
250 update_current_time_hook
,
252 lttvwindow_register_redraw_notify(tab
,
255 lttvwindow_register_continue_notify(tab
,
258 request_background_data(control_flow_data
);
261 return guicontrolflow_get_widget(control_flow_data
) ;
265 int event_selected_hook(void *hook_data
, void *call_data
)
267 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
268 guint
*event_number
= (guint
*) call_data
;
270 g_debug("DEBUG : event selected by main window : %u", *event_number
);
275 static __inline PropertiesLine
prepare_status_line(LttvProcessState
*process
)
277 PropertiesLine prop_line
;
278 prop_line
.line_width
= 2;
279 prop_line
.style
= GDK_LINE_SOLID
;
280 prop_line
.y
= MIDDLE
;
281 //GdkColormap *colormap = gdk_colormap_get_system();
283 g_debug("prepare_status_line for state : %s",
284 g_quark_to_string(process
->state
->s
));
286 /* color of line : status of the process */
287 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
288 prop_line
.color
= drawing_colors
[COL_WHITE
];
289 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
290 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
291 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
292 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
293 else if(process
->state
->s
== LTTV_STATE_EXIT
)
294 prop_line
.color
= drawing_colors
[COL_EXIT
];
295 else if(process
->state
->s
== LTTV_STATE_ZOMBIE
)
296 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
297 else if(process
->state
->s
== LTTV_STATE_WAIT
)
298 prop_line
.color
= drawing_colors
[COL_WAIT
];
299 else if(process
->state
->s
== LTTV_STATE_RUN
)
300 prop_line
.color
= drawing_colors
[COL_RUN
];
302 prop_line
.color
= drawing_colors
[COL_WHITE
];
304 //gdk_colormap_alloc_color(colormap,
315 /* before_schedchange_hook
317 * This function basically draw lines and icons. Two types of lines are drawn :
318 * one small (3 pixels?) representing the state of the process and the second
319 * type is thicker (10 pixels?) representing on which CPU a process is running
320 * (and this only in running state).
322 * Extremums of the lines :
323 * x_min : time of the last event context for this process kept in memory.
324 * x_max : time of the current event.
325 * y : middle of the process in the process list. The process is found in the
326 * list, therefore is it's position in pixels.
328 * The choice of lines'color is defined by the context of the last event for this
333 int before_schedchange_hook(void *hook_data
, void *call_data
)
335 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
336 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
337 Drawing_t
*drawing
= control_flow_data
->drawing
;
339 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
341 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
342 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
347 LttTime evtime
= ltt_event_time(e
);
348 TimeWindow time_window
=
349 lttvwindow_get_time_window(control_flow_data
->tab
);
351 LttTime end_time
= ltt_time_add(time_window
.start_time
,
352 time_window
.time_width
);
354 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
355 || ltt_time_compare(evtime
, end_time
) == 1)
357 guint width
= drawing
->width
;
359 /* we are in a schedchange, before the state update. We must draw the
360 * items corresponding to the state before it changes : now is the right
367 LttField
*f
= ltt_event_field(e
);
369 element
= ltt_field_member(f
,0);
370 pid_out
= ltt_event_get_long_unsigned(e
,element
);
371 element
= ltt_field_member(f
,1);
372 pid_in
= ltt_event_get_long_unsigned(e
,element
);
373 g_debug("out : %u in : %u", pid_out
, pid_in
);
377 /* For the pid_out */
378 /* First, check if the current process is in the state computation
379 * process list. If it is there, that means we must add it right now and
380 * draw items from the beginning of the read for it. If it is not
381 * present, it's a new process and it was not present : it will
382 * be added after the state update. */
383 LttvProcessState
*process
;
384 process
= lttv_state_find_process(tfs
, pid_out
);
386 if(process
!= NULL
) {
387 /* Well, the process_out existed : we must get it in the process hash
388 * or add it, and draw its items.
390 /* Add process to process list (if not present) */
391 guint y
= 0, height
= 0, pl_height
= 0;
392 HashedProcessData
*hashed_process_data
= NULL
;
393 ProcessList
*process_list
=
394 guicontrolflow_get_process_list(control_flow_data
);
395 LttTime birth
= process
->creation_time
;
396 const gchar
*name
= g_quark_to_string(process
->name
);
398 if(processlist_get_process_pixels(process_list
,
402 tfc
->t_context
->index
,
405 &hashed_process_data
) == 1)
407 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
408 /* Process not present */
409 processlist_add(process_list
,
414 tfc
->t_context
->index
,
417 &hashed_process_data
);
418 processlist_get_process_pixels(process_list
,
422 tfc
->t_context
->index
,
425 &hashed_process_data
);
426 drawing_insert_square( drawing
, y
, height
);
429 /* Now, the process is in the state hash and our own process hash.
430 * We definitely can draw the items related to the ending state.
433 /* Check if the x position is unset. In can have been left unset by
434 * a draw closure from a after chunk hook. This should never happen,
435 * because it must be set by before chunk hook to the damage_begin
438 g_assert(hashed_process_data
->x
.middle
!= -1);
441 convert_time_to_pixels(
442 time_window
.start_time
,
449 /* Jump over draw if we are at the same x position */
450 if(x
== hashed_process_data
->x
.middle
)
454 DrawContext draw_context
;
456 /* Now create the drawing context that will be used to draw
457 * items related to the last state. */
458 draw_context
.drawable
= drawing
->pixmap
;
459 draw_context
.gc
= drawing
->gc
;
460 draw_context
.pango_layout
= drawing
->pango_layout
;
461 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
462 draw_context
.drawinfo
.end
.x
= x
;
464 draw_context
.drawinfo
.y
.over
= y
+1;
465 draw_context
.drawinfo
.y
.middle
= y
+(height
/2);
466 draw_context
.drawinfo
.y
.under
= y
+height
;
468 draw_context
.drawinfo
.start
.offset
.over
= 0;
469 draw_context
.drawinfo
.start
.offset
.middle
= 0;
470 draw_context
.drawinfo
.start
.offset
.under
= 0;
471 draw_context
.drawinfo
.end
.offset
.over
= 0;
472 draw_context
.drawinfo
.end
.offset
.middle
= 0;
473 draw_context
.drawinfo
.end
.offset
.under
= 0;
477 PropertiesLine prop_line
= prepare_status_line(process
);
478 draw_line((void*)&prop_line
, (void*)&draw_context
);
481 /* become the last x position */
482 hashed_process_data
->x
.middle
= x
;
490 /* First, check if the current process is in the state computation
491 * process list. If it is there, that means we must add it right now and
492 * draw items from the beginning of the read for it. If it is not
493 * present, it's a new process and it was not present : it will
494 * be added after the state update. */
495 LttvProcessState
*process
;
496 process
= lttv_state_find_process(tfs
, pid_in
);
498 if(process
!= NULL
) {
499 /* Well, the process_out existed : we must get it in the process hash
500 * or add it, and draw its items.
502 /* Add process to process list (if not present) */
503 guint y
= 0, height
= 0, pl_height
= 0;
504 HashedProcessData
*hashed_process_data
= NULL
;
505 ProcessList
*process_list
=
506 guicontrolflow_get_process_list(control_flow_data
);
507 LttTime birth
= process
->creation_time
;
508 const gchar
*name
= g_quark_to_string(process
->name
);
510 if(processlist_get_process_pixels(process_list
,
514 tfc
->t_context
->index
,
517 &hashed_process_data
) == 1)
519 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
520 /* Process not present */
521 processlist_add(process_list
,
526 tfc
->t_context
->index
,
529 &hashed_process_data
);
530 processlist_get_process_pixels(process_list
,
534 tfc
->t_context
->index
,
537 &hashed_process_data
);
538 drawing_insert_square( drawing
, y
, height
);
541 /* Now, the process is in the state hash and our own process hash.
542 * We definitely can draw the items related to the ending state.
545 /* Check if the x position is unset. In can have been left unset by
546 * a draw closure from a after chunk hook. This should never happen,
547 * because it must be set by before chunk hook to the damage_begin
550 g_assert(hashed_process_data
->x
.middle
!= -1);
554 convert_time_to_pixels(
555 time_window
.start_time
,
562 /* Jump over draw if we are at the same x position */
563 if(x
== hashed_process_data
->x
.middle
)
567 DrawContext draw_context
;
569 /* Now create the drawing context that will be used to draw
570 * items related to the last state. */
571 draw_context
.drawable
= drawing
->pixmap
;
572 draw_context
.gc
= drawing
->gc
;
573 draw_context
.pango_layout
= drawing
->pango_layout
;
574 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
575 draw_context
.drawinfo
.end
.x
= x
;
577 draw_context
.drawinfo
.y
.over
= y
+1;
578 draw_context
.drawinfo
.y
.middle
= y
+(height
/2);
579 draw_context
.drawinfo
.y
.under
= y
+height
;
581 draw_context
.drawinfo
.start
.offset
.over
= 0;
582 draw_context
.drawinfo
.start
.offset
.middle
= 0;
583 draw_context
.drawinfo
.start
.offset
.under
= 0;
584 draw_context
.drawinfo
.end
.offset
.over
= 0;
585 draw_context
.drawinfo
.end
.offset
.middle
= 0;
586 draw_context
.drawinfo
.end
.offset
.under
= 0;
590 PropertiesLine prop_line
= prepare_status_line(process
);
591 draw_line((void*)&prop_line
, (void*)&draw_context
);
595 /* become the last x position */
596 hashed_process_data
->x
.middle
= x
;
605 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
606 ControlFlowData
*control_flow_data
=
607 (ControlFlowData
*)events_request
->viewer_data
;
608 Tab
*tab
= control_flow_data
->tab
;
610 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
612 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
613 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
618 LttTime evtime
= ltt_event_time(e
);
619 TimeWindow time_window
=
620 lttvwindow_get_time_window(tab
);
622 LttTime end_time
= ltt_time_add(time_window
.start_time
,
623 time_window
.time_width
);
624 //if(time < time_beg || time > time_end) return;
625 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
626 || ltt_time_compare(evtime
, end_time
) == 1)
629 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
631 g_debug("schedchange!");
633 /* Add process to process list (if not present) and get drawing "y" from
634 * process position */
635 guint pid_out
, pid_in
;
636 LttvProcessState
*process_out
, *process_in
;
638 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
640 ProcessList
*process_list
=
641 guicontrolflow_get_process_list(control_flow_data
);
644 LttField
*f
= ltt_event_field(e
);
646 element
= ltt_field_member(f
,0);
647 pid_out
= ltt_event_get_long_unsigned(e
,element
);
648 element
= ltt_field_member(f
,1);
649 pid_in
= ltt_event_get_long_unsigned(e
,element
);
650 g_debug("out : %u in : %u", pid_out
, pid_in
);
653 /* Find process pid_out in the list... */
654 process_out
= lttv_state_find_process(tfs
, pid_out
);
655 if(process_out
== NULL
) return 0;
656 g_debug("out : %s",g_quark_to_string(process_out
->state
->s
));
658 birth
= process_out
->creation_time
;
659 const gchar
*name
= g_quark_to_string(process_out
->name
);
660 HashedProcessData
*hashed_process_data_out
= NULL
;
662 if(processlist_get_process_pixels(process_list
,
665 tfc
->t_context
->index
,
668 &hashed_process_data_out
) == 1)
670 /* Process not present */
671 processlist_add(process_list
,
674 tfc
->t_context
->index
,
677 &hashed_process_data_out
);
678 g_assert(processlist_get_process_pixels(process_list
,
681 tfc
->t_context
->index
,
684 &hashed_process_data_out
)==0);
685 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
689 /* Find process pid_in in the list... */
690 process_in
= lttv_state_find_process(tfs
, pid_in
);
691 if(process_in
== NULL
) return 0;
692 g_debug("in : %s",g_quark_to_string(process_in
->state
->s
));
694 birth
= process_in
->creation_time
;
695 name
= g_quark_to_string(process_in
->name
);
696 HashedProcessData
*hashed_process_data_in
= NULL
;
698 if(processlist_get_process_pixels(process_list
,
701 tfc
->t_context
->index
,
704 &hashed_process_data_in
) == 1)
706 /* Process not present */
707 processlist_add(process_list
,
710 tfc
->t_context
->index
,
713 &hashed_process_data_in
);
714 processlist_get_process_pixels(process_list
,
717 tfc
->t_context
->index
,
720 &hashed_process_data_in
);
722 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
727 /* Find pixels corresponding to time of the event. If the time does
728 * not fit in the window, show a warning, not supposed to happend. */
730 guint width
= control_flow_data
->drawing
->width
;
732 LttTime time
= ltt_event_time(e
);
734 LttTime window_end
= ltt_time_add(time_window
.time_width
,
735 time_window
.start_time
);
738 convert_time_to_pixels(
739 time_window
.start_time
,
744 //assert(x <= width);
746 /* draw what represents the event for outgoing process. */
748 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
749 draw_context_out
->current
->modify_over
->x
= x
;
750 draw_context_out
->current
->modify_under
->x
= x
;
751 draw_context_out
->current
->modify_over
->y
= y_out
;
752 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
753 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
754 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
755 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
756 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
757 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
758 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
759 //draw_context_out->gc = widget->style->black_gc;
761 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
762 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
764 /* Draw the line/background of the out process */
765 if(draw_context_out
->previous
->middle
->x
== -1)
767 draw_context_out
->previous
->over
->x
=
768 control_flow_data
->drawing
->damage_begin
;
769 draw_context_out
->previous
->middle
->x
=
770 control_flow_data
->drawing
->damage_begin
;
771 draw_context_out
->previous
->under
->x
=
772 control_flow_data
->drawing
->damage_begin
;
774 g_debug("out middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
777 draw_context_out
->current
->middle
->x
= x
;
778 draw_context_out
->current
->over
->x
= x
;
779 draw_context_out
->current
->under
->x
= x
;
780 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
781 draw_context_out
->current
->over
->y
= y_out
;
782 draw_context_out
->current
->under
->y
= y_out
+ height
;
783 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
784 draw_context_out
->previous
->over
->y
= y_out
;
785 draw_context_out
->previous
->under
->y
= y_out
+ height
;
787 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
788 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
790 if(process_out
->state
->s
== LTTV_STATE_RUN
)
792 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
793 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
794 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
796 PropertiesBG prop_bg
;
797 prop_bg
.color
= g_new(GdkColor
,1);
801 prop_bg
.color
->red
= 0x1515;
802 prop_bg
.color
->green
= 0x1515;
803 prop_bg
.color
->blue
= 0x8c8c;
806 prop_bg
.color
->red
= 0x4e4e;
807 prop_bg
.color
->green
= 0xa9a9;
808 prop_bg
.color
->blue
= 0xa4a4;
811 prop_bg
.color
->red
= 0x7a7a;
812 prop_bg
.color
->green
= 0x4a4a;
813 prop_bg
.color
->blue
= 0x8b8b;
816 prop_bg
.color
->red
= 0x8080;
817 prop_bg
.color
->green
= 0x7777;
818 prop_bg
.color
->blue
= 0x4747;
821 prop_bg
.color
->red
= 0xe7e7;
822 prop_bg
.color
->green
= 0xe7e7;
823 prop_bg
.color
->blue
= 0xe7e7;
826 g_debug("calling from draw_event");
827 draw_bg((void*)&prop_bg
, (void*)draw_context_out
);
828 g_free(prop_bg
.color
);
829 //gdk_gc_unref(draw_context_out->gc);
832 draw_context_out
->gc
= widget
->style
->black_gc
;
834 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
835 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
836 PropertiesText prop_text_out
;
837 prop_text_out
.foreground
= &colorfg_out
;
838 prop_text_out
.background
= &colorbg_out
;
839 prop_text_out
.size
= 6;
840 prop_text_out
.position
= OVER
;
842 /* color of text : status of the process */
843 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
845 prop_text_out
.foreground
->red
= 0xffff;
846 prop_text_out
.foreground
->green
= 0xffff;
847 prop_text_out
.foreground
->blue
= 0xffff;
849 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
851 prop_text_out
.foreground
->red
= 0x0fff;
852 prop_text_out
.foreground
->green
= 0xffff;
853 prop_text_out
.foreground
->blue
= 0xfff0;
855 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
857 prop_text_out
.foreground
->red
= 0xffff;
858 prop_text_out
.foreground
->green
= 0xffff;
859 prop_text_out
.foreground
->blue
= 0x0000;
861 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
863 prop_text_out
.foreground
->red
= 0xffff;
864 prop_text_out
.foreground
->green
= 0x0000;
865 prop_text_out
.foreground
->blue
= 0xffff;
867 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
869 prop_text_out
.foreground
->red
= 0xffff;
870 prop_text_out
.foreground
->green
= 0x0000;
871 prop_text_out
.foreground
->blue
= 0x0000;
873 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
875 prop_text_out
.foreground
->red
= 0x0000;
876 prop_text_out
.foreground
->green
= 0xffff;
877 prop_text_out
.foreground
->blue
= 0x0000;
881 prop_text_out
.foreground
->red
= 0xffff;
882 prop_text_out
.foreground
->green
= 0xffff;
883 prop_text_out
.foreground
->blue
= 0xffff;
887 /* Print status of the process : U, WF, WC, E, W, R */
888 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
889 prop_text_out
.text
= "U->";
890 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
891 prop_text_out
.text
= "WF->";
892 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
893 prop_text_out
.text
= "WC->";
894 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
895 prop_text_out
.text
= "E->";
896 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
897 prop_text_out
.text
= "W->";
898 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
899 prop_text_out
.text
= "R->";
901 prop_text_out
.text
= "U";
903 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
904 //gdk_gc_unref(draw_context_out->gc);
906 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
907 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
908 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
910 PropertiesLine prop_line_out
;
911 prop_line_out
.color
= g_new(GdkColor
,1);
912 prop_line_out
.line_width
= 2;
913 prop_line_out
.style
= GDK_LINE_SOLID
;
914 prop_line_out
.position
= MIDDLE
;
916 g_debug("out state : %s", g_quark_to_string(process_out
->state
->s
));
918 /* color of line : status of the process */
919 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
921 prop_line_out
.color
->red
= 0xffff;
922 prop_line_out
.color
->green
= 0xffff;
923 prop_line_out
.color
->blue
= 0xffff;
925 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
927 prop_line_out
.color
->red
= 0x0fff;
928 prop_line_out
.color
->green
= 0xffff;
929 prop_line_out
.color
->blue
= 0xfff0;
931 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
933 prop_line_out
.color
->red
= 0xffff;
934 prop_line_out
.color
->green
= 0xffff;
935 prop_line_out
.color
->blue
= 0x0000;
937 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
939 prop_line_out
.color
->red
= 0xffff;
940 prop_line_out
.color
->green
= 0x0000;
941 prop_line_out
.color
->blue
= 0xffff;
943 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
945 prop_line_out
.color
->red
= 0xffff;
946 prop_line_out
.color
->green
= 0x0000;
947 prop_line_out
.color
->blue
= 0x0000;
949 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
951 prop_line_out
.color
->red
= 0x0000;
952 prop_line_out
.color
->green
= 0xffff;
953 prop_line_out
.color
->blue
= 0x0000;
957 prop_line_out
.color
->red
= 0xffff;
958 prop_line_out
.color
->green
= 0xffff;
959 prop_line_out
.color
->blue
= 0xffff;
962 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
963 g_free(prop_line_out
.color
);
964 //gdk_gc_unref(draw_context_out->gc);
965 /* Note : finishing line will have to be added when trace read over. */
967 /* Finally, update the drawing context of the pid_in. */
969 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
970 draw_context_in
->current
->modify_over
->x
= x
;
971 draw_context_in
->current
->modify_under
->x
= x
;
972 draw_context_in
->current
->modify_over
->y
= y_in
;
973 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
974 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
975 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
976 widget
= control_flow_data
->drawing
->drawing_area
;
977 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
978 //draw_context_in->gc = widget->style->black_gc;
979 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
980 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
982 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
983 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
985 /* Draw the line/bg of the in process */
986 if(draw_context_in
->previous
->middle
->x
== -1)
988 draw_context_in
->previous
->over
->x
=
989 control_flow_data
->drawing
->damage_begin
;
990 draw_context_in
->previous
->middle
->x
=
991 control_flow_data
->drawing
->damage_begin
;
992 draw_context_in
->previous
->under
->x
=
993 control_flow_data
->drawing
->damage_begin
;
995 g_debug("in middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
999 draw_context_in
->current
->middle
->x
= x
;
1000 draw_context_in
->current
->over
->x
= x
;
1001 draw_context_in
->current
->under
->x
= x
;
1002 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
1003 draw_context_in
->current
->over
->y
= y_in
;
1004 draw_context_in
->current
->under
->y
= y_in
+ height
;
1005 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
1006 draw_context_in
->previous
->over
->y
= y_in
;
1007 draw_context_in
->previous
->under
->y
= y_in
+ height
;
1009 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1010 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1013 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1015 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1016 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1017 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1019 PropertiesBG prop_bg
;
1020 prop_bg
.color
= g_new(GdkColor
,1);
1022 switch(tfc
->index
) {
1024 prop_bg
.color
->red
= 0x1515;
1025 prop_bg
.color
->green
= 0x1515;
1026 prop_bg
.color
->blue
= 0x8c8c;
1029 prop_bg
.color
->red
= 0x4e4e;
1030 prop_bg
.color
->green
= 0xa9a9;
1031 prop_bg
.color
->blue
= 0xa4a4;
1034 prop_bg
.color
->red
= 0x7a7a;
1035 prop_bg
.color
->green
= 0x4a4a;
1036 prop_bg
.color
->blue
= 0x8b8b;
1039 prop_bg
.color
->red
= 0x8080;
1040 prop_bg
.color
->green
= 0x7777;
1041 prop_bg
.color
->blue
= 0x4747;
1044 prop_bg
.color
->red
= 0xe7e7;
1045 prop_bg
.color
->green
= 0xe7e7;
1046 prop_bg
.color
->blue
= 0xe7e7;
1050 draw_bg((void*)&prop_bg
, (void*)draw_context_in
);
1051 g_free(prop_bg
.color
);
1052 //gdk_gc_unref(draw_context_in->gc);
1055 draw_context_in
->gc
= widget
->style
->black_gc
;
1057 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1058 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1059 PropertiesText prop_text_in
;
1060 prop_text_in
.foreground
= &colorfg_in
;
1061 prop_text_in
.background
= &colorbg_in
;
1062 prop_text_in
.size
= 6;
1063 prop_text_in
.position
= OVER
;
1065 g_debug("in state : %s", g_quark_to_string(process_in
->state
->s
));
1066 /* foreground of text : status of the process */
1067 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1069 prop_text_in
.foreground
->red
= 0xffff;
1070 prop_text_in
.foreground
->green
= 0xffff;
1071 prop_text_in
.foreground
->blue
= 0xffff;
1073 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1075 prop_text_in
.foreground
->red
= 0x0fff;
1076 prop_text_in
.foreground
->green
= 0xffff;
1077 prop_text_in
.foreground
->blue
= 0xfff0;
1079 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1081 prop_text_in
.foreground
->red
= 0xffff;
1082 prop_text_in
.foreground
->green
= 0xffff;
1083 prop_text_in
.foreground
->blue
= 0x0000;
1085 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1087 prop_text_in
.foreground
->red
= 0xffff;
1088 prop_text_in
.foreground
->green
= 0x0000;
1089 prop_text_in
.foreground
->blue
= 0xffff;
1091 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1093 prop_text_in
.foreground
->red
= 0xffff;
1094 prop_text_in
.foreground
->green
= 0x0000;
1095 prop_text_in
.foreground
->blue
= 0x0000;
1097 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1099 prop_text_in
.foreground
->red
= 0x0000;
1100 prop_text_in
.foreground
->green
= 0xffff;
1101 prop_text_in
.foreground
->blue
= 0x0000;
1105 prop_text_in
.foreground
->red
= 0xffff;
1106 prop_text_in
.foreground
->green
= 0xffff;
1107 prop_text_in
.foreground
->blue
= 0xffff;
1112 /* Print status of the process : U, WF, WC, E, W, R */
1113 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1114 prop_text_in
.text
= "U->";
1115 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1116 prop_text_in
.text
= "WF->";
1117 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1118 prop_text_in
.text
= "WC->";
1119 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1120 prop_text_in
.text
= "E->";
1121 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1122 prop_text_in
.text
= "W->";
1123 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1124 prop_text_in
.text
= "R->";
1126 prop_text_in
.text
= "U";
1128 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1129 //gdk_gc_unref(draw_context_in->gc);
1131 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1132 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1133 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1135 PropertiesLine prop_line_in
;
1136 prop_line_in
.color
= g_new(GdkColor
,1);
1137 prop_line_in
.line_width
= 2;
1138 prop_line_in
.style
= GDK_LINE_SOLID
;
1139 prop_line_in
.position
= MIDDLE
;
1141 /* color of line : status of the process */
1142 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1144 prop_line_in
.color
->red
= 0xffff;
1145 prop_line_in
.color
->green
= 0xffff;
1146 prop_line_in
.color
->blue
= 0xffff;
1148 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1150 prop_line_in
.color
->red
= 0x0fff;
1151 prop_line_in
.color
->green
= 0xffff;
1152 prop_line_in
.color
->blue
= 0xfff0;
1154 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1156 prop_line_in
.color
->red
= 0xffff;
1157 prop_line_in
.color
->green
= 0xffff;
1158 prop_line_in
.color
->blue
= 0x0000;
1160 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1162 prop_line_in
.color
->red
= 0xffff;
1163 prop_line_in
.color
->green
= 0x0000;
1164 prop_line_in
.color
->blue
= 0xffff;
1166 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1168 prop_line_in
.color
->red
= 0xffff;
1169 prop_line_in
.color
->green
= 0x0000;
1170 prop_line_in
.color
->blue
= 0x0000;
1172 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1174 prop_line_in
.color
->red
= 0x0000;
1175 prop_line_in
.color
->green
= 0xffff;
1176 prop_line_in
.color
->blue
= 0x0000;
1180 prop_line_in
.color
->red
= 0xffff;
1181 prop_line_in
.color
->green
= 0xffff;
1182 prop_line_in
.color
->blue
= 0xffff;
1185 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
1186 g_free(prop_line_in
.color
);
1187 //gdk_gc_unref(draw_context_in->gc);
1197 GString
*string
= g_string_new("");;
1198 gboolean field_names
= TRUE
, state
= TRUE
;
1200 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
1201 g_string_append_printf(string
,"\n");
1204 g_string_append_printf(string
, " %s",
1205 g_quark_to_string(tfs
->process
->state
->s
));
1208 g_info("%s",string
->str
);
1210 g_string_free(string
, TRUE
);
1212 /* End of text dump */
1217 /* after_schedchange_hook
1219 * The draw after hook is called by the reading API to have a
1220 * particular event drawn on the screen.
1221 * @param hook_data ControlFlowData structure of the viewer.
1222 * @param call_data Event context.
1224 * This function adds items to be drawn in a queue for each process.
1227 int after_schedchange_hook(void *hook_data
, void *call_data
)
1229 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1230 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1232 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1234 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1235 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1240 LttTime evtime
= ltt_event_time(e
);
1241 TimeWindow time_window
=
1242 lttvwindow_get_time_window(control_flow_data
->tab
);
1244 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1245 time_window
.time_width
);
1247 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1248 || ltt_time_compare(evtime
, end_time
) == 1)
1251 guint width
= control_flow_data
->drawing
->width
;
1253 /* Add process to process list (if not present) */
1254 LttvProcessState
*process_out
, *process_in
;
1256 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1257 HashedProcessData
*hashed_process_data_in
= NULL
;
1259 ProcessList
*process_list
=
1260 guicontrolflow_get_process_list(control_flow_data
);
1265 LttField
*f
= ltt_event_field(e
);
1267 element
= ltt_field_member(f
,0);
1268 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1269 element
= ltt_field_member(f
,1);
1270 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1271 g_debug("out : %u in : %u", pid_out
, pid_in
);
1275 /* Find process pid_in in the list... */
1276 process_in
= lttv_state_find_process(tfs
, pid_in
);
1277 /* It should exist, because we are after the state update. */
1278 g_assert(process_in
!= NULL
);
1280 birth
= process_in
->creation_time
;
1281 const gchar
*name
= g_quark_to_string(process_in
->name
);
1283 if(processlist_get_process_pixels(process_list
,
1285 process_in
->last_cpu
,
1287 tfc
->t_context
->index
,
1290 &hashed_process_data_in
) == 1)
1292 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1293 /* Process not present */
1294 processlist_add(process_list
,
1296 process_in
->last_cpu
,
1299 tfc
->t_context
->index
,
1302 &hashed_process_data_in
);
1303 processlist_get_process_pixels(process_list
,
1305 process_in
->last_cpu
,
1307 tfc
->t_context
->index
,
1310 &hashed_process_data_in
);
1311 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1314 convert_time_to_pixels(
1315 time_window
.start_time
,
1319 &hashed_process_data_in
->x
.middle
);
1325 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1326 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1328 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1330 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1331 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1337 LttTime evtime
= ltt_event_time(e
);
1338 TimeWindow time_window
=
1339 lttvwindow_get_time_window(control_flow_data
->tab
);
1341 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1342 time_window
.time_width
);
1343 //if(time < time_beg || time > time_end) return;
1344 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1345 || ltt_time_compare(evtime
, end_time
) == 1)
1349 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1351 g_debug("schedchange!");
1353 /* Add process to process list (if not present) and get drawing "y" from
1354 * process position */
1355 guint pid_out
, pid_in
;
1356 LttvProcessState
*process_out
, *process_in
;
1358 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1360 ProcessList
*process_list
=
1361 guicontrolflow_get_process_list(control_flow_data
);
1364 LttField
*f
= ltt_event_field(e
);
1366 element
= ltt_field_member(f
,0);
1367 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1368 element
= ltt_field_member(f
,1);
1369 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1370 //g_debug("out : %u in : %u", pid_out, pid_in);
1373 /* Find process pid_out in the list... */
1374 process_out
= lttv_state_find_process(tfs
, pid_out
);
1375 if(process_out
== NULL
) return 0;
1376 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1378 birth
= process_out
->creation_time
;
1379 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1380 HashedProcessData
*hashed_process_data_out
= NULL
;
1382 if(processlist_get_process_pixels(process_list
,
1385 tfc
->t_context
->index
,
1388 &hashed_process_data_out
) == 1)
1390 /* Process not present */
1391 processlist_add(process_list
,
1394 tfc
->t_context
->index
,
1397 &hashed_process_data_out
);
1398 processlist_get_process_pixels(process_list
,
1401 tfc
->t_context
->index
,
1404 &hashed_process_data_out
);
1405 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1410 /* Find process pid_in in the list... */
1411 process_in
= lttv_state_find_process(tfs
, pid_in
);
1412 if(process_in
== NULL
) return 0;
1413 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1415 birth
= process_in
->creation_time
;
1416 name
= strdup(g_quark_to_string(process_in
->name
));
1417 HashedProcessData
*hashed_process_data_in
= NULL
;
1419 if(processlist_get_process_pixels(process_list
,
1422 tfc
->t_context
->index
,
1425 &hashed_process_data_in
) == 1)
1427 /* Process not present */
1428 processlist_add(process_list
,
1431 tfc
->t_context
->index
,
1434 &hashed_process_data_in
);
1435 processlist_get_process_pixels(process_list
,
1438 tfc
->t_context
->index
,
1441 &hashed_process_data_in
);
1443 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1448 /* Find pixels corresponding to time of the event. If the time does
1449 * not fit in the window, show a warning, not supposed to happend. */
1451 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1453 //LttTime time = ltt_event_time(e);
1455 //LttTime window_end = ltt_time_add(time_window->time_width,
1456 // time_window->start_time);
1459 //convert_time_to_pixels(
1460 // time_window->start_time,
1466 //assert(x <= width);
1468 /* draw what represents the event for outgoing process. */
1470 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1471 //draw_context_out->current->modify_over->x = x;
1472 draw_context_out
->current
->modify_over
->y
= y_out
;
1473 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1474 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1475 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1476 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1477 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1479 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1480 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1482 /*if(process_out->state->s == LTTV_STATE_RUN)
1484 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1485 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1486 PropertiesBG prop_bg;
1487 prop_bg.color = g_new(GdkColor,1);
1489 prop_bg.color->red = 0xffff;
1490 prop_bg.color->green = 0xffff;
1491 prop_bg.color->blue = 0xffff;
1493 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1494 g_free(prop_bg.color);
1495 gdk_gc_unref(draw_context_out->gc);
1498 draw_context_out
->gc
= widget
->style
->black_gc
;
1500 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1501 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1502 PropertiesText prop_text_out
;
1503 prop_text_out
.foreground
= &colorfg_out
;
1504 prop_text_out
.background
= &colorbg_out
;
1505 prop_text_out
.size
= 6;
1506 prop_text_out
.position
= OVER
;
1508 /* color of text : status of the process */
1509 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1511 prop_text_out
.foreground
->red
= 0xffff;
1512 prop_text_out
.foreground
->green
= 0xffff;
1513 prop_text_out
.foreground
->blue
= 0xffff;
1515 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1517 prop_text_out
.foreground
->red
= 0x0fff;
1518 prop_text_out
.foreground
->green
= 0xffff;
1519 prop_text_out
.foreground
->blue
= 0xfff0;
1521 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1523 prop_text_out
.foreground
->red
= 0xffff;
1524 prop_text_out
.foreground
->green
= 0xffff;
1525 prop_text_out
.foreground
->blue
= 0x0000;
1527 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1529 prop_text_out
.foreground
->red
= 0xffff;
1530 prop_text_out
.foreground
->green
= 0x0000;
1531 prop_text_out
.foreground
->blue
= 0xffff;
1533 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1535 prop_text_out
.foreground
->red
= 0xffff;
1536 prop_text_out
.foreground
->green
= 0x0000;
1537 prop_text_out
.foreground
->blue
= 0x0000;
1539 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1541 prop_text_out
.foreground
->red
= 0x0000;
1542 prop_text_out
.foreground
->green
= 0xffff;
1543 prop_text_out
.foreground
->blue
= 0x0000;
1547 prop_text_out
.foreground
->red
= 0xffff;
1548 prop_text_out
.foreground
->green
= 0xffff;
1549 prop_text_out
.foreground
->blue
= 0xffff;
1552 /* Print status of the process : U, WF, WC, E, W, R */
1553 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1554 prop_text_out
.text
= "U";
1555 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1556 prop_text_out
.text
= "WF";
1557 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1558 prop_text_out
.text
= "WC";
1559 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1560 prop_text_out
.text
= "E";
1561 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1562 prop_text_out
.text
= "W";
1563 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1564 prop_text_out
.text
= "R";
1566 prop_text_out
.text
= "U";
1568 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1570 //gdk_gc_unref(draw_context_out->gc);
1572 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1573 draw_context_out
->current
->over
->y
= y_out
;
1574 draw_context_out
->current
->under
->y
= y_out
+height
;
1575 draw_context_out
->current
->status
= process_out
->state
->s
;
1577 /* for pid_out : remove previous, Prev = current, new current (default) */
1578 g_free(draw_context_out
->previous
->modify_under
);
1579 g_free(draw_context_out
->previous
->modify_middle
);
1580 g_free(draw_context_out
->previous
->modify_over
);
1581 g_free(draw_context_out
->previous
->under
);
1582 g_free(draw_context_out
->previous
->middle
);
1583 g_free(draw_context_out
->previous
->over
);
1584 g_free(draw_context_out
->previous
);
1586 draw_context_out
->previous
= draw_context_out
->current
;
1588 draw_context_out
->current
= g_new(DrawInfo
,1);
1589 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1590 draw_context_out
->current
->over
->x
= -1;
1591 draw_context_out
->current
->over
->y
= -1;
1592 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1593 draw_context_out
->current
->middle
->x
= -1;
1594 draw_context_out
->current
->middle
->y
= -1;
1595 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1596 draw_context_out
->current
->under
->x
= -1;
1597 draw_context_out
->current
->under
->y
= -1;
1598 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1599 draw_context_out
->current
->modify_over
->x
= -1;
1600 draw_context_out
->current
->modify_over
->y
= -1;
1601 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1602 draw_context_out
->current
->modify_middle
->x
= -1;
1603 draw_context_out
->current
->modify_middle
->y
= -1;
1604 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1605 draw_context_out
->current
->modify_under
->x
= -1;
1606 draw_context_out
->current
->modify_under
->y
= -1;
1607 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1609 /* Finally, update the drawing context of the pid_in. */
1611 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1612 //draw_context_in->current->modify_over->x = x;
1613 draw_context_in
->current
->modify_over
->y
= y_in
;
1614 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1615 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1616 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1617 widget
= control_flow_data
->drawing
->drawing_area
;
1618 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1620 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1621 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1623 /*if(process_in->state->s == LTTV_STATE_RUN)
1625 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1626 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1627 PropertiesBG prop_bg;
1628 prop_bg.color = g_new(GdkColor,1);
1630 prop_bg.color->red = 0xffff;
1631 prop_bg.color->green = 0xffff;
1632 prop_bg.color->blue = 0xffff;
1634 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1635 g_free(prop_bg.color);
1636 gdk_gc_unref(draw_context_in->gc);
1639 draw_context_in
->gc
= widget
->style
->black_gc
;
1641 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1642 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1643 PropertiesText prop_text_in
;
1644 prop_text_in
.foreground
= &colorfg_in
;
1645 prop_text_in
.background
= &colorbg_in
;
1646 prop_text_in
.size
= 6;
1647 prop_text_in
.position
= OVER
;
1649 /* foreground of text : status of the process */
1650 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1652 prop_text_in
.foreground
->red
= 0xffff;
1653 prop_text_in
.foreground
->green
= 0xffff;
1654 prop_text_in
.foreground
->blue
= 0xffff;
1656 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1658 prop_text_in
.foreground
->red
= 0x0fff;
1659 prop_text_in
.foreground
->green
= 0xffff;
1660 prop_text_in
.foreground
->blue
= 0xfff0;
1662 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1664 prop_text_in
.foreground
->red
= 0xffff;
1665 prop_text_in
.foreground
->green
= 0xffff;
1666 prop_text_in
.foreground
->blue
= 0x0000;
1668 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1670 prop_text_in
.foreground
->red
= 0xffff;
1671 prop_text_in
.foreground
->green
= 0x0000;
1672 prop_text_in
.foreground
->blue
= 0xffff;
1674 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1676 prop_text_in
.foreground
->red
= 0xffff;
1677 prop_text_in
.foreground
->green
= 0x0000;
1678 prop_text_in
.foreground
->blue
= 0x0000;
1680 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1682 prop_text_in
.foreground
->red
= 0x0000;
1683 prop_text_in
.foreground
->green
= 0xffff;
1684 prop_text_in
.foreground
->blue
= 0x0000;
1688 prop_text_in
.foreground
->red
= 0xffff;
1689 prop_text_in
.foreground
->green
= 0xffff;
1690 prop_text_in
.foreground
->blue
= 0xffff;
1694 /* Print status of the process : U, WF, WC, E, W, R */
1695 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1696 prop_text_in
.text
= "U";
1697 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1698 prop_text_in
.text
= "WF";
1699 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1700 prop_text_in
.text
= "WC";
1701 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1702 prop_text_in
.text
= "E";
1703 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1704 prop_text_in
.text
= "W";
1705 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1706 prop_text_in
.text
= "R";
1708 prop_text_in
.text
= "U";
1710 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1713 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1716 prop_text_in
.foreground
= &colorfg_in
;
1717 prop_text_in
.background
= &colorbg_in
;
1718 prop_text_in
.foreground
->red
= 0xffff;
1719 prop_text_in
.foreground
->green
= 0xffff;
1720 prop_text_in
.foreground
->blue
= 0xffff;
1721 prop_text_in
.size
= 6;
1722 prop_text_in
.position
= UNDER
;
1724 prop_text_in
.text
= g_new(gchar
, 260);
1725 strcpy(prop_text_in
.text
, "CPU ");
1726 snprintf(tmp
, 255, "%u", tfc
->index
);
1727 strcat(prop_text_in
.text
, tmp
);
1729 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1730 g_free(prop_text_in
.text
);
1734 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1735 draw_context_in
->current
->over
->y
= y_in
;
1736 draw_context_in
->current
->under
->y
= y_in
+height
;
1737 draw_context_in
->current
->status
= process_in
->state
->s
;
1739 /* for pid_in : remove previous, Prev = current, new current (default) */
1740 g_free(draw_context_in
->previous
->modify_under
);
1741 g_free(draw_context_in
->previous
->modify_middle
);
1742 g_free(draw_context_in
->previous
->modify_over
);
1743 g_free(draw_context_in
->previous
->under
);
1744 g_free(draw_context_in
->previous
->middle
);
1745 g_free(draw_context_in
->previous
->over
);
1746 g_free(draw_context_in
->previous
);
1748 draw_context_in
->previous
= draw_context_in
->current
;
1750 draw_context_in
->current
= g_new(DrawInfo
,1);
1751 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1752 draw_context_in
->current
->over
->x
= -1;
1753 draw_context_in
->current
->over
->y
= -1;
1754 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1755 draw_context_in
->current
->middle
->x
= -1;
1756 draw_context_in
->current
->middle
->y
= -1;
1757 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1758 draw_context_in
->current
->under
->x
= -1;
1759 draw_context_in
->current
->under
->y
= -1;
1760 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1761 draw_context_in
->current
->modify_over
->x
= -1;
1762 draw_context_in
->current
->modify_over
->y
= -1;
1763 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1764 draw_context_in
->current
->modify_middle
->x
= -1;
1765 draw_context_in
->current
->modify_middle
->y
= -1;
1766 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1767 draw_context_in
->current
->modify_under
->x
= -1;
1768 draw_context_in
->current
->modify_under
->y
= -1;
1769 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1777 static __inline PropertiesLine
prepare_execmode_line(LttvProcessState
*process
)
1779 PropertiesLine prop_line
;
1780 prop_line
.line_width
= 1;
1781 prop_line
.style
= GDK_LINE_SOLID
;
1783 //GdkColormap *colormap = gdk_colormap_get_system();
1785 /* color of line : execution mode of the process */
1786 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
1787 prop_line
.color
= drawing_colors
[COL_USER_MODE
];
1788 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
1789 prop_line
.color
= drawing_colors
[COL_SYSCALL
];
1790 else if(process
->state
->t
== LTTV_STATE_TRAP
)
1791 prop_line
.color
= drawing_colors
[COL_TRAP
];
1792 else if(process
->state
->t
== LTTV_STATE_IRQ
)
1793 prop_line
.color
= drawing_colors
[COL_IRQ
];
1794 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
1795 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
1797 prop_line
.color
= drawing_colors
[COL_WHITE
];
1799 //gdk_colormap_alloc_color(colormap,
1810 /* before_execmode_hook
1812 * This function basically draw lines and icons. Two types of lines are drawn :
1813 * one small (3 pixels?) representing the state of the process and the second
1814 * type is thicker (10 pixels?) representing on which CPU a process is running
1815 * (and this only in running state).
1817 * Extremums of the lines :
1818 * x_min : time of the last event context for this process kept in memory.
1819 * x_max : time of the current event.
1820 * y : middle of the process in the process list. The process is found in the
1821 * list, therefore is it's position in pixels.
1823 * The choice of lines'color is defined by the context of the last event for this
1828 int before_execmode_hook(void *hook_data
, void *call_data
)
1830 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1831 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1832 Drawing_t
*drawing
= control_flow_data
->drawing
;
1834 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1836 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1837 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1842 LttTime evtime
= ltt_event_time(e
);
1843 TimeWindow time_window
=
1844 lttvwindow_get_time_window(control_flow_data
->tab
);
1846 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1847 time_window
.time_width
);
1849 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1850 || ltt_time_compare(evtime
, end_time
) == 1)
1853 guint width
= drawing
->width
;
1855 /* we are in a execmode, before the state update. We must draw the
1856 * items corresponding to the state before it changes : now is the right
1860 LttvProcessState
*process
= tfs
->process
;
1861 g_assert(process
!= NULL
);
1863 guint pid
= process
->pid
;
1865 /* Well, the process_out existed : we must get it in the process hash
1866 * or add it, and draw its items.
1868 /* Add process to process list (if not present) */
1869 guint y
= 0, height
= 0, pl_height
= 0;
1870 HashedProcessData
*hashed_process_data
= NULL
;
1871 ProcessList
*process_list
=
1872 guicontrolflow_get_process_list(control_flow_data
);
1873 LttTime birth
= process
->creation_time
;
1874 const gchar
*name
= g_quark_to_string(process
->name
);
1876 if(processlist_get_process_pixels(process_list
,
1880 tfc
->t_context
->index
,
1883 &hashed_process_data
) == 1)
1885 g_assert(pid
== 0 || pid
!= process
->ppid
);
1886 /* Process not present */
1887 processlist_add(process_list
,
1892 tfc
->t_context
->index
,
1895 &hashed_process_data
);
1896 processlist_get_process_pixels(process_list
,
1900 tfc
->t_context
->index
,
1903 &hashed_process_data
);
1904 drawing_insert_square( drawing
, y
, height
);
1907 /* Now, the process is in the state hash and our own process hash.
1908 * We definitely can draw the items related to the ending state.
1911 /* Check if the x position is unset. In can have been left unset by
1912 * a draw closure from a after chunk hook. This should never happen,
1913 * because it must be set by before chunk hook to the damage_begin
1916 g_assert(hashed_process_data
->x
.over
!= -1);
1920 convert_time_to_pixels(
1921 time_window
.start_time
,
1928 /* Jump over draw if we are at the same x position */
1929 if(x
== hashed_process_data
->x
.over
)
1934 DrawContext draw_context
;
1935 /* Now create the drawing context that will be used to draw
1936 * items related to the last state. */
1937 draw_context
.drawable
= drawing
->pixmap
;
1938 draw_context
.gc
= drawing
->gc
;
1939 draw_context
.pango_layout
= drawing
->pango_layout
;
1940 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
1941 draw_context
.drawinfo
.end
.x
= x
;
1943 draw_context
.drawinfo
.y
.over
= y
+1;
1944 draw_context
.drawinfo
.y
.middle
= y
+(height
/2);
1945 draw_context
.drawinfo
.y
.under
= y
+height
;
1947 draw_context
.drawinfo
.start
.offset
.over
= 0;
1948 draw_context
.drawinfo
.start
.offset
.middle
= 0;
1949 draw_context
.drawinfo
.start
.offset
.under
= 0;
1950 draw_context
.drawinfo
.end
.offset
.over
= 0;
1951 draw_context
.drawinfo
.end
.offset
.middle
= 0;
1952 draw_context
.drawinfo
.end
.offset
.under
= 0;
1956 PropertiesLine prop_line
= prepare_execmode_line(process
);
1957 draw_line((void*)&prop_line
, (void*)&draw_context
);
1960 /* become the last x position */
1961 hashed_process_data
->x
.over
= x
;
1968 /* after_execmode_hook
1970 * The draw after hook is called by the reading API to have a
1971 * particular event drawn on the screen.
1972 * @param hook_data ControlFlowData structure of the viewer.
1973 * @param call_data Event context.
1975 * This function adds items to be drawn in a queue for each process.
1978 int after_execmode_hook(void *hook_data
, void *call_data
)
1980 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1981 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1983 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1985 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1986 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1991 LttTime evtime
= ltt_event_time(e
);
1992 TimeWindow time_window
=
1993 lttvwindow_get_time_window(control_flow_data
->tab
);
1995 LttTime end_time
= ltt_time_add(time_window
.start_time
,
1996 time_window
.time_width
);
1998 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1999 || ltt_time_compare(evtime
, end_time
) == 1)
2002 guint width
= control_flow_data
->drawing
->width
;
2004 /* Add process to process list (if not present) */
2005 LttvProcessState
*process
;
2007 guint y
= 0, height
= 0, pl_height
= 0;
2008 HashedProcessData
*hashed_process_data
= NULL
;
2010 ProcessList
*process_list
=
2011 guicontrolflow_get_process_list(control_flow_data
);
2014 /* Find process pid_in in the list... */
2015 process
= tfs
->process
;
2016 /* It should exist, because we are after the state update. */
2017 g_assert(process
!= NULL
);
2019 guint pid
= process
->pid
;
2021 birth
= process
->creation_time
;
2022 const gchar
*name
= g_quark_to_string(process
->name
);
2024 if(processlist_get_process_pixels(process_list
,
2028 tfc
->t_context
->index
,
2031 &hashed_process_data
) == 1)
2033 g_assert(pid
== 0 || pid
!= process
->ppid
);
2034 /* Process not present */
2035 processlist_add(process_list
,
2040 tfc
->t_context
->index
,
2043 &hashed_process_data
);
2044 processlist_get_process_pixels(process_list
,
2048 tfc
->t_context
->index
,
2051 &hashed_process_data
);
2052 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
2055 convert_time_to_pixels(
2056 time_window
.start_time
,
2060 &hashed_process_data
->x
.over
);
2066 /* before_process_hook
2068 * Draw lines for process event.
2070 * @param hook_data ControlFlowData structure of the viewer.
2071 * @param call_data Event context.
2073 * This function adds items to be drawn in a queue for each process.
2076 int before_process_hook(void *hook_data
, void *call_data
)
2078 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2079 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2080 Drawing_t
*drawing
= control_flow_data
->drawing
;
2082 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2084 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2085 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
2090 LttTime evtime
= ltt_event_time(e
);
2091 TimeWindow time_window
=
2092 lttvwindow_get_time_window(control_flow_data
->tab
);
2094 LttTime end_time
= ltt_time_add(time_window
.start_time
,
2095 time_window
.time_width
);
2097 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2098 || ltt_time_compare(evtime
, end_time
) == 1)
2101 guint width
= control_flow_data
->drawing
->width
;
2105 LttField
*f
= ltt_event_field(e
);
2107 element
= ltt_field_member(f
,0);
2108 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2111 if(sub_id
== 3) { /* exit */
2113 /* Add process to process list (if not present) */
2114 LttvProcessState
*process
= tfs
->process
;
2115 guint pid
= process
->pid
;
2117 guint y
= 0, height
= 0, pl_height
= 0;
2118 HashedProcessData
*hashed_process_data
= NULL
;
2120 ProcessList
*process_list
=
2121 guicontrolflow_get_process_list(control_flow_data
);
2123 g_assert(process
!= NULL
);
2125 birth
= process
->creation_time
;
2126 const gchar
*name
= g_quark_to_string(process
->name
);
2128 if(processlist_get_process_pixels(process_list
,
2132 tfc
->t_context
->index
,
2135 &hashed_process_data
) == 1)
2137 g_assert(pid
== 0 || pid
!= process
->ppid
);
2138 /* Process not present */
2139 processlist_add(process_list
,
2144 tfc
->t_context
->index
,
2147 &hashed_process_data
);
2148 processlist_get_process_pixels(process_list
,
2152 tfc
->t_context
->index
,
2155 &hashed_process_data
);
2156 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
2159 /* Now, the process is in the state hash and our own process hash.
2160 * We definitely can draw the items related to the ending state.
2163 /* Check if the x position is unset. In can have been left unset by
2164 * a draw closure from a after chunk hook. This should never happen,
2165 * because it must be set by before chunk hook to the damage_begin
2168 g_assert(hashed_process_data
->x
.over
!= -1);
2172 convert_time_to_pixels(
2173 time_window
.start_time
,
2180 /* Jump over draw if we are at the same x position */
2181 if(x
== hashed_process_data
->x
.middle
)
2185 DrawContext draw_context
;
2187 /* Now create the drawing context that will be used to draw
2188 * items related to the last state. */
2189 draw_context
.drawable
= drawing
->pixmap
;
2190 draw_context
.gc
= drawing
->gc
;
2191 draw_context
.pango_layout
= drawing
->pango_layout
;
2192 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2193 draw_context
.drawinfo
.end
.x
= x
;
2195 draw_context
.drawinfo
.y
.over
= y
+1;
2196 draw_context
.drawinfo
.y
.middle
= y
+(height
/2);
2197 draw_context
.drawinfo
.y
.under
= y
+height
;
2199 draw_context
.drawinfo
.start
.offset
.over
= 0;
2200 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2201 draw_context
.drawinfo
.start
.offset
.under
= 0;
2202 draw_context
.drawinfo
.end
.offset
.over
= 0;
2203 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2204 draw_context
.drawinfo
.end
.offset
.under
= 0;
2208 PropertiesLine prop_line
= prepare_status_line(process
);
2209 draw_line((void*)&prop_line
, (void*)&draw_context
);
2212 /* become the last x position */
2213 hashed_process_data
->x
.middle
= x
;
2227 /* after_process_hook
2229 * Create the processlist entry for the child process. Put the last
2230 * position in x at the current time value.
2232 * @param hook_data ControlFlowData structure of the viewer.
2233 * @param call_data Event context.
2235 * This function adds items to be drawn in a queue for each process.
2238 int after_process_hook(void *hook_data
, void *call_data
)
2240 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2241 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2243 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2245 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2246 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
2251 LttTime evtime
= ltt_event_time(e
);
2252 TimeWindow time_window
=
2253 lttvwindow_get_time_window(control_flow_data
->tab
);
2255 LttTime end_time
= ltt_time_add(time_window
.start_time
,
2256 time_window
.time_width
);
2258 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2259 || ltt_time_compare(evtime
, end_time
) == 1)
2262 guint width
= control_flow_data
->drawing
->width
;
2267 LttField
*f
= ltt_event_field(e
);
2269 element
= ltt_field_member(f
,0);
2270 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2271 element
= ltt_field_member(f
,1);
2272 param1
= ltt_event_get_long_unsigned(e
,element
);
2275 if(sub_id
== 2) { /* fork */
2277 guint child_pid
= param1
;
2278 /* Add process to process list (if not present) */
2279 LttvProcessState
*process_child
;
2281 guint y_child
= 0, height
= 0, pl_height
= 0;
2282 HashedProcessData
*hashed_process_data_child
= NULL
;
2284 ProcessList
*process_list
=
2285 guicontrolflow_get_process_list(control_flow_data
);
2288 /* Find child in the list... */
2289 process_child
= lttv_state_find_process(tfs
, child_pid
);
2290 /* It should exist, because we are after the state update. */
2291 g_assert(process_child
!= NULL
);
2293 birth
= process_child
->creation_time
;
2294 const gchar
*name
= g_quark_to_string(process_child
->name
);
2296 if(processlist_get_process_pixels(process_list
,
2298 process_child
->last_cpu
,
2300 tfc
->t_context
->index
,
2303 &hashed_process_data_child
) == 1)
2305 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
2306 /* Process not present */
2307 processlist_add(process_list
,
2309 process_child
->last_cpu
,
2310 process_child
->ppid
,
2312 tfc
->t_context
->index
,
2315 &hashed_process_data_child
);
2316 processlist_get_process_pixels(process_list
,
2318 process_child
->last_cpu
,
2320 tfc
->t_context
->index
,
2323 &hashed_process_data_child
);
2324 drawing_insert_square( control_flow_data
->drawing
, y_child
, height
);
2328 convert_time_to_pixels(
2329 time_window
.start_time
,
2334 hashed_process_data_child
->x
.over
= new_x
;
2335 hashed_process_data_child
->x
.middle
= new_x
;
2336 hashed_process_data_child
->x
.under
= new_x
;
2338 } else if(sub_id
== 3) { /* exit */
2340 /* Add process to process list (if not present) */
2341 LttvProcessState
*process
= tfs
->process
;
2342 guint pid
= process
->pid
;
2344 guint y
= 0, height
= 0, pl_height
= 0;
2345 HashedProcessData
*hashed_process_data
= NULL
;
2347 ProcessList
*process_list
=
2348 guicontrolflow_get_process_list(control_flow_data
);
2351 /* It should exist, because we are after the state update. */
2352 g_assert(process
!= NULL
);
2354 birth
= process
->creation_time
;
2355 const gchar
*name
= g_quark_to_string(process
->name
);
2357 if(processlist_get_process_pixels(process_list
,
2361 tfc
->t_context
->index
,
2364 &hashed_process_data
) == 1)
2366 g_assert(pid
== 0 || pid
!= process
->ppid
);
2367 /* Process not present */
2368 processlist_add(process_list
,
2373 tfc
->t_context
->index
,
2376 &hashed_process_data
);
2377 processlist_get_process_pixels(process_list
,
2381 tfc
->t_context
->index
,
2384 &hashed_process_data
);
2385 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
2389 convert_time_to_pixels(
2390 time_window
.start_time
,
2395 hashed_process_data
->x
.middle
= new_x
;
2402 gint
update_time_window_hook(void *hook_data
, void *call_data
)
2404 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2405 Drawing_t
*drawing
= control_flow_data
->drawing
;
2407 const TimeWindowNotifyData
*time_window_nofify_data
=
2408 ((const TimeWindowNotifyData
*)call_data
);
2410 TimeWindow
*old_time_window
=
2411 time_window_nofify_data
->old_time_window
;
2412 TimeWindow
*new_time_window
=
2413 time_window_nofify_data
->new_time_window
;
2415 /* Update the ruler */
2416 drawing_update_ruler(control_flow_data
->drawing
,
2420 /* Two cases : zoom in/out or scrolling */
2422 /* In order to make sure we can reuse the old drawing, the scale must
2423 * be the same and the new time interval being partly located in the
2424 * currently shown time interval. (reuse is only for scrolling)
2427 g_info("Old time window HOOK : %u, %u to %u, %u",
2428 old_time_window
->start_time
.tv_sec
,
2429 old_time_window
->start_time
.tv_nsec
,
2430 old_time_window
->time_width
.tv_sec
,
2431 old_time_window
->time_width
.tv_nsec
);
2433 g_info("New time window HOOK : %u, %u to %u, %u",
2434 new_time_window
->start_time
.tv_sec
,
2435 new_time_window
->start_time
.tv_nsec
,
2436 new_time_window
->time_width
.tv_sec
,
2437 new_time_window
->time_width
.tv_nsec
);
2439 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
2440 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
2442 /* Same scale (scrolling) */
2443 g_info("scrolling");
2444 LttTime
*ns
= &new_time_window
->start_time
;
2445 LttTime
*os
= &old_time_window
->start_time
;
2446 LttTime old_end
= ltt_time_add(old_time_window
->start_time
,
2447 old_time_window
->time_width
);
2448 LttTime new_end
= ltt_time_add(new_time_window
->start_time
,
2449 new_time_window
->time_width
);
2451 //if(ns<os+w && os+w<ns+w)
2452 //if(ns<old_end && os<ns)
2453 if(ltt_time_compare(*ns
, old_end
) == -1
2454 && ltt_time_compare(*os
, *ns
) == -1)
2456 g_info("scrolling near right");
2457 /* Scroll right, keep right part of the screen */
2459 guint width
= control_flow_data
->drawing
->width
;
2460 convert_time_to_pixels(
2467 /* Copy old data to new location */
2468 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
2469 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2470 control_flow_data
->drawing
->pixmap
,
2473 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
2475 if(drawing
->damage_begin
== drawing
->damage_end
)
2476 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
2478 drawing
->damage_begin
= 0;
2480 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2482 /* Clear the data request background, but not SAFETY */
2483 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2484 //control_flow_data->drawing->drawing_area->style->black_gc,
2485 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2487 drawing
->damage_begin
+SAFETY
, 0,
2488 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2489 control_flow_data
->drawing
->height
);
2491 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2493 control_flow_data
->drawing
->width
,
2494 control_flow_data
->drawing
->height
);
2496 /* Get new data for the rest. */
2497 drawing_data_request(control_flow_data
->drawing
,
2498 &control_flow_data
->drawing
->pixmap
,
2499 drawing
->damage_begin
, 0,
2500 drawing
->damage_end
- drawing
->damage_begin
,
2501 control_flow_data
->drawing
->height
);
2504 //if(ns<os && os<ns+w)
2505 //if(ns<os && os<new_end)
2506 if(ltt_time_compare(*ns
,*os
) == -1
2507 && ltt_time_compare(*os
,new_end
) == -1)
2509 g_info("scrolling near left");
2510 /* Scroll left, keep left part of the screen */
2512 guint width
= control_flow_data
->drawing
->width
;
2513 convert_time_to_pixels(
2521 /* Copy old data to new location */
2522 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
2523 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2524 control_flow_data
->drawing
->pixmap
,
2529 if(drawing
->damage_begin
== drawing
->damage_end
)
2530 drawing
->damage_end
= x
;
2532 drawing
->damage_end
=
2533 control_flow_data
->drawing
->width
;
2535 drawing
->damage_begin
= 0;
2537 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2538 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2540 drawing
->damage_begin
, 0,
2541 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
2542 control_flow_data
->drawing
->height
);
2544 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2546 control_flow_data
->drawing
->width
,
2547 control_flow_data
->drawing
->height
);
2550 /* Get new data for the rest. */
2551 drawing_data_request(control_flow_data
->drawing
,
2552 &control_flow_data
->drawing
->pixmap
,
2553 drawing
->damage_begin
, 0,
2554 drawing
->damage_end
- drawing
->damage_begin
,
2555 control_flow_data
->drawing
->height
);
2558 if(ltt_time_compare(*ns
,*os
) == 0)
2560 g_info("not scrolling");
2562 g_info("scrolling far");
2563 /* Cannot reuse any part of the screen : far jump */
2566 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2567 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2570 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2571 control_flow_data
->drawing
->height
);
2573 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2575 control_flow_data
->drawing
->width
,
2576 control_flow_data
->drawing
->height
);
2578 drawing
->damage_begin
= 0;
2579 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2581 drawing_data_request(control_flow_data
->drawing
,
2582 &control_flow_data
->drawing
->pixmap
,
2584 control_flow_data
->drawing
->width
,
2585 control_flow_data
->drawing
->height
);
2591 /* Different scale (zoom) */
2594 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
2595 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
2598 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
2599 control_flow_data
->drawing
->height
);
2601 gtk_widget_queue_draw_area (drawing
->drawing_area
,
2603 control_flow_data
->drawing
->width
,
2604 control_flow_data
->drawing
->height
);
2606 drawing
->damage_begin
= 0;
2607 drawing
->damage_end
= control_flow_data
->drawing
->width
;
2609 drawing_data_request(control_flow_data
->drawing
,
2610 &control_flow_data
->drawing
->pixmap
,
2612 control_flow_data
->drawing
->width
,
2613 control_flow_data
->drawing
->height
);
2621 gint
traceset_notify(void *hook_data
, void *call_data
)
2623 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2624 Drawing_t
*drawing
= control_flow_data
->drawing
;
2625 GtkWidget
*widget
= drawing
->drawing_area
;
2628 drawing_clear(control_flow_data
->drawing
);
2629 processlist_clear(control_flow_data
->process_list
);
2630 redraw_notify(control_flow_data
, NULL
);
2632 request_background_data(control_flow_data
);
2634 drawing
->damage_begin
= 0;
2635 drawing
->damage_end
= drawing
->width
;
2636 if(drawing
->damage_begin
< drawing
->damage_end
)
2638 drawing_data_request(drawing
,
2640 drawing
->damage_begin
,
2642 drawing
->damage_end
-drawing
->damage_begin
,
2646 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2655 gint
redraw_notify(void *hook_data
, void *call_data
)
2657 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2658 Drawing_t
*drawing
= control_flow_data
->drawing
;
2659 GtkWidget
*widget
= drawing
->drawing_area
;
2661 drawing
->damage_begin
= 0;
2662 drawing
->damage_end
= drawing
->width
;
2664 /* fun feature, to be separated someday... */
2665 drawing_clear(control_flow_data
->drawing
);
2666 processlist_clear(control_flow_data
->process_list
);
2669 gdk_draw_rectangle (drawing
->pixmap
,
2670 widget
->style
->black_gc
,
2673 drawing
->width
+SAFETY
,
2677 if(drawing
->damage_begin
< drawing
->damage_end
)
2679 drawing_data_request(drawing
,
2681 drawing
->damage_begin
,
2683 drawing
->damage_end
-drawing
->damage_begin
,
2687 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2696 gint
continue_notify(void *hook_data
, void *call_data
)
2698 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
2699 Drawing_t
*drawing
= control_flow_data
->drawing
;
2700 GtkWidget
*widget
= drawing
->drawing_area
;
2702 //g_assert(widget->allocation.width == drawing->damage_end);
2704 if(drawing
->damage_begin
< drawing
->damage_end
)
2706 drawing_data_request(drawing
,
2708 drawing
->damage_begin
,
2710 drawing
->damage_end
-drawing
->damage_begin
,
2718 gint
update_current_time_hook(void *hook_data
, void *call_data
)
2720 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
2721 Drawing_t
*drawing
= control_flow_data
->drawing
;
2723 LttTime current_time
= *((LttTime
*)call_data
);
2725 TimeWindow time_window
=
2726 lttvwindow_get_time_window(control_flow_data
->tab
);
2728 LttTime time_begin
= time_window
.start_time
;
2729 LttTime width
= time_window
.time_width
;
2732 guint64 time_ll
= ltt_time_to_uint64(width
);
2733 time_ll
= time_ll
>> 1; /* divide by two */
2734 half_width
= ltt_time_from_uint64(time_ll
);
2736 LttTime time_end
= ltt_time_add(time_begin
, width
);
2738 LttvTracesetContext
* tsc
=
2739 lttvwindow_get_traceset_context(control_flow_data
->tab
);
2741 LttTime trace_start
= tsc
->time_span
.start_time
;
2742 LttTime trace_end
= tsc
->time_span
.end_time
;
2744 g_info("New current time HOOK : %u, %u", current_time
.tv_sec
,
2745 current_time
.tv_nsec
);
2749 /* If current time is inside time interval, just move the highlight
2752 /* Else, we have to change the time interval. We have to tell it
2753 * to the main window. */
2754 /* The time interval change will take care of placing the current
2755 * time at the center of the visible area, or nearest possible if we are
2756 * at one end of the trace. */
2759 if(ltt_time_compare(current_time
, time_begin
) == -1)
2761 TimeWindow new_time_window
;
2763 if(ltt_time_compare(current_time
,
2764 ltt_time_add(trace_start
,half_width
)) == -1)
2765 time_begin
= trace_start
;
2767 time_begin
= ltt_time_sub(current_time
,half_width
);
2769 new_time_window
.start_time
= time_begin
;
2770 new_time_window
.time_width
= width
;
2772 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2774 else if(ltt_time_compare(current_time
, time_end
) == 1)
2776 TimeWindow new_time_window
;
2778 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) == 1)
2779 time_begin
= ltt_time_sub(trace_end
,width
);
2781 time_begin
= ltt_time_sub(current_time
,half_width
);
2783 new_time_window
.start_time
= time_begin
;
2784 new_time_window
.time_width
= width
;
2786 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
2789 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2790 gtk_widget_queue_draw_area(drawing
->drawing_area
,
2798 typedef struct _ClosureData
{
2799 EventsRequest
*events_request
;
2800 LttvTracesetState
*tss
;
2805 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
2807 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
2808 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
2809 ClosureData
*closure_data
= (ClosureData
*)user_data
;
2811 EventsRequest
*events_request
= closure_data
->events_request
;
2812 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2813 Drawing_t
*drawing
= control_flow_data
->drawing
;
2815 LttvTracesetState
*tss
= closure_data
->tss
;
2816 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)closure_data
->tss
;
2818 LttTime evtime
= closure_data
->end_time
;
2819 TimeWindow time_window
=
2820 lttvwindow_get_time_window(control_flow_data
->tab
);
2822 LttTime end_time
= ltt_time_add(time_window
.start_time
,
2823 time_window
.time_width
);
2825 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2826 || ltt_time_compare(evtime
, end_time
) == 1)
2829 guint width
= drawing
->width
;
2832 /* For the process */
2833 /* First, check if the current process is in the state computation
2834 * process list. If it is there, that means we must add it right now and
2835 * draw items from the beginning of the read for it. If it is not
2836 * present, it's a new process and it was not present : it will
2837 * be added after the state update. */
2838 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
2840 /* tracefiles[0] is ok here, because we draw for every PID, and
2841 * assume CPU 0 for PID 0 //FIXME */
2842 LttvTracefileState
*tfs
=
2843 (LttvTracefileState
*)tsc
->traces
[process_info
->trace_num
]->tracefiles
[0];
2845 LttvProcessState
*process
;
2846 process
= lttv_state_find_process(tfs
,
2849 if(process
!= NULL
) {
2851 /* Only draw for processes that are currently in the trace states */
2853 guint y
= 0, height
= 0, pl_height
= 0;
2854 ProcessList
*process_list
=
2855 guicontrolflow_get_process_list(control_flow_data
);
2856 LttTime birth
= process_info
->birth
;
2858 /* Should be alike when background info is ready */
2859 if(control_flow_data
->background_info_waiting
==0)
2860 g_assert(ltt_time_compare(process
->creation_time
,
2861 process_info
->birth
) == 0);
2862 const gchar
*name
= g_quark_to_string(process
->name
);
2864 /* process HAS to be present */
2865 g_assert(processlist_get_process_pixels(process_list
,
2869 process_info
->trace_num
,
2872 &hashed_process_data
) != 1);
2874 /* Now, the process is in the state hash and our own process hash.
2875 * We definitely can draw the items related to the ending state.
2878 /* Check if the x position is unset. In can have been left unset by
2879 * a draw closure from a after chunk hook. This should never happen,
2880 * because it must be set by before chunk hook to the damage_begin
2883 g_assert(hashed_process_data
->x
.over
!= -1);
2887 convert_time_to_pixels(
2888 time_window
.start_time
,
2894 DrawContext draw_context
;
2896 /* Now create the drawing context that will be used to draw
2897 * items related to the last state. */
2898 draw_context
.drawable
= drawing
->pixmap
;
2899 draw_context
.gc
= drawing
->gc
;
2900 draw_context
.pango_layout
= drawing
->pango_layout
;
2901 draw_context
.drawinfo
.end
.x
= x
;
2903 draw_context
.drawinfo
.y
.over
= y
+1;
2904 draw_context
.drawinfo
.y
.middle
= y
+(height
/2);
2905 draw_context
.drawinfo
.y
.under
= y
+height
;
2907 draw_context
.drawinfo
.start
.offset
.over
= 0;
2908 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2909 draw_context
.drawinfo
.start
.offset
.under
= 0;
2910 draw_context
.drawinfo
.end
.offset
.over
= 0;
2911 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2912 draw_context
.drawinfo
.end
.offset
.under
= 0;
2914 /* Jump over draw if we are at the same x position */
2915 if(x
== hashed_process_data
->x
.over
)
2919 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
2921 PropertiesLine prop_line
= prepare_execmode_line(process
);
2922 draw_line((void*)&prop_line
, (void*)&draw_context
);
2924 hashed_process_data
->x
.over
= x
;
2927 if(x
== hashed_process_data
->x
.middle
) {
2930 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2932 PropertiesLine prop_line
= prepare_status_line(process
);
2933 draw_line((void*)&prop_line
, (void*)&draw_context
);
2935 /* become the last x position */
2936 hashed_process_data
->x
.middle
= x
;
2944 int before_chunk(void *hook_data
, void *call_data
)
2946 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2947 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2949 drawing_chunk_begin(events_request
, tss
);
2954 int before_request(void *hook_data
, void *call_data
)
2956 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2957 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2959 drawing_data_request_begin(events_request
, tss
);
2966 * after request is necessary in addition of after chunk in order to draw
2967 * lines until the end of the screen. after chunk just draws lines until
2974 int after_request(void *hook_data
, void *call_data
)
2976 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
2977 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2978 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
2979 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(call_data
);
2981 ProcessList
*process_list
=
2982 guicontrolflow_get_process_list(control_flow_data
);
2983 LttTime end_time
= events_request
->end_time
;
2985 ClosureData closure_data
;
2986 closure_data
.events_request
= (EventsRequest
*)hook_data
;
2987 closure_data
.tss
= tss
;
2988 closure_data
.end_time
= end_time
;
2990 /* Draw last items */
2991 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
2992 (void*)&closure_data
);
2994 /* Request expose */
2995 drawing_request_expose(events_request
, tss
, end_time
);
3004 int after_chunk(void *hook_data
, void *call_data
)
3006 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
3007 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3008 LttvTracesetState
*tss
= LTTV_TRACESET_STATE(call_data
);
3009 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(call_data
);
3010 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
3013 ProcessList
*process_list
=
3014 guicontrolflow_get_process_list(control_flow_data
);
3017 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
3018 else /* end of traceset, or position now out of request : end */
3019 end_time
= events_request
->end_time
;
3021 ClosureData closure_data
;
3022 closure_data
.events_request
= (EventsRequest
*)hook_data
;
3023 closure_data
.tss
= tss
;
3024 closure_data
.end_time
= end_time
;
3026 /* Draw last items */
3027 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
3028 (void*)&closure_data
);
3030 /* Request expose */
3031 drawing_request_expose(events_request
, tss
, end_time
);