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