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
;
390 e
= ltt_tracefile_get_event(tfc
->tf
);
392 LttTime evtime
= ltt_event_time(e
);
394 /* we are in a schedchange, before the state update. We must draw the
395 * items corresponding to the state before it changes : now is the right
402 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
403 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
407 /* For the pid_out */
408 /* First, check if the current process is in the state computation
409 * process list. If it is there, that means we must add it right now and
410 * draw items from the beginning of the read for it. If it is not
411 * present, it's a new process and it was not present : it will
412 * be added after the state update. */
413 LttvProcessState
*process
;
414 /* unknown state, bad current pid */
415 if(tfs
->process
->pid
!= pid_out
)
416 process
= lttv_state_find_process(tfs
, pid_out
);
418 process
= tfs
->process
;
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
,
432 process
->last_cpu_index
,
434 tfc
->t_context
->index
);
435 if(hashed_process_data
== NULL
)
437 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
438 const gchar
*name
= g_quark_to_string(process
->name
);
439 /* Process not present */
440 ProcessInfo
*process_info
;
441 Drawing_t
*drawing
= control_flow_data
->drawing
;
442 processlist_add(process_list
,
445 process
->last_cpu_index
,
448 tfc
->t_context
->index
,
452 &hashed_process_data
);
453 gtk_widget_set_size_request(drawing
->drawing_area
,
456 gtk_widget_queue_draw(drawing
->drawing_area
);
460 /* Now, the process is in the state hash and our own process hash.
461 * We definitely can draw the items related to the ending state.
464 if(ltt_time_compare(hashed_process_data
->next_good_time
,
467 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
469 TimeWindow time_window
=
470 lttvwindow_get_time_window(control_flow_data
->tab
);
472 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
473 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
476 Drawing_t
*drawing
= control_flow_data
->drawing
;
477 guint width
= drawing
->width
;
479 convert_time_to_pixels(
485 /* Draw collision indicator */
486 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
487 gdk_draw_point(hashed_process_data
->pixmap
,
490 (hashed_process_data
->height
/2)-3);
491 hashed_process_data
->x
.middle_marked
= TRUE
;
494 TimeWindow time_window
=
495 lttvwindow_get_time_window(control_flow_data
->tab
);
497 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
498 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
501 Drawing_t
*drawing
= control_flow_data
->drawing
;
502 guint width
= drawing
->width
;
504 convert_time_to_pixels(
511 /* Jump over draw if we are at the same x position */
512 if(x
== hashed_process_data
->x
.middle
&&
513 hashed_process_data
->x
.middle_used
)
515 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
516 /* Draw collision indicator */
517 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
518 gdk_draw_point(hashed_process_data
->pixmap
,
521 (hashed_process_data
->height
/2)-3);
522 hashed_process_data
->x
.middle_marked
= TRUE
;
526 DrawContext draw_context
;
528 /* Now create the drawing context that will be used to draw
529 * items related to the last state. */
530 draw_context
.drawable
= hashed_process_data
->pixmap
;
531 draw_context
.gc
= drawing
->gc
;
532 draw_context
.pango_layout
= drawing
->pango_layout
;
533 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
534 draw_context
.drawinfo
.end
.x
= x
;
536 draw_context
.drawinfo
.y
.over
= 1;
537 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
538 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
540 draw_context
.drawinfo
.start
.offset
.over
= 0;
541 draw_context
.drawinfo
.start
.offset
.middle
= 0;
542 draw_context
.drawinfo
.start
.offset
.under
= 0;
543 draw_context
.drawinfo
.end
.offset
.over
= 0;
544 draw_context
.drawinfo
.end
.offset
.middle
= 0;
545 draw_context
.drawinfo
.end
.offset
.under
= 0;
549 PropertiesLine prop_line
= prepare_s_e_line(process
);
550 draw_line((void*)&prop_line
, (void*)&draw_context
);
553 /* become the last x position */
554 hashed_process_data
->x
.middle
= x
;
555 hashed_process_data
->x
.middle_used
= TRUE
;
556 hashed_process_data
->x
.middle_marked
= FALSE
;
558 /* Calculate the next good time */
559 convert_pixels_to_time(width
, x
+1, time_window
,
560 &hashed_process_data
->next_good_time
);
568 /* First, check if the current process is in the state computation
569 * process list. If it is there, that means we must add it right now and
570 * draw items from the beginning of the read for it. If it is not
571 * present, it's a new process and it was not present : it will
572 * be added after the state update. */
573 LttvProcessState
*process
;
574 process
= lttv_state_find_process(tfs
, pid_in
);
576 if(process
!= NULL
) {
577 /* Well, the process_out existed : we must get it in the process hash
578 * or add it, and draw its items.
580 /* Add process to process list (if not present) */
582 HashedProcessData
*hashed_process_data
= NULL
;
583 ProcessList
*process_list
= control_flow_data
->process_list
;
584 LttTime birth
= process
->creation_time
;
586 hashed_process_data
= processlist_get_process_data(process_list
,
588 process
->last_cpu_index
,
590 tfc
->t_context
->index
);
591 if(hashed_process_data
== NULL
)
593 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
594 const gchar
*name
= g_quark_to_string(process
->name
);
595 /* Process not present */
596 ProcessInfo
*process_info
;
597 Drawing_t
*drawing
= control_flow_data
->drawing
;
598 processlist_add(process_list
,
601 process
->last_cpu_index
,
604 tfc
->t_context
->index
,
608 &hashed_process_data
);
609 gtk_widget_set_size_request(drawing
->drawing_area
,
612 gtk_widget_queue_draw(drawing
->drawing_area
);
615 //We could set the current process and hash here, but will be done
616 //by after schedchange hook
618 /* Now, the process is in the state hash and our own process hash.
619 * We definitely can draw the items related to the ending state.
622 if(ltt_time_compare(hashed_process_data
->next_good_time
,
625 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
627 TimeWindow time_window
=
628 lttvwindow_get_time_window(control_flow_data
->tab
);
630 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
631 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
634 Drawing_t
*drawing
= control_flow_data
->drawing
;
635 guint width
= drawing
->width
;
637 convert_time_to_pixels(
643 /* Draw collision indicator */
644 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
645 gdk_draw_point(hashed_process_data
->pixmap
,
648 (hashed_process_data
->height
/2)-3);
649 hashed_process_data
->x
.middle_marked
= TRUE
;
652 TimeWindow time_window
=
653 lttvwindow_get_time_window(control_flow_data
->tab
);
655 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
656 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
659 Drawing_t
*drawing
= control_flow_data
->drawing
;
660 guint width
= drawing
->width
;
663 convert_time_to_pixels(
670 /* Jump over draw if we are at the same x position */
671 if(x
== hashed_process_data
->x
.middle
&&
672 hashed_process_data
->x
.middle_used
)
674 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
675 /* Draw collision indicator */
676 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
677 gdk_draw_point(hashed_process_data
->pixmap
,
680 (hashed_process_data
->height
/2)-3);
681 hashed_process_data
->x
.middle_marked
= TRUE
;
685 DrawContext draw_context
;
687 /* Now create the drawing context that will be used to draw
688 * items related to the last state. */
689 draw_context
.drawable
= hashed_process_data
->pixmap
;
690 draw_context
.gc
= drawing
->gc
;
691 draw_context
.pango_layout
= drawing
->pango_layout
;
692 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
693 draw_context
.drawinfo
.end
.x
= x
;
695 draw_context
.drawinfo
.y
.over
= 1;
696 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
697 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
699 draw_context
.drawinfo
.start
.offset
.over
= 0;
700 draw_context
.drawinfo
.start
.offset
.middle
= 0;
701 draw_context
.drawinfo
.start
.offset
.under
= 0;
702 draw_context
.drawinfo
.end
.offset
.over
= 0;
703 draw_context
.drawinfo
.end
.offset
.middle
= 0;
704 draw_context
.drawinfo
.end
.offset
.under
= 0;
708 PropertiesLine prop_line
= prepare_s_e_line(process
);
709 draw_line((void*)&prop_line
, (void*)&draw_context
);
713 /* become the last x position */
714 hashed_process_data
->x
.middle
= x
;
715 hashed_process_data
->x
.middle_used
= TRUE
;
716 hashed_process_data
->x
.middle_marked
= FALSE
;
718 /* Calculate the next good time */
719 convert_pixels_to_time(width
, x
+1, time_window
,
720 &hashed_process_data
->next_good_time
);
729 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
730 ControlFlowData
*control_flow_data
=
731 (ControlFlowData
*)events_request
->viewer_data
;
732 Tab
*tab
= control_flow_data
->tab
;
734 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
736 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
737 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
742 LttTime evtime
= ltt_event_time(e
);
743 TimeWindow time_window
=
744 lttvwindow_get_time_window(tab
);
746 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
748 //if(time < time_beg || time > time_end) return;
749 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
750 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
753 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
755 g_debug("schedchange!");
757 /* Add process to process list (if not present) and get drawing "y" from
758 * process position */
759 guint pid_out
, pid_in
;
760 LttvProcessState
*process_out
, *process_in
;
762 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
764 ProcessList
*process_list
= control_flow_data
->process_list
;
767 LttField
*f
= ltt_event_field(e
);
769 element
= ltt_field_member(f
,0);
770 pid_out
= ltt_event_get_long_unsigned(e
,element
);
771 element
= ltt_field_member(f
,1);
772 pid_in
= ltt_event_get_long_unsigned(e
,element
);
773 g_debug("out : %u in : %u", pid_out
, pid_in
);
776 /* Find process pid_out in the list... */
777 process_out
= lttv_state_find_process(tfs
, pid_out
);
778 if(process_out
== NULL
) return 0;
779 g_debug("out : %s",g_quark_to_string(process_out
->state
->s
));
781 birth
= process_out
->creation_time
;
782 const gchar
*name
= g_quark_to_string(process_out
->name
);
783 HashedProcessData
*hashed_process_data_out
= NULL
;
785 if(processlist_get_process_pixels(process_list
,
788 tfc
->t_context
->index
,
791 &hashed_process_data_out
) == 1)
793 /* Process not present */
794 processlist_add(process_list
,
797 tfc
->t_context
->index
,
800 &hashed_process_data_out
);
801 g_assert(processlist_get_process_pixels(process_list
,
804 tfc
->t_context
->index
,
807 &hashed_process_data_out
)==0);
808 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
812 /* Find process pid_in in the list... */
813 process_in
= lttv_state_find_process(tfs
, pid_in
);
814 if(process_in
== NULL
) return 0;
815 g_debug("in : %s",g_quark_to_string(process_in
->state
->s
));
817 birth
= process_in
->creation_time
;
818 name
= g_quark_to_string(process_in
->name
);
819 HashedProcessData
*hashed_process_data_in
= NULL
;
821 if(processlist_get_process_pixels(process_list
,
824 tfc
->t_context
->index
,
827 &hashed_process_data_in
) == 1)
829 /* Process not present */
830 processlist_add(process_list
,
833 tfc
->t_context
->index
,
836 &hashed_process_data_in
);
837 processlist_get_process_pixels(process_list
,
840 tfc
->t_context
->index
,
843 &hashed_process_data_in
);
845 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
850 /* Find pixels corresponding to time of the event. If the time does
851 * not fit in the window, show a warning, not supposed to happend. */
853 guint width
= control_flow_data
->drawing
->width
;
855 LttTime time
= ltt_event_time(e
);
857 LttTime window_end
= time_window
.time_window
.end_time
;
859 convert_time_to_pixels(
864 //assert(x <= width);
866 /* draw what represents the event for outgoing process. */
868 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
869 draw_context_out
->current
->modify_over
->x
= x
;
870 draw_context_out
->current
->modify_under
->x
= x
;
871 draw_context_out
->current
->modify_over
->y
= y_out
;
872 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
873 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
874 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
875 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
876 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
877 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
878 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
879 //draw_context_out->gc = widget->style->black_gc;
881 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
882 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
884 /* Draw the line/background of the out process */
885 if(draw_context_out
->previous
->middle
->x
== -1)
887 draw_context_out
->previous
->over
->x
=
888 control_flow_data
->drawing
->damage_begin
;
889 draw_context_out
->previous
->middle
->x
=
890 control_flow_data
->drawing
->damage_begin
;
891 draw_context_out
->previous
->under
->x
=
892 control_flow_data
->drawing
->damage_begin
;
893 g_debug("out middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
896 draw_context_out
->current
->middle
->x
= x
;
897 draw_context_out
->current
->over
->x
= x
;
898 draw_context_out
->current
->under
->x
= x
;
899 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
900 draw_context_out
->current
->over
->y
= y_out
;
901 draw_context_out
->current
->under
->y
= y_out
+ height
;
902 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
903 draw_context_out
->previous
->over
->y
= y_out
;
904 draw_context_out
->previous
->under
->y
= y_out
+ height
;
906 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
907 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
909 if(process_out
->state
->s
== LTTV_STATE_RUN
)
911 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
912 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
913 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
915 PropertiesBG prop_bg
;
916 prop_bg
.color
= g_new(GdkColor
,1);
918 switch(ltt_tracefile_num(tfc
->tf
)) {
920 prop_bg
.color
->red
= 0x1515;
921 prop_bg
.color
->green
= 0x1515;
922 prop_bg
.color
->blue
= 0x8c8c;
925 prop_bg
.color
->red
= 0x4e4e;
926 prop_bg
.color
->green
= 0xa9a9;
927 prop_bg
.color
->blue
= 0xa4a4;
930 prop_bg
.color
->red
= 0x7a7a;
931 prop_bg
.color
->green
= 0x4a4a;
932 prop_bg
.color
->blue
= 0x8b8b;
935 prop_bg
.color
->red
= 0x8080;
936 prop_bg
.color
->green
= 0x7777;
937 prop_bg
.color
->blue
= 0x4747;
940 prop_bg
.color
->red
= 0xe7e7;
941 prop_bg
.color
->green
= 0xe7e7;
942 prop_bg
.color
->blue
= 0xe7e7;
945 g_debug("calling from draw_event");
946 draw_bg((void*)&prop_bg
, (void*)draw_context_out
);
947 g_free(prop_bg
.color
);
948 //gdk_gc_unref(draw_context_out->gc);
951 draw_context_out
->gc
= widget
->style
->black_gc
;
953 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
954 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
955 PropertiesText prop_text_out
;
956 prop_text_out
.foreground
= &colorfg_out
;
957 prop_text_out
.background
= &colorbg_out
;
958 prop_text_out
.size
= 6;
959 prop_text_out
.position
= OVER
;
961 /* color of text : status of the process */
962 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
964 prop_text_out
.foreground
->red
= 0xffff;
965 prop_text_out
.foreground
->green
= 0xffff;
966 prop_text_out
.foreground
->blue
= 0xffff;
968 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
970 prop_text_out
.foreground
->red
= 0x0fff;
971 prop_text_out
.foreground
->green
= 0xffff;
972 prop_text_out
.foreground
->blue
= 0xfff0;
974 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
976 prop_text_out
.foreground
->red
= 0xffff;
977 prop_text_out
.foreground
->green
= 0xffff;
978 prop_text_out
.foreground
->blue
= 0x0000;
980 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
982 prop_text_out
.foreground
->red
= 0xffff;
983 prop_text_out
.foreground
->green
= 0x0000;
984 prop_text_out
.foreground
->blue
= 0xffff;
986 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
988 prop_text_out
.foreground
->red
= 0xffff;
989 prop_text_out
.foreground
->green
= 0x0000;
990 prop_text_out
.foreground
->blue
= 0x0000;
992 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
994 prop_text_out
.foreground
->red
= 0x0000;
995 prop_text_out
.foreground
->green
= 0xffff;
996 prop_text_out
.foreground
->blue
= 0x0000;
1000 prop_text_out
.foreground
->red
= 0xffff;
1001 prop_text_out
.foreground
->green
= 0xffff;
1002 prop_text_out
.foreground
->blue
= 0xffff;
1006 /* Print status of the process : U, WF, WC, E, W, R */
1007 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1008 prop_text_out
.text
= "U->";
1009 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1010 prop_text_out
.text
= "WF->";
1011 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1012 prop_text_out
.text
= "WC->";
1013 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1014 prop_text_out
.text
= "E->";
1015 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1016 prop_text_out
.text
= "W->";
1017 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1018 prop_text_out
.text
= "R->";
1020 prop_text_out
.text
= "U";
1022 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1023 //gdk_gc_unref(draw_context_out->gc);
1025 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1026 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1027 draw_context_out
->gc
= control_flow_data
->drawing
->gc
;
1029 PropertiesLine prop_line_out
;
1030 prop_line_out
.color
= g_new(GdkColor
,1);
1031 prop_line_out
.line_width
= 2;
1032 prop_line_out
.style
= GDK_LINE_SOLID
;
1033 prop_line_out
.position
= MIDDLE
;
1035 g_debug("out state : %s", g_quark_to_string(process_out
->state
->s
));
1037 /* color of line : status of the process */
1038 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1040 prop_line_out
.color
->red
= 0xffff;
1041 prop_line_out
.color
->green
= 0xffff;
1042 prop_line_out
.color
->blue
= 0xffff;
1044 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1046 prop_line_out
.color
->red
= 0x0fff;
1047 prop_line_out
.color
->green
= 0xffff;
1048 prop_line_out
.color
->blue
= 0xfff0;
1050 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1052 prop_line_out
.color
->red
= 0xffff;
1053 prop_line_out
.color
->green
= 0xffff;
1054 prop_line_out
.color
->blue
= 0x0000;
1056 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1058 prop_line_out
.color
->red
= 0xffff;
1059 prop_line_out
.color
->green
= 0x0000;
1060 prop_line_out
.color
->blue
= 0xffff;
1062 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1064 prop_line_out
.color
->red
= 0xffff;
1065 prop_line_out
.color
->green
= 0x0000;
1066 prop_line_out
.color
->blue
= 0x0000;
1068 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1070 prop_line_out
.color
->red
= 0x0000;
1071 prop_line_out
.color
->green
= 0xffff;
1072 prop_line_out
.color
->blue
= 0x0000;
1076 prop_line_out
.color
->red
= 0xffff;
1077 prop_line_out
.color
->green
= 0xffff;
1078 prop_line_out
.color
->blue
= 0xffff;
1081 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
1082 g_free(prop_line_out
.color
);
1083 //gdk_gc_unref(draw_context_out->gc);
1084 /* Note : finishing line will have to be added when trace read over. */
1086 /* Finally, update the drawing context of the pid_in. */
1088 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1089 draw_context_in
->current
->modify_over
->x
= x
;
1090 draw_context_in
->current
->modify_under
->x
= x
;
1091 draw_context_in
->current
->modify_over
->y
= y_in
;
1092 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1093 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1094 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1095 widget
= control_flow_data
->drawing
->drawing_area
;
1096 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1097 //draw_context_in->gc = widget->style->black_gc;
1098 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1099 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1101 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1102 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1104 /* Draw the line/bg of the in process */
1105 if(draw_context_in
->previous
->middle
->x
== -1)
1107 draw_context_in
->previous
->over
->x
=
1108 control_flow_data
->drawing
->damage_begin
;
1109 draw_context_in
->previous
->middle
->x
=
1110 control_flow_data
->drawing
->damage_begin
;
1111 draw_context_in
->previous
->under
->x
=
1112 control_flow_data
->drawing
->damage_begin
;
1114 g_debug("in middle x_beg : %u",control_flow_data
->drawing
->damage_begin
);
1118 draw_context_in
->current
->middle
->x
= x
;
1119 draw_context_in
->current
->over
->x
= x
;
1120 draw_context_in
->current
->under
->x
= x
;
1121 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
1122 draw_context_in
->current
->over
->y
= y_in
;
1123 draw_context_in
->current
->under
->y
= y_in
+ height
;
1124 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
1125 draw_context_in
->previous
->over
->y
= y_in
;
1126 draw_context_in
->previous
->under
->y
= y_in
+ height
;
1128 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1129 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1132 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1134 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1135 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1136 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1138 PropertiesBG prop_bg
;
1139 prop_bg
.color
= g_new(GdkColor
,1);
1141 switcht(ltt_tracefile_num(tfc
->tf
)) {
1143 prop_bg
.color
->red
= 0x1515;
1144 prop_bg
.color
->green
= 0x1515;
1145 prop_bg
.color
->blue
= 0x8c8c;
1148 prop_bg
.color
->red
= 0x4e4e;
1149 prop_bg
.color
->green
= 0xa9a9;
1150 prop_bg
.color
->blue
= 0xa4a4;
1153 prop_bg
.color
->red
= 0x7a7a;
1154 prop_bg
.color
->green
= 0x4a4a;
1155 prop_bg
.color
->blue
= 0x8b8b;
1158 prop_bg
.color
->red
= 0x8080;
1159 prop_bg
.color
->green
= 0x7777;
1160 prop_bg
.color
->blue
= 0x4747;
1163 prop_bg
.color
->red
= 0xe7e7;
1164 prop_bg
.color
->green
= 0xe7e7;
1165 prop_bg
.color
->blue
= 0xe7e7;
1169 draw_bg((void*)&prop_bg
, (void*)draw_context_in
);
1170 g_free(prop_bg
.color
);
1171 //gdk_gc_unref(draw_context_in->gc);
1174 draw_context_in
->gc
= widget
->style
->black_gc
;
1176 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1177 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1178 PropertiesText prop_text_in
;
1179 prop_text_in
.foreground
= &colorfg_in
;
1180 prop_text_in
.background
= &colorbg_in
;
1181 prop_text_in
.size
= 6;
1182 prop_text_in
.position
= OVER
;
1184 g_debug("in state : %s", g_quark_to_string(process_in
->state
->s
));
1185 /* foreground of text : status of the process */
1186 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1188 prop_text_in
.foreground
->red
= 0xffff;
1189 prop_text_in
.foreground
->green
= 0xffff;
1190 prop_text_in
.foreground
->blue
= 0xffff;
1192 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1194 prop_text_in
.foreground
->red
= 0x0fff;
1195 prop_text_in
.foreground
->green
= 0xffff;
1196 prop_text_in
.foreground
->blue
= 0xfff0;
1198 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1200 prop_text_in
.foreground
->red
= 0xffff;
1201 prop_text_in
.foreground
->green
= 0xffff;
1202 prop_text_in
.foreground
->blue
= 0x0000;
1204 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1206 prop_text_in
.foreground
->red
= 0xffff;
1207 prop_text_in
.foreground
->green
= 0x0000;
1208 prop_text_in
.foreground
->blue
= 0xffff;
1210 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1212 prop_text_in
.foreground
->red
= 0xffff;
1213 prop_text_in
.foreground
->green
= 0x0000;
1214 prop_text_in
.foreground
->blue
= 0x0000;
1216 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1218 prop_text_in
.foreground
->red
= 0x0000;
1219 prop_text_in
.foreground
->green
= 0xffff;
1220 prop_text_in
.foreground
->blue
= 0x0000;
1224 prop_text_in
.foreground
->red
= 0xffff;
1225 prop_text_in
.foreground
->green
= 0xffff;
1226 prop_text_in
.foreground
->blue
= 0xffff;
1231 /* Print status of the process : U, WF, WC, E, W, R */
1232 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1233 prop_text_in
.text
= "U->";
1234 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1235 prop_text_in
.text
= "WF->";
1236 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1237 prop_text_in
.text
= "WC->";
1238 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1239 prop_text_in
.text
= "E->";
1240 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1241 prop_text_in
.text
= "W->";
1242 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1243 prop_text_in
.text
= "R->";
1245 prop_text_in
.text
= "U";
1247 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1248 //gdk_gc_unref(draw_context_in->gc);
1250 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1251 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1252 draw_context_in
->gc
= control_flow_data
->drawing
->gc
;
1254 PropertiesLine prop_line_in
;
1255 prop_line_in
.color
= g_new(GdkColor
,1);
1256 prop_line_in
.line_width
= 2;
1257 prop_line_in
.style
= GDK_LINE_SOLID
;
1258 prop_line_in
.position
= MIDDLE
;
1260 /* color of line : status of the process */
1261 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1263 prop_line_in
.color
->red
= 0xffff;
1264 prop_line_in
.color
->green
= 0xffff;
1265 prop_line_in
.color
->blue
= 0xffff;
1267 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1269 prop_line_in
.color
->red
= 0x0fff;
1270 prop_line_in
.color
->green
= 0xffff;
1271 prop_line_in
.color
->blue
= 0xfff0;
1273 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1275 prop_line_in
.color
->red
= 0xffff;
1276 prop_line_in
.color
->green
= 0xffff;
1277 prop_line_in
.color
->blue
= 0x0000;
1279 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1281 prop_line_in
.color
->red
= 0xffff;
1282 prop_line_in
.color
->green
= 0x0000;
1283 prop_line_in
.color
->blue
= 0xffff;
1285 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1287 prop_line_in
.color
->red
= 0xffff;
1288 prop_line_in
.color
->green
= 0x0000;
1289 prop_line_in
.color
->blue
= 0x0000;
1291 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1293 prop_line_in
.color
->red
= 0x0000;
1294 prop_line_in
.color
->green
= 0xffff;
1295 prop_line_in
.color
->blue
= 0x0000;
1299 prop_line_in
.color
->red
= 0xffff;
1300 prop_line_in
.color
->green
= 0xffff;
1301 prop_line_in
.color
->blue
= 0xffff;
1304 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
1305 g_free(prop_line_in
.color
);
1306 //gdk_gc_unref(draw_context_in->gc);
1316 GString
*string
= g_string_new("");;
1317 gboolean field_names
= TRUE
, state
= TRUE
;
1319 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
1320 g_string_append_printf(string
,"\n");
1323 g_string_append_printf(string
, " %s",
1324 g_quark_to_string(tfs
->process
->state
->s
));
1327 g_info("%s",string
->str
);
1329 g_string_free(string
, TRUE
);
1331 /* End of text dump */
1336 /* after_schedchange_hook
1338 * The draw after hook is called by the reading API to have a
1339 * particular event drawn on the screen.
1340 * @param hook_data ControlFlowData structure of the viewer.
1341 * @param call_data Event context.
1343 * This function adds items to be drawn in a queue for each process.
1346 int after_schedchange_hook(void *hook_data
, void *call_data
)
1348 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1349 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1350 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1352 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1354 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
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(tfs, pid_in);
1379 process_in
= tfs
->process
;
1380 /* It should exist, because we are after the state update. */
1382 g_assert(process_in
!= NULL
);
1383 #endif //EXTRA_CHECK
1384 birth
= process_in
->creation_time
;
1386 hashed_process_data_in
= processlist_get_process_data(process_list
,
1388 process_in
->last_cpu_index
,
1390 tfc
->t_context
->index
);
1391 if(hashed_process_data_in
== NULL
)
1393 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1394 const gchar
*name
= g_quark_to_string(process_in
->name
);
1395 ProcessInfo
*process_info
;
1396 Drawing_t
*drawing
= control_flow_data
->drawing
;
1397 /* Process not present */
1398 processlist_add(process_list
,
1401 process_in
->last_cpu_index
,
1404 tfc
->t_context
->index
,
1408 &hashed_process_data_in
);
1409 gtk_widget_set_size_request(drawing
->drawing_area
,
1412 gtk_widget_queue_draw(drawing
->drawing_area
);
1414 /* Set the current process */
1415 process_list
->current_hash_data
[process_in
->last_cpu_index
] =
1416 hashed_process_data_in
;
1418 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
1421 TimeWindow time_window
=
1422 lttvwindow_get_time_window(control_flow_data
->tab
);
1425 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1426 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1428 #endif //EXTRA_CHECK
1429 Drawing_t
*drawing
= control_flow_data
->drawing
;
1430 guint width
= drawing
->width
;
1433 convert_time_to_pixels(
1439 if(hashed_process_data_in
->x
.middle
!= new_x
) {
1440 hashed_process_data_in
->x
.middle
= new_x
;
1441 hashed_process_data_in
->x
.middle_used
= FALSE
;
1442 hashed_process_data_in
->x
.middle_marked
= FALSE
;
1452 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1453 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1455 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1457 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1458 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1464 LttTime evtime
= ltt_event_time(e
);
1465 TimeWindow time_window
=
1466 lttvwindow_get_time_window(control_flow_data
->tab
);
1468 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
1470 //if(time < time_beg || time > time_end) return;
1471 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1472 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1476 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1478 g_debug("schedchange!");
1480 /* Add process to process list (if not present) and get drawing "y" from
1481 * process position */
1482 guint pid_out
, pid_in
;
1483 LttvProcessState
*process_out
, *process_in
;
1485 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1487 ProcessList
*process_list
= control_flow_data
->process_list
;
1490 LttField
*f
= ltt_event_field(e
);
1492 element
= ltt_field_member(f
,0);
1493 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1494 element
= ltt_field_member(f
,1);
1495 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1496 //g_debug("out : %u in : %u", pid_out, pid_in);
1499 /* Find process pid_out in the list... */
1500 process_out
= lttv_state_find_process(tfs
, pid_out
);
1501 if(process_out
== NULL
) return 0;
1502 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1504 birth
= process_out
->creation_time
;
1505 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1506 HashedProcessData
*hashed_process_data_out
= NULL
;
1508 if(processlist_get_process_pixels(process_list
,
1511 tfc
->t_context
->index
,
1514 &hashed_process_data_out
) == 1)
1516 /* Process not present */
1517 processlist_add(process_list
,
1520 tfc
->t_context
->index
,
1523 &hashed_process_data_out
);
1524 processlist_get_process_pixels(process_list
,
1527 tfc
->t_context
->index
,
1530 &hashed_process_data_out
);
1531 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1536 /* Find process pid_in in the list... */
1537 process_in
= lttv_state_find_process(tfs
, pid_in
);
1538 if(process_in
== NULL
) return 0;
1539 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1541 birth
= process_in
->creation_time
;
1542 name
= strdup(g_quark_to_string(process_in
->name
));
1543 HashedProcessData
*hashed_process_data_in
= NULL
;
1545 if(processlist_get_process_pixels(process_list
,
1548 tfc
->t_context
->index
,
1551 &hashed_process_data_in
) == 1)
1553 /* Process not present */
1554 processlist_add(process_list
,
1557 tfc
->t_context
->index
,
1560 &hashed_process_data_in
);
1561 processlist_get_process_pixels(process_list
,
1564 tfc
->t_context
->index
,
1567 &hashed_process_data_in
);
1569 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1574 /* Find pixels corresponding to time of the event. If the time does
1575 * not fit in the window, show a warning, not supposed to happend. */
1577 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1579 //LttTime time = ltt_event_time(e);
1581 //LttTime window_end = time_window->time_window.end_time;
1584 //convert_time_to_pixels(
1590 //assert(x <= width);
1592 /* draw what represents the event for outgoing process. */
1594 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1595 //draw_context_out->current->modify_over->x = x;
1596 draw_context_out
->current
->modify_over
->y
= y_out
;
1597 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1598 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1599 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1600 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1601 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1603 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1604 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1606 /*if(process_out->state->s == LTTV_STATE_RUN)
1608 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1609 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1610 PropertiesBG prop_bg;
1611 prop_bg.color = g_new(GdkColor,1);
1613 prop_bg.color->red = 0xffff;
1614 prop_bg.color->green = 0xffff;
1615 prop_bg.color->blue = 0xffff;
1617 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1618 g_free(prop_bg.color);
1619 gdk_gc_unref(draw_context_out->gc);
1622 draw_context_out
->gc
= widget
->style
->black_gc
;
1624 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1625 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1626 PropertiesText prop_text_out
;
1627 prop_text_out
.foreground
= &colorfg_out
;
1628 prop_text_out
.background
= &colorbg_out
;
1629 prop_text_out
.size
= 6;
1630 prop_text_out
.position
= OVER
;
1632 /* color of text : status of the process */
1633 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1635 prop_text_out
.foreground
->red
= 0xffff;
1636 prop_text_out
.foreground
->green
= 0xffff;
1637 prop_text_out
.foreground
->blue
= 0xffff;
1639 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1641 prop_text_out
.foreground
->red
= 0x0fff;
1642 prop_text_out
.foreground
->green
= 0xffff;
1643 prop_text_out
.foreground
->blue
= 0xfff0;
1645 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1647 prop_text_out
.foreground
->red
= 0xffff;
1648 prop_text_out
.foreground
->green
= 0xffff;
1649 prop_text_out
.foreground
->blue
= 0x0000;
1651 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1653 prop_text_out
.foreground
->red
= 0xffff;
1654 prop_text_out
.foreground
->green
= 0x0000;
1655 prop_text_out
.foreground
->blue
= 0xffff;
1657 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1659 prop_text_out
.foreground
->red
= 0xffff;
1660 prop_text_out
.foreground
->green
= 0x0000;
1661 prop_text_out
.foreground
->blue
= 0x0000;
1663 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1665 prop_text_out
.foreground
->red
= 0x0000;
1666 prop_text_out
.foreground
->green
= 0xffff;
1667 prop_text_out
.foreground
->blue
= 0x0000;
1671 prop_text_out
.foreground
->red
= 0xffff;
1672 prop_text_out
.foreground
->green
= 0xffff;
1673 prop_text_out
.foreground
->blue
= 0xffff;
1676 /* Print status of the process : U, WF, WC, E, W, R */
1677 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1678 prop_text_out
.text
= "U";
1679 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1680 prop_text_out
.text
= "WF";
1681 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1682 prop_text_out
.text
= "WC";
1683 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1684 prop_text_out
.text
= "E";
1685 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1686 prop_text_out
.text
= "W";
1687 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1688 prop_text_out
.text
= "R";
1690 prop_text_out
.text
= "U";
1692 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1694 //gdk_gc_unref(draw_context_out->gc);
1696 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1697 draw_context_out
->current
->over
->y
= y_out
;
1698 draw_context_out
->current
->under
->y
= y_out
+height
;
1699 draw_context_out
->current
->status
= process_out
->state
->s
;
1701 /* for pid_out : remove previous, Prev = current, new current (default) */
1702 g_free(draw_context_out
->previous
->modify_under
);
1703 g_free(draw_context_out
->previous
->modify_middle
);
1704 g_free(draw_context_out
->previous
->modify_over
);
1705 g_free(draw_context_out
->previous
->under
);
1706 g_free(draw_context_out
->previous
->middle
);
1707 g_free(draw_context_out
->previous
->over
);
1708 g_free(draw_context_out
->previous
);
1710 draw_context_out
->previous
= draw_context_out
->current
;
1712 draw_context_out
->current
= g_new(DrawInfo
,1);
1713 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1714 draw_context_out
->current
->over
->x
= -1;
1715 draw_context_out
->current
->over
->y
= -1;
1716 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1717 draw_context_out
->current
->middle
->x
= -1;
1718 draw_context_out
->current
->middle
->y
= -1;
1719 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1720 draw_context_out
->current
->under
->x
= -1;
1721 draw_context_out
->current
->under
->y
= -1;
1722 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1723 draw_context_out
->current
->modify_over
->x
= -1;
1724 draw_context_out
->current
->modify_over
->y
= -1;
1725 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1726 draw_context_out
->current
->modify_middle
->x
= -1;
1727 draw_context_out
->current
->modify_middle
->y
= -1;
1728 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1729 draw_context_out
->current
->modify_under
->x
= -1;
1730 draw_context_out
->current
->modify_under
->y
= -1;
1731 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1733 /* Finally, update the drawing context of the pid_in. */
1735 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1736 //draw_context_in->current->modify_over->x = x;
1737 draw_context_in
->current
->modify_over
->y
= y_in
;
1738 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1739 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1740 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1741 widget
= control_flow_data
->drawing
->drawing_area
;
1742 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1744 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1745 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1747 /*if(process_in->state->s == LTTV_STATE_RUN)
1749 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1750 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1751 PropertiesBG prop_bg;
1752 prop_bg.color = g_new(GdkColor,1);
1754 prop_bg.color->red = 0xffff;
1755 prop_bg.color->green = 0xffff;
1756 prop_bg.color->blue = 0xffff;
1758 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1759 g_free(prop_bg.color);
1760 gdk_gc_unref(draw_context_in->gc);
1763 draw_context_in
->gc
= widget
->style
->black_gc
;
1765 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1766 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1767 PropertiesText prop_text_in
;
1768 prop_text_in
.foreground
= &colorfg_in
;
1769 prop_text_in
.background
= &colorbg_in
;
1770 prop_text_in
.size
= 6;
1771 prop_text_in
.position
= OVER
;
1773 /* foreground of text : status of the process */
1774 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1776 prop_text_in
.foreground
->red
= 0xffff;
1777 prop_text_in
.foreground
->green
= 0xffff;
1778 prop_text_in
.foreground
->blue
= 0xffff;
1780 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1782 prop_text_in
.foreground
->red
= 0x0fff;
1783 prop_text_in
.foreground
->green
= 0xffff;
1784 prop_text_in
.foreground
->blue
= 0xfff0;
1786 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1788 prop_text_in
.foreground
->red
= 0xffff;
1789 prop_text_in
.foreground
->green
= 0xffff;
1790 prop_text_in
.foreground
->blue
= 0x0000;
1792 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1794 prop_text_in
.foreground
->red
= 0xffff;
1795 prop_text_in
.foreground
->green
= 0x0000;
1796 prop_text_in
.foreground
->blue
= 0xffff;
1798 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1800 prop_text_in
.foreground
->red
= 0xffff;
1801 prop_text_in
.foreground
->green
= 0x0000;
1802 prop_text_in
.foreground
->blue
= 0x0000;
1804 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1806 prop_text_in
.foreground
->red
= 0x0000;
1807 prop_text_in
.foreground
->green
= 0xffff;
1808 prop_text_in
.foreground
->blue
= 0x0000;
1812 prop_text_in
.foreground
->red
= 0xffff;
1813 prop_text_in
.foreground
->green
= 0xffff;
1814 prop_text_in
.foreground
->blue
= 0xffff;
1818 /* Print status of the process : U, WF, WC, E, W, R */
1819 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1820 prop_text_in
.text
= "U";
1821 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1822 prop_text_in
.text
= "WF";
1823 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1824 prop_text_in
.text
= "WC";
1825 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1826 prop_text_in
.text
= "E";
1827 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1828 prop_text_in
.text
= "W";
1829 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1830 prop_text_in
.text
= "R";
1832 prop_text_in
.text
= "U";
1834 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1837 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1840 prop_text_in
.foreground
= &colorfg_in
;
1841 prop_text_in
.background
= &colorbg_in
;
1842 prop_text_in
.foreground
->red
= 0xffff;
1843 prop_text_in
.foreground
->green
= 0xffff;
1844 prop_text_in
.foreground
->blue
= 0xffff;
1845 prop_text_in
.size
= 6;
1846 prop_text_in
.position
= UNDER
;
1848 prop_text_in
.text
= g_new(gchar
, 260);
1849 strcpy(prop_text_in
.text
, "CPU ");
1850 snprintf(tmp
, 255, "%u", ltt_tracefile_num(tfc
->tf
));
1851 strcat(prop_text_in
.text
, tmp
);
1853 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1854 g_free(prop_text_in
.text
);
1858 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1859 draw_context_in
->current
->over
->y
= y_in
;
1860 draw_context_in
->current
->under
->y
= y_in
+height
;
1861 draw_context_in
->current
->status
= process_in
->state
->s
;
1863 /* for pid_in : remove previous, Prev = current, new current (default) */
1864 g_free(draw_context_in
->previous
->modify_under
);
1865 g_free(draw_context_in
->previous
->modify_middle
);
1866 g_free(draw_context_in
->previous
->modify_over
);
1867 g_free(draw_context_in
->previous
->under
);
1868 g_free(draw_context_in
->previous
->middle
);
1869 g_free(draw_context_in
->previous
->over
);
1870 g_free(draw_context_in
->previous
);
1872 draw_context_in
->previous
= draw_context_in
->current
;
1874 draw_context_in
->current
= g_new(DrawInfo
,1);
1875 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1876 draw_context_in
->current
->over
->x
= -1;
1877 draw_context_in
->current
->over
->y
= -1;
1878 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1879 draw_context_in
->current
->middle
->x
= -1;
1880 draw_context_in
->current
->middle
->y
= -1;
1881 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1882 draw_context_in
->current
->under
->x
= -1;
1883 draw_context_in
->current
->under
->y
= -1;
1884 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1885 draw_context_in
->current
->modify_over
->x
= -1;
1886 draw_context_in
->current
->modify_over
->y
= -1;
1887 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1888 draw_context_in
->current
->modify_middle
->x
= -1;
1889 draw_context_in
->current
->modify_middle
->y
= -1;
1890 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1891 draw_context_in
->current
->modify_under
->x
= -1;
1892 draw_context_in
->current
->modify_under
->y
= -1;
1893 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1902 static inline PropertiesLine
prepare_execmode_line(LttvProcessState
*process
)
1904 PropertiesLine prop_line
;
1905 prop_line
.line_width
= 1;
1906 prop_line
.style
= GDK_LINE_SOLID
;
1908 //GdkColormap *colormap = gdk_colormap_get_system();
1910 /* color of line : execution mode of the process */
1911 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
1912 prop_line
.color
= drawing_colors
[COL_USER_MODE
];
1913 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
1914 prop_line
.color
= drawing_colors
[COL_SYSCALL
];
1915 else if(process
->state
->t
== LTTV_STATE_TRAP
)
1916 prop_line
.color
= drawing_colors
[COL_TRAP
];
1917 else if(process
->state
->t
== LTTV_STATE_IRQ
)
1918 prop_line
.color
= drawing_colors
[COL_IRQ
];
1919 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
1920 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
1922 prop_line
.color
= drawing_colors
[COL_WHITE
];
1924 //gdk_colormap_alloc_color(colormap,
1935 /* before_execmode_hook
1937 * This function basically draw lines and icons. Two types of lines are drawn :
1938 * one small (3 pixels?) representing the state of the process and the second
1939 * type is thicker (10 pixels?) representing on which CPU a process is running
1940 * (and this only in running state).
1942 * Extremums of the lines :
1943 * x_min : time of the last event context for this process kept in memory.
1944 * x_max : time of the current event.
1945 * y : middle of the process in the process list. The process is found in the
1946 * list, therefore is it's position in pixels.
1948 * The choice of lines'color is defined by the context of the last event for this
1953 int before_execmode_hook(void *hook_data
, void *call_data
)
1955 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1956 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1957 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1959 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1961 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1964 e
= ltt_tracefile_get_event(tfc
->tf
);
1966 LttTime evtime
= ltt_event_time(e
);
1968 /* we are in a execmode, before the state update. We must draw the
1969 * items corresponding to the state before it changes : now is the right
1973 LttvProcessState
*process
= tfs
->process
;
1974 g_assert(process
!= NULL
);
1976 guint pid
= process
->pid
;
1978 /* Well, the process_out existed : we must get it in the process hash
1979 * or add it, and draw its items.
1981 /* Add process to process list (if not present) */
1982 guint pl_height
= 0;
1983 HashedProcessData
*hashed_process_data
= NULL
;
1984 ProcessList
*process_list
= control_flow_data
->process_list
;
1985 LttTime birth
= process
->creation_time
;
1987 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
1988 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
1990 hashed_process_data
= processlist_get_process_data(process_list
,
1992 process
->last_cpu_index
,
1994 tfc
->t_context
->index
);
1995 if(unlikely(hashed_process_data
== NULL
))
1997 g_assert(pid
== 0 || pid
!= process
->ppid
);
1998 ProcessInfo
*process_info
;
1999 /* Process not present */
2000 Drawing_t
*drawing
= control_flow_data
->drawing
;
2001 const gchar
*name
= g_quark_to_string(process
->name
);
2002 processlist_add(process_list
,
2005 process
->last_cpu_index
,
2008 tfc
->t_context
->index
,
2012 &hashed_process_data
);
2013 gtk_widget_set_size_request(drawing
->drawing_area
,
2016 gtk_widget_queue_draw(drawing
->drawing_area
);
2018 /* Set the current process */
2019 process_list
->current_hash_data
[process
->last_cpu_index
] =
2020 hashed_process_data
;
2023 /* Now, the process is in the state hash and our own process hash.
2024 * We definitely can draw the items related to the ending state.
2027 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2030 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2031 TimeWindow time_window
=
2032 lttvwindow_get_time_window(control_flow_data
->tab
);
2035 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2036 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2038 #endif //EXTRA_CHECK
2039 Drawing_t
*drawing
= control_flow_data
->drawing
;
2040 guint width
= drawing
->width
;
2042 convert_time_to_pixels(
2048 /* Draw collision indicator */
2049 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2050 gdk_draw_point(hashed_process_data
->pixmap
,
2053 (hashed_process_data
->height
/2)-3);
2054 hashed_process_data
->x
.middle_marked
= TRUE
;
2057 TimeWindow time_window
=
2058 lttvwindow_get_time_window(control_flow_data
->tab
);
2061 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2062 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2064 #endif //EXTRA_CHECK
2065 Drawing_t
*drawing
= control_flow_data
->drawing
;
2066 guint width
= drawing
->width
;
2069 convert_time_to_pixels(
2076 /* Jump over draw if we are at the same x position */
2077 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2078 hashed_process_data
->x
.middle_used
))
2080 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2081 /* Draw collision indicator */
2082 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2083 gdk_draw_point(hashed_process_data
->pixmap
,
2086 (hashed_process_data
->height
/2)-3);
2087 hashed_process_data
->x
.middle_marked
= TRUE
;
2092 DrawContext draw_context
;
2093 /* Now create the drawing context that will be used to draw
2094 * items related to the last state. */
2095 draw_context
.drawable
= hashed_process_data
->pixmap
;
2096 draw_context
.gc
= drawing
->gc
;
2097 draw_context
.pango_layout
= drawing
->pango_layout
;
2098 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2099 draw_context
.drawinfo
.end
.x
= x
;
2101 draw_context
.drawinfo
.y
.over
= 1;
2102 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2103 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2105 draw_context
.drawinfo
.start
.offset
.over
= 0;
2106 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2107 draw_context
.drawinfo
.start
.offset
.under
= 0;
2108 draw_context
.drawinfo
.end
.offset
.over
= 0;
2109 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2110 draw_context
.drawinfo
.end
.offset
.under
= 0;
2114 PropertiesLine prop_line
= prepare_s_e_line(process
);
2115 draw_line((void*)&prop_line
, (void*)&draw_context
);
2118 /* become the last x position */
2119 hashed_process_data
->x
.middle
= x
;
2120 hashed_process_data
->x
.middle_used
= TRUE
;
2121 hashed_process_data
->x
.middle_marked
= FALSE
;
2123 /* Calculate the next good time */
2124 convert_pixels_to_time(width
, x
+1, time_window
,
2125 &hashed_process_data
->next_good_time
);
2132 /* after_execmode_hook
2134 * The draw after hook is called by the reading API to have a
2135 * particular event drawn on the screen.
2136 * @param hook_data ControlFlowData structure of the viewer.
2137 * @param call_data Event context.
2139 * This function adds items to be drawn in a queue for each process.
2142 int after_execmode_hook(void *hook_data
, void *call_data
)
2144 /**************** DOES NOTHING!! *************/
2145 /* hook desactivated in drawing.c */
2149 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2150 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2151 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2153 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2155 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2158 e
= ltt_tracefile_get_event(tfc
->tf
);
2160 LttTime evtime
= ltt_event_time(e
);
2162 /* Add process to process list (if not present) */
2163 LttvProcessState
*process
;
2165 guint pl_height
= 0;
2166 HashedProcessData
*hashed_process_data
= NULL
;
2168 ProcessList
*process_list
= control_flow_data
->process_list
;
2170 /* Find process pid_in in the list... */
2171 process
= tfs
->process
;
2172 /* It should exist, because we are after the state update. */
2173 g_assert(process
!= NULL
);
2175 guint pid
= process
->pid
;
2177 birth
= process
->creation_time
;
2179 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
2180 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
2182 hashed_process_data
= processlist_get_process_data(process_list
,
2184 process
->last_cpu_index
,
2186 tfc
->t_context
->index
);
2187 if(unlikely(hashed_process_data
== NULL
))
2189 g_assert(pid
== 0 || pid
!= process
->ppid
);
2190 /* Process not present */
2191 Drawing_t
*drawing
= control_flow_data
->drawing
;
2192 const gchar
*name
= g_quark_to_string(process
->name
);
2193 ProcessInfo
*process_info
;
2194 processlist_add(process_list
,
2197 process
->last_cpu_index
,
2200 tfc
->t_context
->index
,
2204 &hashed_process_data
);
2205 gtk_widget_set_size_request(drawing
->drawing_area
,
2208 gtk_widget_queue_draw(drawing
->drawing_area
);
2210 /* Set the current process */
2211 process_list
->current_hash_data
[process
->last_cpu_index
] =
2212 hashed_process_data
;
2215 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2218 TimeWindow time_window
=
2219 lttvwindow_get_time_window(control_flow_data
->tab
);
2222 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2223 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2225 #endif //EXTRA_CHECK
2226 Drawing_t
*drawing
= control_flow_data
->drawing
;
2227 guint width
= drawing
->width
;
2230 convert_time_to_pixels(
2236 if(hashed_process_data
->x
.middle
!= new_x
) {
2237 hashed_process_data
->x
.middle
= new_x
;
2238 hashed_process_data
->x
.middle_used
= FALSE
;
2239 hashed_process_data
->x
.middle_marked
= FALSE
;
2248 /* before_process_exit_hook
2250 * Draw lines for process event.
2252 * @param hook_data ControlFlowData structure of the viewer.
2253 * @param call_data Event context.
2255 * This function adds items to be drawn in a queue for each process.
2260 int before_process_exit_hook(void *hook_data
, void *call_data
)
2262 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2263 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2265 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2267 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2269 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2272 e
= ltt_tracefile_get_event(tfc
->tf
);
2274 LttTime evtime
= ltt_event_time(e
);
2276 /* Add process to process list (if not present) */
2277 LttvProcessState
*process
= tfs
->process
;
2278 guint pid
= process
->pid
;
2280 guint pl_height
= 0;
2281 HashedProcessData
*hashed_process_data
= NULL
;
2283 ProcessList
*process_list
= control_flow_data
->process_list
;
2285 g_assert(process
!= NULL
);
2287 birth
= process
->creation_time
;
2289 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
2290 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
2292 hashed_process_data
= processlist_get_process_data(process_list
,
2294 process
->last_cpu_index
,
2296 tfc
->t_context
->index
);
2297 if(unlikely(hashed_process_data
== NULL
))
2299 g_assert(pid
== 0 || pid
!= process
->ppid
);
2300 /* Process not present */
2301 Drawing_t
*drawing
= control_flow_data
->drawing
;
2302 const gchar
*name
= g_quark_to_string(process
->name
);
2303 ProcessInfo
*process_info
;
2304 processlist_add(process_list
,
2307 process
->last_cpu_index
,
2310 tfc
->t_context
->index
,
2314 &hashed_process_data
);
2315 gtk_widget_set_size_request(drawing
->drawing_area
,
2318 gtk_widget_queue_draw(drawing
->drawing_area
);
2322 /* Now, the process is in the state hash and our own process hash.
2323 * We definitely can draw the items related to the ending state.
2326 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2329 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2330 TimeWindow time_window
=
2331 lttvwindow_get_time_window(control_flow_data
->tab
);
2334 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2335 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2337 #endif //EXTRA_CHECK
2338 Drawing_t
*drawing
= control_flow_data
->drawing
;
2339 guint width
= drawing
->width
;
2341 convert_time_to_pixels(
2347 /* Draw collision indicator */
2348 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2349 gdk_draw_point(hashed_process_data
->pixmap
,
2352 (hashed_process_data
->height
/2)-3);
2353 hashed_process_data
->x
.middle_marked
= TRUE
;
2356 TimeWindow time_window
=
2357 lttvwindow_get_time_window(control_flow_data
->tab
);
2360 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2361 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2363 #endif //EXTRA_CHECK
2364 Drawing_t
*drawing
= control_flow_data
->drawing
;
2365 guint width
= drawing
->width
;
2368 convert_time_to_pixels(
2375 /* Jump over draw if we are at the same x position */
2376 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2377 hashed_process_data
->x
.middle_used
))
2379 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2380 /* Draw collision indicator */
2381 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2382 gdk_draw_point(hashed_process_data
->pixmap
,
2385 (hashed_process_data
->height
/2)-3);
2386 hashed_process_data
->x
.middle_marked
= TRUE
;
2390 DrawContext draw_context
;
2392 /* Now create the drawing context that will be used to draw
2393 * items related to the last state. */
2394 draw_context
.drawable
= hashed_process_data
->pixmap
;
2395 draw_context
.gc
= drawing
->gc
;
2396 draw_context
.pango_layout
= drawing
->pango_layout
;
2397 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2398 draw_context
.drawinfo
.end
.x
= x
;
2400 draw_context
.drawinfo
.y
.over
= 1;
2401 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2402 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2404 draw_context
.drawinfo
.start
.offset
.over
= 0;
2405 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2406 draw_context
.drawinfo
.start
.offset
.under
= 0;
2407 draw_context
.drawinfo
.end
.offset
.over
= 0;
2408 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2409 draw_context
.drawinfo
.end
.offset
.under
= 0;
2413 PropertiesLine prop_line
= prepare_s_e_line(process
);
2414 draw_line((void*)&prop_line
, (void*)&draw_context
);
2417 /* become the last x position */
2418 hashed_process_data
->x
.middle
= x
;
2419 hashed_process_data
->x
.middle_used
= TRUE
;
2420 hashed_process_data
->x
.middle_marked
= FALSE
;
2422 /* Calculate the next good time */
2423 convert_pixels_to_time(width
, x
+1, time_window
,
2424 &hashed_process_data
->next_good_time
);
2434 /* before_process_release_hook
2436 * Draw lines for process event.
2438 * @param hook_data ControlFlowData structure of the viewer.
2439 * @param call_data Event context.
2441 * This function adds items to be drawn in a queue for each process.
2446 int before_process_release_hook(void *hook_data
, void *call_data
)
2448 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2449 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2451 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2453 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2455 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2458 e
= ltt_tracefile_get_event(tfc
->tf
);
2460 LttTime evtime
= ltt_event_time(e
);
2465 pid
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2468 /* Add process to process list (if not present) */
2469 /* Don't care about the process if it's not in the state hash already :
2470 * that means a process that has never done anything in the trace and
2471 * unknown suddently gets destroyed : no state meaningful to show. */
2472 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
2474 if(process
!= NULL
) {
2476 guint pl_height
= 0;
2477 HashedProcessData
*hashed_process_data
= NULL
;
2479 ProcessList
*process_list
= control_flow_data
->process_list
;
2481 birth
= process
->creation_time
;
2483 /* Cannot use current process : this event happens on another process,
2484 * action done by the parent. */
2485 hashed_process_data
= processlist_get_process_data(process_list
,
2487 process
->last_cpu_index
,
2489 tfc
->t_context
->index
);
2490 if(unlikely(hashed_process_data
== NULL
))
2492 g_assert(pid
== 0 || pid
!= process
->ppid
);
2493 /* Process not present */
2494 Drawing_t
*drawing
= control_flow_data
->drawing
;
2495 const gchar
*name
= g_quark_to_string(process
->name
);
2496 ProcessInfo
*process_info
;
2497 processlist_add(process_list
,
2500 process
->last_cpu_index
,
2503 tfc
->t_context
->index
,
2507 &hashed_process_data
);
2508 gtk_widget_set_size_request(drawing
->drawing_area
,
2511 gtk_widget_queue_draw(drawing
->drawing_area
);
2514 /* Now, the process is in the state hash and our own process hash.
2515 * We definitely can draw the items related to the ending state.
2518 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2521 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2522 TimeWindow time_window
=
2523 lttvwindow_get_time_window(control_flow_data
->tab
);
2526 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2527 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2529 #endif //EXTRA_CHECK
2530 Drawing_t
*drawing
= control_flow_data
->drawing
;
2531 guint width
= drawing
->width
;
2533 convert_time_to_pixels(
2539 /* Draw collision indicator */
2540 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2541 gdk_draw_point(hashed_process_data
->pixmap
,
2544 (hashed_process_data
->height
/2)-3);
2545 hashed_process_data
->x
.middle_marked
= TRUE
;
2548 TimeWindow time_window
=
2549 lttvwindow_get_time_window(control_flow_data
->tab
);
2552 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2553 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2555 #endif //EXTRA_CHECK
2556 Drawing_t
*drawing
= control_flow_data
->drawing
;
2557 guint width
= drawing
->width
;
2560 convert_time_to_pixels(
2567 /* Jump over draw if we are at the same x position */
2568 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2569 hashed_process_data
->x
.middle_used
))
2571 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2572 /* Draw collision indicator */
2573 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2574 gdk_draw_point(hashed_process_data
->pixmap
,
2577 (hashed_process_data
->height
/2)-3);
2578 hashed_process_data
->x
.middle_marked
= TRUE
;
2582 DrawContext draw_context
;
2584 /* Now create the drawing context that will be used to draw
2585 * items related to the last state. */
2586 draw_context
.drawable
= hashed_process_data
->pixmap
;
2587 draw_context
.gc
= drawing
->gc
;
2588 draw_context
.pango_layout
= drawing
->pango_layout
;
2589 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2590 draw_context
.drawinfo
.end
.x
= x
;
2592 draw_context
.drawinfo
.y
.over
= 1;
2593 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2594 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2596 draw_context
.drawinfo
.start
.offset
.over
= 0;
2597 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2598 draw_context
.drawinfo
.start
.offset
.under
= 0;
2599 draw_context
.drawinfo
.end
.offset
.over
= 0;
2600 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2601 draw_context
.drawinfo
.end
.offset
.under
= 0;
2605 PropertiesLine prop_line
= prepare_s_e_line(process
);
2606 draw_line((void*)&prop_line
, (void*)&draw_context
);
2609 /* become the last x position */
2610 hashed_process_data
->x
.middle
= x
;
2611 hashed_process_data
->x
.middle_used
= TRUE
;
2612 hashed_process_data
->x
.middle_marked
= FALSE
;
2614 /* Calculate the next good time */
2615 convert_pixels_to_time(width
, x
+1, time_window
,
2616 &hashed_process_data
->next_good_time
);
2632 /* before_process_hook
2634 * Draw lines for process event.
2636 * @param hook_data ControlFlowData structure of the viewer.
2637 * @param call_data Event context.
2639 * This function adds items to be drawn in a queue for each process.
2642 int before_process_hook(void *hook_data
, void *call_data
)
2644 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2645 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2646 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2648 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2650 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2653 e
= ltt_tracefile_get_event(tfc
->tf
);
2655 LttTime evtime
= ltt_event_time(e
);
2659 LttField
*f
= ltt_event_field(e
);
2661 element
= ltt_field_member(f
,0);
2662 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2665 if(sub_id
== 3) { /* exit */
2667 /* Add process to process list (if not present) */
2668 LttvProcessState
*process
= tfs
->process
;
2669 guint pid
= process
->pid
;
2671 guint pl_height
= 0;
2672 HashedProcessData
*hashed_process_data
= NULL
;
2674 ProcessList
*process_list
= control_flow_data
->process_list
;
2676 g_assert(process
!= NULL
);
2678 birth
= process
->creation_time
;
2680 if(likely(process_list
->current_hash_data
[tfc
->index
] != NULL
)) {
2681 hashed_process_data
= process_list
->current_hash_data
[tfc
->index
];
2683 hashed_process_data
= processlist_get_process_data(process_list
,
2685 process
->last_cpu_index
,
2687 tfc
->t_context
->index
);
2688 if(unlikely(hashed_process_data
== NULL
))
2690 g_assert(pid
== 0 || pid
!= process
->ppid
);
2691 /* Process not present */
2692 Drawing_t
*drawing
= control_flow_data
->drawing
;
2693 const gchar
*name
= g_quark_to_string(process
->name
);
2694 ProcessInfo
*process_info
;
2695 processlist_add(process_list
,
2698 process
->last_cpu_index
,
2701 tfc
->t_context
->index
,
2705 &hashed_process_data
);
2706 gtk_widget_set_size_request(drawing
->drawing_area
,
2709 gtk_widget_queue_draw(drawing
->drawing_area
);
2713 /* Now, the process is in the state hash and our own process hash.
2714 * We definitely can draw the items related to the ending state.
2717 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2720 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2721 TimeWindow time_window
=
2722 lttvwindow_get_time_window(control_flow_data
->tab
);
2725 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2726 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2728 #endif //EXTRA_CHECK
2729 Drawing_t
*drawing
= control_flow_data
->drawing
;
2730 guint width
= drawing
->width
;
2732 convert_time_to_pixels(
2738 /* Draw collision indicator */
2739 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2740 gdk_draw_point(hashed_process_data
->pixmap
,
2743 (hashed_process_data
->height
/2)-3);
2744 hashed_process_data
->x
.middle_marked
= TRUE
;
2747 TimeWindow time_window
=
2748 lttvwindow_get_time_window(control_flow_data
->tab
);
2751 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2752 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2754 #endif //EXTRA_CHECK
2755 Drawing_t
*drawing
= control_flow_data
->drawing
;
2756 guint width
= drawing
->width
;
2759 convert_time_to_pixels(
2766 /* Jump over draw if we are at the same x position */
2767 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2768 hashed_process_data
->x
.middle_used
))
2770 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2771 /* Draw collision indicator */
2772 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2773 gdk_draw_point(hashed_process_data
->pixmap
,
2776 (hashed_process_data
->height
/2)-3);
2777 hashed_process_data
->x
.middle_marked
= TRUE
;
2781 DrawContext draw_context
;
2783 /* Now create the drawing context that will be used to draw
2784 * items related to the last state. */
2785 draw_context
.drawable
= hashed_process_data
->pixmap
;
2786 draw_context
.gc
= drawing
->gc
;
2787 draw_context
.pango_layout
= drawing
->pango_layout
;
2788 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2789 draw_context
.drawinfo
.end
.x
= x
;
2791 draw_context
.drawinfo
.y
.over
= 1;
2792 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2793 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2795 draw_context
.drawinfo
.start
.offset
.over
= 0;
2796 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2797 draw_context
.drawinfo
.start
.offset
.under
= 0;
2798 draw_context
.drawinfo
.end
.offset
.over
= 0;
2799 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2800 draw_context
.drawinfo
.end
.offset
.under
= 0;
2804 PropertiesLine prop_line
= prepare_s_e_line(process
);
2805 draw_line((void*)&prop_line
, (void*)&draw_context
);
2808 /* become the last x position */
2809 hashed_process_data
->x
.middle
= x
;
2810 hashed_process_data
->x
.middle_used
= TRUE
;
2811 hashed_process_data
->x
.middle_marked
= FALSE
;
2813 /* Calculate the next good time */
2814 convert_pixels_to_time(width
, x
+1, time_window
,
2815 &hashed_process_data
->next_good_time
);
2819 } else if(sub_id
== 7) /* release */ {
2823 LttField
*f
= ltt_event_field(e
);
2825 element
= ltt_field_member(f
,1);
2826 pid
= ltt_event_get_long_unsigned(e
,element
);
2829 /* Add process to process list (if not present) */
2830 /* Don't care about the process if it's not in the state hash already :
2831 * that means a process that has never done anything in the trace and
2832 * unknown suddently gets destroyed : no state meaningful to show. */
2833 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
2835 if(process
!= NULL
) {
2837 guint pl_height
= 0;
2838 HashedProcessData
*hashed_process_data
= NULL
;
2840 ProcessList
*process_list
= control_flow_data
->process_list
;
2842 birth
= process
->creation_time
;
2844 /* Cannot use current process : this event happens on another process,
2845 * action done by the parent. */
2846 hashed_process_data
= processlist_get_process_data(process_list
,
2848 process
->last_cpu_index
,
2850 tfc
->t_context
->index
);
2851 if(unlikely(hashed_process_data
== NULL
))
2853 g_assert(pid
== 0 || pid
!= process
->ppid
);
2854 /* Process not present */
2855 Drawing_t
*drawing
= control_flow_data
->drawing
;
2856 const gchar
*name
= g_quark_to_string(process
->name
);
2857 ProcessInfo
*process_info
;
2858 processlist_add(process_list
,
2861 process
->last_cpu_index
,
2864 tfc
->t_context
->index
,
2868 &hashed_process_data
);
2869 gtk_widget_set_size_request(drawing
->drawing_area
,
2872 gtk_widget_queue_draw(drawing
->drawing_area
);
2875 /* Now, the process is in the state hash and our own process hash.
2876 * We definitely can draw the items related to the ending state.
2879 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2882 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2883 TimeWindow time_window
=
2884 lttvwindow_get_time_window(control_flow_data
->tab
);
2887 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2888 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2890 #endif //EXTRA_CHECK
2891 Drawing_t
*drawing
= control_flow_data
->drawing
;
2892 guint width
= drawing
->width
;
2894 convert_time_to_pixels(
2900 /* Draw collision indicator */
2901 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2902 gdk_draw_point(hashed_process_data
->pixmap
,
2905 (hashed_process_data
->height
/2)-3);
2906 hashed_process_data
->x
.middle_marked
= TRUE
;
2909 TimeWindow time_window
=
2910 lttvwindow_get_time_window(control_flow_data
->tab
);
2913 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2914 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2916 #endif //EXTRA_CHECK
2917 Drawing_t
*drawing
= control_flow_data
->drawing
;
2918 guint width
= drawing
->width
;
2921 convert_time_to_pixels(
2928 /* Jump over draw if we are at the same x position */
2929 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2930 hashed_process_data
->x
.middle_used
))
2932 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2933 /* Draw collision indicator */
2934 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2935 gdk_draw_point(hashed_process_data
->pixmap
,
2938 (hashed_process_data
->height
/2)-3);
2939 hashed_process_data
->x
.middle_marked
= TRUE
;
2943 DrawContext draw_context
;
2945 /* Now create the drawing context that will be used to draw
2946 * items related to the last state. */
2947 draw_context
.drawable
= hashed_process_data
->pixmap
;
2948 draw_context
.gc
= drawing
->gc
;
2949 draw_context
.pango_layout
= drawing
->pango_layout
;
2950 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2951 draw_context
.drawinfo
.end
.x
= x
;
2953 draw_context
.drawinfo
.y
.over
= 1;
2954 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2955 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2957 draw_context
.drawinfo
.start
.offset
.over
= 0;
2958 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2959 draw_context
.drawinfo
.start
.offset
.under
= 0;
2960 draw_context
.drawinfo
.end
.offset
.over
= 0;
2961 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2962 draw_context
.drawinfo
.end
.offset
.under
= 0;
2966 PropertiesLine prop_line
= prepare_s_e_line(process
);
2967 draw_line((void*)&prop_line
, (void*)&draw_context
);
2970 /* become the last x position */
2971 hashed_process_data
->x
.middle
= x
;
2972 hashed_process_data
->x
.middle_used
= TRUE
;
2973 hashed_process_data
->x
.middle_marked
= FALSE
;
2975 /* Calculate the next good time */
2976 convert_pixels_to_time(width
, x
+1, time_window
,
2977 &hashed_process_data
->next_good_time
);
2991 /* after_process_fork_hook
2993 * Create the processlist entry for the child process. Put the last
2994 * position in x at the current time value.
2996 * @param hook_data ControlFlowData structure of the viewer.
2997 * @param call_data Event context.
2999 * This function adds items to be drawn in a queue for each process.
3002 int after_process_fork_hook(void *hook_data
, void *call_data
)
3004 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3005 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3006 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3008 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3010 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3013 e
= ltt_tracefile_get_event(tfc
->tf
);
3015 LttTime evtime
= ltt_event_time(e
);
3019 child_pid
= ltt_event_get_long_unsigned(e
, thf
->f2
);
3022 /* Add process to process list (if not present) */
3023 LttvProcessState
*process_child
;
3025 guint pl_height
= 0;
3026 HashedProcessData
*hashed_process_data_child
= NULL
;
3028 ProcessList
*process_list
= control_flow_data
->process_list
;
3030 /* Find child in the list... */
3031 process_child
= lttv_state_find_process(tfs
, child_pid
);
3032 /* It should exist, because we are after the state update. */
3033 g_assert(process_child
!= NULL
);
3035 birth
= process_child
->creation_time
;
3037 /* Cannot use current process, because this action is done by the parent
3039 hashed_process_data_child
= processlist_get_process_data(process_list
,
3041 process_child
->last_cpu_index
,
3043 tfc
->t_context
->index
);
3044 if(likely(hashed_process_data_child
== NULL
))
3046 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3047 /* Process not present */
3048 Drawing_t
*drawing
= control_flow_data
->drawing
;
3049 const gchar
*name
= g_quark_to_string(process_child
->name
);
3050 ProcessInfo
*process_info
;
3051 processlist_add(process_list
,
3054 process_child
->last_cpu_index
,
3055 process_child
->ppid
,
3057 tfc
->t_context
->index
,
3061 &hashed_process_data_child
);
3062 gtk_widget_set_size_request(drawing
->drawing_area
,
3065 gtk_widget_queue_draw(drawing
->drawing_area
);
3069 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3072 TimeWindow time_window
=
3073 lttvwindow_get_time_window(control_flow_data
->tab
);
3076 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3077 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3079 #endif //EXTRA_CHECK
3080 Drawing_t
*drawing
= control_flow_data
->drawing
;
3081 guint width
= drawing
->width
;
3083 convert_time_to_pixels(
3089 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3090 hashed_process_data_child
->x
.over
= new_x
;
3091 hashed_process_data_child
->x
.over_used
= FALSE
;
3092 hashed_process_data_child
->x
.over_marked
= FALSE
;
3094 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3095 hashed_process_data_child
->x
.middle
= new_x
;
3096 hashed_process_data_child
->x
.middle_used
= FALSE
;
3097 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3099 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3100 hashed_process_data_child
->x
.under
= new_x
;
3101 hashed_process_data_child
->x
.under_used
= FALSE
;
3102 hashed_process_data_child
->x
.under_marked
= FALSE
;
3110 /* after_process_exit_hook
3112 * Create the processlist entry for the child process. Put the last
3113 * position in x at the current time value.
3115 * @param hook_data ControlFlowData structure of the viewer.
3116 * @param call_data Event context.
3118 * This function adds items to be drawn in a queue for each process.
3121 int after_process_exit_hook(void *hook_data
, void *call_data
)
3123 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3124 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3125 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3127 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3129 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3132 e
= ltt_tracefile_get_event(tfc
->tf
);
3134 LttTime evtime
= ltt_event_time(e
);
3136 /* Add process to process list (if not present) */
3137 LttvProcessState
*process
= tfs
->process
;
3138 guint pid
= process
->pid
;
3140 guint pl_height
= 0;
3141 HashedProcessData
*hashed_process_data
= NULL
;
3143 ProcessList
*process_list
= control_flow_data
->process_list
;
3145 /* It should exist, because we are after the state update. */
3146 g_assert(process
!= NULL
);
3148 birth
= process
->creation_time
;
3150 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
) ){
3151 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
3153 hashed_process_data
= processlist_get_process_data(process_list
,
3155 process
->last_cpu_index
,
3157 tfc
->t_context
->index
);
3158 if(unlikely(hashed_process_data
== NULL
))
3160 g_assert(pid
== 0 || pid
!= process
->ppid
);
3161 /* Process not present */
3162 Drawing_t
*drawing
= control_flow_data
->drawing
;
3163 const gchar
*name
= g_quark_to_string(process
->name
);
3164 ProcessInfo
*process_info
;
3165 processlist_add(process_list
,
3168 process
->last_cpu_index
,
3171 tfc
->t_context
->index
,
3175 &hashed_process_data
);
3176 gtk_widget_set_size_request(drawing
->drawing_area
,
3179 gtk_widget_queue_draw(drawing
->drawing_area
);
3182 /* Set the current process */
3183 process_list
->current_hash_data
[process
->last_cpu_index
] =
3184 hashed_process_data
;
3187 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3190 TimeWindow time_window
=
3191 lttvwindow_get_time_window(control_flow_data
->tab
);
3194 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3195 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3197 #endif //EXTRA_CHECK
3198 Drawing_t
*drawing
= control_flow_data
->drawing
;
3199 guint width
= drawing
->width
;
3201 convert_time_to_pixels(
3206 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3207 hashed_process_data
->x
.middle
= new_x
;
3208 hashed_process_data
->x
.middle_used
= FALSE
;
3209 hashed_process_data
->x
.middle_marked
= FALSE
;
3219 /* after_process_hook
3221 * Create the processlist entry for the child process. Put the last
3222 * position in x at the current time value.
3224 * @param hook_data ControlFlowData structure of the viewer.
3225 * @param call_data Event context.
3227 * This function adds items to be drawn in a queue for each process.
3230 int after_process_hook(void *hook_data
, void *call_data
)
3232 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3233 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3234 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3236 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3238 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3241 e
= ltt_tracefile_get_event(tfc
->tf
);
3243 LttTime evtime
= ltt_event_time(e
);
3248 LttField
*f
= ltt_event_field(e
);
3250 element
= ltt_field_member(f
,0);
3251 sub_id
= ltt_event_get_long_unsigned(e
,element
);
3252 element
= ltt_field_member(f
,1);
3253 param1
= ltt_event_get_long_unsigned(e
,element
);
3256 if(sub_id
== 2) { /* fork */
3258 guint child_pid
= param1
;
3259 /* Add process to process list (if not present) */
3260 LttvProcessState
*process_child
;
3262 guint pl_height
= 0;
3263 HashedProcessData
*hashed_process_data_child
= NULL
;
3265 ProcessList
*process_list
= control_flow_data
->process_list
;
3267 /* Find child in the list... */
3268 process_child
= lttv_state_find_process(tfs
, child_pid
);
3269 /* It should exist, because we are after the state update. */
3270 g_assert(process_child
!= NULL
);
3272 birth
= process_child
->creation_time
;
3274 /* Cannot use current process, because this action is done by the parent
3276 hashed_process_data_child
= processlist_get_process_data(process_list
,
3278 process_child
->last_cpu_index
,
3280 tfc
->t_context
->index
);
3281 if(likely(hashed_process_data_child
== NULL
))
3283 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3284 /* Process not present */
3285 Drawing_t
*drawing
= control_flow_data
->drawing
;
3286 const gchar
*name
= g_quark_to_string(process_child
->name
);
3287 ProcessInfo
*process_info
;
3288 processlist_add(process_list
,
3291 process_child
->last_cpu_index
,
3292 process_child
->ppid
,
3294 tfc
->t_context
->index
,
3298 &hashed_process_data_child
);
3299 gtk_widget_set_size_request(drawing
->drawing_area
,
3302 gtk_widget_queue_draw(drawing
->drawing_area
);
3306 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3309 TimeWindow time_window
=
3310 lttvwindow_get_time_window(control_flow_data
->tab
);
3313 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3314 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3316 #endif //EXTRA_CHECK
3317 Drawing_t
*drawing
= control_flow_data
->drawing
;
3318 guint width
= drawing
->width
;
3320 convert_time_to_pixels(
3326 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3327 hashed_process_data_child
->x
.over
= new_x
;
3328 hashed_process_data_child
->x
.over_used
= FALSE
;
3329 hashed_process_data_child
->x
.over_marked
= FALSE
;
3331 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3332 hashed_process_data_child
->x
.middle
= new_x
;
3333 hashed_process_data_child
->x
.middle_used
= FALSE
;
3334 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3336 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3337 hashed_process_data_child
->x
.under
= new_x
;
3338 hashed_process_data_child
->x
.under_used
= FALSE
;
3339 hashed_process_data_child
->x
.under_marked
= FALSE
;
3343 } else if(sub_id
== 3) { /* exit */
3345 /* Add process to process list (if not present) */
3346 LttvProcessState
*process
= tfs
->process
;
3347 guint pid
= process
->pid
;
3349 guint pl_height
= 0;
3350 HashedProcessData
*hashed_process_data
= NULL
;
3352 ProcessList
*process_list
= control_flow_data
->process_list
;
3354 /* It should exist, because we are after the state update. */
3355 g_assert(process
!= NULL
);
3357 birth
= process
->creation_time
;
3359 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
) ){
3360 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
3362 hashed_process_data
= processlist_get_process_data(process_list
,
3364 process
->last_cpu_index
,
3366 tfc
->t_context
->index
);
3367 if(unlikely(hashed_process_data
== NULL
))
3369 g_assert(pid
== 0 || pid
!= process
->ppid
);
3370 /* Process not present */
3371 Drawing_t
*drawing
= control_flow_data
->drawing
;
3372 const gchar
*name
= g_quark_to_string(process
->name
);
3373 ProcessInfo
*process_info
;
3374 processlist_add(process_list
,
3377 process
->last_cpu_index
,
3380 tfc
->t_context
->index
,
3384 &hashed_process_data
);
3385 gtk_widget_set_size_request(drawing
->drawing_area
,
3388 gtk_widget_queue_draw(drawing
->drawing_area
);
3391 /* Set the current process */
3392 process_list
->current_hash_data
[process
->last_cpu_index
] =
3393 hashed_process_data
;
3396 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3399 TimeWindow time_window
=
3400 lttvwindow_get_time_window(control_flow_data
->tab
);
3403 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3404 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3406 #endif //EXTRA_CHECK
3407 Drawing_t
*drawing
= control_flow_data
->drawing
;
3408 guint width
= drawing
->width
;
3410 convert_time_to_pixels(
3415 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3416 hashed_process_data
->x
.middle
= new_x
;
3417 hashed_process_data
->x
.middle_used
= FALSE
;
3418 hashed_process_data
->x
.middle_marked
= FALSE
;
3428 gint
update_time_window_hook(void *hook_data
, void *call_data
)
3430 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3431 Drawing_t
*drawing
= control_flow_data
->drawing
;
3432 ProcessList
*process_list
= control_flow_data
->process_list
;
3434 const TimeWindowNotifyData
*time_window_nofify_data
=
3435 ((const TimeWindowNotifyData
*)call_data
);
3437 TimeWindow
*old_time_window
=
3438 time_window_nofify_data
->old_time_window
;
3439 TimeWindow
*new_time_window
=
3440 time_window_nofify_data
->new_time_window
;
3442 /* Update the ruler */
3443 drawing_update_ruler(control_flow_data
->drawing
,
3447 /* Two cases : zoom in/out or scrolling */
3449 /* In order to make sure we can reuse the old drawing, the scale must
3450 * be the same and the new time interval being partly located in the
3451 * currently shown time interval. (reuse is only for scrolling)
3454 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3455 old_time_window
->start_time
.tv_sec
,
3456 old_time_window
->start_time
.tv_nsec
,
3457 old_time_window
->time_width
.tv_sec
,
3458 old_time_window
->time_width
.tv_nsec
);
3460 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3461 new_time_window
->start_time
.tv_sec
,
3462 new_time_window
->start_time
.tv_nsec
,
3463 new_time_window
->time_width
.tv_sec
,
3464 new_time_window
->time_width
.tv_nsec
);
3466 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
3467 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
3469 /* Same scale (scrolling) */
3470 g_info("scrolling");
3471 LttTime
*ns
= &new_time_window
->start_time
;
3472 LttTime
*nw
= &new_time_window
->time_width
;
3473 LttTime
*os
= &old_time_window
->start_time
;
3474 LttTime
*ow
= &old_time_window
->time_width
;
3475 LttTime old_end
= old_time_window
->end_time
;
3476 LttTime new_end
= new_time_window
->end_time
;
3478 //if(ns<os+w && os+w<ns+w)
3479 //if(ns<old_end && os<ns)
3480 if(ltt_time_compare(*ns
, old_end
) == -1
3481 && ltt_time_compare(*os
, *ns
) == -1)
3483 g_info("scrolling near right");
3484 /* Scroll right, keep right part of the screen */
3486 guint width
= control_flow_data
->drawing
->width
;
3487 convert_time_to_pixels(
3493 /* Copy old data to new location */
3494 copy_pixmap_region(process_list
,
3496 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3500 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
3502 if(drawing
->damage_begin
== drawing
->damage_end
)
3503 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
3505 drawing
->damage_begin
= 0;
3507 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3509 /* Clear the data request background, but not SAFETY */
3510 rectangle_pixmap(process_list
,
3511 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3513 drawing
->damage_begin
+SAFETY
, 0,
3514 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3516 gtk_widget_queue_draw(drawing
->drawing_area
);
3517 //gtk_widget_queue_draw_area (drawing->drawing_area,
3519 // control_flow_data->drawing->width,
3520 // control_flow_data->drawing->height);
3522 /* Get new data for the rest. */
3523 drawing_data_request(control_flow_data
->drawing
,
3524 drawing
->damage_begin
, 0,
3525 drawing
->damage_end
- drawing
->damage_begin
,
3526 control_flow_data
->drawing
->height
);
3529 //if(ns<os && os<ns+w)
3530 //if(ns<os && os<new_end)
3531 if(ltt_time_compare(*ns
,*os
) == -1
3532 && ltt_time_compare(*os
,new_end
) == -1)
3534 g_info("scrolling near left");
3535 /* Scroll left, keep left part of the screen */
3537 guint width
= control_flow_data
->drawing
->width
;
3538 convert_time_to_pixels(
3544 /* Copy old data to new location */
3545 copy_pixmap_region (process_list
,
3547 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3553 if(drawing
->damage_begin
== drawing
->damage_end
)
3554 drawing
->damage_end
= x
;
3556 drawing
->damage_end
=
3557 control_flow_data
->drawing
->width
;
3559 drawing
->damage_begin
= 0;
3561 rectangle_pixmap (process_list
,
3562 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3564 drawing
->damage_begin
, 0,
3565 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3568 gtk_widget_queue_draw(drawing
->drawing_area
);
3569 //gtk_widget_queue_draw_area (drawing->drawing_area,
3571 // control_flow_data->drawing->width,
3572 // control_flow_data->drawing->height);
3575 /* Get new data for the rest. */
3576 drawing_data_request(control_flow_data
->drawing
,
3577 drawing
->damage_begin
, 0,
3578 drawing
->damage_end
- drawing
->damage_begin
,
3579 control_flow_data
->drawing
->height
);
3582 if(ltt_time_compare(*ns
,*os
) == 0)
3584 g_info("not scrolling");
3586 g_info("scrolling far");
3587 /* Cannot reuse any part of the screen : far jump */
3590 rectangle_pixmap (process_list
,
3591 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3594 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3597 //gtk_widget_queue_draw_area (drawing->drawing_area,
3599 // control_flow_data->drawing->width,
3600 // control_flow_data->drawing->height);
3601 gtk_widget_queue_draw(drawing
->drawing_area
);
3603 drawing
->damage_begin
= 0;
3604 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3606 drawing_data_request(control_flow_data
->drawing
,
3608 control_flow_data
->drawing
->width
,
3609 control_flow_data
->drawing
->height
);
3615 /* Different scale (zoom) */
3618 rectangle_pixmap (process_list
,
3619 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3622 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3625 //gtk_widget_queue_draw_area (drawing->drawing_area,
3627 // control_flow_data->drawing->width,
3628 // control_flow_data->drawing->height);
3629 gtk_widget_queue_draw(drawing
->drawing_area
);
3631 drawing
->damage_begin
= 0;
3632 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3634 drawing_data_request(control_flow_data
->drawing
,
3636 control_flow_data
->drawing
->width
,
3637 control_flow_data
->drawing
->height
);
3645 gint
traceset_notify(void *hook_data
, void *call_data
)
3647 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3648 Drawing_t
*drawing
= control_flow_data
->drawing
;
3651 drawing_clear(control_flow_data
->drawing
);
3652 processlist_clear(control_flow_data
->process_list
);
3653 gtk_widget_set_size_request(
3654 control_flow_data
->drawing
->drawing_area
,
3655 -1, processlist_get_height(control_flow_data
->process_list
));
3656 redraw_notify(control_flow_data
, NULL
);
3658 request_background_data(control_flow_data
);
3663 gint
redraw_notify(void *hook_data
, void *call_data
)
3665 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3666 Drawing_t
*drawing
= control_flow_data
->drawing
;
3667 GtkWidget
*widget
= drawing
->drawing_area
;
3669 drawing
->damage_begin
= 0;
3670 drawing
->damage_end
= drawing
->width
;
3672 /* fun feature, to be separated someday... */
3673 drawing_clear(control_flow_data
->drawing
);
3674 processlist_clear(control_flow_data
->process_list
);
3675 gtk_widget_set_size_request(
3676 control_flow_data
->drawing
->drawing_area
,
3677 -1, processlist_get_height(control_flow_data
->process_list
));
3679 rectangle_pixmap (control_flow_data
->process_list
,
3680 widget
->style
->black_gc
,
3683 drawing
->alloc_width
,
3686 gtk_widget_queue_draw(drawing
->drawing_area
);
3688 if(drawing
->damage_begin
< drawing
->damage_end
)
3690 drawing_data_request(drawing
,
3691 drawing
->damage_begin
,
3693 drawing
->damage_end
-drawing
->damage_begin
,
3697 //gtk_widget_queue_draw_area(drawing->drawing_area,
3700 // drawing->height);
3706 gint
continue_notify(void *hook_data
, void *call_data
)
3708 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3709 Drawing_t
*drawing
= control_flow_data
->drawing
;
3711 //g_assert(widget->allocation.width == drawing->damage_end);
3713 if(drawing
->damage_begin
< drawing
->damage_end
)
3715 drawing_data_request(drawing
,
3716 drawing
->damage_begin
,
3718 drawing
->damage_end
-drawing
->damage_begin
,
3726 gint
update_current_time_hook(void *hook_data
, void *call_data
)
3728 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
3729 Drawing_t
*drawing
= control_flow_data
->drawing
;
3731 LttTime current_time
= *((LttTime
*)call_data
);
3733 TimeWindow time_window
=
3734 lttvwindow_get_time_window(control_flow_data
->tab
);
3736 LttTime time_begin
= time_window
.start_time
;
3737 LttTime width
= time_window
.time_width
;
3740 guint64 time_ll
= ltt_time_to_uint64(width
);
3741 time_ll
= time_ll
>> 1; /* divide by two */
3742 half_width
= ltt_time_from_uint64(time_ll
);
3744 LttTime time_end
= ltt_time_add(time_begin
, width
);
3746 LttvTracesetContext
* tsc
=
3747 lttvwindow_get_traceset_context(control_flow_data
->tab
);
3749 LttTime trace_start
= tsc
->time_span
.start_time
;
3750 LttTime trace_end
= tsc
->time_span
.end_time
;
3752 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
3753 current_time
.tv_nsec
);
3757 /* If current time is inside time interval, just move the highlight
3760 /* Else, we have to change the time interval. We have to tell it
3761 * to the main window. */
3762 /* The time interval change will take care of placing the current
3763 * time at the center of the visible area, or nearest possible if we are
3764 * at one end of the trace. */
3767 if(ltt_time_compare(current_time
, time_begin
) < 0)
3769 TimeWindow new_time_window
;
3771 if(ltt_time_compare(current_time
,
3772 ltt_time_add(trace_start
,half_width
)) < 0)
3773 time_begin
= trace_start
;
3775 time_begin
= ltt_time_sub(current_time
,half_width
);
3777 new_time_window
.start_time
= time_begin
;
3778 new_time_window
.time_width
= width
;
3779 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3780 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3782 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3784 else if(ltt_time_compare(current_time
, time_end
) > 0)
3786 TimeWindow new_time_window
;
3788 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
3789 time_begin
= ltt_time_sub(trace_end
,width
);
3791 time_begin
= ltt_time_sub(current_time
,half_width
);
3793 new_time_window
.start_time
= time_begin
;
3794 new_time_window
.time_width
= width
;
3795 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3796 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3798 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3801 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
3807 typedef struct _ClosureData
{
3808 EventsRequest
*events_request
;
3809 LttvTracesetState
*tss
;
3815 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
3817 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
3818 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
3819 ClosureData
*closure_data
= (ClosureData
*)user_data
;
3821 EventsRequest
*events_request
= closure_data
->events_request
;
3822 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3824 LttvTracesetState
*tss
= closure_data
->tss
;
3825 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
3827 LttTime evtime
= closure_data
->end_time
;
3830 /* For the process */
3831 /* First, check if the current process is in the state computation
3832 * process list. If it is there, that means we must add it right now and
3833 * draw items from the beginning of the read for it. If it is not
3834 * present, it's a new process and it was not present : it will
3835 * be added after the state update. */
3837 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
3838 #endif //EXTRA_CHECK
3839 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
3841 //FIXME : optimize data structures.
3842 LttvTracefileState
*tfs
;
3843 LttvTracefileContext
*tfc
;
3845 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
3846 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
3847 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
3848 && ltt_tracefile_num(tfc
->tf
) == process_info
->cpu
)
3852 g_assert(i
<tc
->tracefiles
->len
);
3853 tfs
= LTTV_TRACEFILE_STATE(tfc
);
3855 // LttvTracefileState *tfs =
3856 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3857 // tracefiles[process_info->cpu];
3859 LttvProcessState
*process
;
3860 process
= lttv_state_find_process(tfs
,
3863 if(unlikely(process
!= NULL
)) {
3865 /* Only draw for processes that are currently in the trace states */
3867 ProcessList
*process_list
= control_flow_data
->process_list
;
3869 /* Should be alike when background info is ready */
3870 if(control_flow_data
->background_info_waiting
==0)
3871 g_assert(ltt_time_compare(process
->creation_time
,
3872 process_info
->birth
) == 0);
3873 #endif //EXTRA_CHECK
3875 /* Now, the process is in the state hash and our own process hash.
3876 * We definitely can draw the items related to the ending state.
3879 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3882 TimeWindow time_window
=
3883 lttvwindow_get_time_window(control_flow_data
->tab
);
3886 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3887 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3889 #endif //EXTRA_CHECK
3890 Drawing_t
*drawing
= control_flow_data
->drawing
;
3891 guint width
= drawing
->width
;
3893 guint x
= closure_data
->x_end
;
3895 DrawContext draw_context
;
3897 /* Now create the drawing context that will be used to draw
3898 * items related to the last state. */
3899 draw_context
.drawable
= hashed_process_data
->pixmap
;
3900 draw_context
.gc
= drawing
->gc
;
3901 draw_context
.pango_layout
= drawing
->pango_layout
;
3902 draw_context
.drawinfo
.end
.x
= x
;
3904 draw_context
.drawinfo
.y
.over
= 1;
3905 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
3906 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
3908 draw_context
.drawinfo
.start
.offset
.over
= 0;
3909 draw_context
.drawinfo
.start
.offset
.middle
= 0;
3910 draw_context
.drawinfo
.start
.offset
.under
= 0;
3911 draw_context
.drawinfo
.end
.offset
.over
= 0;
3912 draw_context
.drawinfo
.end
.offset
.middle
= 0;
3913 draw_context
.drawinfo
.end
.offset
.under
= 0;
3915 /* Jump over draw if we are at the same x position */
3916 if(x
== hashed_process_data
->x
.over
)
3920 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
3922 PropertiesLine prop_line
= prepare_execmode_line(process
);
3923 draw_line((void*)&prop_line
, (void*)&draw_context
);
3925 hashed_process_data
->x
.over
= x
;
3929 if(unlikely(x
== hashed_process_data
->x
.middle
&&
3930 hashed_process_data
->x
.middle_used
)) {
3931 #if 0 /* do not mark closure : not missing information */
3932 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
3933 /* Draw collision indicator */
3934 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
3935 gdk_draw_point(drawing
->pixmap
,
3939 hashed_process_data
->x
.middle_marked
= TRUE
;
3944 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
3946 PropertiesLine prop_line
= prepare_s_e_line(process
);
3947 draw_line((void*)&prop_line
, (void*)&draw_context
);
3949 /* become the last x position */
3950 if(likely(x
!= hashed_process_data
->x
.middle
)) {
3951 hashed_process_data
->x
.middle
= x
;
3952 /* but don't use the pixel */
3953 hashed_process_data
->x
.middle_used
= FALSE
;
3955 /* Calculate the next good time */
3956 convert_pixels_to_time(width
, x
+1, time_window
,
3957 &hashed_process_data
->next_good_time
);
3966 int before_chunk(void *hook_data
, void *call_data
)
3968 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
3969 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
3970 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
3972 /* Desactivate sort */
3973 gtk_tree_sortable_set_sort_column_id(
3974 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
3976 GTK_SORT_ASCENDING
);
3978 drawing_chunk_begin(events_request
, tss
);
3983 int before_request(void *hook_data
, void *call_data
)
3985 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
3986 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
3988 drawing_data_request_begin(events_request
, tss
);
3995 * after request is necessary in addition of after chunk in order to draw
3996 * lines until the end of the screen. after chunk just draws lines until
4003 int after_request(void *hook_data
, void *call_data
)
4005 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4006 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4007 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4009 ProcessList
*process_list
= control_flow_data
->process_list
;
4010 LttTime end_time
= events_request
->end_time
;
4012 ClosureData closure_data
;
4013 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4014 closure_data
.tss
= tss
;
4015 closure_data
.end_time
= end_time
;
4017 TimeWindow time_window
=
4018 lttvwindow_get_time_window(control_flow_data
->tab
);
4019 guint width
= control_flow_data
->drawing
->width
;
4020 convert_time_to_pixels(
4024 &closure_data
.x_end
);
4027 /* Draw last items */
4028 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4029 (void*)&closure_data
);
4032 /* Request expose */
4033 drawing_request_expose(events_request
, tss
, end_time
);
4042 int after_chunk(void *hook_data
, void *call_data
)
4044 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4045 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4046 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4047 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
4048 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
4051 ProcessList
*process_list
= control_flow_data
->process_list
;
4053 g_free(process_list
->current_hash_data
);
4054 process_list
->current_hash_data
= NULL
;
4057 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
4058 else /* end of traceset, or position now out of request : end */
4059 end_time
= events_request
->end_time
;
4061 ClosureData closure_data
;
4062 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4063 closure_data
.tss
= tss
;
4064 closure_data
.end_time
= end_time
;
4066 TimeWindow time_window
=
4067 lttvwindow_get_time_window(control_flow_data
->tab
);
4068 guint width
= control_flow_data
->drawing
->width
;
4069 convert_time_to_pixels(
4073 &closure_data
.x_end
);
4075 /* Draw last items */
4076 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4077 (void*)&closure_data
);
4079 /* Reactivate sort */
4080 gtk_tree_sortable_set_sort_column_id(
4081 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
4082 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
4083 GTK_SORT_ASCENDING
);
4085 update_index_to_pixmap(control_flow_data
->process_list
);
4086 /* Request a full expose : drawing scrambled */
4087 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
4089 /* Request expose (updates damages zone also) */
4090 drawing_request_expose(events_request
, tss
, end_time
);