1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
25 /* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
52 //#define PANGO_ENABLE_BACKEND
60 //#include <pango/pango.h>
62 #include <ltt/event.h>
65 #include <ltt/trace.h>
67 #include <lttv/lttv.h>
68 #include <lttv/hook.h>
69 #include <lttv/state.h>
70 #include <lttvwindow/lttvwindow.h>
71 #include <lttvwindow/lttvwindowtraces.h>
74 #include "eventhooks.h"
76 #include "processlist.h"
80 #define MAX_PATH_LEN 256
83 typedef struct _ProcessAddClosure
{
88 static void process_add(gpointer key
,
92 LttvProcessState
*process
= (LttvProcessState
*)value
;
93 ProcessAddClosure
*closure
= (ProcessAddClosure
*)user_data
;
94 ControlFlowData
*control_flow_data
= closure
->cfd
;
95 guint trace_num
= closure
->trace_num
;
97 /* Add process to process list (if not present) */
100 guint y
= 0, height
= 0, pl_height
= 0;
102 ProcessList
*process_list
= control_flow_data
->process_list
;
105 birth
= process
->creation_time
;
106 const gchar
*name
= g_quark_to_string(process
->name
);
107 HashedProcessData
*hashed_process_data
= NULL
;
109 if(processlist_get_process_pixels(process_list
,
115 &hashed_process_data
) == 1)
117 /* Process not present */
118 processlist_add(process_list
,
124 &hashed_process_data
);
125 processlist_get_process_pixels(process_list
,
131 &hashed_process_data
);
132 drawing_insert_square( control_flow_data
->drawing
, y
, height
);
138 /* Action to do when background computation completed.
140 * Wait for all the awaited computations to be over.
143 gint
background_ready(void *hook_data
, void *call_data
)
145 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
146 LttvTrace
*trace
= (LttvTrace
*)call_data
;
148 control_flow_data
->background_info_waiting
--;
150 if(control_flow_data
->background_info_waiting
== 0) {
151 g_debug("control flow viewer : background computation data ready.");
153 drawing_clear(control_flow_data
->drawing
);
154 processlist_clear(control_flow_data
->process_list
);
155 gtk_widget_set_size_request(
156 control_flow_data
->drawing
->drawing_area
,
157 -1, processlist_get_height(control_flow_data
->process_list
));
158 redraw_notify(control_flow_data
, NULL
);
165 /* Request background computation. Verify if it is in progress or ready first.
166 * Only for each trace in the tab's traceset.
168 void request_background_data(ControlFlowData
*control_flow_data
)
170 LttvTracesetContext
* tsc
=
171 lttvwindow_get_traceset_context(control_flow_data
->tab
);
172 gint num_traces
= lttv_traceset_number(tsc
->ts
);
176 LttvHooks
*background_ready_hook
=
178 lttv_hooks_add(background_ready_hook
, background_ready
, control_flow_data
,
180 control_flow_data
->background_info_waiting
= 0;
182 for(i
=0;i
<num_traces
;i
++) {
183 trace
= lttv_traceset_get(tsc
->ts
, i
);
185 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
) {
187 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
189 /* We first remove requests that could have been done for the same
190 * information. Happens when two viewers ask for it before servicing
193 lttvwindowtraces_background_request_remove(trace
, "state");
194 lttvwindowtraces_background_request_queue(trace
,
196 lttvwindowtraces_background_notify_queue(control_flow_data
,
200 background_ready_hook
);
201 control_flow_data
->background_info_waiting
++;
202 } else { /* in progress */
204 lttvwindowtraces_background_notify_current(control_flow_data
,
208 background_ready_hook
);
209 control_flow_data
->background_info_waiting
++;
212 /* Data ready. Be its nature, this viewer doesn't need to have
213 * its data ready hook called htere, because a background
214 * request is always linked with a redraw.
220 lttv_hooks_destroy(background_ready_hook
);
227 * Event Viewer's constructor hook
229 * This constructor is given as a parameter to the menuitem and toolbar button
230 * registration. It creates the list.
231 * @param tab A pointer to the parent tab.
232 * @return The widget created.
235 h_guicontrolflow(Tab
*tab
)
237 g_info("h_guicontrolflow, %p", tab
);
238 ControlFlowData
*control_flow_data
= guicontrolflow() ;
240 control_flow_data
->tab
= tab
;
242 // Unreg done in the GuiControlFlow_Destructor
243 lttvwindow_register_traceset_notify(tab
,
247 lttvwindow_register_time_window_notify(tab
,
248 update_time_window_hook
,
250 lttvwindow_register_current_time_notify(tab
,
251 update_current_time_hook
,
253 lttvwindow_register_redraw_notify(tab
,
256 lttvwindow_register_continue_notify(tab
,
259 request_background_data(control_flow_data
);
262 return guicontrolflow_get_widget(control_flow_data
) ;
266 int event_selected_hook(void *hook_data
, void *call_data
)
268 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
269 guint
*event_number
= (guint
*) call_data
;
271 g_debug("DEBUG : event selected by main window : %u", *event_number
);
276 /* Function that selects the color of status&exemode line */
277 static inline PropertiesLine
prepare_s_e_line(LttvProcessState
*process
)
279 PropertiesLine prop_line
;
280 prop_line
.line_width
= 2;
281 prop_line
.style
= GDK_LINE_SOLID
;
282 prop_line
.y
= MIDDLE
;
283 //GdkColormap *colormap = gdk_colormap_get_system();
285 if(process
->state
->s
== LTTV_STATE_RUN
) {
286 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
287 prop_line
.color
= drawing_colors
[COL_RUN_USER_MODE
];
288 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
289 prop_line
.color
= drawing_colors
[COL_RUN_SYSCALL
];
290 else if(process
->state
->t
== LTTV_STATE_TRAP
)
291 prop_line
.color
= drawing_colors
[COL_RUN_TRAP
];
292 else if(process
->state
->t
== LTTV_STATE_IRQ
)
293 prop_line
.color
= drawing_colors
[COL_RUN_IRQ
];
294 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
295 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
297 g_assert(FALSE
); /* RUNNING MODE UNKNOWN */
298 } else if(process
->state
->s
== LTTV_STATE_WAIT
) {
299 /* We don't show if we wait while in user mode, trap, irq or syscall */
300 prop_line
.color
= drawing_colors
[COL_WAIT
];
301 } else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
) {
302 /* We don't show if we wait for CPU while in user mode, trap, irq
304 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
305 } else if(process
->state
->s
== LTTV_STATE_ZOMBIE
) {
306 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
307 } else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
) {
308 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
309 } else if(process
->state
->s
== LTTV_STATE_EXIT
) {
310 prop_line
.color
= drawing_colors
[COL_EXIT
];
311 } else if(process
->state
->s
== LTTV_STATE_UNNAMED
) {
312 prop_line
.color
= drawing_colors
[COL_UNNAMED
];
314 g_assert(FALSE
); /* UNKNOWN STATE */
321 static inline PropertiesLine
prepare_status_line(LttvProcessState
*process
)
323 PropertiesLine prop_line
;
324 prop_line
.line_width
= 2;
325 prop_line
.style
= GDK_LINE_SOLID
;
326 prop_line
.y
= MIDDLE
;
327 //GdkColormap *colormap = gdk_colormap_get_system();
329 g_debug("prepare_status_line for state : %s",
330 g_quark_to_string(process
->state
->s
));
332 /* color of line : status of the process */
333 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
334 prop_line
.color
= drawing_colors
[COL_WHITE
];
335 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
336 prop_line
.color
= drawing_colors
[COL_WAIT_FORK
];
337 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
338 prop_line
.color
= drawing_colors
[COL_WAIT_CPU
];
339 else if(process
->state
->s
== LTTV_STATE_EXIT
)
340 prop_line
.color
= drawing_colors
[COL_EXIT
];
341 else if(process
->state
->s
== LTTV_STATE_ZOMBIE
)
342 prop_line
.color
= drawing_colors
[COL_ZOMBIE
];
343 else if(process
->state
->s
== LTTV_STATE_WAIT
)
344 prop_line
.color
= drawing_colors
[COL_WAIT
];
345 else if(process
->state
->s
== LTTV_STATE_RUN
)
346 prop_line
.color
= drawing_colors
[COL_RUN
];
348 prop_line
.color
= drawing_colors
[COL_WHITE
];
350 //gdk_colormap_alloc_color(colormap,
361 /* before_schedchange_hook
363 * This function basically draw lines and icons. Two types of lines are drawn :
364 * one small (3 pixels?) representing the state of the process and the second
365 * type is thicker (10 pixels?) representing on which CPU a process is running
366 * (and this only in running state).
368 * Extremums of the lines :
369 * x_min : time of the last event context for this process kept in memory.
370 * x_max : time of the current event.
371 * y : middle of the process in the process list. The process is found in the
372 * list, therefore is it's position in pixels.
374 * The choice of lines'color is defined by the context of the last event for this
379 int before_schedchange_hook(void *hook_data
, void *call_data
)
381 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
382 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
383 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
385 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
387 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
388 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
391 e
= ltt_tracefile_get_event(tfc
->tf
);
393 LttTime evtime
= ltt_event_time(e
);
395 /* we are in a schedchange, before the state update. We must draw the
396 * items corresponding to the state before it changes : now is the right
403 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
404 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
408 /* For the pid_out */
409 /* First, check if the current process is in the state computation
410 * process list. If it is there, that means we must add it right now and
411 * draw items from the beginning of the read for it. If it is not
412 * present, it's a new process and it was not present : it will
413 * be added after the state update. */
414 guint cpu
= ltt_tracefile_num(tfc
->tf
);
415 LttvProcessState
*process
= ts
->running_process
[cpu
];
416 /* unknown state, bad current pid */
417 if(process
->pid
!= pid_out
)
418 process
= lttv_state_find_process(ts
,
419 ltt_tracefile_num(tfc
->tf
), pid_out
);
421 if(process
!= NULL
) {
422 /* Well, the process_out existed : we must get it in the process hash
423 * or add it, and draw its items.
425 /* Add process to process list (if not present) */
427 HashedProcessData
*hashed_process_data
= NULL
;
428 ProcessList
*process_list
= control_flow_data
->process_list
;
429 LttTime birth
= process
->creation_time
;
431 hashed_process_data
= processlist_get_process_data(process_list
,
435 tfc
->t_context
->index
);
436 if(hashed_process_data
== NULL
)
438 g_assert(pid_out
== 0 || pid_out
!= process
->ppid
);
439 /* Process not present */
440 ProcessInfo
*process_info
;
441 Drawing_t
*drawing
= control_flow_data
->drawing
;
442 processlist_add(process_list
,
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(ts
,
575 ltt_tracefile_num(tfc
->tf
), pid_in
);
577 if(process
!= NULL
) {
578 /* Well, the process existed : we must get it in the process hash
579 * or add it, and draw its items.
581 /* Add process to process list (if not present) */
583 HashedProcessData
*hashed_process_data
= NULL
;
584 ProcessList
*process_list
= control_flow_data
->process_list
;
585 LttTime birth
= process
->creation_time
;
587 hashed_process_data
= processlist_get_process_data(process_list
,
591 tfc
->t_context
->index
);
592 if(hashed_process_data
== NULL
)
594 g_assert(pid_in
== 0 || pid_in
!= process
->ppid
);
595 /* Process not present */
596 ProcessInfo
*process_info
;
597 Drawing_t
*drawing
= control_flow_data
->drawing
;
598 processlist_add(process_list
,
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
;
1356 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1359 e
= ltt_tracefile_get_event(tfc
->tf
);
1361 LttTime evtime
= ltt_event_time(e
);
1363 /* Add process to process list (if not present) */
1364 LttvProcessState
*process_in
;
1366 guint pl_height
= 0;
1367 HashedProcessData
*hashed_process_data_in
= NULL
;
1369 ProcessList
*process_list
= control_flow_data
->process_list
;
1374 pid_out
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1375 pid_in
= ltt_event_get_long_unsigned(e
, thf
->f2
);
1379 /* Find process pid_in in the list... */
1380 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
1381 //process_in = tfs->process;
1382 guint cpu
= ltt_tracefile_num(tfc
->tf
);
1383 process_in
= ts
->running_process
[cpu
];
1384 /* It should exist, because we are after the state update. */
1386 g_assert(process_in
!= NULL
);
1387 #endif //EXTRA_CHECK
1388 birth
= process_in
->creation_time
;
1390 hashed_process_data_in
= processlist_get_process_data(process_list
,
1394 tfc
->t_context
->index
);
1395 if(hashed_process_data_in
== NULL
)
1397 g_assert(pid_in
== 0 || pid_in
!= process_in
->ppid
);
1398 ProcessInfo
*process_info
;
1399 Drawing_t
*drawing
= control_flow_data
->drawing
;
1400 /* Process not present */
1401 processlist_add(process_list
,
1407 tfc
->t_context
->index
,
1411 &hashed_process_data_in
);
1412 gtk_widget_set_size_request(drawing
->drawing_area
,
1415 gtk_widget_queue_draw(drawing
->drawing_area
);
1417 /* Set the current process */
1418 process_list
->current_hash_data
[process_in
->cpu
] =
1419 hashed_process_data_in
;
1421 if(ltt_time_compare(hashed_process_data_in
->next_good_time
,
1424 TimeWindow time_window
=
1425 lttvwindow_get_time_window(control_flow_data
->tab
);
1428 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1429 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1431 #endif //EXTRA_CHECK
1432 Drawing_t
*drawing
= control_flow_data
->drawing
;
1433 guint width
= drawing
->width
;
1436 convert_time_to_pixels(
1442 if(hashed_process_data_in
->x
.middle
!= new_x
) {
1443 hashed_process_data_in
->x
.middle
= new_x
;
1444 hashed_process_data_in
->x
.middle_used
= FALSE
;
1445 hashed_process_data_in
->x
.middle_marked
= FALSE
;
1455 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1456 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1458 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1460 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1461 LttvTraceState
*ts
=(LttvTraceState
*)LTTV_TRACEFILE_CONTEXT(tfs
)->t_context
;
1467 LttTime evtime
= ltt_event_time(e
);
1468 TimeWindow time_window
=
1469 lttvwindow_get_time_window(control_flow_data
->tab
);
1471 LttTime time_window
.end_time
= time_window
.time_window
.end_time
;
1473 //if(time < time_beg || time > time_end) return;
1474 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1475 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1479 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
1481 g_debug("schedchange!");
1483 /* Add process to process list (if not present) and get drawing "y" from
1484 * process position */
1485 guint pid_out
, pid_in
;
1486 LttvProcessState
*process_out
, *process_in
;
1488 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
1490 ProcessList
*process_list
= control_flow_data
->process_list
;
1493 LttField
*f
= ltt_event_field(e
);
1495 element
= ltt_field_member(f
,0);
1496 pid_out
= ltt_event_get_long_unsigned(e
,element
);
1497 element
= ltt_field_member(f
,1);
1498 pid_in
= ltt_event_get_long_unsigned(e
,element
);
1499 //g_debug("out : %u in : %u", pid_out, pid_in);
1502 /* Find process pid_out in the list... */
1503 process_out
= lttv_state_find_process(tfs
, pid_out
);
1504 if(process_out
== NULL
) return 0;
1505 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1507 birth
= process_out
->creation_time
;
1508 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
1509 HashedProcessData
*hashed_process_data_out
= NULL
;
1511 if(processlist_get_process_pixels(process_list
,
1514 tfc
->t_context
->index
,
1517 &hashed_process_data_out
) == 1)
1519 /* Process not present */
1520 processlist_add(process_list
,
1523 tfc
->t_context
->index
,
1526 &hashed_process_data_out
);
1527 processlist_get_process_pixels(process_list
,
1530 tfc
->t_context
->index
,
1533 &hashed_process_data_out
);
1534 drawing_insert_square( control_flow_data
->drawing
, y_out
, height
);
1539 /* Find process pid_in in the list... */
1540 process_in
= lttv_state_find_process(tfs
, pid_in
);
1541 if(process_in
== NULL
) return 0;
1542 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1544 birth
= process_in
->creation_time
;
1545 name
= strdup(g_quark_to_string(process_in
->name
));
1546 HashedProcessData
*hashed_process_data_in
= NULL
;
1548 if(processlist_get_process_pixels(process_list
,
1551 tfc
->t_context
->index
,
1554 &hashed_process_data_in
) == 1)
1556 /* Process not present */
1557 processlist_add(process_list
,
1560 tfc
->t_context
->index
,
1563 &hashed_process_data_in
);
1564 processlist_get_process_pixels(process_list
,
1567 tfc
->t_context
->index
,
1570 &hashed_process_data_in
);
1572 drawing_insert_square( control_flow_data
->drawing
, y_in
, height
);
1577 /* Find pixels corresponding to time of the event. If the time does
1578 * not fit in the window, show a warning, not supposed to happend. */
1580 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1582 //LttTime time = ltt_event_time(e);
1584 //LttTime window_end = time_window->time_window.end_time;
1587 //convert_time_to_pixels(
1593 //assert(x <= width);
1595 /* draw what represents the event for outgoing process. */
1597 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
1598 //draw_context_out->current->modify_over->x = x;
1599 draw_context_out
->current
->modify_over
->y
= y_out
;
1600 draw_context_out
->current
->modify_under
->y
= y_out
+(height
/2)+2;
1601 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
1602 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1603 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1604 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1606 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1607 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1609 /*if(process_out->state->s == LTTV_STATE_RUN)
1611 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1612 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1613 PropertiesBG prop_bg;
1614 prop_bg.color = g_new(GdkColor,1);
1616 prop_bg.color->red = 0xffff;
1617 prop_bg.color->green = 0xffff;
1618 prop_bg.color->blue = 0xffff;
1620 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1621 g_free(prop_bg.color);
1622 gdk_gc_unref(draw_context_out->gc);
1625 draw_context_out
->gc
= widget
->style
->black_gc
;
1627 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
1628 GdkColor colorbg_out
= { 0, 0x0000, 0x0000, 0x0000 };
1629 PropertiesText prop_text_out
;
1630 prop_text_out
.foreground
= &colorfg_out
;
1631 prop_text_out
.background
= &colorbg_out
;
1632 prop_text_out
.size
= 6;
1633 prop_text_out
.position
= OVER
;
1635 /* color of text : status of the process */
1636 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1638 prop_text_out
.foreground
->red
= 0xffff;
1639 prop_text_out
.foreground
->green
= 0xffff;
1640 prop_text_out
.foreground
->blue
= 0xffff;
1642 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1644 prop_text_out
.foreground
->red
= 0x0fff;
1645 prop_text_out
.foreground
->green
= 0xffff;
1646 prop_text_out
.foreground
->blue
= 0xfff0;
1648 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1650 prop_text_out
.foreground
->red
= 0xffff;
1651 prop_text_out
.foreground
->green
= 0xffff;
1652 prop_text_out
.foreground
->blue
= 0x0000;
1654 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1656 prop_text_out
.foreground
->red
= 0xffff;
1657 prop_text_out
.foreground
->green
= 0x0000;
1658 prop_text_out
.foreground
->blue
= 0xffff;
1660 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1662 prop_text_out
.foreground
->red
= 0xffff;
1663 prop_text_out
.foreground
->green
= 0x0000;
1664 prop_text_out
.foreground
->blue
= 0x0000;
1666 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1668 prop_text_out
.foreground
->red
= 0x0000;
1669 prop_text_out
.foreground
->green
= 0xffff;
1670 prop_text_out
.foreground
->blue
= 0x0000;
1674 prop_text_out
.foreground
->red
= 0xffff;
1675 prop_text_out
.foreground
->green
= 0xffff;
1676 prop_text_out
.foreground
->blue
= 0xffff;
1679 /* Print status of the process : U, WF, WC, E, W, R */
1680 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
1681 prop_text_out
.text
= "U";
1682 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
1683 prop_text_out
.text
= "WF";
1684 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
1685 prop_text_out
.text
= "WC";
1686 else if(process_out
->state
->s
== LTTV_STATE_ZOMBIE
)
1687 prop_text_out
.text
= "E";
1688 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
1689 prop_text_out
.text
= "W";
1690 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
1691 prop_text_out
.text
= "R";
1693 prop_text_out
.text
= "U";
1695 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
1697 //gdk_gc_unref(draw_context_out->gc);
1699 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
1700 draw_context_out
->current
->over
->y
= y_out
;
1701 draw_context_out
->current
->under
->y
= y_out
+height
;
1702 draw_context_out
->current
->status
= process_out
->state
->s
;
1704 /* for pid_out : remove previous, Prev = current, new current (default) */
1705 g_free(draw_context_out
->previous
->modify_under
);
1706 g_free(draw_context_out
->previous
->modify_middle
);
1707 g_free(draw_context_out
->previous
->modify_over
);
1708 g_free(draw_context_out
->previous
->under
);
1709 g_free(draw_context_out
->previous
->middle
);
1710 g_free(draw_context_out
->previous
->over
);
1711 g_free(draw_context_out
->previous
);
1713 draw_context_out
->previous
= draw_context_out
->current
;
1715 draw_context_out
->current
= g_new(DrawInfo
,1);
1716 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
1717 draw_context_out
->current
->over
->x
= -1;
1718 draw_context_out
->current
->over
->y
= -1;
1719 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
1720 draw_context_out
->current
->middle
->x
= -1;
1721 draw_context_out
->current
->middle
->y
= -1;
1722 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
1723 draw_context_out
->current
->under
->x
= -1;
1724 draw_context_out
->current
->under
->y
= -1;
1725 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
1726 draw_context_out
->current
->modify_over
->x
= -1;
1727 draw_context_out
->current
->modify_over
->y
= -1;
1728 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
1729 draw_context_out
->current
->modify_middle
->x
= -1;
1730 draw_context_out
->current
->modify_middle
->y
= -1;
1731 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
1732 draw_context_out
->current
->modify_under
->x
= -1;
1733 draw_context_out
->current
->modify_under
->y
= -1;
1734 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
1736 /* Finally, update the drawing context of the pid_in. */
1738 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
1739 //draw_context_in->current->modify_over->x = x;
1740 draw_context_in
->current
->modify_over
->y
= y_in
;
1741 draw_context_in
->current
->modify_under
->y
= y_in
+(height
/2)+2;
1742 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
1743 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1744 widget
= control_flow_data
->drawing
->drawing_area
;
1745 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1747 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1748 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1750 /*if(process_in->state->s == LTTV_STATE_RUN)
1752 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1753 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1754 PropertiesBG prop_bg;
1755 prop_bg.color = g_new(GdkColor,1);
1757 prop_bg.color->red = 0xffff;
1758 prop_bg.color->green = 0xffff;
1759 prop_bg.color->blue = 0xffff;
1761 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1762 g_free(prop_bg.color);
1763 gdk_gc_unref(draw_context_in->gc);
1766 draw_context_in
->gc
= widget
->style
->black_gc
;
1768 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
1769 GdkColor colorbg_in
= { 0, 0x0000, 0x0000, 0x0000 };
1770 PropertiesText prop_text_in
;
1771 prop_text_in
.foreground
= &colorfg_in
;
1772 prop_text_in
.background
= &colorbg_in
;
1773 prop_text_in
.size
= 6;
1774 prop_text_in
.position
= OVER
;
1776 /* foreground of text : status of the process */
1777 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1779 prop_text_in
.foreground
->red
= 0xffff;
1780 prop_text_in
.foreground
->green
= 0xffff;
1781 prop_text_in
.foreground
->blue
= 0xffff;
1783 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1785 prop_text_in
.foreground
->red
= 0x0fff;
1786 prop_text_in
.foreground
->green
= 0xffff;
1787 prop_text_in
.foreground
->blue
= 0xfff0;
1789 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1791 prop_text_in
.foreground
->red
= 0xffff;
1792 prop_text_in
.foreground
->green
= 0xffff;
1793 prop_text_in
.foreground
->blue
= 0x0000;
1795 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1797 prop_text_in
.foreground
->red
= 0xffff;
1798 prop_text_in
.foreground
->green
= 0x0000;
1799 prop_text_in
.foreground
->blue
= 0xffff;
1801 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1803 prop_text_in
.foreground
->red
= 0xffff;
1804 prop_text_in
.foreground
->green
= 0x0000;
1805 prop_text_in
.foreground
->blue
= 0x0000;
1807 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1809 prop_text_in
.foreground
->red
= 0x0000;
1810 prop_text_in
.foreground
->green
= 0xffff;
1811 prop_text_in
.foreground
->blue
= 0x0000;
1815 prop_text_in
.foreground
->red
= 0xffff;
1816 prop_text_in
.foreground
->green
= 0xffff;
1817 prop_text_in
.foreground
->blue
= 0xffff;
1821 /* Print status of the process : U, WF, WC, E, W, R */
1822 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
1823 prop_text_in
.text
= "U";
1824 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
1825 prop_text_in
.text
= "WF";
1826 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
1827 prop_text_in
.text
= "WC";
1828 else if(process_in
->state
->s
== LTTV_STATE_ZOMBIE
)
1829 prop_text_in
.text
= "E";
1830 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
1831 prop_text_in
.text
= "W";
1832 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
1833 prop_text_in
.text
= "R";
1835 prop_text_in
.text
= "U";
1837 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1840 if(process_in
->state
->s
== LTTV_STATE_RUN
)
1843 prop_text_in
.foreground
= &colorfg_in
;
1844 prop_text_in
.background
= &colorbg_in
;
1845 prop_text_in
.foreground
->red
= 0xffff;
1846 prop_text_in
.foreground
->green
= 0xffff;
1847 prop_text_in
.foreground
->blue
= 0xffff;
1848 prop_text_in
.size
= 6;
1849 prop_text_in
.position
= UNDER
;
1851 prop_text_in
.text
= g_new(gchar
, 260);
1852 strcpy(prop_text_in
.text
, "CPU ");
1853 snprintf(tmp
, 255, "%u", ltt_tracefile_num(tfc
->tf
));
1854 strcat(prop_text_in
.text
, tmp
);
1856 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
1857 g_free(prop_text_in
.text
);
1861 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
1862 draw_context_in
->current
->over
->y
= y_in
;
1863 draw_context_in
->current
->under
->y
= y_in
+height
;
1864 draw_context_in
->current
->status
= process_in
->state
->s
;
1866 /* for pid_in : remove previous, Prev = current, new current (default) */
1867 g_free(draw_context_in
->previous
->modify_under
);
1868 g_free(draw_context_in
->previous
->modify_middle
);
1869 g_free(draw_context_in
->previous
->modify_over
);
1870 g_free(draw_context_in
->previous
->under
);
1871 g_free(draw_context_in
->previous
->middle
);
1872 g_free(draw_context_in
->previous
->over
);
1873 g_free(draw_context_in
->previous
);
1875 draw_context_in
->previous
= draw_context_in
->current
;
1877 draw_context_in
->current
= g_new(DrawInfo
,1);
1878 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
1879 draw_context_in
->current
->over
->x
= -1;
1880 draw_context_in
->current
->over
->y
= -1;
1881 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
1882 draw_context_in
->current
->middle
->x
= -1;
1883 draw_context_in
->current
->middle
->y
= -1;
1884 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
1885 draw_context_in
->current
->under
->x
= -1;
1886 draw_context_in
->current
->under
->y
= -1;
1887 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
1888 draw_context_in
->current
->modify_over
->x
= -1;
1889 draw_context_in
->current
->modify_over
->y
= -1;
1890 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
1891 draw_context_in
->current
->modify_middle
->x
= -1;
1892 draw_context_in
->current
->modify_middle
->y
= -1;
1893 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
1894 draw_context_in
->current
->modify_under
->x
= -1;
1895 draw_context_in
->current
->modify_under
->y
= -1;
1896 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
1905 static inline PropertiesLine
prepare_execmode_line(LttvProcessState
*process
)
1907 PropertiesLine prop_line
;
1908 prop_line
.line_width
= 1;
1909 prop_line
.style
= GDK_LINE_SOLID
;
1911 //GdkColormap *colormap = gdk_colormap_get_system();
1913 /* color of line : execution mode of the process */
1914 if(process
->state
->t
== LTTV_STATE_USER_MODE
)
1915 prop_line
.color
= drawing_colors
[COL_USER_MODE
];
1916 else if(process
->state
->t
== LTTV_STATE_SYSCALL
)
1917 prop_line
.color
= drawing_colors
[COL_SYSCALL
];
1918 else if(process
->state
->t
== LTTV_STATE_TRAP
)
1919 prop_line
.color
= drawing_colors
[COL_TRAP
];
1920 else if(process
->state
->t
== LTTV_STATE_IRQ
)
1921 prop_line
.color
= drawing_colors
[COL_IRQ
];
1922 else if(process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
)
1923 prop_line
.color
= drawing_colors
[COL_MODE_UNKNOWN
];
1925 prop_line
.color
= drawing_colors
[COL_WHITE
];
1927 //gdk_colormap_alloc_color(colormap,
1938 /* before_execmode_hook
1940 * This function basically draw lines and icons. Two types of lines are drawn :
1941 * one small (3 pixels?) representing the state of the process and the second
1942 * type is thicker (10 pixels?) representing on which CPU a process is running
1943 * (and this only in running state).
1945 * Extremums of the lines :
1946 * x_min : time of the last event context for this process kept in memory.
1947 * x_max : time of the current event.
1948 * y : middle of the process in the process list. The process is found in the
1949 * list, therefore is it's position in pixels.
1951 * The choice of lines'color is defined by the context of the last event for this
1956 int before_execmode_hook(void *hook_data
, void *call_data
)
1958 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1959 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1960 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
1962 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1964 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1966 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1969 e
= ltt_tracefile_get_event(tfc
->tf
);
1971 LttTime evtime
= ltt_event_time(e
);
1973 /* we are in a execmode, before the state update. We must draw the
1974 * items corresponding to the state before it changes : now is the right
1978 //LttvProcessState *process = tfs->process;
1979 guint cpu
= ltt_tracefile_num(tfc
->tf
);
1980 LttvProcessState
*process
= ts
->running_process
[cpu
];
1981 g_assert(process
!= NULL
);
1983 guint pid
= process
->pid
;
1985 /* Well, the process_out existed : we must get it in the process hash
1986 * or add it, and draw its items.
1988 /* Add process to process list (if not present) */
1989 guint pl_height
= 0;
1990 HashedProcessData
*hashed_process_data
= NULL
;
1991 ProcessList
*process_list
= control_flow_data
->process_list
;
1992 LttTime birth
= process
->creation_time
;
1994 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
1995 hashed_process_data
= process_list
->current_hash_data
[cpu
];
1997 hashed_process_data
= processlist_get_process_data(process_list
,
2001 tfc
->t_context
->index
);
2002 if(unlikely(hashed_process_data
== NULL
))
2004 g_assert(pid
== 0 || pid
!= process
->ppid
);
2005 ProcessInfo
*process_info
;
2006 /* Process not present */
2007 Drawing_t
*drawing
= control_flow_data
->drawing
;
2008 processlist_add(process_list
,
2014 tfc
->t_context
->index
,
2018 &hashed_process_data
);
2019 gtk_widget_set_size_request(drawing
->drawing_area
,
2022 gtk_widget_queue_draw(drawing
->drawing_area
);
2024 /* Set the current process */
2025 process_list
->current_hash_data
[process
->cpu
] =
2026 hashed_process_data
;
2029 /* Now, the process is in the state hash and our own process hash.
2030 * We definitely can draw the items related to the ending state.
2033 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2036 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2037 TimeWindow time_window
=
2038 lttvwindow_get_time_window(control_flow_data
->tab
);
2041 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2042 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2044 #endif //EXTRA_CHECK
2045 Drawing_t
*drawing
= control_flow_data
->drawing
;
2046 guint width
= drawing
->width
;
2048 convert_time_to_pixels(
2054 /* Draw collision indicator */
2055 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2056 gdk_draw_point(hashed_process_data
->pixmap
,
2059 (hashed_process_data
->height
/2)-3);
2060 hashed_process_data
->x
.middle_marked
= TRUE
;
2063 TimeWindow time_window
=
2064 lttvwindow_get_time_window(control_flow_data
->tab
);
2067 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2068 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2070 #endif //EXTRA_CHECK
2071 Drawing_t
*drawing
= control_flow_data
->drawing
;
2072 guint width
= drawing
->width
;
2075 convert_time_to_pixels(
2082 /* Jump over draw if we are at the same x position */
2083 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2084 hashed_process_data
->x
.middle_used
))
2086 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2087 /* Draw collision indicator */
2088 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2089 gdk_draw_point(hashed_process_data
->pixmap
,
2092 (hashed_process_data
->height
/2)-3);
2093 hashed_process_data
->x
.middle_marked
= TRUE
;
2098 DrawContext draw_context
;
2099 /* Now create the drawing context that will be used to draw
2100 * items related to the last state. */
2101 draw_context
.drawable
= hashed_process_data
->pixmap
;
2102 draw_context
.gc
= drawing
->gc
;
2103 draw_context
.pango_layout
= drawing
->pango_layout
;
2104 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2105 draw_context
.drawinfo
.end
.x
= x
;
2107 draw_context
.drawinfo
.y
.over
= 1;
2108 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2109 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2111 draw_context
.drawinfo
.start
.offset
.over
= 0;
2112 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2113 draw_context
.drawinfo
.start
.offset
.under
= 0;
2114 draw_context
.drawinfo
.end
.offset
.over
= 0;
2115 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2116 draw_context
.drawinfo
.end
.offset
.under
= 0;
2120 PropertiesLine prop_line
= prepare_s_e_line(process
);
2121 draw_line((void*)&prop_line
, (void*)&draw_context
);
2124 /* become the last x position */
2125 hashed_process_data
->x
.middle
= x
;
2126 hashed_process_data
->x
.middle_used
= TRUE
;
2127 hashed_process_data
->x
.middle_marked
= FALSE
;
2129 /* Calculate the next good time */
2130 convert_pixels_to_time(width
, x
+1, time_window
,
2131 &hashed_process_data
->next_good_time
);
2138 /* after_execmode_hook
2140 * The draw after hook is called by the reading API to have a
2141 * particular event drawn on the screen.
2142 * @param hook_data ControlFlowData structure of the viewer.
2143 * @param call_data Event context.
2145 * This function adds items to be drawn in a queue for each process.
2149 int after_execmode_hook(void *hook_data
, void *call_data
)
2151 /**************** DOES NOTHING!! *************/
2152 /* hook desactivated in drawing.c */
2156 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2157 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2158 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2160 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2162 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2165 e
= ltt_tracefile_get_event(tfc
->tf
);
2167 LttTime evtime
= ltt_event_time(e
);
2169 /* Add process to process list (if not present) */
2170 LttvProcessState
*process
;
2172 guint pl_height
= 0;
2173 HashedProcessData
*hashed_process_data
= NULL
;
2175 ProcessList
*process_list
= control_flow_data
->process_list
;
2177 /* Find process pid_in in the list... */
2178 process
= tfs
->process
;
2179 /* It should exist, because we are after the state update. */
2180 g_assert(process
!= NULL
);
2182 guint pid
= process
->pid
;
2184 birth
= process
->creation_time
;
2186 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
)) {
2187 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
2189 hashed_process_data
= processlist_get_process_data(process_list
,
2191 process
->last_cpu_index
,
2193 tfc
->t_context
->index
);
2194 if(unlikely(hashed_process_data
== NULL
))
2196 g_assert(pid
== 0 || pid
!= process
->ppid
);
2197 /* Process not present */
2198 Drawing_t
*drawing
= control_flow_data
->drawing
;
2199 const gchar
*name
= g_quark_to_string(process
->name
);
2200 ProcessInfo
*process_info
;
2201 processlist_add(process_list
,
2204 process
->last_cpu_index
,
2207 tfc
->t_context
->index
,
2211 &hashed_process_data
);
2212 gtk_widget_set_size_request(drawing
->drawing_area
,
2215 gtk_widget_queue_draw(drawing
->drawing_area
);
2217 /* Set the current process */
2218 process_list
->current_hash_data
[process
->last_cpu_index
] =
2219 hashed_process_data
;
2222 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
2225 TimeWindow time_window
=
2226 lttvwindow_get_time_window(control_flow_data
->tab
);
2229 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2230 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2232 #endif //EXTRA_CHECK
2233 Drawing_t
*drawing
= control_flow_data
->drawing
;
2234 guint width
= drawing
->width
;
2237 convert_time_to_pixels(
2243 if(hashed_process_data
->x
.middle
!= new_x
) {
2244 hashed_process_data
->x
.middle
= new_x
;
2245 hashed_process_data
->x
.middle_used
= FALSE
;
2246 hashed_process_data
->x
.middle_marked
= FALSE
;
2255 /* before_process_exit_hook
2257 * Draw lines for process event.
2259 * @param hook_data ControlFlowData structure of the viewer.
2260 * @param call_data Event context.
2262 * This function adds items to be drawn in a queue for each process.
2267 int before_process_exit_hook(void *hook_data
, void *call_data
)
2269 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2270 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2272 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2274 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2276 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2278 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2281 e
= ltt_tracefile_get_event(tfc
->tf
);
2283 LttTime evtime
= ltt_event_time(e
);
2285 /* Add process to process list (if not present) */
2286 //LttvProcessState *process = tfs->process;
2287 guint cpu
= ltt_tracefile_num(tfc
->tf
);
2288 LttvProcessState
*process
= ts
->running_process
[cpu
];
2289 guint pid
= process
->pid
;
2291 guint pl_height
= 0;
2292 HashedProcessData
*hashed_process_data
= NULL
;
2294 ProcessList
*process_list
= control_flow_data
->process_list
;
2296 g_assert(process
!= NULL
);
2298 birth
= process
->creation_time
;
2300 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
2301 hashed_process_data
= process_list
->current_hash_data
[cpu
];
2303 hashed_process_data
= processlist_get_process_data(process_list
,
2307 tfc
->t_context
->index
);
2308 if(unlikely(hashed_process_data
== NULL
))
2310 g_assert(pid
== 0 || pid
!= process
->ppid
);
2311 /* Process not present */
2312 Drawing_t
*drawing
= control_flow_data
->drawing
;
2313 ProcessInfo
*process_info
;
2314 processlist_add(process_list
,
2320 tfc
->t_context
->index
,
2324 &hashed_process_data
);
2325 gtk_widget_set_size_request(drawing
->drawing_area
,
2328 gtk_widget_queue_draw(drawing
->drawing_area
);
2332 /* Now, the process is in the state hash and our own process hash.
2333 * We definitely can draw the items related to the ending state.
2336 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2339 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2340 TimeWindow time_window
=
2341 lttvwindow_get_time_window(control_flow_data
->tab
);
2344 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2345 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2347 #endif //EXTRA_CHECK
2348 Drawing_t
*drawing
= control_flow_data
->drawing
;
2349 guint width
= drawing
->width
;
2351 convert_time_to_pixels(
2357 /* Draw collision indicator */
2358 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2359 gdk_draw_point(hashed_process_data
->pixmap
,
2362 (hashed_process_data
->height
/2)-3);
2363 hashed_process_data
->x
.middle_marked
= TRUE
;
2366 TimeWindow time_window
=
2367 lttvwindow_get_time_window(control_flow_data
->tab
);
2370 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2371 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2373 #endif //EXTRA_CHECK
2374 Drawing_t
*drawing
= control_flow_data
->drawing
;
2375 guint width
= drawing
->width
;
2378 convert_time_to_pixels(
2385 /* Jump over draw if we are at the same x position */
2386 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2387 hashed_process_data
->x
.middle_used
))
2389 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2390 /* Draw collision indicator */
2391 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2392 gdk_draw_point(hashed_process_data
->pixmap
,
2395 (hashed_process_data
->height
/2)-3);
2396 hashed_process_data
->x
.middle_marked
= TRUE
;
2400 DrawContext draw_context
;
2402 /* Now create the drawing context that will be used to draw
2403 * items related to the last state. */
2404 draw_context
.drawable
= hashed_process_data
->pixmap
;
2405 draw_context
.gc
= drawing
->gc
;
2406 draw_context
.pango_layout
= drawing
->pango_layout
;
2407 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2408 draw_context
.drawinfo
.end
.x
= x
;
2410 draw_context
.drawinfo
.y
.over
= 1;
2411 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2412 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2414 draw_context
.drawinfo
.start
.offset
.over
= 0;
2415 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2416 draw_context
.drawinfo
.start
.offset
.under
= 0;
2417 draw_context
.drawinfo
.end
.offset
.over
= 0;
2418 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2419 draw_context
.drawinfo
.end
.offset
.under
= 0;
2423 PropertiesLine prop_line
= prepare_s_e_line(process
);
2424 draw_line((void*)&prop_line
, (void*)&draw_context
);
2427 /* become the last x position */
2428 hashed_process_data
->x
.middle
= x
;
2429 hashed_process_data
->x
.middle_used
= TRUE
;
2430 hashed_process_data
->x
.middle_marked
= FALSE
;
2432 /* Calculate the next good time */
2433 convert_pixels_to_time(width
, x
+1, time_window
,
2434 &hashed_process_data
->next_good_time
);
2444 /* before_process_release_hook
2446 * Draw lines for process event.
2448 * @param hook_data ControlFlowData structure of the viewer.
2449 * @param call_data Event context.
2451 * This function adds items to be drawn in a queue for each process.
2456 int before_process_release_hook(void *hook_data
, void *call_data
)
2458 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2459 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2461 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2463 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2465 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2467 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
2470 e
= ltt_tracefile_get_event(tfc
->tf
);
2472 LttTime evtime
= ltt_event_time(e
);
2477 pid
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2480 /* Add process to process list (if not present) */
2481 /* Don't care about the process if it's not in the state hash already :
2482 * that means a process that has never done anything in the trace and
2483 * unknown suddently gets destroyed : no state meaningful to show. */
2484 LttvProcessState
*process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2486 if(process
!= NULL
) {
2488 guint pl_height
= 0;
2489 HashedProcessData
*hashed_process_data
= NULL
;
2491 ProcessList
*process_list
= control_flow_data
->process_list
;
2493 birth
= process
->creation_time
;
2495 /* Cannot use current process : this event happens on another process,
2496 * action done by the parent. */
2497 hashed_process_data
= processlist_get_process_data(process_list
,
2501 tfc
->t_context
->index
);
2502 if(unlikely(hashed_process_data
== NULL
))
2504 g_assert(pid
== 0 || pid
!= process
->ppid
);
2505 /* Process not present */
2506 Drawing_t
*drawing
= control_flow_data
->drawing
;
2507 ProcessInfo
*process_info
;
2508 processlist_add(process_list
,
2514 tfc
->t_context
->index
,
2518 &hashed_process_data
);
2519 gtk_widget_set_size_request(drawing
->drawing_area
,
2522 gtk_widget_queue_draw(drawing
->drawing_area
);
2525 /* Now, the process is in the state hash and our own process hash.
2526 * We definitely can draw the items related to the ending state.
2529 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2532 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2533 TimeWindow time_window
=
2534 lttvwindow_get_time_window(control_flow_data
->tab
);
2537 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2538 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2540 #endif //EXTRA_CHECK
2541 Drawing_t
*drawing
= control_flow_data
->drawing
;
2542 guint width
= drawing
->width
;
2544 convert_time_to_pixels(
2550 /* Draw collision indicator */
2551 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2552 gdk_draw_point(hashed_process_data
->pixmap
,
2555 (hashed_process_data
->height
/2)-3);
2556 hashed_process_data
->x
.middle_marked
= TRUE
;
2559 TimeWindow time_window
=
2560 lttvwindow_get_time_window(control_flow_data
->tab
);
2563 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2564 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2566 #endif //EXTRA_CHECK
2567 Drawing_t
*drawing
= control_flow_data
->drawing
;
2568 guint width
= drawing
->width
;
2571 convert_time_to_pixels(
2578 /* Jump over draw if we are at the same x position */
2579 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2580 hashed_process_data
->x
.middle_used
))
2582 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2583 /* Draw collision indicator */
2584 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2585 gdk_draw_point(hashed_process_data
->pixmap
,
2588 (hashed_process_data
->height
/2)-3);
2589 hashed_process_data
->x
.middle_marked
= TRUE
;
2593 DrawContext draw_context
;
2595 /* Now create the drawing context that will be used to draw
2596 * items related to the last state. */
2597 draw_context
.drawable
= hashed_process_data
->pixmap
;
2598 draw_context
.gc
= drawing
->gc
;
2599 draw_context
.pango_layout
= drawing
->pango_layout
;
2600 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2601 draw_context
.drawinfo
.end
.x
= x
;
2603 draw_context
.drawinfo
.y
.over
= 1;
2604 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2605 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2607 draw_context
.drawinfo
.start
.offset
.over
= 0;
2608 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2609 draw_context
.drawinfo
.start
.offset
.under
= 0;
2610 draw_context
.drawinfo
.end
.offset
.over
= 0;
2611 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2612 draw_context
.drawinfo
.end
.offset
.under
= 0;
2616 PropertiesLine prop_line
= prepare_s_e_line(process
);
2617 draw_line((void*)&prop_line
, (void*)&draw_context
);
2620 /* become the last x position */
2621 hashed_process_data
->x
.middle
= x
;
2622 hashed_process_data
->x
.middle_used
= TRUE
;
2623 hashed_process_data
->x
.middle_marked
= FALSE
;
2625 /* Calculate the next good time */
2626 convert_pixels_to_time(width
, x
+1, time_window
,
2627 &hashed_process_data
->next_good_time
);
2643 /* before_process_hook
2645 * Draw lines for process event.
2647 * @param hook_data ControlFlowData structure of the viewer.
2648 * @param call_data Event context.
2650 * This function adds items to be drawn in a queue for each process.
2653 int before_process_hook(void *hook_data
, void *call_data
)
2655 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2656 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
2657 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
2659 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2661 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
2664 e
= ltt_tracefile_get_event(tfc
->tf
);
2666 LttTime evtime
= ltt_event_time(e
);
2670 LttField
*f
= ltt_event_field(e
);
2672 element
= ltt_field_member(f
,0);
2673 sub_id
= ltt_event_get_long_unsigned(e
,element
);
2676 if(sub_id
== 3) { /* exit */
2678 /* Add process to process list (if not present) */
2679 LttvProcessState
*process
= tfs
->process
;
2680 guint pid
= process
->pid
;
2682 guint pl_height
= 0;
2683 HashedProcessData
*hashed_process_data
= NULL
;
2685 ProcessList
*process_list
= control_flow_data
->process_list
;
2687 g_assert(process
!= NULL
);
2689 birth
= process
->creation_time
;
2691 if(likely(process_list
->current_hash_data
[tfc
->index
] != NULL
)) {
2692 hashed_process_data
= process_list
->current_hash_data
[tfc
->index
];
2694 hashed_process_data
= processlist_get_process_data(process_list
,
2696 process
->last_cpu_index
,
2698 tfc
->t_context
->index
);
2699 if(unlikely(hashed_process_data
== NULL
))
2701 g_assert(pid
== 0 || pid
!= process
->ppid
);
2702 /* Process not present */
2703 Drawing_t
*drawing
= control_flow_data
->drawing
;
2704 const gchar
*name
= g_quark_to_string(process
->name
);
2705 ProcessInfo
*process_info
;
2706 processlist_add(process_list
,
2709 process
->last_cpu_index
,
2712 tfc
->t_context
->index
,
2716 &hashed_process_data
);
2717 gtk_widget_set_size_request(drawing
->drawing_area
,
2720 gtk_widget_queue_draw(drawing
->drawing_area
);
2724 /* Now, the process is in the state hash and our own process hash.
2725 * We definitely can draw the items related to the ending state.
2728 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2731 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2732 TimeWindow time_window
=
2733 lttvwindow_get_time_window(control_flow_data
->tab
);
2736 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2737 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2739 #endif //EXTRA_CHECK
2740 Drawing_t
*drawing
= control_flow_data
->drawing
;
2741 guint width
= drawing
->width
;
2743 convert_time_to_pixels(
2749 /* Draw collision indicator */
2750 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2751 gdk_draw_point(hashed_process_data
->pixmap
,
2754 (hashed_process_data
->height
/2)-3);
2755 hashed_process_data
->x
.middle_marked
= TRUE
;
2758 TimeWindow time_window
=
2759 lttvwindow_get_time_window(control_flow_data
->tab
);
2762 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2763 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2765 #endif //EXTRA_CHECK
2766 Drawing_t
*drawing
= control_flow_data
->drawing
;
2767 guint width
= drawing
->width
;
2770 convert_time_to_pixels(
2777 /* Jump over draw if we are at the same x position */
2778 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2779 hashed_process_data
->x
.middle_used
))
2781 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2782 /* Draw collision indicator */
2783 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2784 gdk_draw_point(hashed_process_data
->pixmap
,
2787 (hashed_process_data
->height
/2)-3);
2788 hashed_process_data
->x
.middle_marked
= TRUE
;
2792 DrawContext draw_context
;
2794 /* Now create the drawing context that will be used to draw
2795 * items related to the last state. */
2796 draw_context
.drawable
= hashed_process_data
->pixmap
;
2797 draw_context
.gc
= drawing
->gc
;
2798 draw_context
.pango_layout
= drawing
->pango_layout
;
2799 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2800 draw_context
.drawinfo
.end
.x
= x
;
2802 draw_context
.drawinfo
.y
.over
= 1;
2803 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2804 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2806 draw_context
.drawinfo
.start
.offset
.over
= 0;
2807 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2808 draw_context
.drawinfo
.start
.offset
.under
= 0;
2809 draw_context
.drawinfo
.end
.offset
.over
= 0;
2810 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2811 draw_context
.drawinfo
.end
.offset
.under
= 0;
2815 PropertiesLine prop_line
= prepare_s_e_line(process
);
2816 draw_line((void*)&prop_line
, (void*)&draw_context
);
2819 /* become the last x position */
2820 hashed_process_data
->x
.middle
= x
;
2821 hashed_process_data
->x
.middle_used
= TRUE
;
2822 hashed_process_data
->x
.middle_marked
= FALSE
;
2824 /* Calculate the next good time */
2825 convert_pixels_to_time(width
, x
+1, time_window
,
2826 &hashed_process_data
->next_good_time
);
2830 } else if(sub_id
== 7) /* release */ {
2834 LttField
*f
= ltt_event_field(e
);
2836 element
= ltt_field_member(f
,1);
2837 pid
= ltt_event_get_long_unsigned(e
,element
);
2840 /* Add process to process list (if not present) */
2841 /* Don't care about the process if it's not in the state hash already :
2842 * that means a process that has never done anything in the trace and
2843 * unknown suddently gets destroyed : no state meaningful to show. */
2844 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
2846 if(process
!= NULL
) {
2848 guint pl_height
= 0;
2849 HashedProcessData
*hashed_process_data
= NULL
;
2851 ProcessList
*process_list
= control_flow_data
->process_list
;
2853 birth
= process
->creation_time
;
2855 /* Cannot use current process : this event happens on another process,
2856 * action done by the parent. */
2857 hashed_process_data
= processlist_get_process_data(process_list
,
2859 process
->last_cpu_index
,
2861 tfc
->t_context
->index
);
2862 if(unlikely(hashed_process_data
== NULL
))
2864 g_assert(pid
== 0 || pid
!= process
->ppid
);
2865 /* Process not present */
2866 Drawing_t
*drawing
= control_flow_data
->drawing
;
2867 ProcessInfo
*process_info
;
2868 processlist_add(process_list
,
2871 process
->last_cpu_index
,
2874 tfc
->t_context
->index
,
2878 &hashed_process_data
);
2879 gtk_widget_set_size_request(drawing
->drawing_area
,
2882 gtk_widget_queue_draw(drawing
->drawing_area
);
2885 /* Now, the process is in the state hash and our own process hash.
2886 * We definitely can draw the items related to the ending state.
2889 if(likely(ltt_time_compare(hashed_process_data
->next_good_time
,
2892 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2893 TimeWindow time_window
=
2894 lttvwindow_get_time_window(control_flow_data
->tab
);
2897 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2898 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2900 #endif //EXTRA_CHECK
2901 Drawing_t
*drawing
= control_flow_data
->drawing
;
2902 guint width
= drawing
->width
;
2904 convert_time_to_pixels(
2910 /* Draw collision indicator */
2911 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2912 gdk_draw_point(hashed_process_data
->pixmap
,
2915 (hashed_process_data
->height
/2)-3);
2916 hashed_process_data
->x
.middle_marked
= TRUE
;
2919 TimeWindow time_window
=
2920 lttvwindow_get_time_window(control_flow_data
->tab
);
2923 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
2924 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
2926 #endif //EXTRA_CHECK
2927 Drawing_t
*drawing
= control_flow_data
->drawing
;
2928 guint width
= drawing
->width
;
2931 convert_time_to_pixels(
2938 /* Jump over draw if we are at the same x position */
2939 if(unlikely(x
== hashed_process_data
->x
.middle
&&
2940 hashed_process_data
->x
.middle_used
))
2942 if(unlikely(hashed_process_data
->x
.middle_marked
== FALSE
)) {
2943 /* Draw collision indicator */
2944 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
2945 gdk_draw_point(hashed_process_data
->pixmap
,
2948 (hashed_process_data
->height
/2)-3);
2949 hashed_process_data
->x
.middle_marked
= TRUE
;
2953 DrawContext draw_context
;
2955 /* Now create the drawing context that will be used to draw
2956 * items related to the last state. */
2957 draw_context
.drawable
= hashed_process_data
->pixmap
;
2958 draw_context
.gc
= drawing
->gc
;
2959 draw_context
.pango_layout
= drawing
->pango_layout
;
2960 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
2961 draw_context
.drawinfo
.end
.x
= x
;
2963 draw_context
.drawinfo
.y
.over
= 1;
2964 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
2965 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
2967 draw_context
.drawinfo
.start
.offset
.over
= 0;
2968 draw_context
.drawinfo
.start
.offset
.middle
= 0;
2969 draw_context
.drawinfo
.start
.offset
.under
= 0;
2970 draw_context
.drawinfo
.end
.offset
.over
= 0;
2971 draw_context
.drawinfo
.end
.offset
.middle
= 0;
2972 draw_context
.drawinfo
.end
.offset
.under
= 0;
2976 PropertiesLine prop_line
= prepare_s_e_line(process
);
2977 draw_line((void*)&prop_line
, (void*)&draw_context
);
2980 /* become the last x position */
2981 hashed_process_data
->x
.middle
= x
;
2982 hashed_process_data
->x
.middle_used
= TRUE
;
2983 hashed_process_data
->x
.middle_marked
= FALSE
;
2985 /* Calculate the next good time */
2986 convert_pixels_to_time(width
, x
+1, time_window
,
2987 &hashed_process_data
->next_good_time
);
3001 /* after_process_fork_hook
3003 * Create the processlist entry for the child process. Put the last
3004 * position in x at the current time value.
3006 * @param hook_data ControlFlowData structure of the viewer.
3007 * @param call_data Event context.
3009 * This function adds items to be drawn in a queue for each process.
3012 int after_process_fork_hook(void *hook_data
, void *call_data
)
3014 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3015 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3016 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3018 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3020 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3022 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3025 e
= ltt_tracefile_get_event(tfc
->tf
);
3027 LttTime evtime
= ltt_event_time(e
);
3031 child_pid
= ltt_event_get_long_unsigned(e
, thf
->f2
);
3034 /* Add process to process list (if not present) */
3035 LttvProcessState
*process_child
;
3037 guint pl_height
= 0;
3038 HashedProcessData
*hashed_process_data_child
= NULL
;
3040 ProcessList
*process_list
= control_flow_data
->process_list
;
3042 /* Find child in the list... */
3043 process_child
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3044 /* It should exist, because we are after the state update. */
3045 g_assert(process_child
!= NULL
);
3047 birth
= process_child
->creation_time
;
3049 /* Cannot use current process, because this action is done by the parent
3051 hashed_process_data_child
= processlist_get_process_data(process_list
,
3055 tfc
->t_context
->index
);
3056 if(likely(hashed_process_data_child
== NULL
))
3058 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3059 /* Process not present */
3060 Drawing_t
*drawing
= control_flow_data
->drawing
;
3061 ProcessInfo
*process_info
;
3062 processlist_add(process_list
,
3066 process_child
->ppid
,
3068 tfc
->t_context
->index
,
3069 process_child
->name
,
3072 &hashed_process_data_child
);
3073 gtk_widget_set_size_request(drawing
->drawing_area
,
3076 gtk_widget_queue_draw(drawing
->drawing_area
);
3080 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3083 TimeWindow time_window
=
3084 lttvwindow_get_time_window(control_flow_data
->tab
);
3087 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3088 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3090 #endif //EXTRA_CHECK
3091 Drawing_t
*drawing
= control_flow_data
->drawing
;
3092 guint width
= drawing
->width
;
3094 convert_time_to_pixels(
3100 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3101 hashed_process_data_child
->x
.over
= new_x
;
3102 hashed_process_data_child
->x
.over_used
= FALSE
;
3103 hashed_process_data_child
->x
.over_marked
= FALSE
;
3105 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3106 hashed_process_data_child
->x
.middle
= new_x
;
3107 hashed_process_data_child
->x
.middle_used
= FALSE
;
3108 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3110 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3111 hashed_process_data_child
->x
.under
= new_x
;
3112 hashed_process_data_child
->x
.under_used
= FALSE
;
3113 hashed_process_data_child
->x
.under_marked
= FALSE
;
3121 /* after_process_exit_hook
3123 * Create the processlist entry for the child process. Put the last
3124 * position in x at the current time value.
3126 * @param hook_data ControlFlowData structure of the viewer.
3127 * @param call_data Event context.
3129 * This function adds items to be drawn in a queue for each process.
3132 int after_process_exit_hook(void *hook_data
, void *call_data
)
3134 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3135 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3136 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3138 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3140 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3142 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3145 e
= ltt_tracefile_get_event(tfc
->tf
);
3147 LttTime evtime
= ltt_event_time(e
);
3149 /* Add process to process list (if not present) */
3150 //LttvProcessState *process = tfs->process;
3151 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3152 LttvProcessState
*process
= ts
->running_process
[cpu
];
3154 /* It should exist, because we are after the state update. */
3155 g_assert(process
!= NULL
);
3157 guint pid
= process
->pid
;
3159 guint pl_height
= 0;
3160 HashedProcessData
*hashed_process_data
= NULL
;
3162 ProcessList
*process_list
= control_flow_data
->process_list
;
3164 birth
= process
->creation_time
;
3166 if(likely(process_list
->current_hash_data
[cpu
] != NULL
) ){
3167 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3169 hashed_process_data
= processlist_get_process_data(process_list
,
3173 tfc
->t_context
->index
);
3174 if(unlikely(hashed_process_data
== NULL
))
3176 g_assert(pid
== 0 || pid
!= process
->ppid
);
3177 /* Process not present */
3178 Drawing_t
*drawing
= control_flow_data
->drawing
;
3179 ProcessInfo
*process_info
;
3180 processlist_add(process_list
,
3186 tfc
->t_context
->index
,
3190 &hashed_process_data
);
3191 gtk_widget_set_size_request(drawing
->drawing_area
,
3194 gtk_widget_queue_draw(drawing
->drawing_area
);
3197 /* Set the current process */
3198 process_list
->current_hash_data
[process
->cpu
] =
3199 hashed_process_data
;
3202 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3205 TimeWindow time_window
=
3206 lttvwindow_get_time_window(control_flow_data
->tab
);
3209 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3210 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3212 #endif //EXTRA_CHECK
3213 Drawing_t
*drawing
= control_flow_data
->drawing
;
3214 guint width
= drawing
->width
;
3216 convert_time_to_pixels(
3221 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3222 hashed_process_data
->x
.middle
= new_x
;
3223 hashed_process_data
->x
.middle_used
= FALSE
;
3224 hashed_process_data
->x
.middle_marked
= FALSE
;
3234 /* after_process_hook
3236 * Create the processlist entry for the child process. Put the last
3237 * position in x at the current time value.
3239 * @param hook_data ControlFlowData structure of the viewer.
3240 * @param call_data Event context.
3242 * This function adds items to be drawn in a queue for each process.
3245 int after_process_hook(void *hook_data
, void *call_data
)
3247 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3248 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3249 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3251 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3253 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3256 e
= ltt_tracefile_get_event(tfc
->tf
);
3258 LttTime evtime
= ltt_event_time(e
);
3263 LttField
*f
= ltt_event_field(e
);
3265 element
= ltt_field_member(f
,0);
3266 sub_id
= ltt_event_get_long_unsigned(e
,element
);
3267 element
= ltt_field_member(f
,1);
3268 param1
= ltt_event_get_long_unsigned(e
,element
);
3271 if(sub_id
== 2) { /* fork */
3273 guint child_pid
= param1
;
3274 /* Add process to process list (if not present) */
3275 LttvProcessState
*process_child
;
3277 guint pl_height
= 0;
3278 HashedProcessData
*hashed_process_data_child
= NULL
;
3280 ProcessList
*process_list
= control_flow_data
->process_list
;
3282 /* Find child in the list... */
3283 process_child
= lttv_state_find_process(tfs
, child_pid
);
3284 /* It should exist, because we are after the state update. */
3285 g_assert(process_child
!= NULL
);
3287 birth
= process_child
->creation_time
;
3289 /* Cannot use current process, because this action is done by the parent
3291 hashed_process_data_child
= processlist_get_process_data(process_list
,
3293 process_child
->last_cpu_index
,
3295 tfc
->t_context
->index
);
3296 if(likely(hashed_process_data_child
== NULL
))
3298 g_assert(child_pid
== 0 || child_pid
!= process_child
->ppid
);
3299 /* Process not present */
3300 Drawing_t
*drawing
= control_flow_data
->drawing
;
3301 const gchar
*name
= g_quark_to_string(process_child
->name
);
3302 ProcessInfo
*process_info
;
3303 processlist_add(process_list
,
3306 process_child
->last_cpu_index
,
3307 process_child
->ppid
,
3309 tfc
->t_context
->index
,
3313 &hashed_process_data_child
);
3314 gtk_widget_set_size_request(drawing
->drawing_area
,
3317 gtk_widget_queue_draw(drawing
->drawing_area
);
3321 if(likely(ltt_time_compare(hashed_process_data_child
->next_good_time
,
3324 TimeWindow time_window
=
3325 lttvwindow_get_time_window(control_flow_data
->tab
);
3328 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3329 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3331 #endif //EXTRA_CHECK
3332 Drawing_t
*drawing
= control_flow_data
->drawing
;
3333 guint width
= drawing
->width
;
3335 convert_time_to_pixels(
3341 if(likely(hashed_process_data_child
->x
.over
!= new_x
)) {
3342 hashed_process_data_child
->x
.over
= new_x
;
3343 hashed_process_data_child
->x
.over_used
= FALSE
;
3344 hashed_process_data_child
->x
.over_marked
= FALSE
;
3346 if(likely(hashed_process_data_child
->x
.middle
!= new_x
)) {
3347 hashed_process_data_child
->x
.middle
= new_x
;
3348 hashed_process_data_child
->x
.middle_used
= FALSE
;
3349 hashed_process_data_child
->x
.middle_marked
= FALSE
;
3351 if(likely(hashed_process_data_child
->x
.under
!= new_x
)) {
3352 hashed_process_data_child
->x
.under
= new_x
;
3353 hashed_process_data_child
->x
.under_used
= FALSE
;
3354 hashed_process_data_child
->x
.under_marked
= FALSE
;
3358 } else if(sub_id
== 3) { /* exit */
3360 /* Add process to process list (if not present) */
3361 LttvProcessState
*process
= tfs
->process
;
3362 guint pid
= process
->pid
;
3364 guint pl_height
= 0;
3365 HashedProcessData
*hashed_process_data
= NULL
;
3367 ProcessList
*process_list
= control_flow_data
->process_list
;
3369 /* It should exist, because we are after the state update. */
3370 g_assert(process
!= NULL
);
3372 birth
= process
->creation_time
;
3374 if(likely(process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)] != NULL
) ){
3375 hashed_process_data
= process_list
->current_hash_data
[ltt_tracefile_num(tfc
->tf
)];
3377 hashed_process_data
= processlist_get_process_data(process_list
,
3379 process
->last_cpu_index
,
3381 tfc
->t_context
->index
);
3382 if(unlikely(hashed_process_data
== NULL
))
3384 g_assert(pid
== 0 || pid
!= process
->ppid
);
3385 /* Process not present */
3386 Drawing_t
*drawing
= control_flow_data
->drawing
;
3387 const gchar
*name
= g_quark_to_string(process
->name
);
3388 ProcessInfo
*process_info
;
3389 processlist_add(process_list
,
3392 process
->last_cpu_index
,
3395 tfc
->t_context
->index
,
3399 &hashed_process_data
);
3400 gtk_widget_set_size_request(drawing
->drawing_area
,
3403 gtk_widget_queue_draw(drawing
->drawing_area
);
3406 /* Set the current process */
3407 process_list
->current_hash_data
[process
->last_cpu_index
] =
3408 hashed_process_data
;
3411 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3414 TimeWindow time_window
=
3415 lttvwindow_get_time_window(control_flow_data
->tab
);
3418 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3419 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3421 #endif //EXTRA_CHECK
3422 Drawing_t
*drawing
= control_flow_data
->drawing
;
3423 guint width
= drawing
->width
;
3425 convert_time_to_pixels(
3430 if(unlikely(hashed_process_data
->x
.middle
!= new_x
)) {
3431 hashed_process_data
->x
.middle
= new_x
;
3432 hashed_process_data
->x
.middle_used
= FALSE
;
3433 hashed_process_data
->x
.middle_marked
= FALSE
;
3443 /* Get the filename of the process to print */
3444 int after_fs_exec_hook(void *hook_data
, void *call_data
)
3446 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
3447 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
3448 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3450 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3452 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
3454 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
3456 guint cpu
= ltt_tracefile_num(tfc
->tf
);
3457 LttvProcessState
*process
= ts
->running_process
[cpu
];
3458 g_assert(process
!= NULL
);
3460 guint pid
= process
->pid
;
3462 /* Well, the process_out existed : we must get it in the process hash
3463 * or add it, and draw its items.
3465 /* Add process to process list (if not present) */
3466 guint pl_height
= 0;
3467 HashedProcessData
*hashed_process_data
= NULL
;
3468 ProcessList
*process_list
= control_flow_data
->process_list
;
3469 LttTime birth
= process
->creation_time
;
3471 if(likely(process_list
->current_hash_data
[cpu
] != NULL
)) {
3472 hashed_process_data
= process_list
->current_hash_data
[cpu
];
3474 hashed_process_data
= processlist_get_process_data(process_list
,
3478 tfc
->t_context
->index
);
3479 if(unlikely(hashed_process_data
== NULL
))
3481 g_assert(pid
== 0 || pid
!= process
->ppid
);
3482 ProcessInfo
*process_info
;
3483 /* Process not present */
3484 Drawing_t
*drawing
= control_flow_data
->drawing
;
3485 processlist_add(process_list
,
3491 tfc
->t_context
->index
,
3495 &hashed_process_data
);
3496 gtk_widget_set_size_request(drawing
->drawing_area
,
3499 gtk_widget_queue_draw(drawing
->drawing_area
);
3501 /* Set the current process */
3502 process_list
->current_hash_data
[process
->cpu
] =
3503 hashed_process_data
;
3506 processlist_set_name(process_list
, process
->name
, hashed_process_data
);
3515 gint
update_time_window_hook(void *hook_data
, void *call_data
)
3517 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3518 Drawing_t
*drawing
= control_flow_data
->drawing
;
3519 ProcessList
*process_list
= control_flow_data
->process_list
;
3521 const TimeWindowNotifyData
*time_window_nofify_data
=
3522 ((const TimeWindowNotifyData
*)call_data
);
3524 TimeWindow
*old_time_window
=
3525 time_window_nofify_data
->old_time_window
;
3526 TimeWindow
*new_time_window
=
3527 time_window_nofify_data
->new_time_window
;
3529 /* Update the ruler */
3530 drawing_update_ruler(control_flow_data
->drawing
,
3534 /* Two cases : zoom in/out or scrolling */
3536 /* In order to make sure we can reuse the old drawing, the scale must
3537 * be the same and the new time interval being partly located in the
3538 * currently shown time interval. (reuse is only for scrolling)
3541 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3542 old_time_window
->start_time
.tv_sec
,
3543 old_time_window
->start_time
.tv_nsec
,
3544 old_time_window
->time_width
.tv_sec
,
3545 old_time_window
->time_width
.tv_nsec
);
3547 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3548 new_time_window
->start_time
.tv_sec
,
3549 new_time_window
->start_time
.tv_nsec
,
3550 new_time_window
->time_width
.tv_sec
,
3551 new_time_window
->time_width
.tv_nsec
);
3553 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
3554 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
3556 /* Same scale (scrolling) */
3557 g_info("scrolling");
3558 LttTime
*ns
= &new_time_window
->start_time
;
3559 LttTime
*nw
= &new_time_window
->time_width
;
3560 LttTime
*os
= &old_time_window
->start_time
;
3561 LttTime
*ow
= &old_time_window
->time_width
;
3562 LttTime old_end
= old_time_window
->end_time
;
3563 LttTime new_end
= new_time_window
->end_time
;
3565 //if(ns<os+w && os+w<ns+w)
3566 //if(ns<old_end && os<ns)
3567 if(ltt_time_compare(*ns
, old_end
) == -1
3568 && ltt_time_compare(*os
, *ns
) == -1)
3570 g_info("scrolling near right");
3571 /* Scroll right, keep right part of the screen */
3573 guint width
= control_flow_data
->drawing
->width
;
3574 convert_time_to_pixels(
3580 /* Copy old data to new location */
3581 copy_pixmap_region(process_list
,
3583 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3587 control_flow_data
->drawing
->width
-x
+SAFETY
, -1);
3589 if(drawing
->damage_begin
== drawing
->damage_end
)
3590 drawing
->damage_begin
= control_flow_data
->drawing
->width
-x
;
3592 drawing
->damage_begin
= 0;
3594 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3596 /* Clear the data request background, but not SAFETY */
3597 rectangle_pixmap(process_list
,
3598 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3600 drawing
->damage_begin
+SAFETY
, 0,
3601 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3603 gtk_widget_queue_draw(drawing
->drawing_area
);
3604 //gtk_widget_queue_draw_area (drawing->drawing_area,
3606 // control_flow_data->drawing->width,
3607 // control_flow_data->drawing->height);
3609 /* Get new data for the rest. */
3610 drawing_data_request(control_flow_data
->drawing
,
3611 drawing
->damage_begin
, 0,
3612 drawing
->damage_end
- drawing
->damage_begin
,
3613 control_flow_data
->drawing
->height
);
3616 //if(ns<os && os<ns+w)
3617 //if(ns<os && os<new_end)
3618 if(ltt_time_compare(*ns
,*os
) == -1
3619 && ltt_time_compare(*os
,new_end
) == -1)
3621 g_info("scrolling near left");
3622 /* Scroll left, keep left part of the screen */
3624 guint width
= control_flow_data
->drawing
->width
;
3625 convert_time_to_pixels(
3631 /* Copy old data to new location */
3632 copy_pixmap_region (process_list
,
3634 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3640 if(drawing
->damage_begin
== drawing
->damage_end
)
3641 drawing
->damage_end
= x
;
3643 drawing
->damage_end
=
3644 control_flow_data
->drawing
->width
;
3646 drawing
->damage_begin
= 0;
3648 rectangle_pixmap (process_list
,
3649 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3651 drawing
->damage_begin
, 0,
3652 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
3655 gtk_widget_queue_draw(drawing
->drawing_area
);
3656 //gtk_widget_queue_draw_area (drawing->drawing_area,
3658 // control_flow_data->drawing->width,
3659 // control_flow_data->drawing->height);
3662 /* Get new data for the rest. */
3663 drawing_data_request(control_flow_data
->drawing
,
3664 drawing
->damage_begin
, 0,
3665 drawing
->damage_end
- drawing
->damage_begin
,
3666 control_flow_data
->drawing
->height
);
3669 if(ltt_time_compare(*ns
,*os
) == 0)
3671 g_info("not scrolling");
3673 g_info("scrolling far");
3674 /* Cannot reuse any part of the screen : far jump */
3677 rectangle_pixmap (process_list
,
3678 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3681 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3684 //gtk_widget_queue_draw_area (drawing->drawing_area,
3686 // control_flow_data->drawing->width,
3687 // control_flow_data->drawing->height);
3688 gtk_widget_queue_draw(drawing
->drawing_area
);
3690 drawing
->damage_begin
= 0;
3691 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3693 drawing_data_request(control_flow_data
->drawing
,
3695 control_flow_data
->drawing
->width
,
3696 control_flow_data
->drawing
->height
);
3702 /* Different scale (zoom) */
3705 rectangle_pixmap (process_list
,
3706 control_flow_data
->drawing
->drawing_area
->style
->black_gc
,
3709 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
3712 //gtk_widget_queue_draw_area (drawing->drawing_area,
3714 // control_flow_data->drawing->width,
3715 // control_flow_data->drawing->height);
3716 gtk_widget_queue_draw(drawing
->drawing_area
);
3718 drawing
->damage_begin
= 0;
3719 drawing
->damage_end
= control_flow_data
->drawing
->width
;
3721 drawing_data_request(control_flow_data
->drawing
,
3723 control_flow_data
->drawing
->width
,
3724 control_flow_data
->drawing
->height
);
3732 gint
traceset_notify(void *hook_data
, void *call_data
)
3734 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3735 Drawing_t
*drawing
= control_flow_data
->drawing
;
3738 drawing_clear(control_flow_data
->drawing
);
3739 processlist_clear(control_flow_data
->process_list
);
3740 gtk_widget_set_size_request(
3741 control_flow_data
->drawing
->drawing_area
,
3742 -1, processlist_get_height(control_flow_data
->process_list
));
3743 redraw_notify(control_flow_data
, NULL
);
3745 request_background_data(control_flow_data
);
3750 gint
redraw_notify(void *hook_data
, void *call_data
)
3752 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3753 Drawing_t
*drawing
= control_flow_data
->drawing
;
3754 GtkWidget
*widget
= drawing
->drawing_area
;
3756 drawing
->damage_begin
= 0;
3757 drawing
->damage_end
= drawing
->width
;
3759 /* fun feature, to be separated someday... */
3760 drawing_clear(control_flow_data
->drawing
);
3761 processlist_clear(control_flow_data
->process_list
);
3762 gtk_widget_set_size_request(
3763 control_flow_data
->drawing
->drawing_area
,
3764 -1, processlist_get_height(control_flow_data
->process_list
));
3766 rectangle_pixmap (control_flow_data
->process_list
,
3767 widget
->style
->black_gc
,
3770 drawing
->alloc_width
,
3773 gtk_widget_queue_draw(drawing
->drawing_area
);
3775 if(drawing
->damage_begin
< drawing
->damage_end
)
3777 drawing_data_request(drawing
,
3778 drawing
->damage_begin
,
3780 drawing
->damage_end
-drawing
->damage_begin
,
3784 //gtk_widget_queue_draw_area(drawing->drawing_area,
3787 // drawing->height);
3793 gint
continue_notify(void *hook_data
, void *call_data
)
3795 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
3796 Drawing_t
*drawing
= control_flow_data
->drawing
;
3798 //g_assert(widget->allocation.width == drawing->damage_end);
3800 if(drawing
->damage_begin
< drawing
->damage_end
)
3802 drawing_data_request(drawing
,
3803 drawing
->damage_begin
,
3805 drawing
->damage_end
-drawing
->damage_begin
,
3813 gint
update_current_time_hook(void *hook_data
, void *call_data
)
3815 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
3816 Drawing_t
*drawing
= control_flow_data
->drawing
;
3818 LttTime current_time
= *((LttTime
*)call_data
);
3820 TimeWindow time_window
=
3821 lttvwindow_get_time_window(control_flow_data
->tab
);
3823 LttTime time_begin
= time_window
.start_time
;
3824 LttTime width
= time_window
.time_width
;
3827 guint64 time_ll
= ltt_time_to_uint64(width
);
3828 time_ll
= time_ll
>> 1; /* divide by two */
3829 half_width
= ltt_time_from_uint64(time_ll
);
3831 LttTime time_end
= ltt_time_add(time_begin
, width
);
3833 LttvTracesetContext
* tsc
=
3834 lttvwindow_get_traceset_context(control_flow_data
->tab
);
3836 LttTime trace_start
= tsc
->time_span
.start_time
;
3837 LttTime trace_end
= tsc
->time_span
.end_time
;
3839 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
3840 current_time
.tv_nsec
);
3844 /* If current time is inside time interval, just move the highlight
3847 /* Else, we have to change the time interval. We have to tell it
3848 * to the main window. */
3849 /* The time interval change will take care of placing the current
3850 * time at the center of the visible area, or nearest possible if we are
3851 * at one end of the trace. */
3854 if(ltt_time_compare(current_time
, time_begin
) < 0)
3856 TimeWindow new_time_window
;
3858 if(ltt_time_compare(current_time
,
3859 ltt_time_add(trace_start
,half_width
)) < 0)
3860 time_begin
= trace_start
;
3862 time_begin
= ltt_time_sub(current_time
,half_width
);
3864 new_time_window
.start_time
= time_begin
;
3865 new_time_window
.time_width
= width
;
3866 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3867 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3869 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3871 else if(ltt_time_compare(current_time
, time_end
) > 0)
3873 TimeWindow new_time_window
;
3875 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
3876 time_begin
= ltt_time_sub(trace_end
,width
);
3878 time_begin
= ltt_time_sub(current_time
,half_width
);
3880 new_time_window
.start_time
= time_begin
;
3881 new_time_window
.time_width
= width
;
3882 new_time_window
.time_width_double
= ltt_time_to_double(width
);
3883 new_time_window
.end_time
= ltt_time_add(time_begin
, width
);
3885 lttvwindow_report_time_window(control_flow_data
->tab
, new_time_window
);
3888 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
3894 typedef struct _ClosureData
{
3895 EventsRequest
*events_request
;
3896 LttvTracesetState
*tss
;
3902 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
3904 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
3905 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
3906 ClosureData
*closure_data
= (ClosureData
*)user_data
;
3908 EventsRequest
*events_request
= closure_data
->events_request
;
3909 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
3911 LttvTracesetState
*tss
= closure_data
->tss
;
3912 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
3914 LttTime evtime
= closure_data
->end_time
;
3917 /* For the process */
3918 /* First, check if the current process is in the state computation
3919 * process list. If it is there, that means we must add it right now and
3920 * draw items from the beginning of the read for it. If it is not
3921 * present, it's a new process and it was not present : it will
3922 * be added after the state update. */
3924 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
3925 #endif //EXTRA_CHECK
3926 LttvTraceContext
*tc
= tsc
->traces
[process_info
->trace_num
];
3927 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
3930 //FIXME : optimize data structures.
3931 LttvTracefileState
*tfs
;
3932 LttvTracefileContext
*tfc
;
3934 for(i
=0;i
<tc
->tracefiles
->len
;i
++) {
3935 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, i
);
3936 if(ltt_tracefile_name(tfc
->tf
) == LTT_NAME_CPU
3937 && ltt_tracefile_num(tfc
->tf
) == process_info
->cpu
)
3941 g_assert(i
<tc
->tracefiles
->len
);
3942 tfs
= LTTV_TRACEFILE_STATE(tfc
);
3944 // LttvTracefileState *tfs =
3945 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3946 // tracefiles[process_info->cpu];
3948 LttvProcessState
*process
;
3949 process
= lttv_state_find_process(ts
, process_info
->cpu
,
3952 if(unlikely(process
!= NULL
)) {
3954 /* Only draw for processes that are currently in the trace states */
3956 ProcessList
*process_list
= control_flow_data
->process_list
;
3958 /* Should be alike when background info is ready */
3959 if(control_flow_data
->background_info_waiting
==0)
3960 g_assert(ltt_time_compare(process
->creation_time
,
3961 process_info
->birth
) == 0);
3962 #endif //EXTRA_CHECK
3964 /* Now, the process is in the state hash and our own process hash.
3965 * We definitely can draw the items related to the ending state.
3968 if(unlikely(ltt_time_compare(hashed_process_data
->next_good_time
,
3971 TimeWindow time_window
=
3972 lttvwindow_get_time_window(control_flow_data
->tab
);
3975 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
3976 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
3978 #endif //EXTRA_CHECK
3979 Drawing_t
*drawing
= control_flow_data
->drawing
;
3980 guint width
= drawing
->width
;
3982 guint x
= closure_data
->x_end
;
3984 DrawContext draw_context
;
3986 /* Now create the drawing context that will be used to draw
3987 * items related to the last state. */
3988 draw_context
.drawable
= hashed_process_data
->pixmap
;
3989 draw_context
.gc
= drawing
->gc
;
3990 draw_context
.pango_layout
= drawing
->pango_layout
;
3991 draw_context
.drawinfo
.end
.x
= x
;
3993 draw_context
.drawinfo
.y
.over
= 1;
3994 draw_context
.drawinfo
.y
.middle
= (hashed_process_data
->height
/2);
3995 draw_context
.drawinfo
.y
.under
= hashed_process_data
->height
;
3997 draw_context
.drawinfo
.start
.offset
.over
= 0;
3998 draw_context
.drawinfo
.start
.offset
.middle
= 0;
3999 draw_context
.drawinfo
.start
.offset
.under
= 0;
4000 draw_context
.drawinfo
.end
.offset
.over
= 0;
4001 draw_context
.drawinfo
.end
.offset
.middle
= 0;
4002 draw_context
.drawinfo
.end
.offset
.under
= 0;
4004 /* Jump over draw if we are at the same x position */
4005 if(x
== hashed_process_data
->x
.over
)
4009 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.over
;
4011 PropertiesLine prop_line
= prepare_execmode_line(process
);
4012 draw_line((void*)&prop_line
, (void*)&draw_context
);
4014 hashed_process_data
->x
.over
= x
;
4018 if(unlikely(x
== hashed_process_data
->x
.middle
&&
4019 hashed_process_data
->x
.middle_used
)) {
4020 #if 0 /* do not mark closure : not missing information */
4021 if(hashed_process_data
->x
.middle_marked
== FALSE
) {
4022 /* Draw collision indicator */
4023 gdk_gc_set_foreground(drawing
->gc
, &drawing_colors
[COL_WHITE
]);
4024 gdk_draw_point(drawing
->pixmap
,
4028 hashed_process_data
->x
.middle_marked
= TRUE
;
4033 draw_context
.drawinfo
.start
.x
= hashed_process_data
->x
.middle
;
4035 PropertiesLine prop_line
= prepare_s_e_line(process
);
4036 draw_line((void*)&prop_line
, (void*)&draw_context
);
4038 /* become the last x position */
4039 if(likely(x
!= hashed_process_data
->x
.middle
)) {
4040 hashed_process_data
->x
.middle
= x
;
4041 /* but don't use the pixel */
4042 hashed_process_data
->x
.middle_used
= FALSE
;
4044 /* Calculate the next good time */
4045 convert_pixels_to_time(width
, x
+1, time_window
,
4046 &hashed_process_data
->next_good_time
);
4055 int before_chunk(void *hook_data
, void *call_data
)
4057 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4058 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4059 ControlFlowData
*cfd
= (ControlFlowData
*)events_request
->viewer_data
;
4061 /* Desactivate sort */
4062 gtk_tree_sortable_set_sort_column_id(
4063 GTK_TREE_SORTABLE(cfd
->process_list
->list_store
),
4065 GTK_SORT_ASCENDING
);
4067 drawing_chunk_begin(events_request
, tss
);
4072 int before_request(void *hook_data
, void *call_data
)
4074 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4075 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4077 drawing_data_request_begin(events_request
, tss
);
4084 * after request is necessary in addition of after chunk in order to draw
4085 * lines until the end of the screen. after chunk just draws lines until
4092 int after_request(void *hook_data
, void *call_data
)
4094 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4095 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4096 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4098 ProcessList
*process_list
= control_flow_data
->process_list
;
4099 LttTime end_time
= events_request
->end_time
;
4101 ClosureData closure_data
;
4102 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4103 closure_data
.tss
= tss
;
4104 closure_data
.end_time
= end_time
;
4106 TimeWindow time_window
=
4107 lttvwindow_get_time_window(control_flow_data
->tab
);
4108 guint width
= control_flow_data
->drawing
->width
;
4109 convert_time_to_pixels(
4113 &closure_data
.x_end
);
4116 /* Draw last items */
4117 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4118 (void*)&closure_data
);
4121 /* Request expose */
4122 drawing_request_expose(events_request
, tss
, end_time
);
4131 int after_chunk(void *hook_data
, void *call_data
)
4133 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
4134 ControlFlowData
*control_flow_data
= events_request
->viewer_data
;
4135 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
4136 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)call_data
;
4137 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
4140 ProcessList
*process_list
= control_flow_data
->process_list
;
4142 g_free(process_list
->current_hash_data
);
4143 process_list
->current_hash_data
= NULL
;
4146 end_time
= LTT_TIME_MIN(tfc
->timestamp
, events_request
->end_time
);
4147 else /* end of traceset, or position now out of request : end */
4148 end_time
= events_request
->end_time
;
4150 ClosureData closure_data
;
4151 closure_data
.events_request
= (EventsRequest
*)hook_data
;
4152 closure_data
.tss
= tss
;
4153 closure_data
.end_time
= end_time
;
4155 TimeWindow time_window
=
4156 lttvwindow_get_time_window(control_flow_data
->tab
);
4157 guint width
= control_flow_data
->drawing
->width
;
4158 convert_time_to_pixels(
4162 &closure_data
.x_end
);
4164 /* Draw last items */
4165 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
4166 (void*)&closure_data
);
4168 /* Reactivate sort */
4169 gtk_tree_sortable_set_sort_column_id(
4170 GTK_TREE_SORTABLE(control_flow_data
->process_list
->list_store
),
4171 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
4172 GTK_SORT_ASCENDING
);
4174 update_index_to_pixmap(control_flow_data
->process_list
);
4175 /* Request a full expose : drawing scrambled */
4176 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
4178 /* Request expose (updates damages zone also) */
4179 drawing_request_expose(events_request
, tss
, end_time
);