perf fix minor
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
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.
27 *
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.
31 *
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.
34 *
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
41 * hook.
42 *
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
45 * line/background.
46 */
47
48
49 //#define PANGO_ENABLE_BACKEND
50 #include <gtk/gtk.h>
51 #include <gdk/gdk.h>
52 #include <glib.h>
53 #include <assert.h>
54 #include <string.h>
55 #include <stdio.h>
56
57 //#include <pango/pango.h>
58
59 #include <ltt/event.h>
60 #include <ltt/time.h>
61 #include <ltt/type.h>
62
63 #include <lttv/lttv.h>
64 #include <lttv/hook.h>
65 #include <lttv/state.h>
66 #include <lttvwindow/lttvwindow.h>
67 #include <lttvwindow/lttvwindowtraces.h>
68
69
70 #include "eventhooks.h"
71 #include "cfv.h"
72 #include "processlist.h"
73 #include "drawing.h"
74 #include "cfv-private.h"
75
76
77 #define MAX_PATH_LEN 256
78
79
80 #if 0
81 typedef struct _ProcessAddClosure {
82 ControlFlowData *cfd;
83 guint trace_num;
84 } ProcessAddClosure;
85
86 static void process_add(gpointer key,
87 gpointer value,
88 gpointer user_data)
89 {
90 LttvProcessState *process = (LttvProcessState*)value;
91 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
92 ControlFlowData *control_flow_data = closure->cfd;
93 guint trace_num = closure->trace_num;
94
95 /* Add process to process list (if not present) */
96 guint pid;
97 LttTime birth;
98 guint y = 0, height = 0, pl_height = 0;
99
100 ProcessList *process_list = control_flow_data->process_list;
101
102 pid = process->pid;
103 birth = process->creation_time;
104 const gchar *name = g_quark_to_string(process->name);
105 HashedProcessData *hashed_process_data = NULL;
106
107 if(processlist_get_process_pixels(process_list,
108 pid,
109 &birth,
110 trace_num,
111 &y,
112 &height,
113 &hashed_process_data) == 1)
114 {
115 /* Process not present */
116 processlist_add(process_list,
117 pid,
118 &birth,
119 trace_num,
120 name,
121 &pl_height,
122 &hashed_process_data);
123 processlist_get_process_pixels(process_list,
124 pid,
125 &birth,
126 trace_num,
127 &y,
128 &height,
129 &hashed_process_data);
130 drawing_insert_square( control_flow_data->drawing, y, height);
131 }
132 }
133 #endif //0
134
135
136 /* Action to do when background computation completed.
137 *
138 * Wait for all the awaited computations to be over.
139 */
140
141 gint background_ready(void *hook_data, void *call_data)
142 {
143 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
144 LttvTrace *trace = (LttvTrace*)call_data;
145 LttvTracesetContext *tsc =
146 lttvwindow_get_traceset_context(control_flow_data->tab);
147
148 control_flow_data->background_info_waiting--;
149
150 if(control_flow_data->background_info_waiting == 0) {
151 g_debug("control flow viewer : background computation data ready.");
152
153 drawing_clear(control_flow_data->drawing);
154 processlist_clear(control_flow_data->process_list);
155 redraw_notify(control_flow_data, NULL);
156 }
157
158 return 0;
159 }
160
161
162 /* Request background computation. Verify if it is in progress or ready first.
163 * Only for each trace in the tab's traceset.
164 */
165 void request_background_data(ControlFlowData *control_flow_data)
166 {
167 LttvTracesetContext * tsc =
168 lttvwindow_get_traceset_context(control_flow_data->tab);
169 gint num_traces = lttv_traceset_number(tsc->ts);
170 gint i;
171 LttvTrace *trace;
172
173 LttvHooks *background_ready_hook =
174 lttv_hooks_new();
175 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
176 LTTV_PRIO_DEFAULT);
177 control_flow_data->background_info_waiting = 0;
178
179 for(i=0;i<num_traces;i++) {
180 trace = lttv_traceset_get(tsc->ts, i);
181
182 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
183
184 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
185 trace) == FALSE) {
186 /* We first remove requests that could have been done for the same
187 * information. Happens when two viewers ask for it before servicing
188 * starts.
189 */
190 lttvwindowtraces_background_request_remove(trace, "state");
191 lttvwindowtraces_background_request_queue(trace,
192 "state");
193 lttvwindowtraces_background_notify_queue(control_flow_data,
194 trace,
195 ltt_time_infinite,
196 NULL,
197 background_ready_hook);
198 control_flow_data->background_info_waiting++;
199 } else { /* in progress */
200
201 lttvwindowtraces_background_notify_current(control_flow_data,
202 trace,
203 ltt_time_infinite,
204 NULL,
205 background_ready_hook);
206 control_flow_data->background_info_waiting++;
207 }
208 } else {
209 /* Data ready. Be its nature, this viewer doesn't need to have
210 * its data ready hook called htere, because a background
211 * request is always linked with a redraw.
212 */
213 }
214
215 }
216
217 lttv_hooks_destroy(background_ready_hook);
218 }
219
220
221
222
223 /**
224 * Event Viewer's constructor hook
225 *
226 * This constructor is given as a parameter to the menuitem and toolbar button
227 * registration. It creates the list.
228 * @param tab A pointer to the parent tab.
229 * @return The widget created.
230 */
231 GtkWidget *
232 h_guicontrolflow(Tab *tab)
233 {
234 g_info("h_guicontrolflow, %p", tab);
235 ControlFlowData *control_flow_data = guicontrolflow() ;
236
237 control_flow_data->tab = tab;
238
239 //g_debug("time width2 : %u",time_window->time_width);
240 // Unreg done in the GuiControlFlow_Destructor
241 lttvwindow_register_traceset_notify(tab,
242 traceset_notify,
243 control_flow_data);
244
245 lttvwindow_register_time_window_notify(tab,
246 update_time_window_hook,
247 control_flow_data);
248 lttvwindow_register_current_time_notify(tab,
249 update_current_time_hook,
250 control_flow_data);
251 lttvwindow_register_redraw_notify(tab,
252 redraw_notify,
253 control_flow_data);
254 lttvwindow_register_continue_notify(tab,
255 continue_notify,
256 control_flow_data);
257 request_background_data(control_flow_data);
258
259
260 return guicontrolflow_get_widget(control_flow_data) ;
261
262 }
263
264 int event_selected_hook(void *hook_data, void *call_data)
265 {
266 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
267 guint *event_number = (guint*) call_data;
268
269 g_debug("DEBUG : event selected by main window : %u", *event_number);
270
271 }
272
273 /* Function that selects the color of status&exemode line */
274 static __inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
275 {
276 PropertiesLine prop_line;
277 prop_line.line_width = 2;
278 prop_line.style = GDK_LINE_SOLID;
279 prop_line.y = MIDDLE;
280 //GdkColormap *colormap = gdk_colormap_get_system();
281
282 g_debug("prepare_status_line for state : %s",
283 g_quark_to_string(process->state->s));
284
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];
296 else
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
303 * or syscall */
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];
313 } else
314 g_assert(FALSE); /* UNKNOWN STATE */
315
316 return prop_line;
317
318 }
319
320 #if 0
321 static __inline PropertiesLine prepare_status_line(LttvProcessState *process)
322 {
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();
328
329 g_debug("prepare_status_line for state : %s",
330 g_quark_to_string(process->state->s));
331
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];
347 else
348 prop_line.color = drawing_colors[COL_WHITE];
349
350 //gdk_colormap_alloc_color(colormap,
351 // prop_line.color,
352 // FALSE,
353 // TRUE);
354
355 return prop_line;
356
357 }
358 #endif //0
359
360
361 /* before_schedchange_hook
362 *
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).
367 *
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.
373 *
374 * The choice of lines'color is defined by the context of the last event for this
375 * process.
376 */
377
378
379 int before_schedchange_hook(void *hook_data, void *call_data)
380 {
381 EventsRequest *events_request = (EventsRequest*)hook_data;
382 ControlFlowData *control_flow_data = events_request->viewer_data;
383 Drawing_t *drawing = control_flow_data->drawing;
384
385 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
386
387 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
388 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
389
390 LttEvent *e;
391 e = tfc->e;
392
393 LttTime evtime = ltt_event_time(e);
394 TimeWindow time_window =
395 lttvwindow_get_time_window(control_flow_data->tab);
396
397 LttTime end_time = ltt_time_add(time_window.start_time,
398 time_window.time_width);
399
400 if(ltt_time_compare(evtime, time_window.start_time) == -1
401 || ltt_time_compare(evtime, end_time) == 1)
402 return;
403 guint width = drawing->width;
404
405 /* we are in a schedchange, before the state update. We must draw the
406 * items corresponding to the state before it changes : now is the right
407 * time to do it.
408 */
409
410 guint pid_out;
411 guint pid_in;
412 {
413 LttField *f = ltt_event_field(e);
414 LttField *element;
415 element = ltt_field_member(f,0);
416 pid_out = ltt_event_get_long_unsigned(e,element);
417 element = ltt_field_member(f,1);
418 pid_in = ltt_event_get_long_unsigned(e,element);
419 g_debug("out : %u in : %u", pid_out, pid_in);
420 }
421
422 {
423 /* For the pid_out */
424 /* First, check if the current process is in the state computation
425 * process list. If it is there, that means we must add it right now and
426 * draw items from the beginning of the read for it. If it is not
427 * present, it's a new process and it was not present : it will
428 * be added after the state update. */
429 LttvProcessState *process;
430 process = lttv_state_find_process(tfs, pid_out);
431
432 if(process != NULL) {
433 /* Well, the process_out existed : we must get it in the process hash
434 * or add it, and draw its items.
435 */
436 /* Add process to process list (if not present) */
437 guint y = 0, height = 0, pl_height = 0;
438 HashedProcessData *hashed_process_data = NULL;
439 ProcessList *process_list = control_flow_data->process_list;
440 LttTime birth = process->creation_time;
441 const gchar *name = g_quark_to_string(process->name);
442
443 if(processlist_get_process_pixels(process_list,
444 pid_out,
445 process->last_cpu,
446 &birth,
447 tfc->t_context->index,
448 &y,
449 &height,
450 &hashed_process_data) == 1)
451 {
452 g_assert(pid_out == 0 || pid_out != process->ppid);
453 /* Process not present */
454 processlist_add(process_list,
455 pid_out,
456 process->last_cpu,
457 process->ppid,
458 &birth,
459 tfc->t_context->index,
460 name,
461 &pl_height,
462 &hashed_process_data);
463 processlist_get_process_pixels(process_list,
464 pid_out,
465 process->last_cpu,
466 &birth,
467 tfc->t_context->index,
468 &y,
469 &height,
470 &hashed_process_data);
471 drawing_insert_square( drawing, y, height);
472 }
473
474 /* Now, the process is in the state hash and our own process hash.
475 * We definitely can draw the items related to the ending state.
476 */
477
478 /* Check if the x position is unset. In can have been left unset by
479 * a draw closure from a after chunk hook. This should never happen,
480 * because it must be set by before chunk hook to the damage_begin
481 * value.
482 */
483 g_assert(hashed_process_data->x.middle != -1);
484 {
485 guint x;
486 convert_time_to_pixels(
487 time_window.start_time,
488 end_time,
489 evtime,
490 width,
491 &x);
492
493
494 /* Jump over draw if we are at the same x position */
495 if(x == hashed_process_data->x.middle &&
496 hashed_process_data->x.middle_used)
497 {
498 if(hashed_process_data->x.middle_marked == FALSE) {
499 /* Draw collision indicator */
500 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
501 gdk_draw_point(drawing->pixmap,
502 drawing->gc,
503 x,
504 y+(height/2)-3);
505 hashed_process_data->x.middle_marked = TRUE;
506 }
507 /* jump */
508 } else {
509 DrawContext draw_context;
510
511 /* Now create the drawing context that will be used to draw
512 * items related to the last state. */
513 draw_context.drawable = drawing->pixmap;
514 draw_context.gc = drawing->gc;
515 draw_context.pango_layout = drawing->pango_layout;
516 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
517 draw_context.drawinfo.end.x = x;
518
519 draw_context.drawinfo.y.over = y+1;
520 draw_context.drawinfo.y.middle = y+(height/2);
521 draw_context.drawinfo.y.under = y+height;
522
523 draw_context.drawinfo.start.offset.over = 0;
524 draw_context.drawinfo.start.offset.middle = 0;
525 draw_context.drawinfo.start.offset.under = 0;
526 draw_context.drawinfo.end.offset.over = 0;
527 draw_context.drawinfo.end.offset.middle = 0;
528 draw_context.drawinfo.end.offset.under = 0;
529
530 {
531 /* Draw the line */
532 PropertiesLine prop_line = prepare_s_e_line(process);
533 draw_line((void*)&prop_line, (void*)&draw_context);
534
535 }
536 /* become the last x position */
537 hashed_process_data->x.middle = x;
538 hashed_process_data->x.middle_used = TRUE;
539 hashed_process_data->x.middle_marked = FALSE;
540 }
541 }
542 }
543 }
544
545 {
546 /* For the pid_in */
547 /* First, check if the current process is in the state computation
548 * process list. If it is there, that means we must add it right now and
549 * draw items from the beginning of the read for it. If it is not
550 * present, it's a new process and it was not present : it will
551 * be added after the state update. */
552 LttvProcessState *process;
553 process = lttv_state_find_process(tfs, pid_in);
554
555 if(process != NULL) {
556 /* Well, the process_out existed : we must get it in the process hash
557 * or add it, and draw its items.
558 */
559 /* Add process to process list (if not present) */
560 guint y = 0, height = 0, pl_height = 0;
561 HashedProcessData *hashed_process_data = NULL;
562 ProcessList *process_list = control_flow_data->process_list;
563 LttTime birth = process->creation_time;
564 const gchar *name = g_quark_to_string(process->name);
565
566 if(processlist_get_process_pixels(process_list,
567 pid_in,
568 process->last_cpu,
569 &birth,
570 tfc->t_context->index,
571 &y,
572 &height,
573 &hashed_process_data) == 1)
574 {
575 g_assert(pid_in == 0 || pid_in != process->ppid);
576 /* Process not present */
577 processlist_add(process_list,
578 pid_in,
579 process->last_cpu,
580 process->ppid,
581 &birth,
582 tfc->t_context->index,
583 name,
584 &pl_height,
585 &hashed_process_data);
586 processlist_get_process_pixels(process_list,
587 pid_in,
588 process->last_cpu,
589 &birth,
590 tfc->t_context->index,
591 &y,
592 &height,
593 &hashed_process_data);
594 drawing_insert_square( drawing, y, height);
595 }
596
597 /* Now, the process is in the state hash and our own process hash.
598 * We definitely can draw the items related to the ending state.
599 */
600
601 /* Check if the x position is unset. In can have been left unset by
602 * a draw closure from a after chunk hook. This should never happen,
603 * because it must be set by before chunk hook to the damage_begin
604 * value.
605 */
606 g_assert(hashed_process_data->x.middle != -1);
607 {
608 guint x;
609
610 convert_time_to_pixels(
611 time_window.start_time,
612 end_time,
613 evtime,
614 width,
615 &x);
616
617
618 /* Jump over draw if we are at the same x position */
619 if(x == hashed_process_data->x.middle &&
620 hashed_process_data->x.middle_used)
621 {
622 if(hashed_process_data->x.middle_marked == FALSE) {
623 /* Draw collision indicator */
624 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
625 gdk_draw_point(drawing->pixmap,
626 drawing->gc,
627 x,
628 y+(height/2)-3);
629 hashed_process_data->x.middle_marked = TRUE;
630 }
631 /* jump */
632 } else {
633 DrawContext draw_context;
634
635 /* Now create the drawing context that will be used to draw
636 * items related to the last state. */
637 draw_context.drawable = drawing->pixmap;
638 draw_context.gc = drawing->gc;
639 draw_context.pango_layout = drawing->pango_layout;
640 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
641 draw_context.drawinfo.end.x = x;
642
643 draw_context.drawinfo.y.over = y+1;
644 draw_context.drawinfo.y.middle = y+(height/2);
645 draw_context.drawinfo.y.under = y+height;
646
647 draw_context.drawinfo.start.offset.over = 0;
648 draw_context.drawinfo.start.offset.middle = 0;
649 draw_context.drawinfo.start.offset.under = 0;
650 draw_context.drawinfo.end.offset.over = 0;
651 draw_context.drawinfo.end.offset.middle = 0;
652 draw_context.drawinfo.end.offset.under = 0;
653
654 {
655 /* Draw the line */
656 PropertiesLine prop_line = prepare_s_e_line(process);
657 draw_line((void*)&prop_line, (void*)&draw_context);
658 }
659
660
661 /* become the last x position */
662 hashed_process_data->x.middle = x;
663 hashed_process_data->x.middle_used = TRUE;
664 hashed_process_data->x.middle_marked = FALSE;
665 }
666 }
667 }
668 }
669 return 0;
670
671
672 #if 0
673 EventsRequest *events_request = (EventsRequest*)hook_data;
674 ControlFlowData *control_flow_data =
675 (ControlFlowData*)events_request->viewer_data;
676 Tab *tab = control_flow_data->tab;
677
678 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
679
680 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
681 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
682
683 LttEvent *e;
684 e = tfc->e;
685
686 LttTime evtime = ltt_event_time(e);
687 TimeWindow time_window =
688 lttvwindow_get_time_window(tab);
689
690 LttTime end_time = ltt_time_add(time_window.start_time,
691 time_window.time_width);
692 //if(time < time_beg || time > time_end) return;
693 if(ltt_time_compare(evtime, time_window.start_time) == -1
694 || ltt_time_compare(evtime, end_time) == 1)
695 return;
696
697 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
698 {
699 g_debug("schedchange!");
700
701 /* Add process to process list (if not present) and get drawing "y" from
702 * process position */
703 guint pid_out, pid_in;
704 LttvProcessState *process_out, *process_in;
705 LttTime birth;
706 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
707
708 ProcessList *process_list = control_flow_data->process_list;
709
710
711 LttField *f = ltt_event_field(e);
712 LttField *element;
713 element = ltt_field_member(f,0);
714 pid_out = ltt_event_get_long_unsigned(e,element);
715 element = ltt_field_member(f,1);
716 pid_in = ltt_event_get_long_unsigned(e,element);
717 g_debug("out : %u in : %u", pid_out, pid_in);
718
719
720 /* Find process pid_out in the list... */
721 process_out = lttv_state_find_process(tfs, pid_out);
722 if(process_out == NULL) return 0;
723 g_debug("out : %s",g_quark_to_string(process_out->state->s));
724
725 birth = process_out->creation_time;
726 const gchar *name = g_quark_to_string(process_out->name);
727 HashedProcessData *hashed_process_data_out = NULL;
728
729 if(processlist_get_process_pixels(process_list,
730 pid_out,
731 &birth,
732 tfc->t_context->index,
733 &y_out,
734 &height,
735 &hashed_process_data_out) == 1)
736 {
737 /* Process not present */
738 processlist_add(process_list,
739 pid_out,
740 &birth,
741 tfc->t_context->index,
742 name,
743 &pl_height,
744 &hashed_process_data_out);
745 g_assert(processlist_get_process_pixels(process_list,
746 pid_out,
747 &birth,
748 tfc->t_context->index,
749 &y_out,
750 &height,
751 &hashed_process_data_out)==0);
752 drawing_insert_square( control_flow_data->drawing, y_out, height);
753 }
754 //g_free(name);
755
756 /* Find process pid_in in the list... */
757 process_in = lttv_state_find_process(tfs, pid_in);
758 if(process_in == NULL) return 0;
759 g_debug("in : %s",g_quark_to_string(process_in->state->s));
760
761 birth = process_in->creation_time;
762 name = g_quark_to_string(process_in->name);
763 HashedProcessData *hashed_process_data_in = NULL;
764
765 if(processlist_get_process_pixels(process_list,
766 pid_in,
767 &birth,
768 tfc->t_context->index,
769 &y_in,
770 &height,
771 &hashed_process_data_in) == 1)
772 {
773 /* Process not present */
774 processlist_add(process_list,
775 pid_in,
776 &birth,
777 tfc->t_context->index,
778 name,
779 &pl_height,
780 &hashed_process_data_in);
781 processlist_get_process_pixels(process_list,
782 pid_in,
783 &birth,
784 tfc->t_context->index,
785 &y_in,
786 &height,
787 &hashed_process_data_in);
788
789 drawing_insert_square( control_flow_data->drawing, y_in, height);
790 }
791 //g_free(name);
792
793
794 /* Find pixels corresponding to time of the event. If the time does
795 * not fit in the window, show a warning, not supposed to happend. */
796 guint x = 0;
797 guint width = control_flow_data->drawing->width;
798
799 LttTime time = ltt_event_time(e);
800
801 LttTime window_end = ltt_time_add(time_window.time_width,
802 time_window.start_time);
803
804
805 convert_time_to_pixels(
806 time_window.start_time,
807 window_end,
808 time,
809 width,
810 &x);
811 //assert(x <= width);
812 //
813 /* draw what represents the event for outgoing process. */
814
815 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
816 draw_context_out->current->modify_over->x = x;
817 draw_context_out->current->modify_under->x = x;
818 draw_context_out->current->modify_over->y = y_out;
819 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
820 draw_context_out->drawable = control_flow_data->drawing->pixmap;
821 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
822 GtkWidget *widget = control_flow_data->drawing->drawing_area;
823 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
824 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
825 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
826 //draw_context_out->gc = widget->style->black_gc;
827
828 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
829 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
830
831 /* Draw the line/background of the out process */
832 if(draw_context_out->previous->middle->x == -1)
833 {
834 draw_context_out->previous->over->x =
835 control_flow_data->drawing->damage_begin;
836 draw_context_out->previous->middle->x =
837 control_flow_data->drawing->damage_begin;
838 draw_context_out->previous->under->x =
839 control_flow_data->drawing->damage_begin;
840
841 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
842 }
843
844 draw_context_out->current->middle->x = x;
845 draw_context_out->current->over->x = x;
846 draw_context_out->current->under->x = x;
847 draw_context_out->current->middle->y = y_out + height/2;
848 draw_context_out->current->over->y = y_out;
849 draw_context_out->current->under->y = y_out + height;
850 draw_context_out->previous->middle->y = y_out + height/2;
851 draw_context_out->previous->over->y = y_out;
852 draw_context_out->previous->under->y = y_out + height;
853
854 draw_context_out->drawable = control_flow_data->drawing->pixmap;
855 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
856
857 if(process_out->state->s == LTTV_STATE_RUN)
858 {
859 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
860 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
861 draw_context_out->gc = control_flow_data->drawing->gc;
862
863 PropertiesBG prop_bg;
864 prop_bg.color = g_new(GdkColor,1);
865
866 switch(tfc->index) {
867 case 0:
868 prop_bg.color->red = 0x1515;
869 prop_bg.color->green = 0x1515;
870 prop_bg.color->blue = 0x8c8c;
871 break;
872 case 1:
873 prop_bg.color->red = 0x4e4e;
874 prop_bg.color->green = 0xa9a9;
875 prop_bg.color->blue = 0xa4a4;
876 break;
877 case 2:
878 prop_bg.color->red = 0x7a7a;
879 prop_bg.color->green = 0x4a4a;
880 prop_bg.color->blue = 0x8b8b;
881 break;
882 case 3:
883 prop_bg.color->red = 0x8080;
884 prop_bg.color->green = 0x7777;
885 prop_bg.color->blue = 0x4747;
886 break;
887 default:
888 prop_bg.color->red = 0xe7e7;
889 prop_bg.color->green = 0xe7e7;
890 prop_bg.color->blue = 0xe7e7;
891 }
892
893 g_debug("calling from draw_event");
894 draw_bg((void*)&prop_bg, (void*)draw_context_out);
895 g_free(prop_bg.color);
896 //gdk_gc_unref(draw_context_out->gc);
897 }
898
899 draw_context_out->gc = widget->style->black_gc;
900
901 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
902 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
903 PropertiesText prop_text_out;
904 prop_text_out.foreground = &colorfg_out;
905 prop_text_out.background = &colorbg_out;
906 prop_text_out.size = 6;
907 prop_text_out.position = OVER;
908
909 /* color of text : status of the process */
910 if(process_out->state->s == LTTV_STATE_UNNAMED)
911 {
912 prop_text_out.foreground->red = 0xffff;
913 prop_text_out.foreground->green = 0xffff;
914 prop_text_out.foreground->blue = 0xffff;
915 }
916 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
917 {
918 prop_text_out.foreground->red = 0x0fff;
919 prop_text_out.foreground->green = 0xffff;
920 prop_text_out.foreground->blue = 0xfff0;
921 }
922 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
923 {
924 prop_text_out.foreground->red = 0xffff;
925 prop_text_out.foreground->green = 0xffff;
926 prop_text_out.foreground->blue = 0x0000;
927 }
928 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
929 {
930 prop_text_out.foreground->red = 0xffff;
931 prop_text_out.foreground->green = 0x0000;
932 prop_text_out.foreground->blue = 0xffff;
933 }
934 else if(process_out->state->s == LTTV_STATE_WAIT)
935 {
936 prop_text_out.foreground->red = 0xffff;
937 prop_text_out.foreground->green = 0x0000;
938 prop_text_out.foreground->blue = 0x0000;
939 }
940 else if(process_out->state->s == LTTV_STATE_RUN)
941 {
942 prop_text_out.foreground->red = 0x0000;
943 prop_text_out.foreground->green = 0xffff;
944 prop_text_out.foreground->blue = 0x0000;
945 }
946 else
947 {
948 prop_text_out.foreground->red = 0xffff;
949 prop_text_out.foreground->green = 0xffff;
950 prop_text_out.foreground->blue = 0xffff;
951 }
952
953
954 /* Print status of the process : U, WF, WC, E, W, R */
955 if(process_out->state->s == LTTV_STATE_UNNAMED)
956 prop_text_out.text = "U->";
957 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
958 prop_text_out.text = "WF->";
959 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
960 prop_text_out.text = "WC->";
961 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
962 prop_text_out.text = "E->";
963 else if(process_out->state->s == LTTV_STATE_WAIT)
964 prop_text_out.text = "W->";
965 else if(process_out->state->s == LTTV_STATE_RUN)
966 prop_text_out.text = "R->";
967 else
968 prop_text_out.text = "U";
969
970 draw_text((void*)&prop_text_out, (void*)draw_context_out);
971 //gdk_gc_unref(draw_context_out->gc);
972
973 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
974 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
975 draw_context_out->gc = control_flow_data->drawing->gc;
976
977 PropertiesLine prop_line_out;
978 prop_line_out.color = g_new(GdkColor,1);
979 prop_line_out.line_width = 2;
980 prop_line_out.style = GDK_LINE_SOLID;
981 prop_line_out.position = MIDDLE;
982
983 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
984
985 /* color of line : status of the process */
986 if(process_out->state->s == LTTV_STATE_UNNAMED)
987 {
988 prop_line_out.color->red = 0xffff;
989 prop_line_out.color->green = 0xffff;
990 prop_line_out.color->blue = 0xffff;
991 }
992 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
993 {
994 prop_line_out.color->red = 0x0fff;
995 prop_line_out.color->green = 0xffff;
996 prop_line_out.color->blue = 0xfff0;
997 }
998 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
999 {
1000 prop_line_out.color->red = 0xffff;
1001 prop_line_out.color->green = 0xffff;
1002 prop_line_out.color->blue = 0x0000;
1003 }
1004 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1005 {
1006 prop_line_out.color->red = 0xffff;
1007 prop_line_out.color->green = 0x0000;
1008 prop_line_out.color->blue = 0xffff;
1009 }
1010 else if(process_out->state->s == LTTV_STATE_WAIT)
1011 {
1012 prop_line_out.color->red = 0xffff;
1013 prop_line_out.color->green = 0x0000;
1014 prop_line_out.color->blue = 0x0000;
1015 }
1016 else if(process_out->state->s == LTTV_STATE_RUN)
1017 {
1018 prop_line_out.color->red = 0x0000;
1019 prop_line_out.color->green = 0xffff;
1020 prop_line_out.color->blue = 0x0000;
1021 }
1022 else
1023 {
1024 prop_line_out.color->red = 0xffff;
1025 prop_line_out.color->green = 0xffff;
1026 prop_line_out.color->blue = 0xffff;
1027 }
1028
1029 draw_line((void*)&prop_line_out, (void*)draw_context_out);
1030 g_free(prop_line_out.color);
1031 //gdk_gc_unref(draw_context_out->gc);
1032 /* Note : finishing line will have to be added when trace read over. */
1033
1034 /* Finally, update the drawing context of the pid_in. */
1035
1036 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1037 draw_context_in->current->modify_over->x = x;
1038 draw_context_in->current->modify_under->x = x;
1039 draw_context_in->current->modify_over->y = y_in;
1040 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1041 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1042 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1043 widget = control_flow_data->drawing->drawing_area;
1044 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1045 //draw_context_in->gc = widget->style->black_gc;
1046 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1047 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1048
1049 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1050 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1051
1052 /* Draw the line/bg of the in process */
1053 if(draw_context_in->previous->middle->x == -1)
1054 {
1055 draw_context_in->previous->over->x =
1056 control_flow_data->drawing->damage_begin;
1057 draw_context_in->previous->middle->x =
1058 control_flow_data->drawing->damage_begin;
1059 draw_context_in->previous->under->x =
1060 control_flow_data->drawing->damage_begin;
1061
1062 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
1063
1064 }
1065
1066 draw_context_in->current->middle->x = x;
1067 draw_context_in->current->over->x = x;
1068 draw_context_in->current->under->x = x;
1069 draw_context_in->current->middle->y = y_in + height/2;
1070 draw_context_in->current->over->y = y_in;
1071 draw_context_in->current->under->y = y_in + height;
1072 draw_context_in->previous->middle->y = y_in + height/2;
1073 draw_context_in->previous->over->y = y_in;
1074 draw_context_in->previous->under->y = y_in + height;
1075
1076 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1077 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1078
1079
1080 if(process_in->state->s == LTTV_STATE_RUN)
1081 {
1082 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1083 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1084 draw_context_in->gc = control_flow_data->drawing->gc;
1085
1086 PropertiesBG prop_bg;
1087 prop_bg.color = g_new(GdkColor,1);
1088
1089 switch(tfc->index) {
1090 case 0:
1091 prop_bg.color->red = 0x1515;
1092 prop_bg.color->green = 0x1515;
1093 prop_bg.color->blue = 0x8c8c;
1094 break;
1095 case 1:
1096 prop_bg.color->red = 0x4e4e;
1097 prop_bg.color->green = 0xa9a9;
1098 prop_bg.color->blue = 0xa4a4;
1099 break;
1100 case 2:
1101 prop_bg.color->red = 0x7a7a;
1102 prop_bg.color->green = 0x4a4a;
1103 prop_bg.color->blue = 0x8b8b;
1104 break;
1105 case 3:
1106 prop_bg.color->red = 0x8080;
1107 prop_bg.color->green = 0x7777;
1108 prop_bg.color->blue = 0x4747;
1109 break;
1110 default:
1111 prop_bg.color->red = 0xe7e7;
1112 prop_bg.color->green = 0xe7e7;
1113 prop_bg.color->blue = 0xe7e7;
1114 }
1115
1116
1117 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1118 g_free(prop_bg.color);
1119 //gdk_gc_unref(draw_context_in->gc);
1120 }
1121
1122 draw_context_in->gc = widget->style->black_gc;
1123
1124 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1125 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1126 PropertiesText prop_text_in;
1127 prop_text_in.foreground = &colorfg_in;
1128 prop_text_in.background = &colorbg_in;
1129 prop_text_in.size = 6;
1130 prop_text_in.position = OVER;
1131
1132 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1133 /* foreground of text : status of the process */
1134 if(process_in->state->s == LTTV_STATE_UNNAMED)
1135 {
1136 prop_text_in.foreground->red = 0xffff;
1137 prop_text_in.foreground->green = 0xffff;
1138 prop_text_in.foreground->blue = 0xffff;
1139 }
1140 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1141 {
1142 prop_text_in.foreground->red = 0x0fff;
1143 prop_text_in.foreground->green = 0xffff;
1144 prop_text_in.foreground->blue = 0xfff0;
1145 }
1146 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1147 {
1148 prop_text_in.foreground->red = 0xffff;
1149 prop_text_in.foreground->green = 0xffff;
1150 prop_text_in.foreground->blue = 0x0000;
1151 }
1152 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1153 {
1154 prop_text_in.foreground->red = 0xffff;
1155 prop_text_in.foreground->green = 0x0000;
1156 prop_text_in.foreground->blue = 0xffff;
1157 }
1158 else if(process_in->state->s == LTTV_STATE_WAIT)
1159 {
1160 prop_text_in.foreground->red = 0xffff;
1161 prop_text_in.foreground->green = 0x0000;
1162 prop_text_in.foreground->blue = 0x0000;
1163 }
1164 else if(process_in->state->s == LTTV_STATE_RUN)
1165 {
1166 prop_text_in.foreground->red = 0x0000;
1167 prop_text_in.foreground->green = 0xffff;
1168 prop_text_in.foreground->blue = 0x0000;
1169 }
1170 else
1171 {
1172 prop_text_in.foreground->red = 0xffff;
1173 prop_text_in.foreground->green = 0xffff;
1174 prop_text_in.foreground->blue = 0xffff;
1175 }
1176
1177
1178
1179 /* Print status of the process : U, WF, WC, E, W, R */
1180 if(process_in->state->s == LTTV_STATE_UNNAMED)
1181 prop_text_in.text = "U->";
1182 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1183 prop_text_in.text = "WF->";
1184 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1185 prop_text_in.text = "WC->";
1186 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1187 prop_text_in.text = "E->";
1188 else if(process_in->state->s == LTTV_STATE_WAIT)
1189 prop_text_in.text = "W->";
1190 else if(process_in->state->s == LTTV_STATE_RUN)
1191 prop_text_in.text = "R->";
1192 else
1193 prop_text_in.text = "U";
1194
1195 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1196 //gdk_gc_unref(draw_context_in->gc);
1197
1198 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1199 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1200 draw_context_in->gc = control_flow_data->drawing->gc;
1201
1202 PropertiesLine prop_line_in;
1203 prop_line_in.color = g_new(GdkColor,1);
1204 prop_line_in.line_width = 2;
1205 prop_line_in.style = GDK_LINE_SOLID;
1206 prop_line_in.position = MIDDLE;
1207
1208 /* color of line : status of the process */
1209 if(process_in->state->s == LTTV_STATE_UNNAMED)
1210 {
1211 prop_line_in.color->red = 0xffff;
1212 prop_line_in.color->green = 0xffff;
1213 prop_line_in.color->blue = 0xffff;
1214 }
1215 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1216 {
1217 prop_line_in.color->red = 0x0fff;
1218 prop_line_in.color->green = 0xffff;
1219 prop_line_in.color->blue = 0xfff0;
1220 }
1221 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1222 {
1223 prop_line_in.color->red = 0xffff;
1224 prop_line_in.color->green = 0xffff;
1225 prop_line_in.color->blue = 0x0000;
1226 }
1227 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1228 {
1229 prop_line_in.color->red = 0xffff;
1230 prop_line_in.color->green = 0x0000;
1231 prop_line_in.color->blue = 0xffff;
1232 }
1233 else if(process_in->state->s == LTTV_STATE_WAIT)
1234 {
1235 prop_line_in.color->red = 0xffff;
1236 prop_line_in.color->green = 0x0000;
1237 prop_line_in.color->blue = 0x0000;
1238 }
1239 else if(process_in->state->s == LTTV_STATE_RUN)
1240 {
1241 prop_line_in.color->red = 0x0000;
1242 prop_line_in.color->green = 0xffff;
1243 prop_line_in.color->blue = 0x0000;
1244 }
1245 else
1246 {
1247 prop_line_in.color->red = 0xffff;
1248 prop_line_in.color->green = 0xffff;
1249 prop_line_in.color->blue = 0xffff;
1250 }
1251
1252 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1253 g_free(prop_line_in.color);
1254 //gdk_gc_unref(draw_context_in->gc);
1255 }
1256
1257 return 0;
1258 #endif //0
1259
1260
1261
1262 /* Text dump */
1263 #ifdef DONTSHOW
1264 GString *string = g_string_new("");;
1265 gboolean field_names = TRUE, state = TRUE;
1266
1267 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1268 g_string_append_printf(string,"\n");
1269
1270 if(state) {
1271 g_string_append_printf(string, " %s",
1272 g_quark_to_string(tfs->process->state->s));
1273 }
1274
1275 g_info("%s",string->str);
1276
1277 g_string_free(string, TRUE);
1278
1279 /* End of text dump */
1280 #endif //DONTSHOW
1281
1282 }
1283
1284 /* after_schedchange_hook
1285 *
1286 * The draw after hook is called by the reading API to have a
1287 * particular event drawn on the screen.
1288 * @param hook_data ControlFlowData structure of the viewer.
1289 * @param call_data Event context.
1290 *
1291 * This function adds items to be drawn in a queue for each process.
1292 *
1293 */
1294 int after_schedchange_hook(void *hook_data, void *call_data)
1295 {
1296 EventsRequest *events_request = (EventsRequest*)hook_data;
1297 ControlFlowData *control_flow_data = events_request->viewer_data;
1298
1299 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1300
1301 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1302 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1303
1304 LttEvent *e;
1305 e = tfc->e;
1306
1307 LttTime evtime = ltt_event_time(e);
1308 TimeWindow time_window =
1309 lttvwindow_get_time_window(control_flow_data->tab);
1310
1311 LttTime end_time = ltt_time_add(time_window.start_time,
1312 time_window.time_width);
1313
1314 if(ltt_time_compare(evtime, time_window.start_time) == -1
1315 || ltt_time_compare(evtime, end_time) == 1)
1316 return;
1317
1318 guint width = control_flow_data->drawing->width;
1319
1320 /* Add process to process list (if not present) */
1321 LttvProcessState *process_out, *process_in;
1322 LttTime birth;
1323 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1324 HashedProcessData *hashed_process_data_in = NULL;
1325
1326 ProcessList *process_list = control_flow_data->process_list;
1327
1328 guint pid_in;
1329 {
1330 guint pid_out;
1331 LttField *f = ltt_event_field(e);
1332 LttField *element;
1333 element = ltt_field_member(f,0);
1334 pid_out = ltt_event_get_long_unsigned(e,element);
1335 element = ltt_field_member(f,1);
1336 pid_in = ltt_event_get_long_unsigned(e,element);
1337 g_debug("out : %u in : %u", pid_out, pid_in);
1338 }
1339
1340
1341 /* Find process pid_in in the list... */
1342 process_in = lttv_state_find_process(tfs, pid_in);
1343 /* It should exist, because we are after the state update. */
1344 g_assert(process_in != NULL);
1345
1346 birth = process_in->creation_time;
1347 const gchar *name = g_quark_to_string(process_in->name);
1348
1349 if(processlist_get_process_pixels(process_list,
1350 pid_in,
1351 process_in->last_cpu,
1352 &birth,
1353 tfc->t_context->index,
1354 &y_in,
1355 &height,
1356 &hashed_process_data_in) == 1)
1357 {
1358 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1359 /* Process not present */
1360 processlist_add(process_list,
1361 pid_in,
1362 process_in->last_cpu,
1363 process_in->ppid,
1364 &birth,
1365 tfc->t_context->index,
1366 name,
1367 &pl_height,
1368 &hashed_process_data_in);
1369 processlist_get_process_pixels(process_list,
1370 pid_in,
1371 process_in->last_cpu,
1372 &birth,
1373 tfc->t_context->index,
1374 &y_in,
1375 &height,
1376 &hashed_process_data_in);
1377 drawing_insert_square( control_flow_data->drawing, y_in, height);
1378 }
1379
1380 guint new_x;
1381
1382 convert_time_to_pixels(
1383 time_window.start_time,
1384 end_time,
1385 evtime,
1386 width,
1387 &new_x);
1388
1389 if(hashed_process_data_in->x.middle != new_x) {
1390 hashed_process_data_in->x.middle = new_x;
1391 hashed_process_data_in->x.middle_used = FALSE;
1392 hashed_process_data_in->x.middle_marked = FALSE;
1393 }
1394
1395 return 0;
1396
1397
1398
1399
1400
1401 #if 0
1402 EventsRequest *events_request = (EventsRequest*)hook_data;
1403 ControlFlowData *control_flow_data = events_request->viewer_data;
1404
1405 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1406
1407 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1408 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1409
1410
1411 LttEvent *e;
1412 e = tfc->e;
1413
1414 LttTime evtime = ltt_event_time(e);
1415 TimeWindow time_window =
1416 lttvwindow_get_time_window(control_flow_data->tab);
1417
1418 LttTime end_time = ltt_time_add(time_window.start_time,
1419 time_window.time_width);
1420 //if(time < time_beg || time > time_end) return;
1421 if(ltt_time_compare(evtime, time_window.start_time) == -1
1422 || ltt_time_compare(evtime, end_time) == 1)
1423 return;
1424
1425
1426 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1427 {
1428 g_debug("schedchange!");
1429
1430 /* Add process to process list (if not present) and get drawing "y" from
1431 * process position */
1432 guint pid_out, pid_in;
1433 LttvProcessState *process_out, *process_in;
1434 LttTime birth;
1435 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1436
1437 ProcessList *process_list = control_flow_data->process_list;
1438
1439
1440 LttField *f = ltt_event_field(e);
1441 LttField *element;
1442 element = ltt_field_member(f,0);
1443 pid_out = ltt_event_get_long_unsigned(e,element);
1444 element = ltt_field_member(f,1);
1445 pid_in = ltt_event_get_long_unsigned(e,element);
1446 //g_debug("out : %u in : %u", pid_out, pid_in);
1447
1448
1449 /* Find process pid_out in the list... */
1450 process_out = lttv_state_find_process(tfs, pid_out);
1451 if(process_out == NULL) return 0;
1452 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1453
1454 birth = process_out->creation_time;
1455 gchar *name = strdup(g_quark_to_string(process_out->name));
1456 HashedProcessData *hashed_process_data_out = NULL;
1457
1458 if(processlist_get_process_pixels(process_list,
1459 pid_out,
1460 &birth,
1461 tfc->t_context->index,
1462 &y_out,
1463 &height,
1464 &hashed_process_data_out) == 1)
1465 {
1466 /* Process not present */
1467 processlist_add(process_list,
1468 pid_out,
1469 &birth,
1470 tfc->t_context->index,
1471 name,
1472 &pl_height,
1473 &hashed_process_data_out);
1474 processlist_get_process_pixels(process_list,
1475 pid_out,
1476 &birth,
1477 tfc->t_context->index,
1478 &y_out,
1479 &height,
1480 &hashed_process_data_out);
1481 drawing_insert_square( control_flow_data->drawing, y_out, height);
1482 }
1483
1484 g_free(name);
1485
1486 /* Find process pid_in in the list... */
1487 process_in = lttv_state_find_process(tfs, pid_in);
1488 if(process_in == NULL) return 0;
1489 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1490
1491 birth = process_in->creation_time;
1492 name = strdup(g_quark_to_string(process_in->name));
1493 HashedProcessData *hashed_process_data_in = NULL;
1494
1495 if(processlist_get_process_pixels(process_list,
1496 pid_in,
1497 &birth,
1498 tfc->t_context->index,
1499 &y_in,
1500 &height,
1501 &hashed_process_data_in) == 1)
1502 {
1503 /* Process not present */
1504 processlist_add(process_list,
1505 pid_in,
1506 &birth,
1507 tfc->t_context->index,
1508 name,
1509 &pl_height,
1510 &hashed_process_data_in);
1511 processlist_get_process_pixels(process_list,
1512 pid_in,
1513 &birth,
1514 tfc->t_context->index,
1515 &y_in,
1516 &height,
1517 &hashed_process_data_in);
1518
1519 drawing_insert_square( control_flow_data->drawing, y_in, height);
1520 }
1521 g_free(name);
1522
1523
1524 /* Find pixels corresponding to time of the event. If the time does
1525 * not fit in the window, show a warning, not supposed to happend. */
1526 //guint x = 0;
1527 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1528
1529 //LttTime time = ltt_event_time(e);
1530
1531 //LttTime window_end = ltt_time_add(time_window->time_width,
1532 // time_window->start_time);
1533
1534
1535 //convert_time_to_pixels(
1536 // time_window->start_time,
1537 // window_end,
1538 // time,
1539 // width,
1540 // &x);
1541
1542 //assert(x <= width);
1543
1544 /* draw what represents the event for outgoing process. */
1545
1546 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1547 //draw_context_out->current->modify_over->x = x;
1548 draw_context_out->current->modify_over->y = y_out;
1549 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1550 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1551 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1552 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1553 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1554
1555 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1556 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1557
1558 /*if(process_out->state->s == LTTV_STATE_RUN)
1559 {
1560 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1561 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1562 PropertiesBG prop_bg;
1563 prop_bg.color = g_new(GdkColor,1);
1564
1565 prop_bg.color->red = 0xffff;
1566 prop_bg.color->green = 0xffff;
1567 prop_bg.color->blue = 0xffff;
1568
1569 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1570 g_free(prop_bg.color);
1571 gdk_gc_unref(draw_context_out->gc);
1572 }*/
1573
1574 draw_context_out->gc = widget->style->black_gc;
1575
1576 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1577 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1578 PropertiesText prop_text_out;
1579 prop_text_out.foreground = &colorfg_out;
1580 prop_text_out.background = &colorbg_out;
1581 prop_text_out.size = 6;
1582 prop_text_out.position = OVER;
1583
1584 /* color of text : status of the process */
1585 if(process_out->state->s == LTTV_STATE_UNNAMED)
1586 {
1587 prop_text_out.foreground->red = 0xffff;
1588 prop_text_out.foreground->green = 0xffff;
1589 prop_text_out.foreground->blue = 0xffff;
1590 }
1591 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1592 {
1593 prop_text_out.foreground->red = 0x0fff;
1594 prop_text_out.foreground->green = 0xffff;
1595 prop_text_out.foreground->blue = 0xfff0;
1596 }
1597 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1598 {
1599 prop_text_out.foreground->red = 0xffff;
1600 prop_text_out.foreground->green = 0xffff;
1601 prop_text_out.foreground->blue = 0x0000;
1602 }
1603 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1604 {
1605 prop_text_out.foreground->red = 0xffff;
1606 prop_text_out.foreground->green = 0x0000;
1607 prop_text_out.foreground->blue = 0xffff;
1608 }
1609 else if(process_out->state->s == LTTV_STATE_WAIT)
1610 {
1611 prop_text_out.foreground->red = 0xffff;
1612 prop_text_out.foreground->green = 0x0000;
1613 prop_text_out.foreground->blue = 0x0000;
1614 }
1615 else if(process_out->state->s == LTTV_STATE_RUN)
1616 {
1617 prop_text_out.foreground->red = 0x0000;
1618 prop_text_out.foreground->green = 0xffff;
1619 prop_text_out.foreground->blue = 0x0000;
1620 }
1621 else
1622 {
1623 prop_text_out.foreground->red = 0xffff;
1624 prop_text_out.foreground->green = 0xffff;
1625 prop_text_out.foreground->blue = 0xffff;
1626 }
1627
1628 /* Print status of the process : U, WF, WC, E, W, R */
1629 if(process_out->state->s == LTTV_STATE_UNNAMED)
1630 prop_text_out.text = "U";
1631 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1632 prop_text_out.text = "WF";
1633 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1634 prop_text_out.text = "WC";
1635 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1636 prop_text_out.text = "E";
1637 else if(process_out->state->s == LTTV_STATE_WAIT)
1638 prop_text_out.text = "W";
1639 else if(process_out->state->s == LTTV_STATE_RUN)
1640 prop_text_out.text = "R";
1641 else
1642 prop_text_out.text = "U";
1643
1644 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1645
1646 //gdk_gc_unref(draw_context_out->gc);
1647
1648 draw_context_out->current->middle->y = y_out+height/2;
1649 draw_context_out->current->over->y = y_out;
1650 draw_context_out->current->under->y = y_out+height;
1651 draw_context_out->current->status = process_out->state->s;
1652
1653 /* for pid_out : remove previous, Prev = current, new current (default) */
1654 g_free(draw_context_out->previous->modify_under);
1655 g_free(draw_context_out->previous->modify_middle);
1656 g_free(draw_context_out->previous->modify_over);
1657 g_free(draw_context_out->previous->under);
1658 g_free(draw_context_out->previous->middle);
1659 g_free(draw_context_out->previous->over);
1660 g_free(draw_context_out->previous);
1661
1662 draw_context_out->previous = draw_context_out->current;
1663
1664 draw_context_out->current = g_new(DrawInfo,1);
1665 draw_context_out->current->over = g_new(ItemInfo,1);
1666 draw_context_out->current->over->x = -1;
1667 draw_context_out->current->over->y = -1;
1668 draw_context_out->current->middle = g_new(ItemInfo,1);
1669 draw_context_out->current->middle->x = -1;
1670 draw_context_out->current->middle->y = -1;
1671 draw_context_out->current->under = g_new(ItemInfo,1);
1672 draw_context_out->current->under->x = -1;
1673 draw_context_out->current->under->y = -1;
1674 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1675 draw_context_out->current->modify_over->x = -1;
1676 draw_context_out->current->modify_over->y = -1;
1677 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1678 draw_context_out->current->modify_middle->x = -1;
1679 draw_context_out->current->modify_middle->y = -1;
1680 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1681 draw_context_out->current->modify_under->x = -1;
1682 draw_context_out->current->modify_under->y = -1;
1683 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1684
1685 /* Finally, update the drawing context of the pid_in. */
1686
1687 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1688 //draw_context_in->current->modify_over->x = x;
1689 draw_context_in->current->modify_over->y = y_in;
1690 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1691 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1692 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1693 widget = control_flow_data->drawing->drawing_area;
1694 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1695
1696 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1697 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1698
1699 /*if(process_in->state->s == LTTV_STATE_RUN)
1700 {
1701 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1702 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1703 PropertiesBG prop_bg;
1704 prop_bg.color = g_new(GdkColor,1);
1705
1706 prop_bg.color->red = 0xffff;
1707 prop_bg.color->green = 0xffff;
1708 prop_bg.color->blue = 0xffff;
1709
1710 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1711 g_free(prop_bg.color);
1712 gdk_gc_unref(draw_context_in->gc);
1713 }*/
1714
1715 draw_context_in->gc = widget->style->black_gc;
1716
1717 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1718 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1719 PropertiesText prop_text_in;
1720 prop_text_in.foreground = &colorfg_in;
1721 prop_text_in.background = &colorbg_in;
1722 prop_text_in.size = 6;
1723 prop_text_in.position = OVER;
1724
1725 /* foreground of text : status of the process */
1726 if(process_in->state->s == LTTV_STATE_UNNAMED)
1727 {
1728 prop_text_in.foreground->red = 0xffff;
1729 prop_text_in.foreground->green = 0xffff;
1730 prop_text_in.foreground->blue = 0xffff;
1731 }
1732 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1733 {
1734 prop_text_in.foreground->red = 0x0fff;
1735 prop_text_in.foreground->green = 0xffff;
1736 prop_text_in.foreground->blue = 0xfff0;
1737 }
1738 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1739 {
1740 prop_text_in.foreground->red = 0xffff;
1741 prop_text_in.foreground->green = 0xffff;
1742 prop_text_in.foreground->blue = 0x0000;
1743 }
1744 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1745 {
1746 prop_text_in.foreground->red = 0xffff;
1747 prop_text_in.foreground->green = 0x0000;
1748 prop_text_in.foreground->blue = 0xffff;
1749 }
1750 else if(process_in->state->s == LTTV_STATE_WAIT)
1751 {
1752 prop_text_in.foreground->red = 0xffff;
1753 prop_text_in.foreground->green = 0x0000;
1754 prop_text_in.foreground->blue = 0x0000;
1755 }
1756 else if(process_in->state->s == LTTV_STATE_RUN)
1757 {
1758 prop_text_in.foreground->red = 0x0000;
1759 prop_text_in.foreground->green = 0xffff;
1760 prop_text_in.foreground->blue = 0x0000;
1761 }
1762 else
1763 {
1764 prop_text_in.foreground->red = 0xffff;
1765 prop_text_in.foreground->green = 0xffff;
1766 prop_text_in.foreground->blue = 0xffff;
1767 }
1768
1769
1770 /* Print status of the process : U, WF, WC, E, W, R */
1771 if(process_in->state->s == LTTV_STATE_UNNAMED)
1772 prop_text_in.text = "U";
1773 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1774 prop_text_in.text = "WF";
1775 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1776 prop_text_in.text = "WC";
1777 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1778 prop_text_in.text = "E";
1779 else if(process_in->state->s == LTTV_STATE_WAIT)
1780 prop_text_in.text = "W";
1781 else if(process_in->state->s == LTTV_STATE_RUN)
1782 prop_text_in.text = "R";
1783 else
1784 prop_text_in.text = "U";
1785
1786 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1787
1788
1789 if(process_in->state->s == LTTV_STATE_RUN)
1790 {
1791 gchar tmp[255];
1792 prop_text_in.foreground = &colorfg_in;
1793 prop_text_in.background = &colorbg_in;
1794 prop_text_in.foreground->red = 0xffff;
1795 prop_text_in.foreground->green = 0xffff;
1796 prop_text_in.foreground->blue = 0xffff;
1797 prop_text_in.size = 6;
1798 prop_text_in.position = UNDER;
1799
1800 prop_text_in.text = g_new(gchar, 260);
1801 strcpy(prop_text_in.text, "CPU ");
1802 snprintf(tmp, 255, "%u", tfc->index);
1803 strcat(prop_text_in.text, tmp);
1804
1805 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1806 g_free(prop_text_in.text);
1807 }
1808
1809
1810 draw_context_in->current->middle->y = y_in+height/2;
1811 draw_context_in->current->over->y = y_in;
1812 draw_context_in->current->under->y = y_in+height;
1813 draw_context_in->current->status = process_in->state->s;
1814
1815 /* for pid_in : remove previous, Prev = current, new current (default) */
1816 g_free(draw_context_in->previous->modify_under);
1817 g_free(draw_context_in->previous->modify_middle);
1818 g_free(draw_context_in->previous->modify_over);
1819 g_free(draw_context_in->previous->under);
1820 g_free(draw_context_in->previous->middle);
1821 g_free(draw_context_in->previous->over);
1822 g_free(draw_context_in->previous);
1823
1824 draw_context_in->previous = draw_context_in->current;
1825
1826 draw_context_in->current = g_new(DrawInfo,1);
1827 draw_context_in->current->over = g_new(ItemInfo,1);
1828 draw_context_in->current->over->x = -1;
1829 draw_context_in->current->over->y = -1;
1830 draw_context_in->current->middle = g_new(ItemInfo,1);
1831 draw_context_in->current->middle->x = -1;
1832 draw_context_in->current->middle->y = -1;
1833 draw_context_in->current->under = g_new(ItemInfo,1);
1834 draw_context_in->current->under->x = -1;
1835 draw_context_in->current->under->y = -1;
1836 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1837 draw_context_in->current->modify_over->x = -1;
1838 draw_context_in->current->modify_over->y = -1;
1839 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1840 draw_context_in->current->modify_middle->x = -1;
1841 draw_context_in->current->modify_middle->y = -1;
1842 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1843 draw_context_in->current->modify_under->x = -1;
1844 draw_context_in->current->modify_under->y = -1;
1845 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1846
1847 }
1848
1849 return 0;
1850 #endif //0
1851 }
1852
1853 #if 0
1854 static __inline PropertiesLine prepare_execmode_line(LttvProcessState *process)
1855 {
1856 PropertiesLine prop_line;
1857 prop_line.line_width = 1;
1858 prop_line.style = GDK_LINE_SOLID;
1859 prop_line.y = OVER;
1860 //GdkColormap *colormap = gdk_colormap_get_system();
1861
1862 /* color of line : execution mode of the process */
1863 if(process->state->t == LTTV_STATE_USER_MODE)
1864 prop_line.color = drawing_colors[COL_USER_MODE];
1865 else if(process->state->t == LTTV_STATE_SYSCALL)
1866 prop_line.color = drawing_colors[COL_SYSCALL];
1867 else if(process->state->t == LTTV_STATE_TRAP)
1868 prop_line.color = drawing_colors[COL_TRAP];
1869 else if(process->state->t == LTTV_STATE_IRQ)
1870 prop_line.color = drawing_colors[COL_IRQ];
1871 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1872 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1873 else
1874 prop_line.color = drawing_colors[COL_WHITE];
1875
1876 //gdk_colormap_alloc_color(colormap,
1877 // prop_line.color,
1878 // FALSE,
1879 // TRUE);
1880
1881 return prop_line;
1882
1883 }
1884 #endif //0
1885
1886
1887 /* before_execmode_hook
1888 *
1889 * This function basically draw lines and icons. Two types of lines are drawn :
1890 * one small (3 pixels?) representing the state of the process and the second
1891 * type is thicker (10 pixels?) representing on which CPU a process is running
1892 * (and this only in running state).
1893 *
1894 * Extremums of the lines :
1895 * x_min : time of the last event context for this process kept in memory.
1896 * x_max : time of the current event.
1897 * y : middle of the process in the process list. The process is found in the
1898 * list, therefore is it's position in pixels.
1899 *
1900 * The choice of lines'color is defined by the context of the last event for this
1901 * process.
1902 */
1903
1904
1905 int before_execmode_hook(void *hook_data, void *call_data)
1906 {
1907 EventsRequest *events_request = (EventsRequest*)hook_data;
1908 ControlFlowData *control_flow_data = events_request->viewer_data;
1909 Drawing_t *drawing = control_flow_data->drawing;
1910
1911 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1912
1913 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1914 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1915
1916 LttEvent *e;
1917 e = tfc->e;
1918
1919 LttTime evtime = ltt_event_time(e);
1920 TimeWindow time_window =
1921 lttvwindow_get_time_window(control_flow_data->tab);
1922
1923 LttTime end_time = ltt_time_add(time_window.start_time,
1924 time_window.time_width);
1925
1926 if(ltt_time_compare(evtime, time_window.start_time) == -1
1927 || ltt_time_compare(evtime, end_time) == 1)
1928 return;
1929
1930 guint width = drawing->width;
1931
1932 /* we are in a execmode, before the state update. We must draw the
1933 * items corresponding to the state before it changes : now is the right
1934 * time to do it.
1935 */
1936 /* For the pid */
1937 LttvProcessState *process = tfs->process;
1938 g_assert(process != NULL);
1939
1940 guint pid = process->pid;
1941
1942 /* Well, the process_out existed : we must get it in the process hash
1943 * or add it, and draw its items.
1944 */
1945 /* Add process to process list (if not present) */
1946 guint y = 0, height = 0, pl_height = 0;
1947 HashedProcessData *hashed_process_data = NULL;
1948 ProcessList *process_list = control_flow_data->process_list;
1949 LttTime birth = process->creation_time;
1950 const gchar *name = g_quark_to_string(process->name);
1951
1952 if(processlist_get_process_pixels(process_list,
1953 pid,
1954 process->last_cpu,
1955 &birth,
1956 tfc->t_context->index,
1957 &y,
1958 &height,
1959 &hashed_process_data) == 1)
1960 {
1961 g_assert(pid == 0 || pid != process->ppid);
1962 /* Process not present */
1963 processlist_add(process_list,
1964 pid,
1965 process->last_cpu,
1966 process->ppid,
1967 &birth,
1968 tfc->t_context->index,
1969 name,
1970 &pl_height,
1971 &hashed_process_data);
1972 processlist_get_process_pixels(process_list,
1973 pid,
1974 process->last_cpu,
1975 &birth,
1976 tfc->t_context->index,
1977 &y,
1978 &height,
1979 &hashed_process_data);
1980 drawing_insert_square( drawing, y, height);
1981 }
1982
1983 /* Now, the process is in the state hash and our own process hash.
1984 * We definitely can draw the items related to the ending state.
1985 */
1986
1987 /* Check if the x position is unset. In can have been left unset by
1988 * a draw closure from a after chunk hook. This should never happen,
1989 * because it must be set by before chunk hook to the damage_begin
1990 * value.
1991 */
1992 g_assert(hashed_process_data->x.over != -1);
1993 {
1994 guint x;
1995
1996 convert_time_to_pixels(
1997 time_window.start_time,
1998 end_time,
1999 evtime,
2000 width,
2001 &x);
2002
2003
2004 /* Jump over draw if we are at the same x position */
2005 if(x == hashed_process_data->x.middle &&
2006 hashed_process_data->x.middle_used)
2007 {
2008 if(hashed_process_data->x.middle_marked == FALSE) {
2009 /* Draw collision indicator */
2010 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2011 gdk_draw_point(drawing->pixmap,
2012 drawing->gc,
2013 x,
2014 y+(height/2)-3);
2015 hashed_process_data->x.middle_marked = TRUE;
2016 }
2017 /* jump */
2018 } else {
2019
2020 DrawContext draw_context;
2021 /* Now create the drawing context that will be used to draw
2022 * items related to the last state. */
2023 draw_context.drawable = drawing->pixmap;
2024 draw_context.gc = drawing->gc;
2025 draw_context.pango_layout = drawing->pango_layout;
2026 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2027 draw_context.drawinfo.end.x = x;
2028
2029 draw_context.drawinfo.y.over = y+1;
2030 draw_context.drawinfo.y.middle = y+(height/2);
2031 draw_context.drawinfo.y.under = y+height;
2032
2033 draw_context.drawinfo.start.offset.over = 0;
2034 draw_context.drawinfo.start.offset.middle = 0;
2035 draw_context.drawinfo.start.offset.under = 0;
2036 draw_context.drawinfo.end.offset.over = 0;
2037 draw_context.drawinfo.end.offset.middle = 0;
2038 draw_context.drawinfo.end.offset.under = 0;
2039
2040 {
2041 /* Draw the line */
2042 PropertiesLine prop_line = prepare_s_e_line(process);
2043 draw_line((void*)&prop_line, (void*)&draw_context);
2044
2045 }
2046 /* become the last x position */
2047 hashed_process_data->x.middle = x;
2048 hashed_process_data->x.middle_used = TRUE;
2049 hashed_process_data->x.middle_marked = FALSE;
2050 }
2051 }
2052
2053 return 0;
2054 }
2055
2056 /* after_execmode_hook
2057 *
2058 * The draw after hook is called by the reading API to have a
2059 * particular event drawn on the screen.
2060 * @param hook_data ControlFlowData structure of the viewer.
2061 * @param call_data Event context.
2062 *
2063 * This function adds items to be drawn in a queue for each process.
2064 *
2065 */
2066 int after_execmode_hook(void *hook_data, void *call_data)
2067 {
2068 EventsRequest *events_request = (EventsRequest*)hook_data;
2069 ControlFlowData *control_flow_data = events_request->viewer_data;
2070
2071 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2072
2073 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2074 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
2075
2076 LttEvent *e;
2077 e = tfc->e;
2078
2079 LttTime evtime = ltt_event_time(e);
2080 TimeWindow time_window =
2081 lttvwindow_get_time_window(control_flow_data->tab);
2082
2083 LttTime end_time = ltt_time_add(time_window.start_time,
2084 time_window.time_width);
2085
2086 if(ltt_time_compare(evtime, time_window.start_time) == -1
2087 || ltt_time_compare(evtime, end_time) == 1)
2088 return;
2089
2090 guint width = control_flow_data->drawing->width;
2091
2092 /* Add process to process list (if not present) */
2093 LttvProcessState *process;
2094 LttTime birth;
2095 guint y = 0, height = 0, pl_height = 0;
2096 HashedProcessData *hashed_process_data = NULL;
2097
2098 ProcessList *process_list = control_flow_data->process_list;
2099
2100 /* Find process pid_in in the list... */
2101 process = tfs->process;
2102 /* It should exist, because we are after the state update. */
2103 g_assert(process != NULL);
2104
2105 guint pid = process->pid;
2106
2107 birth = process->creation_time;
2108 const gchar *name = g_quark_to_string(process->name);
2109
2110 if(processlist_get_process_pixels(process_list,
2111 pid,
2112 process->last_cpu,
2113 &birth,
2114 tfc->t_context->index,
2115 &y,
2116 &height,
2117 &hashed_process_data) == 1)
2118 {
2119 g_assert(pid == 0 || pid != process->ppid);
2120 /* Process not present */
2121 processlist_add(process_list,
2122 pid,
2123 process->last_cpu,
2124 process->ppid,
2125 &birth,
2126 tfc->t_context->index,
2127 name,
2128 &pl_height,
2129 &hashed_process_data);
2130 processlist_get_process_pixels(process_list,
2131 pid,
2132 process->last_cpu,
2133 &birth,
2134 tfc->t_context->index,
2135 &y,
2136 &height,
2137 &hashed_process_data);
2138 drawing_insert_square( control_flow_data->drawing, y, height);
2139 }
2140
2141 guint new_x;
2142
2143 convert_time_to_pixels(
2144 time_window.start_time,
2145 end_time,
2146 evtime,
2147 width,
2148 &new_x);
2149
2150 if(hashed_process_data->x.middle != new_x) {
2151 hashed_process_data->x.middle = new_x;
2152 hashed_process_data->x.middle_used = FALSE;
2153 hashed_process_data->x.middle_marked = FALSE;
2154 }
2155
2156 return 0;
2157 }
2158
2159
2160
2161 /* before_process_hook
2162 *
2163 * Draw lines for process event.
2164 *
2165 * @param hook_data ControlFlowData structure of the viewer.
2166 * @param call_data Event context.
2167 *
2168 * This function adds items to be drawn in a queue for each process.
2169 *
2170 */
2171 int before_process_hook(void *hook_data, void *call_data)
2172 {
2173 EventsRequest *events_request = (EventsRequest*)hook_data;
2174 ControlFlowData *control_flow_data = events_request->viewer_data;
2175 Drawing_t *drawing = control_flow_data->drawing;
2176
2177 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2178
2179 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2180 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
2181
2182 LttEvent *e;
2183 e = tfc->e;
2184
2185 LttTime evtime = ltt_event_time(e);
2186 TimeWindow time_window =
2187 lttvwindow_get_time_window(control_flow_data->tab);
2188
2189 LttTime end_time = ltt_time_add(time_window.start_time,
2190 time_window.time_width);
2191
2192 if(ltt_time_compare(evtime, time_window.start_time) == -1
2193 || ltt_time_compare(evtime, end_time) == 1)
2194 return;
2195
2196 guint width = control_flow_data->drawing->width;
2197
2198 guint sub_id;
2199 {
2200 LttField *f = ltt_event_field(e);
2201 LttField *element;
2202 element = ltt_field_member(f,0);
2203 sub_id = ltt_event_get_long_unsigned(e,element);
2204 }
2205
2206 if(sub_id == 3) { /* exit */
2207
2208 /* Add process to process list (if not present) */
2209 LttvProcessState *process = tfs->process;
2210 guint pid = process->pid;
2211 LttTime birth;
2212 guint y = 0, height = 0, pl_height = 0;
2213 HashedProcessData *hashed_process_data = NULL;
2214
2215 ProcessList *process_list = control_flow_data->process_list;
2216
2217 g_assert(process != NULL);
2218
2219 birth = process->creation_time;
2220 const gchar *name = g_quark_to_string(process->name);
2221
2222 if(processlist_get_process_pixels(process_list,
2223 pid,
2224 process->last_cpu,
2225 &birth,
2226 tfc->t_context->index,
2227 &y,
2228 &height,
2229 &hashed_process_data) == 1)
2230 {
2231 g_assert(pid == 0 || pid != process->ppid);
2232 /* Process not present */
2233 processlist_add(process_list,
2234 pid,
2235 process->last_cpu,
2236 process->ppid,
2237 &birth,
2238 tfc->t_context->index,
2239 name,
2240 &pl_height,
2241 &hashed_process_data);
2242 processlist_get_process_pixels(process_list,
2243 pid,
2244 process->last_cpu,
2245 &birth,
2246 tfc->t_context->index,
2247 &y,
2248 &height,
2249 &hashed_process_data);
2250 drawing_insert_square( control_flow_data->drawing, y, height);
2251 }
2252
2253 /* Now, the process is in the state hash and our own process hash.
2254 * We definitely can draw the items related to the ending state.
2255 */
2256
2257 /* Check if the x position is unset. In can have been left unset by
2258 * a draw closure from a after chunk hook. This should never happen,
2259 * because it must be set by before chunk hook to the damage_begin
2260 * value.
2261 */
2262 g_assert(hashed_process_data->x.over != -1);
2263 {
2264 guint x;
2265
2266 convert_time_to_pixels(
2267 time_window.start_time,
2268 end_time,
2269 evtime,
2270 width,
2271 &x);
2272
2273
2274 /* Jump over draw if we are at the same x position */
2275 if(x == hashed_process_data->x.middle &&
2276 hashed_process_data->x.middle_used)
2277 {
2278 if(hashed_process_data->x.middle_marked == FALSE) {
2279 /* Draw collision indicator */
2280 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2281 gdk_draw_point(drawing->pixmap,
2282 drawing->gc,
2283 x,
2284 y+(height/2)-3);
2285 hashed_process_data->x.middle_marked = TRUE;
2286 }
2287 /* jump */
2288 } else {
2289 DrawContext draw_context;
2290
2291 /* Now create the drawing context that will be used to draw
2292 * items related to the last state. */
2293 draw_context.drawable = drawing->pixmap;
2294 draw_context.gc = drawing->gc;
2295 draw_context.pango_layout = drawing->pango_layout;
2296 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2297 draw_context.drawinfo.end.x = x;
2298
2299 draw_context.drawinfo.y.over = y+1;
2300 draw_context.drawinfo.y.middle = y+(height/2);
2301 draw_context.drawinfo.y.under = y+height;
2302
2303 draw_context.drawinfo.start.offset.over = 0;
2304 draw_context.drawinfo.start.offset.middle = 0;
2305 draw_context.drawinfo.start.offset.under = 0;
2306 draw_context.drawinfo.end.offset.over = 0;
2307 draw_context.drawinfo.end.offset.middle = 0;
2308 draw_context.drawinfo.end.offset.under = 0;
2309
2310 {
2311 /* Draw the line */
2312 PropertiesLine prop_line = prepare_s_e_line(process);
2313 draw_line((void*)&prop_line, (void*)&draw_context);
2314
2315 }
2316 /* become the last x position */
2317 hashed_process_data->x.middle = x;
2318 hashed_process_data->x.middle_used = TRUE;
2319 hashed_process_data->x.middle_marked = FALSE;
2320 }
2321 }
2322
2323 }
2324 return 0;
2325
2326 }
2327
2328
2329
2330
2331
2332
2333 /* after_process_hook
2334 *
2335 * Create the processlist entry for the child process. Put the last
2336 * position in x at the current time value.
2337 *
2338 * @param hook_data ControlFlowData structure of the viewer.
2339 * @param call_data Event context.
2340 *
2341 * This function adds items to be drawn in a queue for each process.
2342 *
2343 */
2344 int after_process_hook(void *hook_data, void *call_data)
2345 {
2346 EventsRequest *events_request = (EventsRequest*)hook_data;
2347 ControlFlowData *control_flow_data = events_request->viewer_data;
2348
2349 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2350
2351 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2352 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
2353
2354 LttEvent *e;
2355 e = tfc->e;
2356
2357 LttTime evtime = ltt_event_time(e);
2358 TimeWindow time_window =
2359 lttvwindow_get_time_window(control_flow_data->tab);
2360
2361 LttTime end_time = ltt_time_add(time_window.start_time,
2362 time_window.time_width);
2363
2364 if(ltt_time_compare(evtime, time_window.start_time) == -1
2365 || ltt_time_compare(evtime, end_time) == 1)
2366 return;
2367
2368 guint width = control_flow_data->drawing->width;
2369
2370 guint sub_id;
2371 guint param1;
2372 {
2373 LttField *f = ltt_event_field(e);
2374 LttField *element;
2375 element = ltt_field_member(f,0);
2376 sub_id = ltt_event_get_long_unsigned(e,element);
2377 element = ltt_field_member(f,1);
2378 param1 = ltt_event_get_long_unsigned(e,element);
2379 }
2380
2381 if(sub_id == 2) { /* fork */
2382
2383 guint child_pid = param1;
2384 /* Add process to process list (if not present) */
2385 LttvProcessState *process_child;
2386 LttTime birth;
2387 guint y_child = 0, height = 0, pl_height = 0;
2388 HashedProcessData *hashed_process_data_child = NULL;
2389
2390 ProcessList *process_list = control_flow_data->process_list;
2391
2392 /* Find child in the list... */
2393 process_child = lttv_state_find_process(tfs, child_pid);
2394 /* It should exist, because we are after the state update. */
2395 g_assert(process_child != NULL);
2396
2397 birth = process_child->creation_time;
2398 const gchar *name = g_quark_to_string(process_child->name);
2399
2400 if(processlist_get_process_pixels(process_list,
2401 child_pid,
2402 process_child->last_cpu,
2403 &birth,
2404 tfc->t_context->index,
2405 &y_child,
2406 &height,
2407 &hashed_process_data_child) == 1)
2408 {
2409 g_assert(child_pid == 0 || child_pid != process_child->ppid);
2410 /* Process not present */
2411 processlist_add(process_list,
2412 child_pid,
2413 process_child->last_cpu,
2414 process_child->ppid,
2415 &birth,
2416 tfc->t_context->index,
2417 name,
2418 &pl_height,
2419 &hashed_process_data_child);
2420 processlist_get_process_pixels(process_list,
2421 child_pid,
2422 process_child->last_cpu,
2423 &birth,
2424 tfc->t_context->index,
2425 &y_child,
2426 &height,
2427 &hashed_process_data_child);
2428 drawing_insert_square( control_flow_data->drawing, y_child, height);
2429 }
2430
2431 guint new_x;
2432 convert_time_to_pixels(
2433 time_window.start_time,
2434 end_time,
2435 evtime,
2436 width,
2437 &new_x);
2438
2439 if(hashed_process_data_child->x.over != new_x) {
2440 hashed_process_data_child->x.over = new_x;
2441 hashed_process_data_child->x.over_used = FALSE;
2442 hashed_process_data_child->x.over_marked = FALSE;
2443 }
2444 if(hashed_process_data_child->x.middle != new_x) {
2445 hashed_process_data_child->x.middle = new_x;
2446 hashed_process_data_child->x.middle_used = FALSE;
2447 hashed_process_data_child->x.middle_marked = FALSE;
2448 }
2449 if(hashed_process_data_child->x.under != new_x) {
2450 hashed_process_data_child->x.under = new_x;
2451 hashed_process_data_child->x.under_used = FALSE;
2452 hashed_process_data_child->x.under_marked = FALSE;
2453 }
2454
2455 } else if(sub_id == 3) { /* exit */
2456
2457 /* Add process to process list (if not present) */
2458 LttvProcessState *process = tfs->process;
2459 guint pid = process->pid;
2460 LttTime birth;
2461 guint y = 0, height = 0, pl_height = 0;
2462 HashedProcessData *hashed_process_data = NULL;
2463
2464 ProcessList *process_list = control_flow_data->process_list;
2465
2466 /* It should exist, because we are after the state update. */
2467 g_assert(process != NULL);
2468
2469 birth = process->creation_time;
2470 const gchar *name = g_quark_to_string(process->name);
2471
2472 if(processlist_get_process_pixels(process_list,
2473 pid,
2474 process->last_cpu,
2475 &birth,
2476 tfc->t_context->index,
2477 &y,
2478 &height,
2479 &hashed_process_data) == 1)
2480 {
2481 g_assert(pid == 0 || pid != process->ppid);
2482 /* Process not present */
2483 processlist_add(process_list,
2484 pid,
2485 process->last_cpu,
2486 process->ppid,
2487 &birth,
2488 tfc->t_context->index,
2489 name,
2490 &pl_height,
2491 &hashed_process_data);
2492 processlist_get_process_pixels(process_list,
2493 pid,
2494 process->last_cpu,
2495 &birth,
2496 tfc->t_context->index,
2497 &y,
2498 &height,
2499 &hashed_process_data);
2500 drawing_insert_square( control_flow_data->drawing, y, height);
2501 }
2502
2503 guint new_x;
2504 convert_time_to_pixels(
2505 time_window.start_time,
2506 end_time,
2507 evtime,
2508 width,
2509 &new_x);
2510 if(hashed_process_data->x.middle != new_x) {
2511 hashed_process_data->x.middle = new_x;
2512 hashed_process_data->x.middle_used = FALSE;
2513 hashed_process_data->x.middle_marked = FALSE;
2514 }
2515
2516
2517 }
2518 return 0;
2519
2520 }
2521
2522
2523 gint update_time_window_hook(void *hook_data, void *call_data)
2524 {
2525 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2526 Drawing_t *drawing = control_flow_data->drawing;
2527
2528 const TimeWindowNotifyData *time_window_nofify_data =
2529 ((const TimeWindowNotifyData *)call_data);
2530
2531 TimeWindow *old_time_window =
2532 time_window_nofify_data->old_time_window;
2533 TimeWindow *new_time_window =
2534 time_window_nofify_data->new_time_window;
2535
2536 /* Update the ruler */
2537 drawing_update_ruler(control_flow_data->drawing,
2538 new_time_window);
2539
2540
2541 /* Two cases : zoom in/out or scrolling */
2542
2543 /* In order to make sure we can reuse the old drawing, the scale must
2544 * be the same and the new time interval being partly located in the
2545 * currently shown time interval. (reuse is only for scrolling)
2546 */
2547
2548 g_info("Old time window HOOK : %u, %u to %u, %u",
2549 old_time_window->start_time.tv_sec,
2550 old_time_window->start_time.tv_nsec,
2551 old_time_window->time_width.tv_sec,
2552 old_time_window->time_width.tv_nsec);
2553
2554 g_info("New time window HOOK : %u, %u to %u, %u",
2555 new_time_window->start_time.tv_sec,
2556 new_time_window->start_time.tv_nsec,
2557 new_time_window->time_width.tv_sec,
2558 new_time_window->time_width.tv_nsec);
2559
2560 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2561 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
2562 {
2563 /* Same scale (scrolling) */
2564 g_info("scrolling");
2565 LttTime *ns = &new_time_window->start_time;
2566 LttTime *os = &old_time_window->start_time;
2567 LttTime old_end = ltt_time_add(old_time_window->start_time,
2568 old_time_window->time_width);
2569 LttTime new_end = ltt_time_add(new_time_window->start_time,
2570 new_time_window->time_width);
2571 //if(ns<os+w<ns+w)
2572 //if(ns<os+w && os+w<ns+w)
2573 //if(ns<old_end && os<ns)
2574 if(ltt_time_compare(*ns, old_end) == -1
2575 && ltt_time_compare(*os, *ns) == -1)
2576 {
2577 g_info("scrolling near right");
2578 /* Scroll right, keep right part of the screen */
2579 guint x = 0;
2580 guint width = control_flow_data->drawing->width;
2581 convert_time_to_pixels(
2582 *os,
2583 old_end,
2584 *ns,
2585 width,
2586 &x);
2587
2588 /* Copy old data to new location */
2589 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2590 control_flow_data->drawing->drawing_area->style->black_gc,
2591 control_flow_data->drawing->pixmap,
2592 x, 0,
2593 0, 0,
2594 control_flow_data->drawing->width-x+SAFETY, -1);
2595
2596 if(drawing->damage_begin == drawing->damage_end)
2597 drawing->damage_begin = control_flow_data->drawing->width-x;
2598 else
2599 drawing->damage_begin = 0;
2600
2601 drawing->damage_end = control_flow_data->drawing->width;
2602
2603 /* Clear the data request background, but not SAFETY */
2604 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2605 //control_flow_data->drawing->drawing_area->style->black_gc,
2606 control_flow_data->drawing->drawing_area->style->black_gc,
2607 TRUE,
2608 drawing->damage_begin+SAFETY, 0,
2609 drawing->damage_end - drawing->damage_begin, // do not overlap
2610 control_flow_data->drawing->height);
2611
2612 gtk_widget_queue_draw_area (drawing->drawing_area,
2613 0,0,
2614 control_flow_data->drawing->width,
2615 control_flow_data->drawing->height);
2616
2617 /* Get new data for the rest. */
2618 drawing_data_request(control_flow_data->drawing,
2619 &control_flow_data->drawing->pixmap,
2620 drawing->damage_begin, 0,
2621 drawing->damage_end - drawing->damage_begin,
2622 control_flow_data->drawing->height);
2623 } else {
2624 //if(ns<os<ns+w)
2625 //if(ns<os && os<ns+w)
2626 //if(ns<os && os<new_end)
2627 if(ltt_time_compare(*ns,*os) == -1
2628 && ltt_time_compare(*os,new_end) == -1)
2629 {
2630 g_info("scrolling near left");
2631 /* Scroll left, keep left part of the screen */
2632 guint x = 0;
2633 guint width = control_flow_data->drawing->width;
2634 convert_time_to_pixels(
2635 *ns,
2636 new_end,
2637 *os,
2638 width,
2639 &x);
2640
2641
2642 /* Copy old data to new location */
2643 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2644 control_flow_data->drawing->drawing_area->style->black_gc,
2645 control_flow_data->drawing->pixmap,
2646 0, 0,
2647 x, 0,
2648 -1, -1);
2649
2650 if(drawing->damage_begin == drawing->damage_end)
2651 drawing->damage_end = x;
2652 else
2653 drawing->damage_end =
2654 control_flow_data->drawing->width;
2655
2656 drawing->damage_begin = 0;
2657
2658 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2659 control_flow_data->drawing->drawing_area->style->black_gc,
2660 TRUE,
2661 drawing->damage_begin, 0,
2662 drawing->damage_end - drawing->damage_begin, // do not overlap
2663 control_flow_data->drawing->height);
2664
2665 gtk_widget_queue_draw_area (drawing->drawing_area,
2666 0,0,
2667 control_flow_data->drawing->width,
2668 control_flow_data->drawing->height);
2669
2670
2671 /* Get new data for the rest. */
2672 drawing_data_request(control_flow_data->drawing,
2673 &control_flow_data->drawing->pixmap,
2674 drawing->damage_begin, 0,
2675 drawing->damage_end - drawing->damage_begin,
2676 control_flow_data->drawing->height);
2677
2678 } else {
2679 if(ltt_time_compare(*ns,*os) == 0)
2680 {
2681 g_info("not scrolling");
2682 } else {
2683 g_info("scrolling far");
2684 /* Cannot reuse any part of the screen : far jump */
2685
2686
2687 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2688 control_flow_data->drawing->drawing_area->style->black_gc,
2689 TRUE,
2690 0, 0,
2691 control_flow_data->drawing->width+SAFETY, // do not overlap
2692 control_flow_data->drawing->height);
2693
2694 gtk_widget_queue_draw_area (drawing->drawing_area,
2695 0,0,
2696 control_flow_data->drawing->width,
2697 control_flow_data->drawing->height);
2698
2699 drawing->damage_begin = 0;
2700 drawing->damage_end = control_flow_data->drawing->width;
2701
2702 drawing_data_request(control_flow_data->drawing,
2703 &control_flow_data->drawing->pixmap,
2704 0, 0,
2705 control_flow_data->drawing->width,
2706 control_flow_data->drawing->height);
2707
2708 }
2709 }
2710 }
2711 } else {
2712 /* Different scale (zoom) */
2713 g_info("zoom");
2714
2715 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2716 control_flow_data->drawing->drawing_area->style->black_gc,
2717 TRUE,
2718 0, 0,
2719 control_flow_data->drawing->width+SAFETY, // do not overlap
2720 control_flow_data->drawing->height);
2721
2722 gtk_widget_queue_draw_area (drawing->drawing_area,
2723 0,0,
2724 control_flow_data->drawing->width,
2725 control_flow_data->drawing->height);
2726
2727 drawing->damage_begin = 0;
2728 drawing->damage_end = control_flow_data->drawing->width;
2729
2730 drawing_data_request(control_flow_data->drawing,
2731 &control_flow_data->drawing->pixmap,
2732 0, 0,
2733 control_flow_data->drawing->width,
2734 control_flow_data->drawing->height);
2735 }
2736
2737
2738
2739 return 0;
2740 }
2741
2742 gint traceset_notify(void *hook_data, void *call_data)
2743 {
2744 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2745 Drawing_t *drawing = control_flow_data->drawing;
2746 GtkWidget *widget = drawing->drawing_area;
2747
2748
2749 drawing_clear(control_flow_data->drawing);
2750 processlist_clear(control_flow_data->process_list);
2751 redraw_notify(control_flow_data, NULL);
2752
2753 request_background_data(control_flow_data);
2754 #if 0
2755 drawing->damage_begin = 0;
2756 drawing->damage_end = drawing->width;
2757 if(drawing->damage_begin < drawing->damage_end)
2758 {
2759 drawing_data_request(drawing,
2760 &drawing->pixmap,
2761 drawing->damage_begin,
2762 0,
2763 drawing->damage_end-drawing->damage_begin,
2764 drawing->height);
2765 }
2766
2767 gtk_widget_queue_draw_area(drawing->drawing_area,
2768 0,0,
2769 drawing->width,
2770 drawing->height);
2771 #endif //0
2772
2773 return FALSE;
2774 }
2775
2776 gint redraw_notify(void *hook_data, void *call_data)
2777 {
2778 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2779 Drawing_t *drawing = control_flow_data->drawing;
2780 GtkWidget *widget = drawing->drawing_area;
2781
2782 drawing->damage_begin = 0;
2783 drawing->damage_end = drawing->width;
2784
2785 /* fun feature, to be separated someday... */
2786 drawing_clear(control_flow_data->drawing);
2787 processlist_clear(control_flow_data->process_list);
2788
2789 // Clear the image
2790 gdk_draw_rectangle (drawing->pixmap,
2791 widget->style->black_gc,
2792 TRUE,
2793 0, 0,
2794 drawing->width+SAFETY,
2795 drawing->height);
2796
2797
2798 if(drawing->damage_begin < drawing->damage_end)
2799 {
2800 drawing_data_request(drawing,
2801 &drawing->pixmap,
2802 drawing->damage_begin,
2803 0,
2804 drawing->damage_end-drawing->damage_begin,
2805 drawing->height);
2806 }
2807
2808 gtk_widget_queue_draw_area(drawing->drawing_area,
2809 0,0,
2810 drawing->width,
2811 drawing->height);
2812 return FALSE;
2813
2814 }
2815
2816
2817 gint continue_notify(void *hook_data, void *call_data)
2818 {
2819 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2820 Drawing_t *drawing = control_flow_data->drawing;
2821 GtkWidget *widget = drawing->drawing_area;
2822
2823 //g_assert(widget->allocation.width == drawing->damage_end);
2824
2825 if(drawing->damage_begin < drawing->damage_end)
2826 {
2827 drawing_data_request(drawing,
2828 &drawing->pixmap,
2829 drawing->damage_begin,
2830 0,
2831 drawing->damage_end-drawing->damage_begin,
2832 drawing->height);
2833 }
2834
2835 return FALSE;
2836 }
2837
2838
2839 gint update_current_time_hook(void *hook_data, void *call_data)
2840 {
2841 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
2842 Drawing_t *drawing = control_flow_data->drawing;
2843
2844 LttTime current_time = *((LttTime*)call_data);
2845
2846 TimeWindow time_window =
2847 lttvwindow_get_time_window(control_flow_data->tab);
2848
2849 LttTime time_begin = time_window.start_time;
2850 LttTime width = time_window.time_width;
2851 LttTime half_width;
2852 {
2853 guint64 time_ll = ltt_time_to_uint64(width);
2854 time_ll = time_ll >> 1; /* divide by two */
2855 half_width = ltt_time_from_uint64(time_ll);
2856 }
2857 LttTime time_end = ltt_time_add(time_begin, width);
2858
2859 LttvTracesetContext * tsc =
2860 lttvwindow_get_traceset_context(control_flow_data->tab);
2861
2862 LttTime trace_start = tsc->time_span.start_time;
2863 LttTime trace_end = tsc->time_span.end_time;
2864
2865 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
2866 current_time.tv_nsec);
2867
2868
2869
2870 /* If current time is inside time interval, just move the highlight
2871 * bar */
2872
2873 /* Else, we have to change the time interval. We have to tell it
2874 * to the main window. */
2875 /* The time interval change will take care of placing the current
2876 * time at the center of the visible area, or nearest possible if we are
2877 * at one end of the trace. */
2878
2879
2880 if(ltt_time_compare(current_time, time_begin) == -1)
2881 {
2882 TimeWindow new_time_window;
2883
2884 if(ltt_time_compare(current_time,
2885 ltt_time_add(trace_start,half_width)) == -1)
2886 time_begin = trace_start;
2887 else
2888 time_begin = ltt_time_sub(current_time,half_width);
2889
2890 new_time_window.start_time = time_begin;
2891 new_time_window.time_width = width;
2892
2893 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2894 }
2895 else if(ltt_time_compare(current_time, time_end) == 1)
2896 {
2897 TimeWindow new_time_window;
2898
2899 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
2900 time_begin = ltt_time_sub(trace_end,width);
2901 else
2902 time_begin = ltt_time_sub(current_time,half_width);
2903
2904 new_time_window.start_time = time_begin;
2905 new_time_window.time_width = width;
2906
2907 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2908
2909 }
2910 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2911 gtk_widget_queue_draw_area(drawing->drawing_area,
2912 0,0,
2913 drawing->width,
2914 drawing->height);
2915
2916 return 0;
2917 }
2918
2919 typedef struct _ClosureData {
2920 EventsRequest *events_request;
2921 LttvTracesetState *tss;
2922 LttTime end_time;
2923 } ClosureData;
2924
2925
2926 void draw_closure(gpointer key, gpointer value, gpointer user_data)
2927 {
2928 ProcessInfo *process_info = (ProcessInfo*)key;
2929 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2930 ClosureData *closure_data = (ClosureData*)user_data;
2931
2932 EventsRequest *events_request = closure_data->events_request;
2933 ControlFlowData *control_flow_data = events_request->viewer_data;
2934 Drawing_t *drawing = control_flow_data->drawing;
2935
2936 LttvTracesetState *tss = closure_data->tss;
2937 LttvTracesetContext *tsc = (LttvTracesetContext*)closure_data->tss;
2938
2939 LttTime evtime = closure_data->end_time;
2940 TimeWindow time_window =
2941 lttvwindow_get_time_window(control_flow_data->tab);
2942
2943 LttTime end_time = ltt_time_add(time_window.start_time,
2944 time_window.time_width);
2945
2946 if(ltt_time_compare(evtime, time_window.start_time) == -1
2947 || ltt_time_compare(evtime, end_time) == 1)
2948 return;
2949
2950 guint width = drawing->width;
2951
2952 {
2953 /* For the process */
2954 /* First, check if the current process is in the state computation
2955 * process list. If it is there, that means we must add it right now and
2956 * draw items from the beginning of the read for it. If it is not
2957 * present, it's a new process and it was not present : it will
2958 * be added after the state update. */
2959 g_assert(lttv_traceset_number(tsc->ts) > 0);
2960
2961 /* tracefiles[0] is ok here, because we draw for every PID, and
2962 * assume CPU 0 for PID 0 //FIXME */
2963 LttvTracefileState *tfs =
2964 (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
2965
2966 LttvProcessState *process;
2967 process = lttv_state_find_process(tfs,
2968 process_info->pid);
2969
2970 if(process != NULL) {
2971
2972 /* Only draw for processes that are currently in the trace states */
2973
2974 guint y = 0, height = 0, pl_height = 0;
2975 ProcessList *process_list = control_flow_data->process_list;
2976 LttTime birth = process_info->birth;
2977
2978 /* Should be alike when background info is ready */
2979 if(control_flow_data->background_info_waiting==0)
2980 g_assert(ltt_time_compare(process->creation_time,
2981 process_info->birth) == 0);
2982 const gchar *name = g_quark_to_string(process->name);
2983
2984 /* process HAS to be present */
2985 g_assert(processlist_get_process_pixels(process_list,
2986 process_info->pid,
2987 process_info->cpu,
2988 &birth,
2989 process_info->trace_num,
2990 &y,
2991 &height,
2992 &hashed_process_data) != 1);
2993
2994 /* Now, the process is in the state hash and our own process hash.
2995 * We definitely can draw the items related to the ending state.
2996 */
2997
2998 /* Check if the x position is unset. In can have been left unset by
2999 * a draw closure from a after chunk hook. This should never happen,
3000 * because it must be set by before chunk hook to the damage_begin
3001 * value.
3002 */
3003 g_assert(hashed_process_data->x.over != -1);
3004 {
3005 guint x;
3006
3007 convert_time_to_pixels(
3008 time_window.start_time,
3009 end_time,
3010 evtime,
3011 width,
3012 &x);
3013
3014 DrawContext draw_context;
3015
3016 /* Now create the drawing context that will be used to draw
3017 * items related to the last state. */
3018 draw_context.drawable = drawing->pixmap;
3019 draw_context.gc = drawing->gc;
3020 draw_context.pango_layout = drawing->pango_layout;
3021 draw_context.drawinfo.end.x = x;
3022
3023 draw_context.drawinfo.y.over = y+1;
3024 draw_context.drawinfo.y.middle = y+(height/2);
3025 draw_context.drawinfo.y.under = y+height;
3026
3027 draw_context.drawinfo.start.offset.over = 0;
3028 draw_context.drawinfo.start.offset.middle = 0;
3029 draw_context.drawinfo.start.offset.under = 0;
3030 draw_context.drawinfo.end.offset.over = 0;
3031 draw_context.drawinfo.end.offset.middle = 0;
3032 draw_context.drawinfo.end.offset.under = 0;
3033 #if 0
3034 /* Jump over draw if we are at the same x position */
3035 if(x == hashed_process_data->x.over)
3036 {
3037 /* jump */
3038 } else {
3039 draw_context.drawinfo.start.x = hashed_process_data->x.over;
3040 /* Draw the line */
3041 PropertiesLine prop_line = prepare_execmode_line(process);
3042 draw_line((void*)&prop_line, (void*)&draw_context);
3043
3044 hashed_process_data->x.over = x;
3045 }
3046 #endif //0
3047
3048 if(x == hashed_process_data->x.middle &&
3049 hashed_process_data->x.middle_used) {
3050 if(hashed_process_data->x.middle_marked == FALSE) {
3051 /* Draw collision indicator */
3052 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
3053 gdk_draw_point(drawing->pixmap,
3054 drawing->gc,
3055 x,
3056 y+(height/2)-3);
3057 hashed_process_data->x.middle_marked = TRUE;
3058 }
3059 /* Jump */
3060 } else {
3061 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
3062 /* Draw the line */
3063 PropertiesLine prop_line = prepare_s_e_line(process);
3064 draw_line((void*)&prop_line, (void*)&draw_context);
3065
3066 /* become the last x position */
3067 if(x != hashed_process_data->x.middle) {
3068 hashed_process_data->x.middle = x;
3069 /* but don't use the pixel */
3070 hashed_process_data->x.middle_used = FALSE;
3071 }
3072 }
3073 }
3074 }
3075 }
3076 return;
3077 }
3078
3079 int before_chunk(void *hook_data, void *call_data)
3080 {
3081 EventsRequest *events_request = (EventsRequest*)hook_data;
3082 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
3083
3084 drawing_chunk_begin(events_request, tss);
3085
3086 return 0;
3087 }
3088
3089 int before_request(void *hook_data, void *call_data)
3090 {
3091 EventsRequest *events_request = (EventsRequest*)hook_data;
3092 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
3093
3094 drawing_data_request_begin(events_request, tss);
3095
3096 return 0;
3097 }
3098
3099
3100 /*
3101 * after request is necessary in addition of after chunk in order to draw
3102 * lines until the end of the screen. after chunk just draws lines until
3103 * the last event.
3104 *
3105 * for each process
3106 * draw closing line
3107 * expose
3108 */
3109 int after_request(void *hook_data, void *call_data)
3110 {
3111 EventsRequest *events_request = (EventsRequest*)hook_data;
3112 ControlFlowData *control_flow_data = events_request->viewer_data;
3113 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
3114 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
3115
3116 ProcessList *process_list = control_flow_data->process_list;
3117 LttTime end_time = events_request->end_time;
3118
3119 ClosureData closure_data;
3120 closure_data.events_request = (EventsRequest*)hook_data;
3121 closure_data.tss = tss;
3122 closure_data.end_time = end_time;
3123
3124 /* Draw last items */
3125 g_hash_table_foreach(process_list->process_hash, draw_closure,
3126 (void*)&closure_data);
3127
3128 /* Request expose */
3129 drawing_request_expose(events_request, tss, end_time);
3130 return 0;
3131 }
3132
3133 /*
3134 * for each process
3135 * draw closing line
3136 * expose
3137 */
3138 int after_chunk(void *hook_data, void *call_data)
3139 {
3140 EventsRequest *events_request = (EventsRequest*)hook_data;
3141 ControlFlowData *control_flow_data = events_request->viewer_data;
3142 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
3143 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
3144 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
3145 LttTime end_time;
3146
3147 ProcessList *process_list = control_flow_data->process_list;
3148
3149 if(tfc != NULL)
3150 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
3151 else /* end of traceset, or position now out of request : end */
3152 end_time = events_request->end_time;
3153
3154 ClosureData closure_data;
3155 closure_data.events_request = (EventsRequest*)hook_data;
3156 closure_data.tss = tss;
3157 closure_data.end_time = end_time;
3158
3159 /* Draw last items */
3160 g_hash_table_foreach(process_list->process_hash, draw_closure,
3161 (void*)&closure_data);
3162
3163 /* Request expose */
3164 drawing_request_expose(events_request, tss, end_time);
3165
3166 return 0;
3167 }
3168
This page took 0.095327 seconds and 4 git commands to generate.