1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
25 /* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
52 //#define PANGO_ENABLE_BACKEND
60 //#include <pango/pango.h>
62 #include <ltt/event.h>
65 #include <ltt/trace.h>
67 #include <lttv/lttv.h>
68 #include <lttv/hook.h>
69 #include <lttv/state.h>
70 #include <lttvwindow/lttvwindow.h>
71 #include <lttvwindow/lttvwindowtraces.h>
74 #include "eventhooks.h"
76 #include "processlist.h"
80 #define MAX_PATH_LEN 256
83 typedef struct _ProcessAddClosure
{
88 static void process_add(gpointer key
,
92 LttvProcessState
*process
= (LttvProcessState
*)value
;
93 ProcessAddClosure
*closure
= (ProcessAddClosure
*)user_data
;
94 ControlFlowData
*control_flow_data
= closure
->cfd
;
95 guint trace_num
= closure
->trace_num
;
97 /* Add process to process list (if not present) */
100 guint y
= 0, height
= 0, pl_height
= 0;
102 ProcessList
*process_list
= control_flow_data
->process_list
;
105 birth
= process
->creation_time
;
106 const gchar
*name
= g_quark_to_string(process
->name
);
107 HashedProcessData
*hashed_process_data
= NULL
;
109 if(processlist_get_process_pixels(process_list
,
115 &hashed_process_data
) == 1)
117 /* Process not present */
118 processlist_add(process_list
,
124 &hashed_process_data
);
125 processlist_get_process_pixels(process_list
,
131 &hashed_process_data
);
132 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
138 /* Action to do when background computation completed.
140 * Wait for all the awaited computations to be over.
143 gint
background_ready(void *hook_data
, void *call_data
)
145 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
146 LttvTrace
*trace
= (LttvTrace
*)call_data
;
148 control_flow_data
->background_info_waiting
--;
150 if(control_flow_data
->background_info_waiting
== 0) {
151 g_debug("control flow viewer : background computation data ready.");
153 drawing_clear(control_flow_data
->drawing
);
154 processlist_clear(control_flow_data
->process_list
);
155 gtk_widget_set_size_request(
156 control_flow_data
->drawing
->drawing_area
,
157 -1, processlist_get_height(control_flow_data
->process_list
));
158 redraw_notify(control_flow_data
, NULL
);
165 /* Request background computation. Verify if it is in progress or ready first.
166 * Only for each trace in the tab's traceset.
168 void request_background_data(ControlFlowData
*control_flow_data
)
170 LttvTracesetContext
* tsc
=
171 lttvwindow_get_traceset_context(control_flow_data
->tab
);
172 gint num_traces
= lttv_traceset_number(tsc
->ts
);
176 LttvHooks
*background_ready_hook
=
178 lttv_hooks_add(background_ready_hook
, background_ready
, control_flow_data
,
180 control_flow_data
->background_info_waiting
= 0;
182 for(i
=0;i
<num_traces
;i
++) {
183 trace
= lttv_traceset_get(tsc
->ts
, i
);
185 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
) {
187 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
189 /* We first remove requests that could have been done for the same
190 * information. Happens when two viewers ask for it before servicing
193 lttvwindowtraces_background_request_remove(trace
, "state");
194 lttvwindowtraces_background_request_queue(trace
,
196 lttvwindowtraces_background_notify_queue(control_flow_data
,
200 background_ready_hook
);
201 control_flow_data
->background_info_waiting
++;
202 } else { /* in progress */
204 lttvwindowtraces_background_notify_current(control_flow_data
,
208 background_ready_hook
);
209 control_flow_data
->background_info_waiting
++;
212 /* Data ready. Be its nature, this viewer doesn't need to have
213 * its data ready hook called htere, because a background
214 * request is always linked with a redraw.
220 lttv_hooks_destroy(background_ready_hook
);
227 * Event Viewer's constructor hook
229 * This constructor is given as a parameter to the menuitem and toolbar button
230 * registration. It creates the list.
231 * @param tab A pointer to the parent tab.
232 * @return The widget created.
235 h_guicontrolflow(Tab
*tab
)
237 g_info("h_guicontrolflow, %p", tab
);
238 ControlFlowData
*control_flow_data
= guicontrolflow() ;
240 control_flow_data
->tab
= tab
;
242 // Unreg done in the GuiControlFlow_Destructor
243 lttvwindow_register_traceset_notify(tab
,
247 lttvwindow_register_time_window_notify(tab
,
248 update_time_window_hook
,
250 lttvwindow_register_current_time_notify(tab
,
251 update_current_time_hook
,
253 lttvwindow_register_redraw_notify(tab
,
256 lttvwindow_register_continue_notify(tab
,
259 request_background_data(control_flow_data
);
262 return guicontrolflow_get_widget(control_flow_data
) ;
266 int event_selected_hook(void *hook_data
, void *call_data
)
268 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
269 guint
*event_number
= (guint
*) call_data
;
271 g_debug("DEBUG : event selected by main window : %u", *event_number
);
276 /* Function that selects the color of status&exemode line */
277 static inline PropertiesLine
prepare_s_e_line(LttvProcessState
*process
)
279 PropertiesLine prop_line
;
280 prop_line
.line_width
= 2;
281 prop_line
.style
= GDK_LINE_SOLID
;
282 prop_line
.y
= MIDDLE
;
283 //GdkColormap *colormap = gdk_colormap_get_system();
285 if(process
->state
->s
== LTTV_STATE_RUN
) {
286 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
287 prop_line
.color
= drawing_colors
[COL_RUN_USER_MODE
];
288 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
289 prop_line
.color
= drawing_colors
[COL_RUN_SYSCALL
];
290 else if(process
->state
->t
== LTTV_STATE_TRAP
)
291 prop_line
.color
= drawing_colors
[COL_RUN_TRAP
];
292 else if(process
->state
->t
== LTTV_STATE_IRQ
)
293 prop_line
.color
= drawing_colors
[COL_RUN_IRQ
];
294 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
295 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
297 g_assert(FALSE
); /* RUNNING MODE UNKNOWN */
298 } else if(process
->state
->s
== LTTV_STATE_WAIT
) {
299 /* We don't show if we wait while in user mode, trap, irq or syscall */
300 prop_line
.color
= drawing_colors
[COL_WAIT
];
301 } else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
) {
302 /* We don't show if we wait for CPU while in user mode, trap, irq
304 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
305 } else if(process
->state
->s
== LTTV_STATE_ZOMBIE
) {
306 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
307 } else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
) {
308 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
309 } else if(process
->state
->s
== LTTV_STATE_EXIT
) {
310 prop_line
.color
= drawing_colors
[COL_EXIT
];
311 } else if(process
->state
->s
== LTTV_STATE_UNNAMED
) {
312 prop_line
.color
= drawing_colors
[COL_UNNAMED
];
314 g_assert(FALSE
); /* UNKNOWN STATE */
321 static inline PropertiesLine
prepare_status_line(LttvProcessState
*process
)
323 PropertiesLine prop_line
;
324 prop_line
.line_width
= 2;
325 prop_line
.style
= GDK_LINE_SOLID
;
326 prop_line
.y
= MIDDLE
;
327 //GdkColormap *colormap = gdk_colormap_get_system();
329 g_debug("prepare_status_line for state : %s",
330 g_quark_to_string(process
->state
->s
));
332 /* color of line : status of the process */
333 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
334 prop_line
.color
= drawing_colors
[COL_WHITE
];
335 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
336 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
337 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
338 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
339 else if(process
->state
->s
== LTTV_STATE_EXIT
)
340 prop_line
.color
= drawing_colors
[COL_EXIT
];
341 else if(process
->state
->s
== LTTV_STATE_ZOMBIE
)
342 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
343 else if(process
->state
->s
== LTTV_STATE_WAIT
)
344 prop_line
.color
= drawing_colors
[COL_WAIT
];
345 else if(process
->state
->s
== LTTV_STATE_RUN
)
346 prop_line
.color
= drawing_colors
[COL_RUN
];
348 prop_line
.color
= drawing_colors
[COL_WHITE
];
350 //gdk_colormap_alloc_color(colormap,
361 /* before_schedchange_hook
363 * This function basically draw lines and icons. Two types of lines are drawn :
364 * one small (3 pixels?) representing the state of the process and the second
365 * type is thicker (10 pixels?) representing on which CPU a process is running
366 * (and this only in running state).
368 * Extremums of the lines :
369 * x_min : time of the last event context for this process kept in memory.
370 * x_max : time of the current event.
371 * y : middle of the process in the process list. The process is found in the
372 * list, therefore is it's position in pixels.
374 * The choice of lines'color is defined by the context of the last event for this
379 int before_schedchange_hook(void *hook_data
, void *call_data
)
381 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
382 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
383 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
385 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
387 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
388 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
391 e
= ltt_tracefile_get_event(tfc
->tf
);
393 LttTime evtime
= ltt_event_time(e
);
395 /* we are in a schedchange, before the state update. We must draw the
396 * items corresponding to the state before it changes : now is the right
403 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
404 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
408 /* For the pid_out */
409 /* First, check if the current process is in the state computation
410 * process list. If it is there, that means we must add it right now and
411 * draw items from the beginning of the read for it. If it is not
412 * present, it's a new process and it was not present : it will
413 * be added after the state update. */
414 guint cpu
= ltt_tracefile_num(tfc
->tf
);
415 LttvProcessState
*process
= ts
->running_process
[cpu
];
416 /* unknown state, bad current pid */
417 if(process
->pid
!= pid_out
)
418 process
= lttv_state_find_process(ts
, ANY_CPU
, pid_out
);
420 if(process
!= NULL
) {
421 /* Well, the process_out existed : we must get it in the process hash
422 * or add it, and draw its items.
424 /* Add process to process list (if not present) */
426 HashedProcessData
*hashed_process_data
= NULL
;
427 ProcessList
*process_list
= control_flow_data
->process_list
;
428 LttTime birth
= process
->creation_time
;
430 hashed_process_data
= processlist_get_process_data(process_list
,
434 tfc
->t_context
->index
);
435 if(hashed_process_data
== NULL
)
437 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
438 /* Process not present */
439 ProcessInfo
*process_info
;
440 Drawing_t
*drawing
= control_flow_data
->drawing
;
441 processlist_add(process_list
,
447 tfc
->t_context
->index
,
451 &hashed_process_data
);
452 gtk_widget_set_size_request(drawing
->drawing_area
,
455 gtk_widget_queue_draw(drawing
->drawing_area
);
459 /* Now, the process is in the state hash and our own process hash.
460 * We definitely can draw the items related to the ending state.
463 if(ltt_time_compare(hashed_process_data
->next_good_time
,
466 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
468 TimeWindow time_window
=
469 lttvwindow_get_time_window(control_flow_data
->tab
);
471 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
472 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
475 Drawing_t
*drawing
= control_flow_data
->drawing
;
476 guint width
= drawing
->width
;
478 convert_time_to_pixels(
484 /* Draw collision indicator */
485 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
486 gdk_draw_point(hashed_process_data
->pixmap
,
489 (hashed_process_data
->height
/2)-3);
490 hashed_process_data
->x
.middle_marked
= TRUE
;
493 TimeWindow time_window
=
494 lttvwindow_get_time_window(control_flow_data
->tab
);
496 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
497 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
500 Drawing_t
*drawing
= control_flow_data
->drawing
;
501 guint width
= drawing
->width
;
503 convert_time_to_pixels(
510 /* Jump over draw if we are at the same x position */
511 if(x
== hashed_process_data
->x
.middle
&&
512 hashed_process_data
->x
.middle_used
)
514 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
515 /* Draw collision indicator */
516 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
517 gdk_draw_point(hashed_process_data
->pixmap
,
520 (hashed_process_data
->height
/2)-3);
521 hashed_process_data
->x
.middle_marked
= TRUE
;
525 DrawContext draw_context
;
527 /* Now create the drawing context that will be used to draw
528 * items related to the last state. */
529 draw_context
.drawable
= hashed_process_data
->pixmap
;
530 draw_context
.gc
= drawing
->gc
;
531 draw_context
.pango_layout
= drawing
->pango_layout
;
532 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
533 draw_context
.drawinfo
.end
.x
= x
;
535 draw_context
.drawinfo
.y
.over
= 1;
536 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
537 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
539 draw_context
.drawinfo
.start
.offset
.over
= 0;
540 draw_context
.drawinfo
.start
.offset
.middle
= 0;
541 draw_context
.drawinfo
.start
.offset
.under
= 0;
542 draw_context
.drawinfo
.end
.offset
.over
= 0;
543 draw_context
.drawinfo
.end
.offset
.middle
= 0;
544 draw_context
.drawinfo
.end
.offset
.under
= 0;
548 PropertiesLine prop_line
= prepare_s_e_line(process
);
549 draw_line((void*)&prop_line
, (void*)&draw_context
);
552 /* become the last x position */
553 hashed_process_data
->x
.middle
= x
;
554 hashed_process_data
->x
.middle_used
= TRUE
;
555 hashed_process_data
->x
.middle_marked
= FALSE
;
557 /* Calculate the next good time */
558 convert_pixels_to_time(width
, x
+1, time_window
,
559 &hashed_process_data
->next_good_time
);
567 /* First, check if the current process is in the state computation
568 * process list. If it is there, that means we must add it right now and
569 * draw items from the beginning of the read for it. If it is not
570 * present, it's a new process and it was not present : it will
571 * be added after the state update. */
572 LttvProcessState
*process
;
573 process
= lttv_state_find_process(ts
, ANY_CPU
, pid_in
);
575 if(process
!= NULL
) {
576 /* Well, the process_out existed : we must get it in the process hash
577 * or add it, and draw its items.
579 /* Add process to process list (if not present) */
581 HashedProcessData
*hashed_process_data
= NULL
;
582 ProcessList
*process_list
= control_flow_data
->process_list
;
583 LttTime birth
= process
->creation_time
;
585 hashed_process_data
= processlist_get_process_data(process_list
,
589 tfc
->t_context
->index
);
590 if(hashed_process_data
== NULL
)
592 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
593 /* Process not present */
594 ProcessInfo
*process_info
;
595 Drawing_t
*drawing
= control_flow_data
->drawing
;
596 processlist_add(process_list
,
602 tfc
->t_context
->index
,
606 &hashed_process_data
);
607 gtk_widget_set_size_request(drawing
->drawing_area
,
610 gtk_widget_queue_draw(drawing
->drawing_area
);
613 //We could set the current process and hash here, but will be done
614 //by after schedchange hook
616 /* Now, the process is in the state hash and our own process hash.
617 * We definitely can draw the items related to the ending state.
620 if(ltt_time_compare(hashed_process_data
->next_good_time
,
623 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
625 TimeWindow time_window
=
626 lttvwindow_get_time_window(control_flow_data
->tab
);
628 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
629 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
632 Drawing_t
*drawing
= control_flow_data
->drawing
;
633 guint width
= drawing
->width
;
635 convert_time_to_pixels(
641 /* Draw collision indicator */
642 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
643 gdk_draw_point(hashed_process_data
->pixmap
,
646 (hashed_process_data
->height
/2)-3);
647 hashed_process_data
->x
.middle_marked
= TRUE
;
650 TimeWindow time_window
=
651 lttvwindow_get_time_window(control_flow_data
->tab
);
653 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
654 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
657 Drawing_t
*drawing
= control_flow_data
->drawing
;
658 guint width
= drawing
->width
;
661 convert_time_to_pixels(
668 /* Jump over draw if we are at the same x position */
669 if(x
== hashed_process_data
->x
.middle
&&
670 hashed_process_data
->x
.middle_used
)
672 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
673 /* Draw collision indicator */
674 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
675 gdk_draw_point(hashed_process_data
->pixmap
,
678 (hashed_process_data
->height
/2)-3);
679 hashed_process_data
->x
.middle_marked
= TRUE
;
683 DrawContext draw_context
;
685 /* Now create the drawing context that will be used to draw
686 * items related to the last state. */
687 draw_context
.drawable
= hashed_process_data
->pixmap
;
688 draw_context
.gc
= drawing
->gc
;
689 draw_context
.pango_layout
= drawing
->pango_layout
;
690 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
691 draw_context
.drawinfo
.end
.x
= x
;
693 draw_context
.drawinfo
.y
.over
= 1;
694 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
695 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
697 draw_context
.drawinfo
.start
.offset
.over
= 0;
698 draw_context
.drawinfo
.start
.offset
.middle
= 0;
699 draw_context
.drawinfo
.start
.offset
.under
= 0;
700 draw_context
.drawinfo
.end
.offset
.over
= 0;
701 draw_context
.drawinfo
.end
.offset
.middle
= 0;
702 draw_context
.drawinfo
.end
.offset
.under
= 0;
706 PropertiesLine prop_line
= prepare_s_e_line(process
);
707 draw_line((void*)&prop_line
, (void*)&draw_context
);
711 /* become the last x position */
712 hashed_process_data
->x
.middle
= x
;
713 hashed_process_data
->x
.middle_used
= TRUE
;
714 hashed_process_data
->x
.middle_marked
= FALSE
;
716 /* Calculate the next good time */
717 convert_pixels_to_time(width
, x
+1, time_window
,
718 &hashed_process_data
->next_good_time
);
727 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
728 ControlFlowData
*control_flow_data
=
729 (ControlFlowData
*)events_request
->viewer_data
;
730 Tab
*tab
= control_flow_data
->tab
;
732 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
734 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
735 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
740 LttTime evtime
= ltt_event_time(e
);
741 TimeWindow time_window
=
742 lttvwindow_get_time_window(tab
);
744 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
746 //if(time < time_beg || time > time_end) return;
747 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
748 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
751 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
753 g_debug("schedchange!");
755 /* Add process to process list (if not present) and get drawing "y" from
756 * process position */
757 guint pid_out
, pid_in
;
758 LttvProcessState
*process_out
, *process_in
;
760 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
762 ProcessList
*process_list
= control_flow_data
->process_list
;
765 LttField
*f
= ltt_event_field(e
);
767 element
= ltt_field_member(f
,0);
768 pid_out
= ltt_event_get_long_unsigned(e
,element
);
769 element
= ltt_field_member(f
,1);
770 pid_in
= ltt_event_get_long_unsigned(e
,element
);
771 g_debug("out : %u in : %u", pid_out
, pid_in
);
774 /* Find process pid_out in the list... */
775 process_out
= lttv_state_find_process(tfs
, pid_out
);
776 if(process_out
== NULL
) return 0;
777 g_debug("out : %s",g_quark_to_string(process_out
->state
->s
));
779 birth
= process_out
->creation_time
;
780 const gchar
*name
= g_quark_to_string(process_out
->name
);
781 HashedProcessData
*hashed_process_data_out
= NULL
;
783 if(processlist_get_process_pixels(process_list
,
786 tfc
->t_context
->index
,
789 &hashed_process_data_out
) == 1)
791 /* Process not present */
792 processlist_add(process_list
,
795 tfc
->t_context
->index
,
798 &hashed_process_data_out
);
799 g_assert(processlist_get_process_pixels(process_list
,
802 tfc
->t_context
->index
,
805 &hashed_process_data_out
)==0);
806 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
810 /* Find process pid_in in the list... */
811 process_in
= lttv_state_find_process(tfs
, pid_in
);
812 if(process_in
== NULL
) return 0;
813 g_debug("in : %s",g_quark_to_string(process_in
->state
->s
));
815 birth
= process_in
->creation_time
;
816 name
= g_quark_to_string(process_in
->name
);
817 HashedProcessData
*hashed_process_data_in
= NULL
;
819 if(processlist_get_process_pixels(process_list
,
822 tfc
->t_context
->index
,
825 &hashed_process_data_in
) == 1)
827 /* Process not present */
828 processlist_add(process_list
,
831 tfc
->t_context
->index
,
834 &hashed_process_data_in
);
835 processlist_get_process_pixels(process_list
,
838 tfc
->t_context
->index
,
841 &hashed_process_data_in
);
843 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
848 /* Find pixels corresponding to time of the event. If the time does
849 * not fit in the window, show a warning, not supposed to happend. */
851 guint width
= control_flow_data
->drawing
->width
;
853 LttTime time
= ltt_event_time(e
);
855 LttTime window_end
= time_window
.time_window
.end_time
;
857 convert_time_to_pixels(
862 //assert(x <= width);
864 /* draw what represents the event for outgoing process. */
866 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
867 draw_context_out
->current
->modify_over
->x
= x
;
868 draw_context_out
->current
->modify_under
->x
= x
;
869 draw_context_out
->current
->modify_over
->y
= y_out
;
870 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
871 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
872 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
873 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
874 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
875 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
876 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
877 //draw_context_out->gc = widget->style->black_gc;
879 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
880 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
882 /* Draw the line/background of the out process */
883 if(draw_context_out
->previous
->middle
->x
== -1)
885 draw_context_out
->previous
->over
->x
=
886 control_flow_data
->drawing
->damage_begin
;
887 draw_context_out
->previous
->middle
->x
=
888 control_flow_data
->drawing
->damage_begin
;
889 draw_context_out
->previous
->under
->x
=
890 control_flow_data
->drawing
->damage_begin
;
891 g_debug("out middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
894 draw_context_out
->current
->middle
->x
= x
;
895 draw_context_out
->current
->over
->x
= x
;
896 draw_context_out
->current
->under
->x
= x
;
897 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
898 draw_context_out
->current
->over
->y
= y_out
;
899 draw_context_out
->current
->under
->y
= y_out
+ height
;
900 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
901 draw_context_out
->previous
->over
->y
= y_out
;
902 draw_context_out
->previous
->under
->y
= y_out
+ height
;
904 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
905 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
907 if(process_out
->state
->s
== LTTV_STATE_RUN
)
909 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
910 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
911 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
913 PropertiesBG prop_bg
;
914 prop_bg
.color
= g_new(GdkColor
,1);
916 switch(ltt_tracefile_num(tfc
->tf
)) {
918 prop_bg
.color
->red
= 0x1515;
919 prop_bg
.color
->green
= 0x1515;
920 prop_bg
.color
->blue
= 0x8c8c;
923 prop_bg
.color
->red
= 0x4e4e;
924 prop_bg
.color
->green
= 0xa9a9;
925 prop_bg
.color
->blue
= 0xa4a4;
928 prop_bg
.color
->red
= 0x7a7a;
929 prop_bg
.color
->green
= 0x4a4a;
930 prop_bg
.color
->blue
= 0x8b8b;
933 prop_bg
.color
->red
= 0x8080;
934 prop_bg
.color
->green
= 0x7777;
935 prop_bg
.color
->blue
= 0x4747;
938 prop_bg
.color
->red
= 0xe7e7;
939 prop_bg
.color
->green
= 0xe7e7;
940 prop_bg
.color
->blue
= 0xe7e7;
943 g_debug("calling from draw_event");
944 draw_bg((void*)&prop_bg
, (void*)draw_context_out
);
945 g_free(prop_bg
.color
);
946 //gdk_gc_unref(draw_context_out->gc);
949 draw_context_out
->gc
= widget
->style
->black_gc
;
951 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
952 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
953 PropertiesText prop_text_out
;
954 prop_text_out
.foreground
= &colorfg_out
;
955 prop_text_out
.background
= &colorbg_out
;
956 prop_text_out
.size
= 6;
957 prop_text_out
.position
= OVER
;
959 /* color of text : status of the process */
960 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
962 prop_text_out
.foreground
->red
= 0xffff;
963 prop_text_out
.foreground
->green
= 0xffff;
964 prop_text_out
.foreground
->blue
= 0xffff;
966 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
968 prop_text_out
.foreground
->red
= 0x0fff;
969 prop_text_out
.foreground
->green
= 0xffff;
970 prop_text_out
.foreground
->blue
= 0xfff0;
972 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
974 prop_text_out
.foreground
->red
= 0xffff;
975 prop_text_out
.foreground
->green
= 0xffff;
976 prop_text_out
.foreground
->blue
= 0x0000;
978 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
980 prop_text_out
.foreground
->red
= 0xffff;
981 prop_text_out
.foreground
->green
= 0x0000;
982 prop_text_out
.foreground
->blue
= 0xffff;
984 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
986 prop_text_out
.foreground
->red
= 0xffff;
987 prop_text_out
.foreground
->green
= 0x0000;
988 prop_text_out
.foreground
->blue
= 0x0000;
990 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
992 prop_text_out
.foreground
->red
= 0x0000;
993 prop_text_out
.foreground
->green
= 0xffff;
994 prop_text_out
.foreground
->blue
= 0x0000;
998 prop_text_out
.foreground
->red
= 0xffff;
999 prop_text_out
.foreground
->green
= 0xffff;
1000 prop_text_out
.foreground
->blue
= 0xffff;
1004 /* Print status of the process : U, WF, WC, E, W, R */
1005 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1006 prop_text_out
.text
= "U->";
1007 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1008 prop_text_out
.text
= "WF->";
1009 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1010 prop_text_out
.text
= "WC->";
1011 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1012 prop_text_out
.text
= "E->";
1013 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1014 prop_text_out
.text
= "W->";
1015 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1016 prop_text_out
.text
= "R->";
1018 prop_text_out
.text
= "U";
1020 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1021 //gdk_gc_unref(draw_context_out->gc);
1023 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1024 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1025 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
1027 PropertiesLine prop_line_out
;
1028 prop_line_out
.color
= g_new(GdkColor
,1);
1029 prop_line_out
.line_width
= 2;
1030 prop_line_out
.style
= GDK_LINE_SOLID
;
1031 prop_line_out
.position
= MIDDLE
;
1033 g_debug("out state : %s", g_quark_to_string(process_out
->state
->s
));
1035 /* color of line : status of the process */
1036 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1038 prop_line_out
.color
->red
= 0xffff;
1039 prop_line_out
.color
->green
= 0xffff;
1040 prop_line_out
.color
->blue
= 0xffff;
1042 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1044 prop_line_out
.color
->red
= 0x0fff;
1045 prop_line_out
.color
->green
= 0xffff;
1046 prop_line_out
.color
->blue
= 0xfff0;
1048 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1050 prop_line_out
.color
->red
= 0xffff;
1051 prop_line_out
.color
->green
= 0xffff;
1052 prop_line_out
.color
->blue
= 0x0000;
1054 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1056 prop_line_out
.color
->red
= 0xffff;
1057 prop_line_out
.color
->green
= 0x0000;
1058 prop_line_out
.color
->blue
= 0xffff;
1060 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1062 prop_line_out
.color
->red
= 0xffff;
1063 prop_line_out
.color
->green
= 0x0000;
1064 prop_line_out
.color
->blue
= 0x0000;
1066 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1068 prop_line_out
.color
->red
= 0x0000;
1069 prop_line_out
.color
->green
= 0xffff;
1070 prop_line_out
.color
->blue
= 0x0000;
1074 prop_line_out
.color
->red
= 0xffff;
1075 prop_line_out
.color
->green
= 0xffff;
1076 prop_line_out
.color
->blue
= 0xffff;
1079 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
1080 g_free(prop_line_out
.color
);
1081 //gdk_gc_unref(draw_context_out->gc);
1082 /* Note : finishing line will have to be added when trace read over. */
1084 /* Finally, update the drawing context of the pid_in. */
1086 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1087 draw_context_in
->current
->modify_over
->x
= x
;
1088 draw_context_in
->current
->modify_under
->x
= x
;
1089 draw_context_in
->current
->modify_over
->y
= y_in
;
1090 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1091 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1092 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1093 widget
= control_flow_data
->drawing
->drawing_area
;
1094 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1095 //draw_context_in->gc = widget->style->black_gc;
1096 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1097 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1099 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1100 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1102 /* Draw the line/bg of the in process */
1103 if(draw_context_in
->previous
->middle
->x
== -1)
1105 draw_context_in
->previous
->over
->x
=
1106 control_flow_data
->drawing
->damage_begin
;
1107 draw_context_in
->previous
->middle
->x
=
1108 control_flow_data
->drawing
->damage_begin
;
1109 draw_context_in
->previous
->under
->x
=
1110 control_flow_data
->drawing
->damage_begin
;
1112 g_debug("in middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
1116 draw_context_in
->current
->middle
->x
= x
;
1117 draw_context_in
->current
->over
->x
= x
;
1118 draw_context_in
->current
->under
->x
= x
;
1119 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
1120 draw_context_in
->current
->over
->y
= y_in
;
1121 draw_context_in
->current
->under
->y
= y_in
+ height
;
1122 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
1123 draw_context_in
->previous
->over
->y
= y_in
;
1124 draw_context_in
->previous
->under
->y
= y_in
+ height
;
1126 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1127 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1130 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1132 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1133 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1134 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1136 PropertiesBG prop_bg
;
1137 prop_bg
.color
= g_new(GdkColor
,1);
1139 switcht(ltt_tracefile_num(tfc
->tf
)) {
1141 prop_bg
.color
->red
= 0x1515;
1142 prop_bg
.color
->green
= 0x1515;
1143 prop_bg
.color
->blue
= 0x8c8c;
1146 prop_bg
.color
->red
= 0x4e4e;
1147 prop_bg
.color
->green
= 0xa9a9;
1148 prop_bg
.color
->blue
= 0xa4a4;
1151 prop_bg
.color
->red
= 0x7a7a;
1152 prop_bg
.color
->green
= 0x4a4a;
1153 prop_bg
.color
->blue
= 0x8b8b;
1156 prop_bg
.color
->red
= 0x8080;
1157 prop_bg
.color
->green
= 0x7777;
1158 prop_bg
.color
->blue
= 0x4747;
1161 prop_bg
.color
->red
= 0xe7e7;
1162 prop_bg
.color
->green
= 0xe7e7;
1163 prop_bg
.color
->blue
= 0xe7e7;
1167 draw_bg((void*)&prop_bg
, (void*)draw_context_in
);
1168 g_free(prop_bg
.color
);
1169 //gdk_gc_unref(draw_context_in->gc);
1172 draw_context_in
->gc
= widget
->style
->black_gc
;
1174 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1175 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1176 PropertiesText prop_text_in
;
1177 prop_text_in
.foreground
= &colorfg_in
;
1178 prop_text_in
.background
= &colorbg_in
;
1179 prop_text_in
.size
= 6;
1180 prop_text_in
.position
= OVER
;
1182 g_debug("in state : %s", g_quark_to_string(process_in
->state
->s
));
1183 /* foreground of text : status of the process */
1184 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1186 prop_text_in
.foreground
->red
= 0xffff;
1187 prop_text_in
.foreground
->green
= 0xffff;
1188 prop_text_in
.foreground
->blue
= 0xffff;
1190 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1192 prop_text_in
.foreground
->red
= 0x0fff;
1193 prop_text_in
.foreground
->green
= 0xffff;
1194 prop_text_in
.foreground
->blue
= 0xfff0;
1196 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1198 prop_text_in
.foreground
->red
= 0xffff;
1199 prop_text_in
.foreground
->green
= 0xffff;
1200 prop_text_in
.foreground
->blue
= 0x0000;
1202 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1204 prop_text_in
.foreground
->red
= 0xffff;
1205 prop_text_in
.foreground
->green
= 0x0000;
1206 prop_text_in
.foreground
->blue
= 0xffff;
1208 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1210 prop_text_in
.foreground
->red
= 0xffff;
1211 prop_text_in
.foreground
->green
= 0x0000;
1212 prop_text_in
.foreground
->blue
= 0x0000;
1214 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1216 prop_text_in
.foreground
->red
= 0x0000;
1217 prop_text_in
.foreground
->green
= 0xffff;
1218 prop_text_in
.foreground
->blue
= 0x0000;
1222 prop_text_in
.foreground
->red
= 0xffff;
1223 prop_text_in
.foreground
->green
= 0xffff;
1224 prop_text_in
.foreground
->blue
= 0xffff;
1229 /* Print status of the process : U, WF, WC, E, W, R */
1230 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1231 prop_text_in
.text
= "U->";
1232 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1233 prop_text_in
.text
= "WF->";
1234 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1235 prop_text_in
.text
= "WC->";
1236 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1237 prop_text_in
.text
= "E->";
1238 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1239 prop_text_in
.text
= "W->";
1240 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1241 prop_text_in
.text
= "R->";
1243 prop_text_in
.text
= "U";
1245 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1246 //gdk_gc_unref(draw_context_in->gc);
1248 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1249 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1250 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1252 PropertiesLine prop_line_in
;
1253 prop_line_in
.color
= g_new(GdkColor
,1);
1254 prop_line_in
.line_width
= 2;
1255 prop_line_in
.style
= GDK_LINE_SOLID
;
1256 prop_line_in
.position
= MIDDLE
;
1258 /* color of line : status of the process */
1259 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1261 prop_line_in
.color
->red
= 0xffff;
1262 prop_line_in
.color
->green
= 0xffff;
1263 prop_line_in
.color
->blue
= 0xffff;
1265 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1267 prop_line_in
.color
->red
= 0x0fff;
1268 prop_line_in
.color
->green
= 0xffff;
1269 prop_line_in
.color
->blue
= 0xfff0;
1271 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1273 prop_line_in
.color
->red
= 0xffff;
1274 prop_line_in
.color
->green
= 0xffff;
1275 prop_line_in
.color
->blue
= 0x0000;
1277 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1279 prop_line_in
.color
->red
= 0xffff;
1280 prop_line_in
.color
->green
= 0x0000;
1281 prop_line_in
.color
->blue
= 0xffff;
1283 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1285 prop_line_in
.color
->red
= 0xffff;
1286 prop_line_in
.color
->green
= 0x0000;
1287 prop_line_in
.color
->blue
= 0x0000;
1289 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1291 prop_line_in
.color
->red
= 0x0000;
1292 prop_line_in
.color
->green
= 0xffff;
1293 prop_line_in
.color
->blue
= 0x0000;
1297 prop_line_in
.color
->red
= 0xffff;
1298 prop_line_in
.color
->green
= 0xffff;
1299 prop_line_in
.color
->blue
= 0xffff;
1302 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
1303 g_free(prop_line_in
.color
);
1304 //gdk_gc_unref(draw_context_in->gc);
1314 GString
*string
= g_string_new("");;
1315 gboolean field_names
= TRUE
, state
= TRUE
;
1317 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
1318 g_string_append_printf(string
,"\n");
1321 g_string_append_printf(string
, " %s",
1322 g_quark_to_string(tfs
->process
->state
->s
));
1325 g_info("%s",string
->str
);
1327 g_string_free(string
, TRUE
);
1329 /* End of text dump */
1334 /* after_schedchange_hook
1336 * The draw after hook is called by the reading API to have a
1337 * particular event drawn on the screen.
1338 * @param hook_data ControlFlowData structure of the viewer.
1339 * @param call_data Event context.
1341 * This function adds items to be drawn in a queue for each process.
1344 int after_schedchange_hook(void *hook_data
, void *call_data
)
1346 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1347 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1348 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1350 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1352 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1354 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1357 e
= ltt_tracefile_get_event(tfc
->tf
);
1359 LttTime evtime
= ltt_event_time(e
);
1361 /* Add process to process list (if not present) */
1362 LttvProcessState
*process_in
;
1364 guint pl_height
= 0;
1365 HashedProcessData
*hashed_process_data_in
= NULL
;
1367 ProcessList
*process_list
= control_flow_data
->process_list
;
1372 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1373 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
1377 /* Find process pid_in in the list... */
1378 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
1379 //process_in = tfs->process;
1380 guint cpu
= ltt_tracefile_num(tfc
->tf
);
1381 process_in
= ts
->running_process
[cpu
];
1382 /* It should exist, because we are after the state update. */
1384 g_assert(process_in
!= NULL
);
1385 #endif //EXTRA_CHECK
1386 birth
= process_in
->creation_time
;
1388 hashed_process_data_in
= processlist_get_process_data(process_list
,
1392 tfc
->t_context
->index
);
1393 if(hashed_process_data_in
== NULL
)
1395 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1396 ProcessInfo
*process_info
;
1397 Drawing_t
*drawing
= control_flow_data
->drawing
;
1398 /* Process not present */
1399 processlist_add(process_list
,
1405 tfc
->t_context
->index
,
1409 &hashed_process_data_in
);
1410 gtk_widget_set_size_request(drawing
->drawing_area
,
1413 gtk_widget_queue_draw(drawing
->drawing_area
);
1415 /* Set the current process */
1416 process_list
->current_hash_data
[process_in
->cpu
] =
1417 hashed_process_data_in
;
1419 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
1422 TimeWindow time_window
=
1423 lttvwindow_get_time_window(control_flow_data
->tab
);
1426 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1427 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1429 #endif //EXTRA_CHECK
1430 Drawing_t
*drawing
= control_flow_data
->drawing
;
1431 guint width
= drawing
->width
;
1434 convert_time_to_pixels(
1440 if(hashed_process_data_in
->x
.middle
!= new_x
) {
1441 hashed_process_data_in
->x
.middle
= new_x
;
1442 hashed_process_data_in
->x
.middle_used
= FALSE
;
1443 hashed_process_data_in
->x
.middle_marked
= FALSE
;
1453 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1454 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1456 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1458 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1459 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1465 LttTime evtime
= ltt_event_time(e
);
1466 TimeWindow time_window
=
1467 lttvwindow_get_time_window(control_flow_data
->tab
);
1469 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
1471 //if(time < time_beg || time > time_end) return;
1472 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1473 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1477 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1479 g_debug("schedchange!");
1481 /* Add process to process list (if not present) and get drawing "y" from
1482 * process position */
1483 guint pid_out
, pid_in
;
1484 LttvProcessState
*process_out
, *process_in
;
1486 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1488 ProcessList
*process_list
= control_flow_data
->process_list
;
1491 LttField
*f
= ltt_event_field(e
);
1493 element
= ltt_field_member(f
,0);
1494 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1495 element
= ltt_field_member(f
,1);
1496 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1497 //g_debug("out : %u in : %u", pid_out, pid_in);
1500 /* Find process pid_out in the list... */
1501 process_out
= lttv_state_find_process(tfs
, pid_out
);
1502 if(process_out
== NULL
) return 0;
1503 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1505 birth
= process_out
->creation_time
;
1506 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1507 HashedProcessData
*hashed_process_data_out
= NULL
;
1509 if(processlist_get_process_pixels(process_list
,
1512 tfc
->t_context
->index
,
1515 &hashed_process_data_out
) == 1)
1517 /* Process not present */
1518 processlist_add(process_list
,
1521 tfc
->t_context
->index
,
1524 &hashed_process_data_out
);
1525 processlist_get_process_pixels(process_list
,
1528 tfc
->t_context
->index
,
1531 &hashed_process_data_out
);
1532 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1537 /* Find process pid_in in the list... */
1538 process_in
= lttv_state_find_process(tfs
, pid_in
);
1539 if(process_in
== NULL
) return 0;
1540 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1542 birth
= process_in
->creation_time
;
1543 name
= strdup(g_quark_to_string(process_in
->name
));
1544 HashedProcessData
*hashed_process_data_in
= NULL
;
1546 if(processlist_get_process_pixels(process_list
,
1549 tfc
->t_context
->index
,
1552 &hashed_process_data_in
) == 1)
1554 /* Process not present */
1555 processlist_add(process_list
,
1558 tfc
->t_context
->index
,
1561 &hashed_process_data_in
);
1562 processlist_get_process_pixels(process_list
,
1565 tfc
->t_context
->index
,
1568 &hashed_process_data_in
);
1570 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1575 /* Find pixels corresponding to time of the event. If the time does
1576 * not fit in the window, show a warning, not supposed to happend. */
1578 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1580 //LttTime time = ltt_event_time(e);
1582 //LttTime window_end = time_window->time_window.end_time;
1585 //convert_time_to_pixels(
1591 //assert(x <= width);
1593 /* draw what represents the event for outgoing process. */
1595 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1596 //draw_context_out->current->modify_over->x = x;
1597 draw_context_out
->current
->modify_over
->y
= y_out
;
1598 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1599 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1600 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1601 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1602 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1604 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1605 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1607 /*if(process_out->state->s == LTTV_STATE_RUN)
1609 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1610 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1611 PropertiesBG prop_bg;
1612 prop_bg.color = g_new(GdkColor,1);
1614 prop_bg.color->red = 0xffff;
1615 prop_bg.color->green = 0xffff;
1616 prop_bg.color->blue = 0xffff;
1618 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1619 g_free(prop_bg.color);
1620 gdk_gc_unref(draw_context_out->gc);
1623 draw_context_out
->gc
= widget
->style
->black_gc
;
1625 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1626 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1627 PropertiesText prop_text_out
;
1628 prop_text_out
.foreground
= &colorfg_out
;
1629 prop_text_out
.background
= &colorbg_out
;
1630 prop_text_out
.size
= 6;
1631 prop_text_out
.position
= OVER
;
1633 /* color of text : status of the process */
1634 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1636 prop_text_out
.foreground
->red
= 0xffff;
1637 prop_text_out
.foreground
->green
= 0xffff;
1638 prop_text_out
.foreground
->blue
= 0xffff;
1640 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1642 prop_text_out
.foreground
->red
= 0x0fff;
1643 prop_text_out
.foreground
->green
= 0xffff;
1644 prop_text_out
.foreground
->blue
= 0xfff0;
1646 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1648 prop_text_out
.foreground
->red
= 0xffff;
1649 prop_text_out
.foreground
->green
= 0xffff;
1650 prop_text_out
.foreground
->blue
= 0x0000;
1652 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1654 prop_text_out
.foreground
->red
= 0xffff;
1655 prop_text_out
.foreground
->green
= 0x0000;
1656 prop_text_out
.foreground
->blue
= 0xffff;
1658 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1660 prop_text_out
.foreground
->red
= 0xffff;
1661 prop_text_out
.foreground
->green
= 0x0000;
1662 prop_text_out
.foreground
->blue
= 0x0000;
1664 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1666 prop_text_out
.foreground
->red
= 0x0000;
1667 prop_text_out
.foreground
->green
= 0xffff;
1668 prop_text_out
.foreground
->blue
= 0x0000;
1672 prop_text_out
.foreground
->red
= 0xffff;
1673 prop_text_out
.foreground
->green
= 0xffff;
1674 prop_text_out
.foreground
->blue
= 0xffff;
1677 /* Print status of the process : U, WF, WC, E, W, R */
1678 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1679 prop_text_out
.text
= "U";
1680 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1681 prop_text_out
.text
= "WF";
1682 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1683 prop_text_out
.text
= "WC";
1684 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1685 prop_text_out
.text
= "E";
1686 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1687 prop_text_out
.text
= "W";
1688 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1689 prop_text_out
.text
= "R";
1691 prop_text_out
.text
= "U";
1693 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1695 //gdk_gc_unref(draw_context_out->gc);
1697 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1698 draw_context_out
->current
->over
->y
= y_out
;
1699 draw_context_out
->current
->under
->y
= y_out
+height
;
1700 draw_context_out
->current
->status
= process_out
->state
->s
;
1702 /* for pid_out : remove previous, Prev = current, new current (default) */
1703 g_free(draw_context_out
->previous
->modify_under
);
1704 g_free(draw_context_out
->previous
->modify_middle
);
1705 g_free(draw_context_out
->previous
->modify_over
);
1706 g_free(draw_context_out
->previous
->under
);
1707 g_free(draw_context_out
->previous
->middle
);
1708 g_free(draw_context_out
->previous
->over
);
1709 g_free(draw_context_out
->previous
);
1711 draw_context_out
->previous
= draw_context_out
->current
;
1713 draw_context_out
->current
= g_new(DrawInfo
,1);
1714 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1715 draw_context_out
->current
->over
->x
= -1;
1716 draw_context_out
->current
->over
->y
= -1;
1717 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1718 draw_context_out
->current
->middle
->x
= -1;
1719 draw_context_out
->current
->middle
->y
= -1;
1720 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1721 draw_context_out
->current
->under
->x
= -1;
1722 draw_context_out
->current
->under
->y
= -1;
1723 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1724 draw_context_out
->current
->modify_over
->x
= -1;
1725 draw_context_out
->current
->modify_over
->y
= -1;
1726 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1727 draw_context_out
->current
->modify_middle
->x
= -1;
1728 draw_context_out
->current
->modify_middle
->y
= -1;
1729 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1730 draw_context_out
->current
->modify_under
->x
= -1;
1731 draw_context_out
->current
->modify_under
->y
= -1;
1732 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1734 /* Finally, update the drawing context of the pid_in. */
1736 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1737 //draw_context_in->current->modify_over->x = x;
1738 draw_context_in
->current
->modify_over
->y
= y_in
;
1739 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1740 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1741 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1742 widget
= control_flow_data
->drawing
->drawing_area
;
1743 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1745 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1746 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1748 /*if(process_in->state->s == LTTV_STATE_RUN)
1750 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1751 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1752 PropertiesBG prop_bg;
1753 prop_bg.color = g_new(GdkColor,1);
1755 prop_bg.color->red = 0xffff;
1756 prop_bg.color->green = 0xffff;
1757 prop_bg.color->blue = 0xffff;
1759 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1760 g_free(prop_bg.color);
1761 gdk_gc_unref(draw_context_in->gc);
1764 draw_context_in
->gc
= widget
->style
->black_gc
;
1766 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1767 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1768 PropertiesText prop_text_in
;
1769 prop_text_in
.foreground
= &colorfg_in
;
1770 prop_text_in
.background
= &colorbg_in
;
1771 prop_text_in
.size
= 6;
1772 prop_text_in
.position
= OVER
;
1774 /* foreground of text : status of the process */
1775 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1777 prop_text_in
.foreground
->red
= 0xffff;
1778 prop_text_in
.foreground
->green
= 0xffff;
1779 prop_text_in
.foreground
->blue
= 0xffff;
1781 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1783 prop_text_in
.foreground
->red
= 0x0fff;
1784 prop_text_in
.foreground
->green
= 0xffff;
1785 prop_text_in
.foreground
->blue
= 0xfff0;
1787 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1789 prop_text_in
.foreground
->red
= 0xffff;
1790 prop_text_in
.foreground
->green
= 0xffff;
1791 prop_text_in
.foreground
->blue
= 0x0000;
1793 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1795 prop_text_in
.foreground
->red
= 0xffff;
1796 prop_text_in
.foreground
->green
= 0x0000;
1797 prop_text_in
.foreground
->blue
= 0xffff;
1799 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1801 prop_text_in
.foreground
->red
= 0xffff;
1802 prop_text_in
.foreground
->green
= 0x0000;
1803 prop_text_in
.foreground
->blue
= 0x0000;
1805 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1807 prop_text_in
.foreground
->red
= 0x0000;
1808 prop_text_in
.foreground
->green
= 0xffff;
1809 prop_text_in
.foreground
->blue
= 0x0000;
1813 prop_text_in
.foreground
->red
= 0xffff;
1814 prop_text_in
.foreground
->green
= 0xffff;
1815 prop_text_in
.foreground
->blue
= 0xffff;
1819 /* Print status of the process : U, WF, WC, E, W, R */
1820 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1821 prop_text_in
.text
= "U";
1822 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1823 prop_text_in
.text
= "WF";
1824 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1825 prop_text_in
.text
= "WC";
1826 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1827 prop_text_in
.text
= "E";
1828 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1829 prop_text_in
.text
= "W";
1830 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1831 prop_text_in
.text
= "R";
1833 prop_text_in
.text
= "U";
1835 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1838 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1841 prop_text_in
.foreground
= &colorfg_in
;
1842 prop_text_in
.background
= &colorbg_in
;
1843 prop_text_in
.foreground
->red
= 0xffff;
1844 prop_text_in
.foreground
->green
= 0xffff;
1845 prop_text_in
.foreground
->blue
= 0xffff;
1846 prop_text_in
.size
= 6;
1847 prop_text_in
.position
= UNDER
;
1849 prop_text_in
.text
= g_new(gchar
, 260);
1850 strcpy(prop_text_in
.text
, "CPU ");
1851 snprintf(tmp
, 255, "%u", ltt_tracefile_num(tfc
->tf
));
1852 strcat(prop_text_in
.text
, tmp
);
1854 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1855 g_free(prop_text_in
.text
);
1859 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1860 draw_context_in
->current
->over
->y
= y_in
;
1861 draw_context_in
->current
->under
->y
= y_in
+height
;
1862 draw_context_in
->current
->status
= process_in
->state
->s
;
1864 /* for pid_in : remove previous, Prev = current, new current (default) */
1865 g_free(draw_context_in
->previous
->modify_under
);
1866 g_free(draw_context_in
->previous
->modify_middle
);
1867 g_free(draw_context_in
->previous
->modify_over
);
1868 g_free(draw_context_in
->previous
->under
);
1869 g_free(draw_context_in
->previous
->middle
);
1870 g_free(draw_context_in
->previous
->over
);
1871 g_free(draw_context_in
->previous
);
1873 draw_context_in
->previous
= draw_context_in
->current
;
1875 draw_context_in
->current
= g_new(DrawInfo
,1);
1876 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1877 draw_context_in
->current
->over
->x
= -1;
1878 draw_context_in
->current
->over
->y
= -1;
1879 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1880 draw_context_in
->current
->middle
->x
= -1;
1881 draw_context_in
->current
->middle
->y
= -1;
1882 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1883 draw_context_in
->current
->under
->x
= -1;
1884 draw_context_in
->current
->under
->y
= -1;
1885 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1886 draw_context_in
->current
->modify_over
->x
= -1;
1887 draw_context_in
->current
->modify_over
->y
= -1;
1888 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1889 draw_context_in
->current
->modify_middle
->x
= -1;
1890 draw_context_in
->current
->modify_middle
->y
= -1;
1891 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1892 draw_context_in
->current
->modify_under
->x
= -1;
1893 draw_context_in
->current
->modify_under
->y
= -1;
1894 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1903 static inline PropertiesLine
prepare_execmode_line(LttvProcessState
*process
)
1905 PropertiesLine prop_line
;
1906 prop_line
.line_width
= 1;
1907 prop_line
.style
= GDK_LINE_SOLID
;
1909 //GdkColormap *colormap = gdk_colormap_get_system();
1911 /* color of line : execution mode of the process */
1912 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
1913 prop_line
.color
= drawing_colors
[COL_USER_MODE
];
1914 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
1915 prop_line
.color
= drawing_colors
[COL_SYSCALL
];
1916 else if(process
->state
->t
== LTTV_STATE_TRAP
)
1917 prop_line
.color
= drawing_colors
[COL_TRAP
];
1918 else if(process
->state
->t
== LTTV_STATE_IRQ
)
1919 prop_line
.color
= drawing_colors
[COL_IRQ
];
1920 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
1921 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
1923 prop_line
.color
= drawing_colors
[COL_WHITE
];
1925 //gdk_colormap_alloc_color(colormap,
1936 /* before_execmode_hook
1938 * This function basically draw lines and icons. Two types of lines are drawn :
1939 * one small (3 pixels?) representing the state of the process and the second
1940 * type is thicker (10 pixels?) representing on which CPU a process is running
1941 * (and this only in running state).
1943 * Extremums of the lines :
1944 * x_min : time of the last event context for this process kept in memory.
1945 * x_max : time of the current event.
1946 * y : middle of the process in the process list. The process is found in the
1947 * list, therefore is it's position in pixels.
1949 * The choice of lines'color is defined by the context of the last event for this
1954 int before_execmode_hook(void *hook_data
, void *call_data
)
1956 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1957 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1958 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1960 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1962 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1964 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1967 e
= ltt_tracefile_get_event(tfc
->tf
);
1969 LttTime evtime
= ltt_event_time(e
);
1971 /* we are in a execmode, before the state update. We must draw the
1972 * items corresponding to the state before it changes : now is the right
1976 //LttvProcessState *process = tfs->process;
1977 guint cpu
= ltt_tracefile_num(tfc
->tf
);
1978 LttvProcessState
*process
= ts
->running_process
[cpu
];
1979 g_assert(process
!= NULL
);
1981 guint pid
= process
->pid
;
1983 /* Well, the process_out existed : we must get it in the process hash
1984 * or add it, and draw its items.
1986 /* Add process to process list (if not present) */
1987 guint pl_height
= 0;
1988 HashedProcessData
*hashed_process_data
= NULL
;
1989 ProcessList
*process_list
= control_flow_data
->process_list
;
1990 LttTime birth
= process
->creation_time
;
1992 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
1993 hashed_process_data
= process_list
->current_hash_data
[cpu
];
1995 hashed_process_data
= processlist_get_process_data(process_list
,
1999 tfc
->t_context
->index
);
2000 if(unlikely(hashed_process_data
== NULL
))
2002 g_assert(pid
== 0 || pid
!= process
->ppid
);
2003 ProcessInfo
*process_info
;
2004 /* Process not present */
2005 Drawing_t
*drawing
= control_flow_data
->drawing
;
2006 processlist_add(process_list
,
2012 tfc
->t_context
->index
,
2016 &hashed_process_data
);
2017 gtk_widget_set_size_request(drawing
->drawing_area
,
2020 gtk_widget_queue_draw(drawing
->drawing_area
);
2022 /* Set the current process */
2023 process_list
->current_hash_data
[process
->cpu
] =
2024 hashed_process_data
;
2027 /* Now, the process is in the state hash and our own process hash.
2028 * We definitely can draw the items related to the ending state.
2031 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2034 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2035 TimeWindow time_window
=
2036 lttvwindow_get_time_window(control_flow_data
->tab
);
2039 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2040 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2042 #endif //EXTRA_CHECK
2043 Drawing_t
*drawing
= control_flow_data
->drawing
;
2044 guint width
= drawing
->width
;
2046 convert_time_to_pixels(
2052 /* Draw collision indicator */
2053 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2054 gdk_draw_point(hashed_process_data
->pixmap
,
2057 (hashed_process_data
->height
/2)-3);
2058 hashed_process_data
->x
.middle_marked
= TRUE
;
2061 TimeWindow time_window
=
2062 lttvwindow_get_time_window(control_flow_data
->tab
);
2065 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2066 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2068 #endif //EXTRA_CHECK
2069 Drawing_t
*drawing
= control_flow_data
->drawing
;
2070 guint width
= drawing
->width
;
2073 convert_time_to_pixels(
2080 /* Jump over draw if we are at the same x position */
2081 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2082 hashed_process_data
->x
.middle_used
))
2084 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2085 /* Draw collision indicator */
2086 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2087 gdk_draw_point(hashed_process_data
->pixmap
,
2090 (hashed_process_data
->height
/2)-3);
2091 hashed_process_data
->x
.middle_marked
= TRUE
;
2096 DrawContext draw_context
;
2097 /* Now create the drawing context that will be used to draw
2098 * items related to the last state. */
2099 draw_context
.drawable
= hashed_process_data
->pixmap
;
2100 draw_context
.gc
= drawing
->gc
;
2101 draw_context
.pango_layout
= drawing
->pango_layout
;
2102 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2103 draw_context
.drawinfo
.end
.x
= x
;
2105 draw_context
.drawinfo
.y
.over
= 1;
2106 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2107 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2109 draw_context
.drawinfo
.start
.offset
.over
= 0;
2110 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2111 draw_context
.drawinfo
.start
.offset
.under
= 0;
2112 draw_context
.drawinfo
.end
.offset
.over
= 0;
2113 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2114 draw_context
.drawinfo
.end
.offset
.under
= 0;
2118 PropertiesLine prop_line
= prepare_s_e_line(process
);
2119 draw_line((void*)&prop_line
, (void*)&draw_context
);
2122 /* become the last x position */
2123 hashed_process_data
->x
.middle
= x
;
2124 hashed_process_data
->x
.middle_used
= TRUE
;
2125 hashed_process_data
->x
.middle_marked
= FALSE
;
2127 /* Calculate the next good time */
2128 convert_pixels_to_time(width
, x
+1, time_window
,
2129 &hashed_process_data
->next_good_time
);
2136 /* after_execmode_hook
2138 * The draw after hook is called by the reading API to have a
2139 * particular event drawn on the screen.
2140 * @param hook_data ControlFlowData structure of the viewer.
2141 * @param call_data Event context.
2143 * This function adds items to be drawn in a queue for each process.
2147 int after_execmode_hook(void *hook_data
, void *call_data
)
2149 /**************** DOES NOTHING!! *************/
2150 /* hook desactivated in drawing.c */
2154 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2155 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2156 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2158 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2160 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2163 e
= ltt_tracefile_get_event(tfc
->tf
);
2165 LttTime evtime
= ltt_event_time(e
);
2167 /* Add process to process list (if not present) */
2168 LttvProcessState
*process
;
2170 guint pl_height
= 0;
2171 HashedProcessData
*hashed_process_data
= NULL
;
2173 ProcessList
*process_list
= control_flow_data
->process_list
;
2175 /* Find process pid_in in the list... */
2176 process
= tfs
->process
;
2177 /* It should exist, because we are after the state update. */
2178 g_assert(process
!= NULL
);
2180 guint pid
= process
->pid
;
2182 birth
= process
->creation_time
;
2184 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
2185 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
2187 hashed_process_data
= processlist_get_process_data(process_list
,
2189 process
->last_cpu_index
,
2191 tfc
->t_context
->index
);
2192 if(unlikely(hashed_process_data
== NULL
))
2194 g_assert(pid
== 0 || pid
!= process
->ppid
);
2195 /* Process not present */
2196 Drawing_t
*drawing
= control_flow_data
->drawing
;
2197 const gchar
*name
= g_quark_to_string(process
->name
);
2198 ProcessInfo
*process_info
;
2199 processlist_add(process_list
,
2202 process
->last_cpu_index
,
2205 tfc
->t_context
->index
,
2209 &hashed_process_data
);
2210 gtk_widget_set_size_request(drawing
->drawing_area
,
2213 gtk_widget_queue_draw(drawing
->drawing_area
);
2215 /* Set the current process */
2216 process_list
->current_hash_data
[process
->last_cpu_index
] =
2217 hashed_process_data
;
2220 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2223 TimeWindow time_window
=
2224 lttvwindow_get_time_window(control_flow_data
->tab
);
2227 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2228 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2230 #endif //EXTRA_CHECK
2231 Drawing_t
*drawing
= control_flow_data
->drawing
;
2232 guint width
= drawing
->width
;
2235 convert_time_to_pixels(
2241 if(hashed_process_data
->x
.middle
!= new_x
) {
2242 hashed_process_data
->x
.middle
= new_x
;
2243 hashed_process_data
->x
.middle_used
= FALSE
;
2244 hashed_process_data
->x
.middle_marked
= FALSE
;
2253 /* before_process_exit_hook
2255 * Draw lines for process event.
2257 * @param hook_data ControlFlowData structure of the viewer.
2258 * @param call_data Event context.
2260 * This function adds items to be drawn in a queue for each process.
2265 int before_process_exit_hook(void *hook_data
, void *call_data
)
2267 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2268 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2270 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2272 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2274 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2276 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2279 e
= ltt_tracefile_get_event(tfc
->tf
);
2281 LttTime evtime
= ltt_event_time(e
);
2283 /* Add process to process list (if not present) */
2284 //LttvProcessState *process = tfs->process;
2285 guint cpu
= ltt_tracefile_num(tfc
->tf
);
2286 LttvProcessState
*process
= ts
->running_process
[cpu
];
2287 guint pid
= process
->pid
;
2289 guint pl_height
= 0;
2290 HashedProcessData
*hashed_process_data
= NULL
;
2292 ProcessList
*process_list
= control_flow_data
->process_list
;
2294 g_assert(process
!= NULL
);
2296 birth
= process
->creation_time
;
2298 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
2299 hashed_process_data
= process_list
->current_hash_data
[cpu
];
2301 hashed_process_data
= processlist_get_process_data(process_list
,
2305 tfc
->t_context
->index
);
2306 if(unlikely(hashed_process_data
== NULL
))
2308 g_assert(pid
== 0 || pid
!= process
->ppid
);
2309 /* Process not present */
2310 Drawing_t
*drawing
= control_flow_data
->drawing
;
2311 ProcessInfo
*process_info
;
2312 processlist_add(process_list
,
2318 tfc
->t_context
->index
,
2322 &hashed_process_data
);
2323 gtk_widget_set_size_request(drawing
->drawing_area
,
2326 gtk_widget_queue_draw(drawing
->drawing_area
);
2330 /* Now, the process is in the state hash and our own process hash.
2331 * We definitely can draw the items related to the ending state.
2334 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2337 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2338 TimeWindow time_window
=
2339 lttvwindow_get_time_window(control_flow_data
->tab
);
2342 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2343 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2345 #endif //EXTRA_CHECK
2346 Drawing_t
*drawing
= control_flow_data
->drawing
;
2347 guint width
= drawing
->width
;
2349 convert_time_to_pixels(
2355 /* Draw collision indicator */
2356 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2357 gdk_draw_point(hashed_process_data
->pixmap
,
2360 (hashed_process_data
->height
/2)-3);
2361 hashed_process_data
->x
.middle_marked
= TRUE
;
2364 TimeWindow time_window
=
2365 lttvwindow_get_time_window(control_flow_data
->tab
);
2368 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2369 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2371 #endif //EXTRA_CHECK
2372 Drawing_t
*drawing
= control_flow_data
->drawing
;
2373 guint width
= drawing
->width
;
2376 convert_time_to_pixels(
2383 /* Jump over draw if we are at the same x position */
2384 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2385 hashed_process_data
->x
.middle_used
))
2387 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2388 /* Draw collision indicator */
2389 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2390 gdk_draw_point(hashed_process_data
->pixmap
,
2393 (hashed_process_data
->height
/2)-3);
2394 hashed_process_data
->x
.middle_marked
= TRUE
;
2398 DrawContext draw_context
;
2400 /* Now create the drawing context that will be used to draw
2401 * items related to the last state. */
2402 draw_context
.drawable
= hashed_process_data
->pixmap
;
2403 draw_context
.gc
= drawing
->gc
;
2404 draw_context
.pango_layout
= drawing
->pango_layout
;
2405 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2406 draw_context
.drawinfo
.end
.x
= x
;
2408 draw_context
.drawinfo
.y
.over
= 1;
2409 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2410 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2412 draw_context
.drawinfo
.start
.offset
.over
= 0;
2413 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2414 draw_context
.drawinfo
.start
.offset
.under
= 0;
2415 draw_context
.drawinfo
.end
.offset
.over
= 0;
2416 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2417 draw_context
.drawinfo
.end
.offset
.under
= 0;
2421 PropertiesLine prop_line
= prepare_s_e_line(process
);
2422 draw_line((void*)&prop_line
, (void*)&draw_context
);
2425 /* become the last x position */
2426 hashed_process_data
->x
.middle
= x
;
2427 hashed_process_data
->x
.middle_used
= TRUE
;
2428 hashed_process_data
->x
.middle_marked
= FALSE
;
2430 /* Calculate the next good time */
2431 convert_pixels_to_time(width
, x
+1, time_window
,
2432 &hashed_process_data
->next_good_time
);
2442 /* before_process_release_hook
2444 * Draw lines for process event.
2446 * @param hook_data ControlFlowData structure of the viewer.
2447 * @param call_data Event context.
2449 * This function adds items to be drawn in a queue for each process.
2454 int before_process_release_hook(void *hook_data
, void *call_data
)
2456 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2457 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2459 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2461 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2463 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2465 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2468 e
= ltt_tracefile_get_event(tfc
->tf
);
2470 LttTime evtime
= ltt_event_time(e
);
2475 pid
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2478 /* Add process to process list (if not present) */
2479 /* Don't care about the process if it's not in the state hash already :
2480 * that means a process that has never done anything in the trace and
2481 * unknown suddently gets destroyed : no state meaningful to show. */
2482 LttvProcessState
*process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2484 if(process
!= NULL
) {
2486 guint pl_height
= 0;
2487 HashedProcessData
*hashed_process_data
= NULL
;
2489 ProcessList
*process_list
= control_flow_data
->process_list
;
2491 birth
= process
->creation_time
;
2493 /* Cannot use current process : this event happens on another process,
2494 * action done by the parent. */
2495 hashed_process_data
= processlist_get_process_data(process_list
,
2499 tfc
->t_context
->index
);
2500 if(unlikely(hashed_process_data
== NULL
))
2502 g_assert(pid
== 0 || pid
!= process
->ppid
);
2503 /* Process not present */
2504 Drawing_t
*drawing
= control_flow_data
->drawing
;
2505 ProcessInfo
*process_info
;
2506 processlist_add(process_list
,
2512 tfc
->t_context
->index
,
2516 &hashed_process_data
);
2517 gtk_widget_set_size_request(drawing
->drawing_area
,
2520 gtk_widget_queue_draw(drawing
->drawing_area
);
2523 /* Now, the process is in the state hash and our own process hash.
2524 * We definitely can draw the items related to the ending state.
2527 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2530 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2531 TimeWindow time_window
=
2532 lttvwindow_get_time_window(control_flow_data
->tab
);
2535 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2536 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2538 #endif //EXTRA_CHECK
2539 Drawing_t
*drawing
= control_flow_data
->drawing
;
2540 guint width
= drawing
->width
;
2542 convert_time_to_pixels(
2548 /* Draw collision indicator */
2549 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2550 gdk_draw_point(hashed_process_data
->pixmap
,
2553 (hashed_process_data
->height
/2)-3);
2554 hashed_process_data
->x
.middle_marked
= TRUE
;
2557 TimeWindow time_window
=
2558 lttvwindow_get_time_window(control_flow_data
->tab
);
2561 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2562 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2564 #endif //EXTRA_CHECK
2565 Drawing_t
*drawing
= control_flow_data
->drawing
;
2566 guint width
= drawing
->width
;
2569 convert_time_to_pixels(
2576 /* Jump over draw if we are at the same x position */
2577 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2578 hashed_process_data
->x
.middle_used
))
2580 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2581 /* Draw collision indicator */
2582 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2583 gdk_draw_point(hashed_process_data
->pixmap
,
2586 (hashed_process_data
->height
/2)-3);
2587 hashed_process_data
->x
.middle_marked
= TRUE
;
2591 DrawContext draw_context
;
2593 /* Now create the drawing context that will be used to draw
2594 * items related to the last state. */
2595 draw_context
.drawable
= hashed_process_data
->pixmap
;
2596 draw_context
.gc
= drawing
->gc
;
2597 draw_context
.pango_layout
= drawing
->pango_layout
;
2598 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2599 draw_context
.drawinfo
.end
.x
= x
;
2601 draw_context
.drawinfo
.y
.over
= 1;
2602 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2603 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2605 draw_context
.drawinfo
.start
.offset
.over
= 0;
2606 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2607 draw_context
.drawinfo
.start
.offset
.under
= 0;
2608 draw_context
.drawinfo
.end
.offset
.over
= 0;
2609 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2610 draw_context
.drawinfo
.end
.offset
.under
= 0;
2614 PropertiesLine prop_line
= prepare_s_e_line(process
);
2615 draw_line((void*)&prop_line
, (void*)&draw_context
);
2618 /* become the last x position */
2619 hashed_process_data
->x
.middle
= x
;
2620 hashed_process_data
->x
.middle_used
= TRUE
;
2621 hashed_process_data
->x
.middle_marked
= FALSE
;
2623 /* Calculate the next good time */
2624 convert_pixels_to_time(width
, x
+1, time_window
,
2625 &hashed_process_data
->next_good_time
);
2641 /* before_process_hook
2643 * Draw lines for process event.
2645 * @param hook_data ControlFlowData structure of the viewer.
2646 * @param call_data Event context.
2648 * This function adds items to be drawn in a queue for each process.
2651 int before_process_hook(void *hook_data
, void *call_data
)
2653 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2654 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2655 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2657 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2659 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2662 e
= ltt_tracefile_get_event(tfc
->tf
);
2664 LttTime evtime
= ltt_event_time(e
);
2668 LttField
*f
= ltt_event_field(e
);
2670 element
= ltt_field_member(f
,0);
2671 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2674 if(sub_id
== 3) { /* exit */
2676 /* Add process to process list (if not present) */
2677 LttvProcessState
*process
= tfs
->process
;
2678 guint pid
= process
->pid
;
2680 guint pl_height
= 0;
2681 HashedProcessData
*hashed_process_data
= NULL
;
2683 ProcessList
*process_list
= control_flow_data
->process_list
;
2685 g_assert(process
!= NULL
);
2687 birth
= process
->creation_time
;
2689 if(likely(process_list
->current_hash_data
[tfc
->index
] != NULL
)) {
2690 hashed_process_data
= process_list
->current_hash_data
[tfc
->index
];
2692 hashed_process_data
= processlist_get_process_data(process_list
,
2694 process
->last_cpu_index
,
2696 tfc
->t_context
->index
);
2697 if(unlikely(hashed_process_data
== NULL
))
2699 g_assert(pid
== 0 || pid
!= process
->ppid
);
2700 /* Process not present */
2701 Drawing_t
*drawing
= control_flow_data
->drawing
;
2702 const gchar
*name
= g_quark_to_string(process
->name
);
2703 ProcessInfo
*process_info
;
2704 processlist_add(process_list
,
2707 process
->last_cpu_index
,
2710 tfc
->t_context
->index
,
2714 &hashed_process_data
);
2715 gtk_widget_set_size_request(drawing
->drawing_area
,
2718 gtk_widget_queue_draw(drawing
->drawing_area
);
2722 /* Now, the process is in the state hash and our own process hash.
2723 * We definitely can draw the items related to the ending state.
2726 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2729 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2730 TimeWindow time_window
=
2731 lttvwindow_get_time_window(control_flow_data
->tab
);
2734 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2735 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2737 #endif //EXTRA_CHECK
2738 Drawing_t
*drawing
= control_flow_data
->drawing
;
2739 guint width
= drawing
->width
;
2741 convert_time_to_pixels(
2747 /* Draw collision indicator */
2748 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2749 gdk_draw_point(hashed_process_data
->pixmap
,
2752 (hashed_process_data
->height
/2)-3);
2753 hashed_process_data
->x
.middle_marked
= TRUE
;
2756 TimeWindow time_window
=
2757 lttvwindow_get_time_window(control_flow_data
->tab
);
2760 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2761 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2763 #endif //EXTRA_CHECK
2764 Drawing_t
*drawing
= control_flow_data
->drawing
;
2765 guint width
= drawing
->width
;
2768 convert_time_to_pixels(
2775 /* Jump over draw if we are at the same x position */
2776 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2777 hashed_process_data
->x
.middle_used
))
2779 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2780 /* Draw collision indicator */
2781 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2782 gdk_draw_point(hashed_process_data
->pixmap
,
2785 (hashed_process_data
->height
/2)-3);
2786 hashed_process_data
->x
.middle_marked
= TRUE
;
2790 DrawContext draw_context
;
2792 /* Now create the drawing context that will be used to draw
2793 * items related to the last state. */
2794 draw_context
.drawable
= hashed_process_data
->pixmap
;
2795 draw_context
.gc
= drawing
->gc
;
2796 draw_context
.pango_layout
= drawing
->pango_layout
;
2797 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2798 draw_context
.drawinfo
.end
.x
= x
;
2800 draw_context
.drawinfo
.y
.over
= 1;
2801 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2802 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2804 draw_context
.drawinfo
.start
.offset
.over
= 0;
2805 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2806 draw_context
.drawinfo
.start
.offset
.under
= 0;
2807 draw_context
.drawinfo
.end
.offset
.over
= 0;
2808 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2809 draw_context
.drawinfo
.end
.offset
.under
= 0;
2813 PropertiesLine prop_line
= prepare_s_e_line(process
);
2814 draw_line((void*)&prop_line
, (void*)&draw_context
);
2817 /* become the last x position */
2818 hashed_process_data
->x
.middle
= x
;
2819 hashed_process_data
->x
.middle_used
= TRUE
;
2820 hashed_process_data
->x
.middle_marked
= FALSE
;
2822 /* Calculate the next good time */
2823 convert_pixels_to_time(width
, x
+1, time_window
,
2824 &hashed_process_data
->next_good_time
);
2828 } else if(sub_id
== 7) /* release */ {
2832 LttField
*f
= ltt_event_field(e
);
2834 element
= ltt_field_member(f
,1);
2835 pid
= ltt_event_get_long_unsigned(e
,element
);
2838 /* Add process to process list (if not present) */
2839 /* Don't care about the process if it's not in the state hash already :
2840 * that means a process that has never done anything in the trace and
2841 * unknown suddently gets destroyed : no state meaningful to show. */
2842 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
2844 if(process
!= NULL
) {
2846 guint pl_height
= 0;
2847 HashedProcessData
*hashed_process_data
= NULL
;
2849 ProcessList
*process_list
= control_flow_data
->process_list
;
2851 birth
= process
->creation_time
;
2853 /* Cannot use current process : this event happens on another process,
2854 * action done by the parent. */
2855 hashed_process_data
= processlist_get_process_data(process_list
,
2857 process
->last_cpu_index
,
2859 tfc
->t_context
->index
);
2860 if(unlikely(hashed_process_data
== NULL
))
2862 g_assert(pid
== 0 || pid
!= process
->ppid
);
2863 /* Process not present */
2864 Drawing_t
*drawing
= control_flow_data
->drawing
;
2865 ProcessInfo
*process_info
;
2866 processlist_add(process_list
,
2869 process
->last_cpu_index
,
2872 tfc
->t_context
->index
,
2876 &hashed_process_data
);
2877 gtk_widget_set_size_request(drawing
->drawing_area
,
2880 gtk_widget_queue_draw(drawing
->drawing_area
);
2883 /* Now, the process is in the state hash and our own process hash.
2884 * We definitely can draw the items related to the ending state.
2887 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2890 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2891 TimeWindow time_window
=
2892 lttvwindow_get_time_window(control_flow_data
->tab
);
2895 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2896 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2898 #endif //EXTRA_CHECK
2899 Drawing_t
*drawing
= control_flow_data
->drawing
;
2900 guint width
= drawing
->width
;
2902 convert_time_to_pixels(
2908 /* Draw collision indicator */
2909 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2910 gdk_draw_point(hashed_process_data
->pixmap
,
2913 (hashed_process_data
->height
/2)-3);
2914 hashed_process_data
->x
.middle_marked
= TRUE
;
2917 TimeWindow time_window
=
2918 lttvwindow_get_time_window(control_flow_data
->tab
);
2921 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2922 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2924 #endif //EXTRA_CHECK
2925 Drawing_t
*drawing
= control_flow_data
->drawing
;
2926 guint width
= drawing
->width
;
2929 convert_time_to_pixels(
2936 /* Jump over draw if we are at the same x position */
2937 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2938 hashed_process_data
->x
.middle_used
))
2940 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2941 /* Draw collision indicator */
2942 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2943 gdk_draw_point(hashed_process_data
->pixmap
,
2946 (hashed_process_data
->height
/2)-3);
2947 hashed_process_data
->x
.middle_marked
= TRUE
;
2951 DrawContext draw_context
;
2953 /* Now create the drawing context that will be used to draw
2954 * items related to the last state. */
2955 draw_context
.drawable
= hashed_process_data
->pixmap
;
2956 draw_context
.gc
= drawing
->gc
;
2957 draw_context
.pango_layout
= drawing
->pango_layout
;
2958 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2959 draw_context
.drawinfo
.end
.x
= x
;
2961 draw_context
.drawinfo
.y
.over
= 1;
2962 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2963 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2965 draw_context
.drawinfo
.start
.offset
.over
= 0;
2966 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2967 draw_context
.drawinfo
.start
.offset
.under
= 0;
2968 draw_context
.drawinfo
.end
.offset
.over
= 0;
2969 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2970 draw_context
.drawinfo
.end
.offset
.under
= 0;
2974 PropertiesLine prop_line
= prepare_s_e_line(process
);
2975 draw_line((void*)&prop_line
, (void*)&draw_context
);
2978 /* become the last x position */
2979 hashed_process_data
->x
.middle
= x
;
2980 hashed_process_data
->x
.middle_used
= TRUE
;
2981 hashed_process_data
->x
.middle_marked
= FALSE
;
2983 /* Calculate the next good time */
2984 convert_pixels_to_time(width
, x
+1, time_window
,
2985 &hashed_process_data
->next_good_time
);
2999 /* after_process_fork_hook
3001 * Create the processlist entry for the child process. Put the last
3002 * position in x at the current time value.
3004 * @param hook_data ControlFlowData structure of the viewer.
3005 * @param call_data Event context.
3007 * This function adds items to be drawn in a queue for each process.
3010 int after_process_fork_hook(void *hook_data
, void *call_data
)
3012 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3013 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3014 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3016 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3018 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3020 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3023 e
= ltt_tracefile_get_event(tfc
->tf
);
3025 LttTime evtime
= ltt_event_time(e
);
3029 child_pid
= ltt_event_get_long_unsigned(e
, thf
->f2
);
3032 /* Add process to process list (if not present) */
3033 LttvProcessState
*process_child
;
3035 guint pl_height
= 0;
3036 HashedProcessData
*hashed_process_data_child
= NULL
;
3038 ProcessList
*process_list
= control_flow_data
->process_list
;
3040 /* Find child in the list... */
3041 process_child
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3042 /* It should exist, because we are after the state update. */
3043 g_assert(process_child
!= NULL
);
3045 birth
= process_child
->creation_time
;
3047 /* Cannot use current process, because this action is done by the parent
3049 hashed_process_data_child
= processlist_get_process_data(process_list
,
3053 tfc
->t_context
->index
);
3054 if(likely(hashed_process_data_child
== NULL
))
3056 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3057 /* Process not present */
3058 Drawing_t
*drawing
= control_flow_data
->drawing
;
3059 ProcessInfo
*process_info
;
3060 processlist_add(process_list
,
3064 process_child
->ppid
,
3066 tfc
->t_context
->index
,
3067 process_child
->name
,
3070 &hashed_process_data_child
);
3071 gtk_widget_set_size_request(drawing
->drawing_area
,
3074 gtk_widget_queue_draw(drawing
->drawing_area
);
3078 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3081 TimeWindow time_window
=
3082 lttvwindow_get_time_window(control_flow_data
->tab
);
3085 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3086 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3088 #endif //EXTRA_CHECK
3089 Drawing_t
*drawing
= control_flow_data
->drawing
;
3090 guint width
= drawing
->width
;
3092 convert_time_to_pixels(
3098 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3099 hashed_process_data_child
->x
.over
= new_x
;
3100 hashed_process_data_child
->x
.over_used
= FALSE
;
3101 hashed_process_data_child
->x
.over_marked
= FALSE
;
3103 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3104 hashed_process_data_child
->x
.middle
= new_x
;
3105 hashed_process_data_child
->x
.middle_used
= FALSE
;
3106 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3108 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3109 hashed_process_data_child
->x
.under
= new_x
;
3110 hashed_process_data_child
->x
.under_used
= FALSE
;
3111 hashed_process_data_child
->x
.under_marked
= FALSE
;
3119 /* after_process_exit_hook
3121 * Create the processlist entry for the child process. Put the last
3122 * position in x at the current time value.
3124 * @param hook_data ControlFlowData structure of the viewer.
3125 * @param call_data Event context.
3127 * This function adds items to be drawn in a queue for each process.
3130 int after_process_exit_hook(void *hook_data
, void *call_data
)
3132 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3133 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3134 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3136 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3138 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3140 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3143 e
= ltt_tracefile_get_event(tfc
->tf
);
3145 LttTime evtime
= ltt_event_time(e
);
3147 /* Add process to process list (if not present) */
3148 //LttvProcessState *process = tfs->process;
3149 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3150 LttvProcessState
*process
= ts
->running_process
[cpu
];
3152 /* It should exist, because we are after the state update. */
3153 g_assert(process
!= NULL
);
3155 guint pid
= process
->pid
;
3157 guint pl_height
= 0;
3158 HashedProcessData
*hashed_process_data
= NULL
;
3160 ProcessList
*process_list
= control_flow_data
->process_list
;
3162 birth
= process
->creation_time
;
3164 if(likely(process_list
->current_hash_data
[cpu
] != NULL
) ){
3165 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3167 hashed_process_data
= processlist_get_process_data(process_list
,
3171 tfc
->t_context
->index
);
3172 if(unlikely(hashed_process_data
== NULL
))
3174 g_assert(pid
== 0 || pid
!= process
->ppid
);
3175 /* Process not present */
3176 Drawing_t
*drawing
= control_flow_data
->drawing
;
3177 ProcessInfo
*process_info
;
3178 processlist_add(process_list
,
3184 tfc
->t_context
->index
,
3188 &hashed_process_data
);
3189 gtk_widget_set_size_request(drawing
->drawing_area
,
3192 gtk_widget_queue_draw(drawing
->drawing_area
);
3195 /* Set the current process */
3196 process_list
->current_hash_data
[process
->cpu
] =
3197 hashed_process_data
;
3200 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3203 TimeWindow time_window
=
3204 lttvwindow_get_time_window(control_flow_data
->tab
);
3207 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3208 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3210 #endif //EXTRA_CHECK
3211 Drawing_t
*drawing
= control_flow_data
->drawing
;
3212 guint width
= drawing
->width
;
3214 convert_time_to_pixels(
3219 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3220 hashed_process_data
->x
.middle
= new_x
;
3221 hashed_process_data
->x
.middle_used
= FALSE
;
3222 hashed_process_data
->x
.middle_marked
= FALSE
;
3232 /* after_process_hook
3234 * Create the processlist entry for the child process. Put the last
3235 * position in x at the current time value.
3237 * @param hook_data ControlFlowData structure of the viewer.
3238 * @param call_data Event context.
3240 * This function adds items to be drawn in a queue for each process.
3243 int after_process_hook(void *hook_data
, void *call_data
)
3245 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3246 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3247 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3249 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3251 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3254 e
= ltt_tracefile_get_event(tfc
->tf
);
3256 LttTime evtime
= ltt_event_time(e
);
3261 LttField
*f
= ltt_event_field(e
);
3263 element
= ltt_field_member(f
,0);
3264 sub_id
= ltt_event_get_long_unsigned(e
,element
);
3265 element
= ltt_field_member(f
,1);
3266 param1
= ltt_event_get_long_unsigned(e
,element
);
3269 if(sub_id
== 2) { /* fork */
3271 guint child_pid
= param1
;
3272 /* Add process to process list (if not present) */
3273 LttvProcessState
*process_child
;
3275 guint pl_height
= 0;
3276 HashedProcessData
*hashed_process_data_child
= NULL
;
3278 ProcessList
*process_list
= control_flow_data
->process_list
;
3280 /* Find child in the list... */
3281 process_child
= lttv_state_find_process(tfs
, child_pid
);
3282 /* It should exist, because we are after the state update. */
3283 g_assert(process_child
!= NULL
);
3285 birth
= process_child
->creation_time
;
3287 /* Cannot use current process, because this action is done by the parent
3289 hashed_process_data_child
= processlist_get_process_data(process_list
,
3291 process_child
->last_cpu_index
,
3293 tfc
->t_context
->index
);
3294 if(likely(hashed_process_data_child
== NULL
))
3296 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3297 /* Process not present */
3298 Drawing_t
*drawing
= control_flow_data
->drawing
;
3299 const gchar
*name
= g_quark_to_string(process_child
->name
);
3300 ProcessInfo
*process_info
;
3301 processlist_add(process_list
,
3304 process_child
->last_cpu_index
,
3305 process_child
->ppid
,
3307 tfc
->t_context
->index
,
3311 &hashed_process_data_child
);
3312 gtk_widget_set_size_request(drawing
->drawing_area
,
3315 gtk_widget_queue_draw(drawing
->drawing_area
);
3319 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3322 TimeWindow time_window
=
3323 lttvwindow_get_time_window(control_flow_data
->tab
);
3326 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3327 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3329 #endif //EXTRA_CHECK
3330 Drawing_t
*drawing
= control_flow_data
->drawing
;
3331 guint width
= drawing
->width
;
3333 convert_time_to_pixels(
3339 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3340 hashed_process_data_child
->x
.over
= new_x
;
3341 hashed_process_data_child
->x
.over_used
= FALSE
;
3342 hashed_process_data_child
->x
.over_marked
= FALSE
;
3344 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3345 hashed_process_data_child
->x
.middle
= new_x
;
3346 hashed_process_data_child
->x
.middle_used
= FALSE
;
3347 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3349 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3350 hashed_process_data_child
->x
.under
= new_x
;
3351 hashed_process_data_child
->x
.under_used
= FALSE
;
3352 hashed_process_data_child
->x
.under_marked
= FALSE
;
3356 } else if(sub_id
== 3) { /* exit */
3358 /* Add process to process list (if not present) */
3359 LttvProcessState
*process
= tfs
->process
;
3360 guint pid
= process
->pid
;
3362 guint pl_height
= 0;
3363 HashedProcessData
*hashed_process_data
= NULL
;
3365 ProcessList
*process_list
= control_flow_data
->process_list
;
3367 /* It should exist, because we are after the state update. */
3368 g_assert(process
!= NULL
);
3370 birth
= process
->creation_time
;
3372 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
) ){
3373 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
3375 hashed_process_data
= processlist_get_process_data(process_list
,
3377 process
->last_cpu_index
,
3379 tfc
->t_context
->index
);
3380 if(unlikely(hashed_process_data
== NULL
))
3382 g_assert(pid
== 0 || pid
!= process
->ppid
);
3383 /* Process not present */
3384 Drawing_t
*drawing
= control_flow_data
->drawing
;
3385 const gchar
*name
= g_quark_to_string(process
->name
);
3386 ProcessInfo
*process_info
;
3387 processlist_add(process_list
,
3390 process
->last_cpu_index
,
3393 tfc
->t_context
->index
,
3397 &hashed_process_data
);
3398 gtk_widget_set_size_request(drawing
->drawing_area
,
3401 gtk_widget_queue_draw(drawing
->drawing_area
);
3404 /* Set the current process */
3405 process_list
->current_hash_data
[process
->last_cpu_index
] =
3406 hashed_process_data
;
3409 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3412 TimeWindow time_window
=
3413 lttvwindow_get_time_window(control_flow_data
->tab
);
3416 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3417 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3419 #endif //EXTRA_CHECK
3420 Drawing_t
*drawing
= control_flow_data
->drawing
;
3421 guint width
= drawing
->width
;
3423 convert_time_to_pixels(
3428 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3429 hashed_process_data
->x
.middle
= new_x
;
3430 hashed_process_data
->x
.middle_used
= FALSE
;
3431 hashed_process_data
->x
.middle_marked
= FALSE
;
3441 /* Get the filename of the process to print */
3442 int after_fs_exec_hook(void *hook_data
, void *call_data
)
3444 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3445 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3446 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3448 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3450 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3452 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3454 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3455 LttvProcessState
*process
= ts
->running_process
[cpu
];
3456 g_assert(process
!= NULL
);
3458 guint pid
= process
->pid
;
3460 /* Well, the process_out existed : we must get it in the process hash
3461 * or add it, and draw its items.
3463 /* Add process to process list (if not present) */
3464 guint pl_height
= 0;
3465 HashedProcessData
*hashed_process_data
= NULL
;
3466 ProcessList
*process_list
= control_flow_data
->process_list
;
3467 LttTime birth
= process
->creation_time
;
3469 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
3470 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3472 hashed_process_data
= processlist_get_process_data(process_list
,
3476 tfc
->t_context
->index
);
3477 if(unlikely(hashed_process_data
== NULL
))
3479 g_assert(pid
== 0 || pid
!= process
->ppid
);
3480 ProcessInfo
*process_info
;
3481 /* Process not present */
3482 Drawing_t
*drawing
= control_flow_data
->drawing
;
3483 processlist_add(process_list
,
3489 tfc
->t_context
->index
,
3493 &hashed_process_data
);
3494 gtk_widget_set_size_request(drawing
->drawing_area
,
3497 gtk_widget_queue_draw(drawing
->drawing_area
);
3499 /* Set the current process */
3500 process_list
->current_hash_data
[process
->cpu
] =
3501 hashed_process_data
;
3504 processlist_set_name(process_list
, process
->name
, hashed_process_data
);
3513 gint
update_time_window_hook(void *hook_data
, void *call_data
)
3515 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3516 Drawing_t
*drawing
= control_flow_data
->drawing
;
3517 ProcessList
*process_list
= control_flow_data
->process_list
;
3519 const TimeWindowNotifyData
*time_window_nofify_data
=
3520 ((const TimeWindowNotifyData
*)call_data
);
3522 TimeWindow
*old_time_window
=
3523 time_window_nofify_data
->old_time_window
;
3524 TimeWindow
*new_time_window
=
3525 time_window_nofify_data
->new_time_window
;
3527 /* Update the ruler */
3528 drawing_update_ruler(control_flow_data
->drawing
,
3532 /* Two cases : zoom in/out or scrolling */
3534 /* In order to make sure we can reuse the old drawing, the scale must
3535 * be the same and the new time interval being partly located in the
3536 * currently shown time interval. (reuse is only for scrolling)
3539 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3540 old_time_window
->start_time
.tv_sec
,
3541 old_time_window
->start_time
.tv_nsec
,
3542 old_time_window
->time_width
.tv_sec
,
3543 old_time_window
->time_width
.tv_nsec
);
3545 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3546 new_time_window
->start_time
.tv_sec
,
3547 new_time_window
->start_time
.tv_nsec
,
3548 new_time_window
->time_width
.tv_sec
,
3549 new_time_window
->time_width
.tv_nsec
);
3551 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
3552 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
3554 /* Same scale (scrolling) */
3555 g_info("scrolling");
3556 LttTime
*ns
= &new_time_window
->start_time
;
3557 LttTime
*nw
= &new_time_window
->time_width
;
3558 LttTime
*os
= &old_time_window
->start_time
;
3559 LttTime
*ow
= &old_time_window
->time_width
;
3560 LttTime old_end
= old_time_window
->end_time
;
3561 LttTime new_end
= new_time_window
->end_time
;
3563 //if(ns<os+w && os+w<ns+w)
3564 //if(ns<old_end && os<ns)
3565 if(ltt_time_compare(*ns
, old_end
) == -1
3566 && ltt_time_compare(*os
, *ns
) == -1)
3568 g_info("scrolling near right");
3569 /* Scroll right, keep right part of the screen */
3571 guint width
= control_flow_data
->drawing
->width
;
3572 convert_time_to_pixels(
3578 /* Copy old data to new location */
3579 copy_pixmap_region(process_list
,
3581 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3585 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
3587 if(drawing
->damage_begin
== drawing
->damage_end
)
3588 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
3590 drawing
->damage_begin
= 0;
3592 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3594 /* Clear the data request background, but not SAFETY */
3595 rectangle_pixmap(process_list
,
3596 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3598 drawing
->damage_begin
+SAFETY
, 0,
3599 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3601 gtk_widget_queue_draw(drawing
->drawing_area
);
3602 //gtk_widget_queue_draw_area (drawing->drawing_area,
3604 // control_flow_data->drawing->width,
3605 // control_flow_data->drawing->height);
3607 /* Get new data for the rest. */
3608 drawing_data_request(control_flow_data
->drawing
,
3609 drawing
->damage_begin
, 0,
3610 drawing
->damage_end
- drawing
->damage_begin
,
3611 control_flow_data
->drawing
->height
);
3614 //if(ns<os && os<ns+w)
3615 //if(ns<os && os<new_end)
3616 if(ltt_time_compare(*ns
,*os
) == -1
3617 && ltt_time_compare(*os
,new_end
) == -1)
3619 g_info("scrolling near left");
3620 /* Scroll left, keep left part of the screen */
3622 guint width
= control_flow_data
->drawing
->width
;
3623 convert_time_to_pixels(
3629 /* Copy old data to new location */
3630 copy_pixmap_region (process_list
,
3632 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3638 if(drawing
->damage_begin
== drawing
->damage_end
)
3639 drawing
->damage_end
= x
;
3641 drawing
->damage_end
=
3642 control_flow_data
->drawing
->width
;
3644 drawing
->damage_begin
= 0;
3646 rectangle_pixmap (process_list
,
3647 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3649 drawing
->damage_begin
, 0,
3650 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3653 gtk_widget_queue_draw(drawing
->drawing_area
);
3654 //gtk_widget_queue_draw_area (drawing->drawing_area,
3656 // control_flow_data->drawing->width,
3657 // control_flow_data->drawing->height);
3660 /* Get new data for the rest. */
3661 drawing_data_request(control_flow_data
->drawing
,
3662 drawing
->damage_begin
, 0,
3663 drawing
->damage_end
- drawing
->damage_begin
,
3664 control_flow_data
->drawing
->height
);
3667 if(ltt_time_compare(*ns
,*os
) == 0)
3669 g_info("not scrolling");
3671 g_info("scrolling far");
3672 /* Cannot reuse any part of the screen : far jump */
3675 rectangle_pixmap (process_list
,
3676 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3679 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3682 //gtk_widget_queue_draw_area (drawing->drawing_area,
3684 // control_flow_data->drawing->width,
3685 // control_flow_data->drawing->height);
3686 gtk_widget_queue_draw(drawing
->drawing_area
);
3688 drawing
->damage_begin
= 0;
3689 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3691 drawing_data_request(control_flow_data
->drawing
,
3693 control_flow_data
->drawing
->width
,
3694 control_flow_data
->drawing
->height
);
3700 /* Different scale (zoom) */
3703 rectangle_pixmap (process_list
,
3704 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3707 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3710 //gtk_widget_queue_draw_area (drawing->drawing_area,
3712 // control_flow_data->drawing->width,
3713 // control_flow_data->drawing->height);
3714 gtk_widget_queue_draw(drawing
->drawing_area
);
3716 drawing
->damage_begin
= 0;
3717 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3719 drawing_data_request(control_flow_data
->drawing
,
3721 control_flow_data
->drawing
->width
,
3722 control_flow_data
->drawing
->height
);
3730 gint
traceset_notify(void *hook_data
, void *call_data
)
3732 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3733 Drawing_t
*drawing
= control_flow_data
->drawing
;
3736 drawing_clear(control_flow_data
->drawing
);
3737 processlist_clear(control_flow_data
->process_list
);
3738 gtk_widget_set_size_request(
3739 control_flow_data
->drawing
->drawing_area
,
3740 -1, processlist_get_height(control_flow_data
->process_list
));
3741 redraw_notify(control_flow_data
, NULL
);
3743 request_background_data(control_flow_data
);
3748 gint
redraw_notify(void *hook_data
, void *call_data
)
3750 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3751 Drawing_t
*drawing
= control_flow_data
->drawing
;
3752 GtkWidget
*widget
= drawing
->drawing_area
;
3754 drawing
->damage_begin
= 0;
3755 drawing
->damage_end
= drawing
->width
;
3757 /* fun feature, to be separated someday... */
3758 drawing_clear(control_flow_data
->drawing
);
3759 processlist_clear(control_flow_data
->process_list
);
3760 gtk_widget_set_size_request(
3761 control_flow_data
->drawing
->drawing_area
,
3762 -1, processlist_get_height(control_flow_data
->process_list
));
3764 rectangle_pixmap (control_flow_data
->process_list
,
3765 widget
->style
->black_gc
,
3768 drawing
->alloc_width
,
3771 gtk_widget_queue_draw(drawing
->drawing_area
);
3773 if(drawing
->damage_begin
< drawing
->damage_end
)
3775 drawing_data_request(drawing
,
3776 drawing
->damage_begin
,
3778 drawing
->damage_end
-drawing
->damage_begin
,
3782 //gtk_widget_queue_draw_area(drawing->drawing_area,
3785 // drawing->height);
3791 gint
continue_notify(void *hook_data
, void *call_data
)
3793 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3794 Drawing_t
*drawing
= control_flow_data
->drawing
;
3796 //g_assert(widget->allocation.width == drawing->damage_end);
3798 if(drawing
->damage_begin
< drawing
->damage_end
)
3800 drawing_data_request(drawing
,
3801 drawing
->damage_begin
,
3803 drawing
->damage_end
-drawing
->damage_begin
,
3811 gint
update_current_time_hook(void *hook_data
, void *call_data
)
3813 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
3814 Drawing_t
*drawing
= control_flow_data
->drawing
;
3816 LttTime current_time
= *((LttTime
*)call_data
);
3818 TimeWindow time_window
=
3819 lttvwindow_get_time_window(control_flow_data
->tab
);
3821 LttTime time_begin
= time_window
.start_time
;
3822 LttTime width
= time_window
.time_width
;
3825 guint64 time_ll
= ltt_time_to_uint64(width
);
3826 time_ll
= time_ll
>> 1; /* divide by two */
3827 half_width
= ltt_time_from_uint64(time_ll
);
3829 LttTime time_end
= ltt_time_add(time_begin
, width
);
3831 LttvTracesetContext
* tsc
=
3832 lttvwindow_get_traceset_context(control_flow_data
->tab
);
3834 LttTime trace_start
= tsc
->time_span
.start_time
;
3835 LttTime trace_end
= tsc
->time_span
.end_time
;
3837 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
3838 current_time
.tv_nsec
);
3842 /* If current time is inside time interval, just move the highlight
3845 /* Else, we have to change the time interval. We have to tell it
3846 * to the main window. */
3847 /* The time interval change will take care of placing the current
3848 * time at the center of the visible area, or nearest possible if we are
3849 * at one end of the trace. */
3852 if(ltt_time_compare(current_time
, time_begin
) < 0)
3854 TimeWindow new_time_window
;
3856 if(ltt_time_compare(current_time
,
3857 ltt_time_add(trace_start
,half_width
)) < 0)
3858 time_begin
= trace_start
;
3860 time_begin
= ltt_time_sub(current_time
,half_width
);
3862 new_time_window
.start_time
= time_begin
;
3863 new_time_window
.time_width
= width
;
3864 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3865 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3867 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3869 else if(ltt_time_compare(current_time
, time_end
) > 0)
3871 TimeWindow new_time_window
;
3873 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
3874 time_begin
= ltt_time_sub(trace_end
,width
);
3876 time_begin
= ltt_time_sub(current_time
,half_width
);
3878 new_time_window
.start_time
= time_begin
;
3879 new_time_window
.time_width
= width
;
3880 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3881 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3883 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3886 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
3892 typedef struct _ClosureData
{
3893 EventsRequest
*events_request
;
3894 LttvTracesetState
*tss
;
3900 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
3902 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
3903 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
3904 ClosureData
*closure_data
= (ClosureData
*)user_data
;
3906 EventsRequest
*events_request
= closure_data
->events_request
;
3907 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3909 LttvTracesetState
*tss
= closure_data
->tss
;
3910 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
3912 LttTime evtime
= closure_data
->end_time
;
3915 /* For the process */
3916 /* First, check if the current process is in the state computation
3917 * process list. If it is there, that means we must add it right now and
3918 * draw items from the beginning of the read for it. If it is not
3919 * present, it's a new process and it was not present : it will
3920 * be added after the state update. */
3922 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
3923 #endif //EXTRA_CHECK
3924 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
3925 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
3928 //FIXME : optimize data structures.
3929 LttvTracefileState
*tfs
;
3930 LttvTracefileContext
*tfc
;
3932 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
3933 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
3934 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
3935 && ltt_tracefile_num(tfc
->tf
) == process_info
->cpu
)
3939 g_assert(i
<tc
->tracefiles
->len
);
3940 tfs
= LTTV_TRACEFILE_STATE(tfc
);
3942 // LttvTracefileState *tfs =
3943 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3944 // tracefiles[process_info->cpu];
3946 LttvProcessState
*process
;
3947 process
= lttv_state_find_process(ts
, process_info
->cpu
,
3950 if(unlikely(process
!= NULL
)) {
3952 /* Only draw for processes that are currently in the trace states */
3954 ProcessList
*process_list
= control_flow_data
->process_list
;
3956 /* Should be alike when background info is ready */
3957 if(control_flow_data
->background_info_waiting
==0)
3958 g_assert(ltt_time_compare(process
->creation_time
,
3959 process_info
->birth
) == 0);
3960 #endif //EXTRA_CHECK
3962 /* Now, the process is in the state hash and our own process hash.
3963 * We definitely can draw the items related to the ending state.
3966 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3969 TimeWindow time_window
=
3970 lttvwindow_get_time_window(control_flow_data
->tab
);
3973 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3974 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3976 #endif //EXTRA_CHECK
3977 Drawing_t
*drawing
= control_flow_data
->drawing
;
3978 guint width
= drawing
->width
;
3980 guint x
= closure_data
->x_end
;
3982 DrawContext draw_context
;
3984 /* Now create the drawing context that will be used to draw
3985 * items related to the last state. */
3986 draw_context
.drawable
= hashed_process_data
->pixmap
;
3987 draw_context
.gc
= drawing
->gc
;
3988 draw_context
.pango_layout
= drawing
->pango_layout
;
3989 draw_context
.drawinfo
.end
.x
= x
;
3991 draw_context
.drawinfo
.y
.over
= 1;
3992 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
3993 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
3995 draw_context
.drawinfo
.start
.offset
.over
= 0;
3996 draw_context
.drawinfo
.start
.offset
.middle
= 0;
3997 draw_context
.drawinfo
.start
.offset
.under
= 0;
3998 draw_context
.drawinfo
.end
.offset
.over
= 0;
3999 draw_context
.drawinfo
.end
.offset
.middle
= 0;
4000 draw_context
.drawinfo
.end
.offset
.under
= 0;
4002 /* Jump over draw if we are at the same x position */
4003 if(x
== hashed_process_data
->x
.over
)
4007 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
4009 PropertiesLine prop_line
= prepare_execmode_line(process
);
4010 draw_line((void*)&prop_line
, (void*)&draw_context
);
4012 hashed_process_data
->x
.over
= x
;
4016 if(unlikely(x
== hashed_process_data
->x
.middle
&&
4017 hashed_process_data
->x
.middle_used
)) {
4018 #if 0 /* do not mark closure : not missing information */
4019 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
4020 /* Draw collision indicator */
4021 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
4022 gdk_draw_point(drawing
->pixmap
,
4026 hashed_process_data
->x
.middle_marked
= TRUE
;
4031 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
4033 PropertiesLine prop_line
= prepare_s_e_line(process
);
4034 draw_line((void*)&prop_line
, (void*)&draw_context
);
4036 /* become the last x position */
4037 if(likely(x
!= hashed_process_data
->x
.middle
)) {
4038 hashed_process_data
->x
.middle
= x
;
4039 /* but don't use the pixel */
4040 hashed_process_data
->x
.middle_used
= FALSE
;
4042 /* Calculate the next good time */
4043 convert_pixels_to_time(width
, x
+1, time_window
,
4044 &hashed_process_data
->next_good_time
);
4053 int before_chunk(void *hook_data
, void *call_data
)
4055 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4056 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4057 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
4059 /* Desactivate sort */
4060 gtk_tree_sortable_set_sort_column_id(
4061 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
4063 GTK_SORT_ASCENDING
);
4065 drawing_chunk_begin(events_request
, tss
);
4070 int before_request(void *hook_data
, void *call_data
)
4072 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4073 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4075 drawing_data_request_begin(events_request
, tss
);
4082 * after request is necessary in addition of after chunk in order to draw
4083 * lines until the end of the screen. after chunk just draws lines until
4090 int after_request(void *hook_data
, void *call_data
)
4092 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4093 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4094 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4096 ProcessList
*process_list
= control_flow_data
->process_list
;
4097 LttTime end_time
= events_request
->end_time
;
4099 ClosureData closure_data
;
4100 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4101 closure_data
.tss
= tss
;
4102 closure_data
.end_time
= end_time
;
4104 TimeWindow time_window
=
4105 lttvwindow_get_time_window(control_flow_data
->tab
);
4106 guint width
= control_flow_data
->drawing
->width
;
4107 convert_time_to_pixels(
4111 &closure_data
.x_end
);
4114 /* Draw last items */
4115 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4116 (void*)&closure_data
);
4119 /* Request expose */
4120 drawing_request_expose(events_request
, tss
, end_time
);
4129 int after_chunk(void *hook_data
, void *call_data
)
4131 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4132 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4133 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4134 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
4135 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
4138 ProcessList
*process_list
= control_flow_data
->process_list
;
4140 g_free(process_list
->current_hash_data
);
4141 process_list
->current_hash_data
= NULL
;
4144 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
4145 else /* end of traceset, or position now out of request : end */
4146 end_time
= events_request
->end_time
;
4148 ClosureData closure_data
;
4149 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4150 closure_data
.tss
= tss
;
4151 closure_data
.end_time
= end_time
;
4153 TimeWindow time_window
=
4154 lttvwindow_get_time_window(control_flow_data
->tab
);
4155 guint width
= control_flow_data
->drawing
->width
;
4156 convert_time_to_pixels(
4160 &closure_data
.x_end
);
4162 /* Draw last items */
4163 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4164 (void*)&closure_data
);
4166 /* Reactivate sort */
4167 gtk_tree_sortable_set_sort_column_id(
4168 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
4169 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
4170 GTK_SORT_ASCENDING
);
4172 update_index_to_pixmap(control_flow_data
->process_list
);
4173 /* Request a full expose : drawing scrambled */
4174 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
4176 /* Request expose (updates damages zone also) */
4177 drawing_request_expose(events_request
, tss
, end_time
);