fix memleak
[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 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51
52 //#define PANGO_ENABLE_BACKEND
53 #include <gtk/gtk.h>
54 #include <gdk/gdk.h>
55 #include <glib.h>
56 #include <assert.h>
57 #include <string.h>
58 #include <stdio.h>
59
60 //#include <pango/pango.h>
61
62 #include <ltt/event.h>
63 #include <ltt/time.h>
64 #include <ltt/type.h>
65 #include <ltt/trace.h>
66
67 #include <lttv/lttv.h>
68 #include <lttv/hook.h>
69 #include <lttv/state.h>
70 #include <lttvwindow/lttvwindow.h>
71 #include <lttvwindow/lttvwindowtraces.h>
72 #include <lttvwindow/support.h>
73
74
75 #include "eventhooks.h"
76 #include "cfv.h"
77 #include "processlist.h"
78 #include "drawing.h"
79
80
81 #define MAX_PATH_LEN 256
82
83 extern GSList *g_legend_list;
84
85 #if 0
86 typedef struct _ProcessAddClosure {
87 ControlFlowData *cfd;
88 guint trace_num;
89 } ProcessAddClosure;
90
91 static void process_add(gpointer key,
92 gpointer value,
93 gpointer user_data)
94 {
95 LttvProcessState *process = (LttvProcessState*)value;
96 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
97 ControlFlowData *control_flow_data = closure->cfd;
98 guint trace_num = closure->trace_num;
99
100 /* Add process to process list (if not present) */
101 guint pid;
102 LttTime birth;
103 guint y = 0, height = 0, pl_height = 0;
104
105 ProcessList *process_list = control_flow_data->process_list;
106
107 pid = process->pid;
108 birth = process->creation_time;
109 const gchar *name = g_quark_to_string(process->name);
110 HashedProcessData *hashed_process_data = NULL;
111
112 if(processlist_get_process_pixels(process_list,
113 pid,
114 &birth,
115 trace_num,
116 &y,
117 &height,
118 &hashed_process_data) == 1)
119 {
120 /* Process not present */
121 processlist_add(process_list,
122 pid,
123 &birth,
124 trace_num,
125 name,
126 &pl_height,
127 &hashed_process_data);
128 processlist_get_process_pixels(process_list,
129 pid,
130 &birth,
131 trace_num,
132 &y,
133 &height,
134 &hashed_process_data);
135 drawing_insert_square( control_flow_data->drawing, y, height);
136 }
137 }
138 #endif //0
139
140
141 /* Action to do when background computation completed.
142 *
143 * Wait for all the awaited computations to be over.
144 */
145
146 gint background_ready(void *hook_data, void *call_data)
147 {
148 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
149 LttvTrace *trace = (LttvTrace*)call_data;
150
151 control_flow_data->background_info_waiting--;
152
153 if(control_flow_data->background_info_waiting == 0) {
154 g_debug("control flow viewer : background computation data ready.");
155
156 drawing_clear(control_flow_data->drawing);
157 processlist_clear(control_flow_data->process_list);
158 gtk_widget_set_size_request(
159 control_flow_data->drawing->drawing_area,
160 -1, processlist_get_height(control_flow_data->process_list));
161 redraw_notify(control_flow_data, NULL);
162 }
163
164 return 0;
165 }
166
167
168 /* Request background computation. Verify if it is in progress or ready first.
169 * Only for each trace in the tab's traceset.
170 */
171 void request_background_data(ControlFlowData *control_flow_data)
172 {
173 LttvTracesetContext * tsc =
174 lttvwindow_get_traceset_context(control_flow_data->tab);
175 gint num_traces = lttv_traceset_number(tsc->ts);
176 gint i;
177 LttvTrace *trace;
178
179 LttvHooks *background_ready_hook =
180 lttv_hooks_new();
181 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
182 LTTV_PRIO_DEFAULT);
183 control_flow_data->background_info_waiting = 0;
184
185 for(i=0;i<num_traces;i++) {
186 trace = lttv_traceset_get(tsc->ts, i);
187
188 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
189
190 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
191 trace) == FALSE) {
192 /* We first remove requests that could have been done for the same
193 * information. Happens when two viewers ask for it before servicing
194 * starts.
195 */
196 lttvwindowtraces_background_request_remove(trace, "state");
197 lttvwindowtraces_background_request_queue(trace,
198 "state");
199 lttvwindowtraces_background_notify_queue(control_flow_data,
200 trace,
201 ltt_time_infinite,
202 NULL,
203 background_ready_hook);
204 control_flow_data->background_info_waiting++;
205 } else { /* in progress */
206
207 lttvwindowtraces_background_notify_current(control_flow_data,
208 trace,
209 ltt_time_infinite,
210 NULL,
211 background_ready_hook);
212 control_flow_data->background_info_waiting++;
213 }
214 } else {
215 /* Data ready. Be its nature, this viewer doesn't need to have
216 * its data ready hook called htere, because a background
217 * request is always linked with a redraw.
218 */
219 }
220
221 }
222
223 lttv_hooks_destroy(background_ready_hook);
224 }
225
226
227
228
229 /**
230 * Event Viewer's constructor hook
231 *
232 * This constructor is given as a parameter to the menuitem and toolbar button
233 * registration. It creates the list.
234 * @param tab A pointer to the parent tab.
235 * @return The widget created.
236 */
237 GtkWidget *
238 h_guicontrolflow(Tab *tab)
239 {
240 g_info("h_guicontrolflow, %p", tab);
241 ControlFlowData *control_flow_data = guicontrolflow() ;
242
243 control_flow_data->tab = tab;
244
245 // Unreg done in the GuiControlFlow_Destructor
246 lttvwindow_register_traceset_notify(tab,
247 traceset_notify,
248 control_flow_data);
249
250 lttvwindow_register_time_window_notify(tab,
251 update_time_window_hook,
252 control_flow_data);
253 lttvwindow_register_current_time_notify(tab,
254 update_current_time_hook,
255 control_flow_data);
256 lttvwindow_register_redraw_notify(tab,
257 redraw_notify,
258 control_flow_data);
259 lttvwindow_register_continue_notify(tab,
260 continue_notify,
261 control_flow_data);
262 request_background_data(control_flow_data);
263
264
265 return guicontrolflow_get_widget(control_flow_data) ;
266
267 }
268
269 void legend_destructor(GtkWindow *legend)
270 {
271 g_legend_list = g_slist_remove(g_legend_list, legend);
272 }
273
274 /* Create a popup legend */
275 GtkWidget *
276 h_legend(Tab *tab)
277 {
278 g_info("h_legend, %p", tab);
279
280 GtkWindow *legend = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
281
282 g_legend_list = g_slist_append(
283 g_legend_list,
284 legend);
285
286 g_object_set_data_full(
287 G_OBJECT(legend),
288 "legend",
289 legend,
290 (GDestroyNotify)legend_destructor);
291
292 gtk_window_set_title(legend, "Control Flow View Legend");
293
294 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(legend), "lttv-color-list.png");
295
296 // GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixmap(
297 // GDK_PIXMAP(pixmap), NULL));
298
299 gtk_container_add(GTK_CONTAINER(legend), GTK_WIDGET(pixmap));
300
301 gtk_widget_show(GTK_WIDGET(pixmap));
302 gtk_widget_show(GTK_WIDGET(legend));
303
304
305 return NULL; /* This is a popup window */
306 }
307
308
309 int event_selected_hook(void *hook_data, void *call_data)
310 {
311 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
312 guint *event_number = (guint*) call_data;
313
314 g_debug("DEBUG : event selected by main window : %u", *event_number);
315
316 return 0;
317 }
318
319 /* Function that selects the color of status&exemode line */
320 static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
321 {
322 PropertiesLine prop_line;
323 prop_line.line_width = 2;
324 prop_line.style = GDK_LINE_SOLID;
325 prop_line.y = MIDDLE;
326 //GdkColormap *colormap = gdk_colormap_get_system();
327
328 if(process->state->s == LTTV_STATE_RUN) {
329 if(process->state->t == LTTV_STATE_USER_MODE)
330 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
331 else if(process->state->t == LTTV_STATE_SYSCALL)
332 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
333 else if(process->state->t == LTTV_STATE_TRAP)
334 prop_line.color = drawing_colors[COL_RUN_TRAP];
335 else if(process->state->t == LTTV_STATE_IRQ)
336 prop_line.color = drawing_colors[COL_RUN_IRQ];
337 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
338 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
339 else
340 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
341 } else if(process->state->s == LTTV_STATE_WAIT) {
342 /* We don't show if we wait while in user mode, trap, irq or syscall */
343 prop_line.color = drawing_colors[COL_WAIT];
344 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
345 /* We don't show if we wait for CPU while in user mode, trap, irq
346 * or syscall */
347 prop_line.color = drawing_colors[COL_WAIT_CPU];
348 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
349 prop_line.color = drawing_colors[COL_ZOMBIE];
350 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
351 prop_line.color = drawing_colors[COL_WAIT_FORK];
352 } else if(process->state->s == LTTV_STATE_EXIT) {
353 prop_line.color = drawing_colors[COL_EXIT];
354 } else if(process->state->s == LTTV_STATE_UNNAMED) {
355 prop_line.color = drawing_colors[COL_UNNAMED];
356 } else
357 g_assert(FALSE); /* UNKNOWN STATE */
358
359 return prop_line;
360
361 }
362
363 #if 0
364 static inline PropertiesLine prepare_status_line(LttvProcessState *process)
365 {
366 PropertiesLine prop_line;
367 prop_line.line_width = 2;
368 prop_line.style = GDK_LINE_SOLID;
369 prop_line.y = MIDDLE;
370 //GdkColormap *colormap = gdk_colormap_get_system();
371
372 g_debug("prepare_status_line for state : %s",
373 g_quark_to_string(process->state->s));
374
375 /* color of line : status of the process */
376 if(process->state->s == LTTV_STATE_UNNAMED)
377 prop_line.color = drawing_colors[COL_WHITE];
378 else if(process->state->s == LTTV_STATE_WAIT_FORK)
379 prop_line.color = drawing_colors[COL_WAIT_FORK];
380 else if(process->state->s == LTTV_STATE_WAIT_CPU)
381 prop_line.color = drawing_colors[COL_WAIT_CPU];
382 else if(process->state->s == LTTV_STATE_EXIT)
383 prop_line.color = drawing_colors[COL_EXIT];
384 else if(process->state->s == LTTV_STATE_ZOMBIE)
385 prop_line.color = drawing_colors[COL_ZOMBIE];
386 else if(process->state->s == LTTV_STATE_WAIT)
387 prop_line.color = drawing_colors[COL_WAIT];
388 else if(process->state->s == LTTV_STATE_RUN)
389 prop_line.color = drawing_colors[COL_RUN];
390 else
391 prop_line.color = drawing_colors[COL_WHITE];
392
393 //gdk_colormap_alloc_color(colormap,
394 // prop_line.color,
395 // FALSE,
396 // TRUE);
397
398 return prop_line;
399
400 }
401 #endif //0
402
403
404 /* before_schedchange_hook
405 *
406 * This function basically draw lines and icons. Two types of lines are drawn :
407 * one small (3 pixels?) representing the state of the process and the second
408 * type is thicker (10 pixels?) representing on which CPU a process is running
409 * (and this only in running state).
410 *
411 * Extremums of the lines :
412 * x_min : time of the last event context for this process kept in memory.
413 * x_max : time of the current event.
414 * y : middle of the process in the process list. The process is found in the
415 * list, therefore is it's position in pixels.
416 *
417 * The choice of lines'color is defined by the context of the last event for this
418 * process.
419 */
420
421
422 int before_schedchange_hook(void *hook_data, void *call_data)
423 {
424 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
425 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
426 ControlFlowData *control_flow_data = events_request->viewer_data;
427
428 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
429
430 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
431 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
432
433 LttEvent *e;
434 e = ltt_tracefile_get_event(tfc->tf);
435
436 LttTime evtime = ltt_event_time(e);
437
438 /* we are in a schedchange, before the state update. We must draw the
439 * items corresponding to the state before it changes : now is the right
440 * time to do it.
441 */
442
443 guint pid_out;
444 guint pid_in;
445 {
446 pid_out = ltt_event_get_long_unsigned(e, thf->f1);
447 pid_in = ltt_event_get_long_unsigned(e, thf->f2);
448 }
449
450 {
451 /* For the pid_out */
452 /* First, check if the current process is in the state computation
453 * process list. If it is there, that means we must add it right now and
454 * draw items from the beginning of the read for it. If it is not
455 * present, it's a new process and it was not present : it will
456 * be added after the state update. */
457 guint cpu = ltt_tracefile_num(tfc->tf);
458 LttvProcessState *process = ts->running_process[cpu];
459 /* unknown state, bad current pid */
460 if(process->pid != pid_out)
461 process = lttv_state_find_process(ts,
462 ltt_tracefile_num(tfc->tf), pid_out);
463
464 if(process != NULL) {
465 /* Well, the process_out existed : we must get it in the process hash
466 * or add it, and draw its items.
467 */
468 /* Add process to process list (if not present) */
469 guint pl_height = 0;
470 HashedProcessData *hashed_process_data = NULL;
471 ProcessList *process_list = control_flow_data->process_list;
472 LttTime birth = process->creation_time;
473
474 hashed_process_data = processlist_get_process_data(process_list,
475 pid_out,
476 process->cpu,
477 &birth,
478 tfc->t_context->index);
479 if(hashed_process_data == NULL)
480 {
481 g_assert(pid_out == 0 || pid_out != process->ppid);
482 /* Process not present */
483 ProcessInfo *process_info;
484 Drawing_t *drawing = control_flow_data->drawing;
485 processlist_add(process_list,
486 drawing,
487 pid_out,
488 process->cpu,
489 process->ppid,
490 &birth,
491 tfc->t_context->index,
492 process->name,
493 &pl_height,
494 &process_info,
495 &hashed_process_data);
496 gtk_widget_set_size_request(drawing->drawing_area,
497 -1,
498 pl_height);
499 gtk_widget_queue_draw(drawing->drawing_area);
500
501 }
502
503 /* Now, the process is in the state hash and our own process hash.
504 * We definitely can draw the items related to the ending state.
505 */
506
507 if(ltt_time_compare(hashed_process_data->next_good_time,
508 evtime) > 0)
509 {
510 if(hashed_process_data->x.middle_marked == FALSE) {
511
512 TimeWindow time_window =
513 lttvwindow_get_time_window(control_flow_data->tab);
514 #ifdef EXTRA_CHECK
515 if(ltt_time_compare(evtime, time_window.start_time) == -1
516 || ltt_time_compare(evtime, time_window.end_time) == 1)
517 return;
518 #endif //EXTRA_CHECK
519 Drawing_t *drawing = control_flow_data->drawing;
520 guint width = drawing->width;
521 guint x;
522 convert_time_to_pixels(
523 time_window,
524 evtime,
525 width,
526 &x);
527
528 /* Draw collision indicator */
529 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
530 gdk_draw_point(hashed_process_data->pixmap,
531 drawing->gc,
532 x,
533 (hashed_process_data->height/2)-3);
534 hashed_process_data->x.middle_marked = TRUE;
535 }
536 } else {
537 TimeWindow time_window =
538 lttvwindow_get_time_window(control_flow_data->tab);
539 #ifdef EXTRA_CHECK
540 if(ltt_time_compare(evtime, time_window.start_time) == -1
541 || ltt_time_compare(evtime, time_window.end_time) == 1)
542 return;
543 #endif //EXTRA_CHECK
544 Drawing_t *drawing = control_flow_data->drawing;
545 guint width = drawing->width;
546 guint x;
547 convert_time_to_pixels(
548 time_window,
549 evtime,
550 width,
551 &x);
552
553
554 /* Jump over draw if we are at the same x position */
555 if(x == hashed_process_data->x.middle &&
556 hashed_process_data->x.middle_used)
557 {
558 if(hashed_process_data->x.middle_marked == FALSE) {
559 /* Draw collision indicator */
560 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
561 gdk_draw_point(hashed_process_data->pixmap,
562 drawing->gc,
563 x,
564 (hashed_process_data->height/2)-3);
565 hashed_process_data->x.middle_marked = TRUE;
566 }
567 /* jump */
568 } else {
569 DrawContext draw_context;
570
571 /* Now create the drawing context that will be used to draw
572 * items related to the last state. */
573 draw_context.drawable = hashed_process_data->pixmap;
574 draw_context.gc = drawing->gc;
575 draw_context.pango_layout = drawing->pango_layout;
576 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
577 draw_context.drawinfo.end.x = x;
578
579 draw_context.drawinfo.y.over = 1;
580 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
581 draw_context.drawinfo.y.under = hashed_process_data->height;
582
583 draw_context.drawinfo.start.offset.over = 0;
584 draw_context.drawinfo.start.offset.middle = 0;
585 draw_context.drawinfo.start.offset.under = 0;
586 draw_context.drawinfo.end.offset.over = 0;
587 draw_context.drawinfo.end.offset.middle = 0;
588 draw_context.drawinfo.end.offset.under = 0;
589
590 {
591 /* Draw the line */
592 PropertiesLine prop_line = prepare_s_e_line(process);
593 draw_line((void*)&prop_line, (void*)&draw_context);
594
595 }
596 /* become the last x position */
597 hashed_process_data->x.middle = x;
598 hashed_process_data->x.middle_used = TRUE;
599 hashed_process_data->x.middle_marked = FALSE;
600
601 /* Calculate the next good time */
602 convert_pixels_to_time(width, x+1, time_window,
603 &hashed_process_data->next_good_time);
604 }
605 }
606 }
607 }
608
609 {
610 /* For the pid_in */
611 /* First, check if the current process is in the state computation
612 * process list. If it is there, that means we must add it right now and
613 * draw items from the beginning of the read for it. If it is not
614 * present, it's a new process and it was not present : it will
615 * be added after the state update. */
616 LttvProcessState *process;
617 process = lttv_state_find_process(ts,
618 ltt_tracefile_num(tfc->tf), pid_in);
619
620 if(process != NULL) {
621 /* Well, the process existed : we must get it in the process hash
622 * or add it, and draw its items.
623 */
624 /* Add process to process list (if not present) */
625 guint pl_height = 0;
626 HashedProcessData *hashed_process_data = NULL;
627 ProcessList *process_list = control_flow_data->process_list;
628 LttTime birth = process->creation_time;
629
630 hashed_process_data = processlist_get_process_data(process_list,
631 pid_in,
632 process->cpu,
633 &birth,
634 tfc->t_context->index);
635 if(hashed_process_data == NULL)
636 {
637 g_assert(pid_in == 0 || pid_in != process->ppid);
638 /* Process not present */
639 ProcessInfo *process_info;
640 Drawing_t *drawing = control_flow_data->drawing;
641 processlist_add(process_list,
642 drawing,
643 pid_in,
644 process->cpu,
645 process->ppid,
646 &birth,
647 tfc->t_context->index,
648 process->name,
649 &pl_height,
650 &process_info,
651 &hashed_process_data);
652 gtk_widget_set_size_request(drawing->drawing_area,
653 -1,
654 pl_height);
655 gtk_widget_queue_draw(drawing->drawing_area);
656
657 }
658 //We could set the current process and hash here, but will be done
659 //by after schedchange hook
660
661 /* Now, the process is in the state hash and our own process hash.
662 * We definitely can draw the items related to the ending state.
663 */
664
665 if(ltt_time_compare(hashed_process_data->next_good_time,
666 evtime) > 0)
667 {
668 if(hashed_process_data->x.middle_marked == FALSE) {
669
670 TimeWindow time_window =
671 lttvwindow_get_time_window(control_flow_data->tab);
672 #ifdef EXTRA_CHECK
673 if(ltt_time_compare(evtime, time_window.start_time) == -1
674 || ltt_time_compare(evtime, time_window.end_time) == 1)
675 return;
676 #endif //EXTRA_CHECK
677 Drawing_t *drawing = control_flow_data->drawing;
678 guint width = drawing->width;
679 guint x;
680 convert_time_to_pixels(
681 time_window,
682 evtime,
683 width,
684 &x);
685
686 /* Draw collision indicator */
687 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
688 gdk_draw_point(hashed_process_data->pixmap,
689 drawing->gc,
690 x,
691 (hashed_process_data->height/2)-3);
692 hashed_process_data->x.middle_marked = TRUE;
693 }
694 } else {
695 TimeWindow time_window =
696 lttvwindow_get_time_window(control_flow_data->tab);
697 #ifdef EXTRA_CHECK
698 if(ltt_time_compare(evtime, time_window.start_time) == -1
699 || ltt_time_compare(evtime, time_window.end_time) == 1)
700 return;
701 #endif //EXTRA_CHECK
702 Drawing_t *drawing = control_flow_data->drawing;
703 guint width = drawing->width;
704 guint x;
705
706 convert_time_to_pixels(
707 time_window,
708 evtime,
709 width,
710 &x);
711
712
713 /* Jump over draw if we are at the same x position */
714 if(x == hashed_process_data->x.middle &&
715 hashed_process_data->x.middle_used)
716 {
717 if(hashed_process_data->x.middle_marked == FALSE) {
718 /* Draw collision indicator */
719 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
720 gdk_draw_point(hashed_process_data->pixmap,
721 drawing->gc,
722 x,
723 (hashed_process_data->height/2)-3);
724 hashed_process_data->x.middle_marked = TRUE;
725 }
726 /* jump */
727 } else {
728 DrawContext draw_context;
729
730 /* Now create the drawing context that will be used to draw
731 * items related to the last state. */
732 draw_context.drawable = hashed_process_data->pixmap;
733 draw_context.gc = drawing->gc;
734 draw_context.pango_layout = drawing->pango_layout;
735 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
736 draw_context.drawinfo.end.x = x;
737
738 draw_context.drawinfo.y.over = 1;
739 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
740 draw_context.drawinfo.y.under = hashed_process_data->height;
741
742 draw_context.drawinfo.start.offset.over = 0;
743 draw_context.drawinfo.start.offset.middle = 0;
744 draw_context.drawinfo.start.offset.under = 0;
745 draw_context.drawinfo.end.offset.over = 0;
746 draw_context.drawinfo.end.offset.middle = 0;
747 draw_context.drawinfo.end.offset.under = 0;
748
749 {
750 /* Draw the line */
751 PropertiesLine prop_line = prepare_s_e_line(process);
752 draw_line((void*)&prop_line, (void*)&draw_context);
753 }
754
755
756 /* become the last x position */
757 hashed_process_data->x.middle = x;
758 hashed_process_data->x.middle_used = TRUE;
759 hashed_process_data->x.middle_marked = FALSE;
760
761 /* Calculate the next good time */
762 convert_pixels_to_time(width, x+1, time_window,
763 &hashed_process_data->next_good_time);
764 }
765 }
766 }
767 }
768 return 0;
769
770
771 #if 0
772 EventsRequest *events_request = (EventsRequest*)hook_data;
773 ControlFlowData *control_flow_data =
774 (ControlFlowData*)events_request->viewer_data;
775 Tab *tab = control_flow_data->tab;
776
777 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
778
779 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
780 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
781
782 LttEvent *e;
783 e = tfc->e;
784
785 LttTime evtime = ltt_event_time(e);
786 TimeWindow time_window =
787 lttvwindow_get_time_window(tab);
788
789 LttTime time_window.end_time = time_window.time_window.end_time;
790
791 //if(time < time_beg || time > time_end) return;
792 if(ltt_time_compare(evtime, time_window.start_time) == -1
793 || ltt_time_compare(evtime, time_window.end_time) == 1)
794 return;
795
796 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
797 {
798 g_debug("schedchange!");
799
800 /* Add process to process list (if not present) and get drawing "y" from
801 * process position */
802 guint pid_out, pid_in;
803 LttvProcessState *process_out, *process_in;
804 LttTime birth;
805 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
806
807 ProcessList *process_list = control_flow_data->process_list;
808
809
810 LttField *f = ltt_event_field(e);
811 LttField *element;
812 element = ltt_field_member(f,0);
813 pid_out = ltt_event_get_long_unsigned(e,element);
814 element = ltt_field_member(f,1);
815 pid_in = ltt_event_get_long_unsigned(e,element);
816 g_debug("out : %u in : %u", pid_out, pid_in);
817
818
819 /* Find process pid_out in the list... */
820 process_out = lttv_state_find_process(tfs, pid_out);
821 if(process_out == NULL) return 0;
822 g_debug("out : %s",g_quark_to_string(process_out->state->s));
823
824 birth = process_out->creation_time;
825 const gchar *name = g_quark_to_string(process_out->name);
826 HashedProcessData *hashed_process_data_out = NULL;
827
828 if(processlist_get_process_pixels(process_list,
829 pid_out,
830 &birth,
831 tfc->t_context->index,
832 &y_out,
833 &height,
834 &hashed_process_data_out) == 1)
835 {
836 /* Process not present */
837 processlist_add(process_list,
838 pid_out,
839 &birth,
840 tfc->t_context->index,
841 name,
842 &pl_height,
843 &hashed_process_data_out);
844 g_assert(processlist_get_process_pixels(process_list,
845 pid_out,
846 &birth,
847 tfc->t_context->index,
848 &y_out,
849 &height,
850 &hashed_process_data_out)==0);
851 drawing_insert_square( control_flow_data->drawing, y_out, height);
852 }
853 //g_free(name);
854
855 /* Find process pid_in in the list... */
856 process_in = lttv_state_find_process(tfs, pid_in);
857 if(process_in == NULL) return 0;
858 g_debug("in : %s",g_quark_to_string(process_in->state->s));
859
860 birth = process_in->creation_time;
861 name = g_quark_to_string(process_in->name);
862 HashedProcessData *hashed_process_data_in = NULL;
863
864 if(processlist_get_process_pixels(process_list,
865 pid_in,
866 &birth,
867 tfc->t_context->index,
868 &y_in,
869 &height,
870 &hashed_process_data_in) == 1)
871 {
872 /* Process not present */
873 processlist_add(process_list,
874 pid_in,
875 &birth,
876 tfc->t_context->index,
877 name,
878 &pl_height,
879 &hashed_process_data_in);
880 processlist_get_process_pixels(process_list,
881 pid_in,
882 &birth,
883 tfc->t_context->index,
884 &y_in,
885 &height,
886 &hashed_process_data_in);
887
888 drawing_insert_square( control_flow_data->drawing, y_in, height);
889 }
890 //g_free(name);
891
892
893 /* Find pixels corresponding to time of the event. If the time does
894 * not fit in the window, show a warning, not supposed to happend. */
895 guint x = 0;
896 guint width = control_flow_data->drawing->width;
897
898 LttTime time = ltt_event_time(e);
899
900 LttTime window_end = time_window.time_window.end_time;
901
902 convert_time_to_pixels(
903 time_window,
904 time,
905 width,
906 &x);
907 //assert(x <= width);
908 //
909 /* draw what represents the event for outgoing process. */
910
911 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
912 draw_context_out->current->modify_over->x = x;
913 draw_context_out->current->modify_under->x = x;
914 draw_context_out->current->modify_over->y = y_out;
915 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
916 draw_context_out->drawable = control_flow_data->drawing->pixmap;
917 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
918 GtkWidget *widget = control_flow_data->drawing->drawing_area;
919 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
920 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
921 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
922 //draw_context_out->gc = widget->style->black_gc;
923
924 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
925 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
926
927 /* Draw the line/background of the out process */
928 if(draw_context_out->previous->middle->x == -1)
929 {
930 draw_context_out->previous->over->x =
931 control_flow_data->drawing->damage_begin;
932 draw_context_out->previous->middle->x =
933 control_flow_data->drawing->damage_begin;
934 draw_context_out->previous->under->x =
935 control_flow_data->drawing->damage_begin;
936 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
937 }
938
939 draw_context_out->current->middle->x = x;
940 draw_context_out->current->over->x = x;
941 draw_context_out->current->under->x = x;
942 draw_context_out->current->middle->y = y_out + height/2;
943 draw_context_out->current->over->y = y_out;
944 draw_context_out->current->under->y = y_out + height;
945 draw_context_out->previous->middle->y = y_out + height/2;
946 draw_context_out->previous->over->y = y_out;
947 draw_context_out->previous->under->y = y_out + height;
948
949 draw_context_out->drawable = control_flow_data->drawing->pixmap;
950 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
951
952 if(process_out->state->s == LTTV_STATE_RUN)
953 {
954 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
955 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
956 draw_context_out->gc = control_flow_data->drawing->gc;
957
958 PropertiesBG prop_bg;
959 prop_bg.color = g_new(GdkColor,1);
960
961 switch(ltt_tracefile_num(tfc->tf)) {
962 case 0:
963 prop_bg.color->red = 0x1515;
964 prop_bg.color->green = 0x1515;
965 prop_bg.color->blue = 0x8c8c;
966 break;
967 case 1:
968 prop_bg.color->red = 0x4e4e;
969 prop_bg.color->green = 0xa9a9;
970 prop_bg.color->blue = 0xa4a4;
971 break;
972 case 2:
973 prop_bg.color->red = 0x7a7a;
974 prop_bg.color->green = 0x4a4a;
975 prop_bg.color->blue = 0x8b8b;
976 break;
977 case 3:
978 prop_bg.color->red = 0x8080;
979 prop_bg.color->green = 0x7777;
980 prop_bg.color->blue = 0x4747;
981 break;
982 default:
983 prop_bg.color->red = 0xe7e7;
984 prop_bg.color->green = 0xe7e7;
985 prop_bg.color->blue = 0xe7e7;
986 }
987
988 g_debug("calling from draw_event");
989 draw_bg((void*)&prop_bg, (void*)draw_context_out);
990 g_free(prop_bg.color);
991 //gdk_gc_unref(draw_context_out->gc);
992 }
993
994 draw_context_out->gc = widget->style->black_gc;
995
996 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
997 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
998 PropertiesText prop_text_out;
999 prop_text_out.foreground = &colorfg_out;
1000 prop_text_out.background = &colorbg_out;
1001 prop_text_out.size = 6;
1002 prop_text_out.position = OVER;
1003
1004 /* color of text : status of the process */
1005 if(process_out->state->s == LTTV_STATE_UNNAMED)
1006 {
1007 prop_text_out.foreground->red = 0xffff;
1008 prop_text_out.foreground->green = 0xffff;
1009 prop_text_out.foreground->blue = 0xffff;
1010 }
1011 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1012 {
1013 prop_text_out.foreground->red = 0x0fff;
1014 prop_text_out.foreground->green = 0xffff;
1015 prop_text_out.foreground->blue = 0xfff0;
1016 }
1017 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1018 {
1019 prop_text_out.foreground->red = 0xffff;
1020 prop_text_out.foreground->green = 0xffff;
1021 prop_text_out.foreground->blue = 0x0000;
1022 }
1023 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1024 {
1025 prop_text_out.foreground->red = 0xffff;
1026 prop_text_out.foreground->green = 0x0000;
1027 prop_text_out.foreground->blue = 0xffff;
1028 }
1029 else if(process_out->state->s == LTTV_STATE_WAIT)
1030 {
1031 prop_text_out.foreground->red = 0xffff;
1032 prop_text_out.foreground->green = 0x0000;
1033 prop_text_out.foreground->blue = 0x0000;
1034 }
1035 else if(process_out->state->s == LTTV_STATE_RUN)
1036 {
1037 prop_text_out.foreground->red = 0x0000;
1038 prop_text_out.foreground->green = 0xffff;
1039 prop_text_out.foreground->blue = 0x0000;
1040 }
1041 else
1042 {
1043 prop_text_out.foreground->red = 0xffff;
1044 prop_text_out.foreground->green = 0xffff;
1045 prop_text_out.foreground->blue = 0xffff;
1046 }
1047
1048
1049 /* Print status of the process : U, WF, WC, E, W, R */
1050 if(process_out->state->s == LTTV_STATE_UNNAMED)
1051 prop_text_out.text = "U->";
1052 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1053 prop_text_out.text = "WF->";
1054 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1055 prop_text_out.text = "WC->";
1056 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1057 prop_text_out.text = "E->";
1058 else if(process_out->state->s == LTTV_STATE_WAIT)
1059 prop_text_out.text = "W->";
1060 else if(process_out->state->s == LTTV_STATE_RUN)
1061 prop_text_out.text = "R->";
1062 else
1063 prop_text_out.text = "U";
1064
1065 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1066 //gdk_gc_unref(draw_context_out->gc);
1067
1068 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1069 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1070 draw_context_out->gc = control_flow_data->drawing->gc;
1071
1072 PropertiesLine prop_line_out;
1073 prop_line_out.color = g_new(GdkColor,1);
1074 prop_line_out.line_width = 2;
1075 prop_line_out.style = GDK_LINE_SOLID;
1076 prop_line_out.position = MIDDLE;
1077
1078 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
1079
1080 /* color of line : status of the process */
1081 if(process_out->state->s == LTTV_STATE_UNNAMED)
1082 {
1083 prop_line_out.color->red = 0xffff;
1084 prop_line_out.color->green = 0xffff;
1085 prop_line_out.color->blue = 0xffff;
1086 }
1087 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1088 {
1089 prop_line_out.color->red = 0x0fff;
1090 prop_line_out.color->green = 0xffff;
1091 prop_line_out.color->blue = 0xfff0;
1092 }
1093 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1094 {
1095 prop_line_out.color->red = 0xffff;
1096 prop_line_out.color->green = 0xffff;
1097 prop_line_out.color->blue = 0x0000;
1098 }
1099 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1100 {
1101 prop_line_out.color->red = 0xffff;
1102 prop_line_out.color->green = 0x0000;
1103 prop_line_out.color->blue = 0xffff;
1104 }
1105 else if(process_out->state->s == LTTV_STATE_WAIT)
1106 {
1107 prop_line_out.color->red = 0xffff;
1108 prop_line_out.color->green = 0x0000;
1109 prop_line_out.color->blue = 0x0000;
1110 }
1111 else if(process_out->state->s == LTTV_STATE_RUN)
1112 {
1113 prop_line_out.color->red = 0x0000;
1114 prop_line_out.color->green = 0xffff;
1115 prop_line_out.color->blue = 0x0000;
1116 }
1117 else
1118 {
1119 prop_line_out.color->red = 0xffff;
1120 prop_line_out.color->green = 0xffff;
1121 prop_line_out.color->blue = 0xffff;
1122 }
1123
1124 draw_line((void*)&prop_line_out, (void*)draw_context_out);
1125 g_free(prop_line_out.color);
1126 //gdk_gc_unref(draw_context_out->gc);
1127 /* Note : finishing line will have to be added when trace read over. */
1128
1129 /* Finally, update the drawing context of the pid_in. */
1130
1131 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1132 draw_context_in->current->modify_over->x = x;
1133 draw_context_in->current->modify_under->x = x;
1134 draw_context_in->current->modify_over->y = y_in;
1135 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1136 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1137 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1138 widget = control_flow_data->drawing->drawing_area;
1139 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1140 //draw_context_in->gc = widget->style->black_gc;
1141 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1142 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1143
1144 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1145 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1146
1147 /* Draw the line/bg of the in process */
1148 if(draw_context_in->previous->middle->x == -1)
1149 {
1150 draw_context_in->previous->over->x =
1151 control_flow_data->drawing->damage_begin;
1152 draw_context_in->previous->middle->x =
1153 control_flow_data->drawing->damage_begin;
1154 draw_context_in->previous->under->x =
1155 control_flow_data->drawing->damage_begin;
1156
1157 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
1158
1159 }
1160
1161 draw_context_in->current->middle->x = x;
1162 draw_context_in->current->over->x = x;
1163 draw_context_in->current->under->x = x;
1164 draw_context_in->current->middle->y = y_in + height/2;
1165 draw_context_in->current->over->y = y_in;
1166 draw_context_in->current->under->y = y_in + height;
1167 draw_context_in->previous->middle->y = y_in + height/2;
1168 draw_context_in->previous->over->y = y_in;
1169 draw_context_in->previous->under->y = y_in + height;
1170
1171 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1172 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1173
1174
1175 if(process_in->state->s == LTTV_STATE_RUN)
1176 {
1177 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1178 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1179 draw_context_in->gc = control_flow_data->drawing->gc;
1180
1181 PropertiesBG prop_bg;
1182 prop_bg.color = g_new(GdkColor,1);
1183
1184 switcht(ltt_tracefile_num(tfc->tf)) {
1185 case 0:
1186 prop_bg.color->red = 0x1515;
1187 prop_bg.color->green = 0x1515;
1188 prop_bg.color->blue = 0x8c8c;
1189 break;
1190 case 1:
1191 prop_bg.color->red = 0x4e4e;
1192 prop_bg.color->green = 0xa9a9;
1193 prop_bg.color->blue = 0xa4a4;
1194 break;
1195 case 2:
1196 prop_bg.color->red = 0x7a7a;
1197 prop_bg.color->green = 0x4a4a;
1198 prop_bg.color->blue = 0x8b8b;
1199 break;
1200 case 3:
1201 prop_bg.color->red = 0x8080;
1202 prop_bg.color->green = 0x7777;
1203 prop_bg.color->blue = 0x4747;
1204 break;
1205 default:
1206 prop_bg.color->red = 0xe7e7;
1207 prop_bg.color->green = 0xe7e7;
1208 prop_bg.color->blue = 0xe7e7;
1209 }
1210
1211
1212 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1213 g_free(prop_bg.color);
1214 //gdk_gc_unref(draw_context_in->gc);
1215 }
1216
1217 draw_context_in->gc = widget->style->black_gc;
1218
1219 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1220 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1221 PropertiesText prop_text_in;
1222 prop_text_in.foreground = &colorfg_in;
1223 prop_text_in.background = &colorbg_in;
1224 prop_text_in.size = 6;
1225 prop_text_in.position = OVER;
1226
1227 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1228 /* foreground of text : status of the process */
1229 if(process_in->state->s == LTTV_STATE_UNNAMED)
1230 {
1231 prop_text_in.foreground->red = 0xffff;
1232 prop_text_in.foreground->green = 0xffff;
1233 prop_text_in.foreground->blue = 0xffff;
1234 }
1235 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1236 {
1237 prop_text_in.foreground->red = 0x0fff;
1238 prop_text_in.foreground->green = 0xffff;
1239 prop_text_in.foreground->blue = 0xfff0;
1240 }
1241 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1242 {
1243 prop_text_in.foreground->red = 0xffff;
1244 prop_text_in.foreground->green = 0xffff;
1245 prop_text_in.foreground->blue = 0x0000;
1246 }
1247 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1248 {
1249 prop_text_in.foreground->red = 0xffff;
1250 prop_text_in.foreground->green = 0x0000;
1251 prop_text_in.foreground->blue = 0xffff;
1252 }
1253 else if(process_in->state->s == LTTV_STATE_WAIT)
1254 {
1255 prop_text_in.foreground->red = 0xffff;
1256 prop_text_in.foreground->green = 0x0000;
1257 prop_text_in.foreground->blue = 0x0000;
1258 }
1259 else if(process_in->state->s == LTTV_STATE_RUN)
1260 {
1261 prop_text_in.foreground->red = 0x0000;
1262 prop_text_in.foreground->green = 0xffff;
1263 prop_text_in.foreground->blue = 0x0000;
1264 }
1265 else
1266 {
1267 prop_text_in.foreground->red = 0xffff;
1268 prop_text_in.foreground->green = 0xffff;
1269 prop_text_in.foreground->blue = 0xffff;
1270 }
1271
1272
1273
1274 /* Print status of the process : U, WF, WC, E, W, R */
1275 if(process_in->state->s == LTTV_STATE_UNNAMED)
1276 prop_text_in.text = "U->";
1277 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1278 prop_text_in.text = "WF->";
1279 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1280 prop_text_in.text = "WC->";
1281 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1282 prop_text_in.text = "E->";
1283 else if(process_in->state->s == LTTV_STATE_WAIT)
1284 prop_text_in.text = "W->";
1285 else if(process_in->state->s == LTTV_STATE_RUN)
1286 prop_text_in.text = "R->";
1287 else
1288 prop_text_in.text = "U";
1289
1290 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1291 //gdk_gc_unref(draw_context_in->gc);
1292
1293 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1294 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1295 draw_context_in->gc = control_flow_data->drawing->gc;
1296
1297 PropertiesLine prop_line_in;
1298 prop_line_in.color = g_new(GdkColor,1);
1299 prop_line_in.line_width = 2;
1300 prop_line_in.style = GDK_LINE_SOLID;
1301 prop_line_in.position = MIDDLE;
1302
1303 /* color of line : status of the process */
1304 if(process_in->state->s == LTTV_STATE_UNNAMED)
1305 {
1306 prop_line_in.color->red = 0xffff;
1307 prop_line_in.color->green = 0xffff;
1308 prop_line_in.color->blue = 0xffff;
1309 }
1310 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1311 {
1312 prop_line_in.color->red = 0x0fff;
1313 prop_line_in.color->green = 0xffff;
1314 prop_line_in.color->blue = 0xfff0;
1315 }
1316 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1317 {
1318 prop_line_in.color->red = 0xffff;
1319 prop_line_in.color->green = 0xffff;
1320 prop_line_in.color->blue = 0x0000;
1321 }
1322 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1323 {
1324 prop_line_in.color->red = 0xffff;
1325 prop_line_in.color->green = 0x0000;
1326 prop_line_in.color->blue = 0xffff;
1327 }
1328 else if(process_in->state->s == LTTV_STATE_WAIT)
1329 {
1330 prop_line_in.color->red = 0xffff;
1331 prop_line_in.color->green = 0x0000;
1332 prop_line_in.color->blue = 0x0000;
1333 }
1334 else if(process_in->state->s == LTTV_STATE_RUN)
1335 {
1336 prop_line_in.color->red = 0x0000;
1337 prop_line_in.color->green = 0xffff;
1338 prop_line_in.color->blue = 0x0000;
1339 }
1340 else
1341 {
1342 prop_line_in.color->red = 0xffff;
1343 prop_line_in.color->green = 0xffff;
1344 prop_line_in.color->blue = 0xffff;
1345 }
1346
1347 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1348 g_free(prop_line_in.color);
1349 //gdk_gc_unref(draw_context_in->gc);
1350 }
1351
1352 return 0;
1353 #endif //0
1354
1355
1356
1357 /* Text dump */
1358 #ifdef DONTSHOW
1359 GString *string = g_string_new("");;
1360 gboolean field_names = TRUE, state = TRUE;
1361
1362 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1363 g_string_append_printf(string,"\n");
1364
1365 if(state) {
1366 g_string_append_printf(string, " %s",
1367 g_quark_to_string(tfs->process->state->s));
1368 }
1369
1370 g_info("%s",string->str);
1371
1372 g_string_free(string, TRUE);
1373
1374 /* End of text dump */
1375 #endif //DONTSHOW
1376
1377 }
1378
1379 /* after_schedchange_hook
1380 *
1381 * The draw after hook is called by the reading API to have a
1382 * particular event drawn on the screen.
1383 * @param hook_data ControlFlowData structure of the viewer.
1384 * @param call_data Event context.
1385 *
1386 * This function adds items to be drawn in a queue for each process.
1387 *
1388 */
1389 int after_schedchange_hook(void *hook_data, void *call_data)
1390 {
1391 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1392 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1393 ControlFlowData *control_flow_data = events_request->viewer_data;
1394
1395 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1396
1397 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1398
1399 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1400
1401 LttEvent *e;
1402 e = ltt_tracefile_get_event(tfc->tf);
1403
1404 LttTime evtime = ltt_event_time(e);
1405
1406 /* Add process to process list (if not present) */
1407 LttvProcessState *process_in;
1408 LttTime birth;
1409 guint pl_height = 0;
1410 HashedProcessData *hashed_process_data_in = NULL;
1411
1412 ProcessList *process_list = control_flow_data->process_list;
1413
1414 guint pid_in;
1415 {
1416 guint pid_out;
1417 pid_out = ltt_event_get_long_unsigned(e, thf->f1);
1418 pid_in = ltt_event_get_long_unsigned(e, thf->f2);
1419 }
1420
1421
1422 /* Find process pid_in in the list... */
1423 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
1424 //process_in = tfs->process;
1425 guint cpu = ltt_tracefile_num(tfc->tf);
1426 process_in = ts->running_process[cpu];
1427 /* It should exist, because we are after the state update. */
1428 #ifdef EXTRA_CHECK
1429 g_assert(process_in != NULL);
1430 #endif //EXTRA_CHECK
1431 birth = process_in->creation_time;
1432
1433 hashed_process_data_in = processlist_get_process_data(process_list,
1434 pid_in,
1435 process_in->cpu,
1436 &birth,
1437 tfc->t_context->index);
1438 if(hashed_process_data_in == NULL)
1439 {
1440 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1441 ProcessInfo *process_info;
1442 Drawing_t *drawing = control_flow_data->drawing;
1443 /* Process not present */
1444 processlist_add(process_list,
1445 drawing,
1446 pid_in,
1447 process_in->cpu,
1448 process_in->ppid,
1449 &birth,
1450 tfc->t_context->index,
1451 process_in->name,
1452 &pl_height,
1453 &process_info,
1454 &hashed_process_data_in);
1455 gtk_widget_set_size_request(drawing->drawing_area,
1456 -1,
1457 pl_height);
1458 gtk_widget_queue_draw(drawing->drawing_area);
1459 }
1460 /* Set the current process */
1461 process_list->current_hash_data[process_in->cpu] =
1462 hashed_process_data_in;
1463
1464 if(ltt_time_compare(hashed_process_data_in->next_good_time,
1465 evtime) <= 0)
1466 {
1467 TimeWindow time_window =
1468 lttvwindow_get_time_window(control_flow_data->tab);
1469
1470 #ifdef EXTRA_CHECK
1471 if(ltt_time_compare(evtime, time_window.start_time) == -1
1472 || ltt_time_compare(evtime, time_window.end_time) == 1)
1473 return;
1474 #endif //EXTRA_CHECK
1475 Drawing_t *drawing = control_flow_data->drawing;
1476 guint width = drawing->width;
1477 guint new_x;
1478
1479 convert_time_to_pixels(
1480 time_window,
1481 evtime,
1482 width,
1483 &new_x);
1484
1485 if(hashed_process_data_in->x.middle != new_x) {
1486 hashed_process_data_in->x.middle = new_x;
1487 hashed_process_data_in->x.middle_used = FALSE;
1488 hashed_process_data_in->x.middle_marked = FALSE;
1489 }
1490 }
1491 return 0;
1492
1493
1494
1495
1496
1497 #if 0
1498 EventsRequest *events_request = (EventsRequest*)hook_data;
1499 ControlFlowData *control_flow_data = events_request->viewer_data;
1500
1501 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1502
1503 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1504 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1505
1506
1507 LttEvent *e;
1508 e = tfc->e;
1509
1510 LttTime evtime = ltt_event_time(e);
1511 TimeWindow time_window =
1512 lttvwindow_get_time_window(control_flow_data->tab);
1513
1514 LttTime time_window.end_time = time_window.time_window.end_time;
1515
1516 //if(time < time_beg || time > time_end) return;
1517 if(ltt_time_compare(evtime, time_window.start_time) == -1
1518 || ltt_time_compare(evtime, time_window.end_time) == 1)
1519 return;
1520
1521
1522 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1523 {
1524 g_debug("schedchange!");
1525
1526 /* Add process to process list (if not present) and get drawing "y" from
1527 * process position */
1528 guint pid_out, pid_in;
1529 LttvProcessState *process_out, *process_in;
1530 LttTime birth;
1531 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1532
1533 ProcessList *process_list = control_flow_data->process_list;
1534
1535
1536 LttField *f = ltt_event_field(e);
1537 LttField *element;
1538 element = ltt_field_member(f,0);
1539 pid_out = ltt_event_get_long_unsigned(e,element);
1540 element = ltt_field_member(f,1);
1541 pid_in = ltt_event_get_long_unsigned(e,element);
1542 //g_debug("out : %u in : %u", pid_out, pid_in);
1543
1544
1545 /* Find process pid_out in the list... */
1546 process_out = lttv_state_find_process(tfs, pid_out);
1547 if(process_out == NULL) return 0;
1548 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1549
1550 birth = process_out->creation_time;
1551 gchar *name = strdup(g_quark_to_string(process_out->name));
1552 HashedProcessData *hashed_process_data_out = NULL;
1553
1554 if(processlist_get_process_pixels(process_list,
1555 pid_out,
1556 &birth,
1557 tfc->t_context->index,
1558 &y_out,
1559 &height,
1560 &hashed_process_data_out) == 1)
1561 {
1562 /* Process not present */
1563 processlist_add(process_list,
1564 pid_out,
1565 &birth,
1566 tfc->t_context->index,
1567 name,
1568 &pl_height,
1569 &hashed_process_data_out);
1570 processlist_get_process_pixels(process_list,
1571 pid_out,
1572 &birth,
1573 tfc->t_context->index,
1574 &y_out,
1575 &height,
1576 &hashed_process_data_out);
1577 drawing_insert_square( control_flow_data->drawing, y_out, height);
1578 }
1579
1580 g_free(name);
1581
1582 /* Find process pid_in in the list... */
1583 process_in = lttv_state_find_process(tfs, pid_in);
1584 if(process_in == NULL) return 0;
1585 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1586
1587 birth = process_in->creation_time;
1588 name = strdup(g_quark_to_string(process_in->name));
1589 HashedProcessData *hashed_process_data_in = NULL;
1590
1591 if(processlist_get_process_pixels(process_list,
1592 pid_in,
1593 &birth,
1594 tfc->t_context->index,
1595 &y_in,
1596 &height,
1597 &hashed_process_data_in) == 1)
1598 {
1599 /* Process not present */
1600 processlist_add(process_list,
1601 pid_in,
1602 &birth,
1603 tfc->t_context->index,
1604 name,
1605 &pl_height,
1606 &hashed_process_data_in);
1607 processlist_get_process_pixels(process_list,
1608 pid_in,
1609 &birth,
1610 tfc->t_context->index,
1611 &y_in,
1612 &height,
1613 &hashed_process_data_in);
1614
1615 drawing_insert_square( control_flow_data->drawing, y_in, height);
1616 }
1617 g_free(name);
1618
1619
1620 /* Find pixels corresponding to time of the event. If the time does
1621 * not fit in the window, show a warning, not supposed to happend. */
1622 //guint x = 0;
1623 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1624
1625 //LttTime time = ltt_event_time(e);
1626
1627 //LttTime window_end = time_window->time_window.end_time;
1628
1629
1630 //convert_time_to_pixels(
1631 // *time_window,
1632 // time,
1633 // width,
1634 // &x);
1635
1636 //assert(x <= width);
1637
1638 /* draw what represents the event for outgoing process. */
1639
1640 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1641 //draw_context_out->current->modify_over->x = x;
1642 draw_context_out->current->modify_over->y = y_out;
1643 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1644 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1645 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1646 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1647 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1648
1649 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1650 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1651
1652 /*if(process_out->state->s == LTTV_STATE_RUN)
1653 {
1654 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1655 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1656 PropertiesBG prop_bg;
1657 prop_bg.color = g_new(GdkColor,1);
1658
1659 prop_bg.color->red = 0xffff;
1660 prop_bg.color->green = 0xffff;
1661 prop_bg.color->blue = 0xffff;
1662
1663 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1664 g_free(prop_bg.color);
1665 gdk_gc_unref(draw_context_out->gc);
1666 }*/
1667
1668 draw_context_out->gc = widget->style->black_gc;
1669
1670 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1671 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1672 PropertiesText prop_text_out;
1673 prop_text_out.foreground = &colorfg_out;
1674 prop_text_out.background = &colorbg_out;
1675 prop_text_out.size = 6;
1676 prop_text_out.position = OVER;
1677
1678 /* color of text : status of the process */
1679 if(process_out->state->s == LTTV_STATE_UNNAMED)
1680 {
1681 prop_text_out.foreground->red = 0xffff;
1682 prop_text_out.foreground->green = 0xffff;
1683 prop_text_out.foreground->blue = 0xffff;
1684 }
1685 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1686 {
1687 prop_text_out.foreground->red = 0x0fff;
1688 prop_text_out.foreground->green = 0xffff;
1689 prop_text_out.foreground->blue = 0xfff0;
1690 }
1691 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1692 {
1693 prop_text_out.foreground->red = 0xffff;
1694 prop_text_out.foreground->green = 0xffff;
1695 prop_text_out.foreground->blue = 0x0000;
1696 }
1697 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1698 {
1699 prop_text_out.foreground->red = 0xffff;
1700 prop_text_out.foreground->green = 0x0000;
1701 prop_text_out.foreground->blue = 0xffff;
1702 }
1703 else if(process_out->state->s == LTTV_STATE_WAIT)
1704 {
1705 prop_text_out.foreground->red = 0xffff;
1706 prop_text_out.foreground->green = 0x0000;
1707 prop_text_out.foreground->blue = 0x0000;
1708 }
1709 else if(process_out->state->s == LTTV_STATE_RUN)
1710 {
1711 prop_text_out.foreground->red = 0x0000;
1712 prop_text_out.foreground->green = 0xffff;
1713 prop_text_out.foreground->blue = 0x0000;
1714 }
1715 else
1716 {
1717 prop_text_out.foreground->red = 0xffff;
1718 prop_text_out.foreground->green = 0xffff;
1719 prop_text_out.foreground->blue = 0xffff;
1720 }
1721
1722 /* Print status of the process : U, WF, WC, E, W, R */
1723 if(process_out->state->s == LTTV_STATE_UNNAMED)
1724 prop_text_out.text = "U";
1725 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1726 prop_text_out.text = "WF";
1727 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1728 prop_text_out.text = "WC";
1729 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1730 prop_text_out.text = "E";
1731 else if(process_out->state->s == LTTV_STATE_WAIT)
1732 prop_text_out.text = "W";
1733 else if(process_out->state->s == LTTV_STATE_RUN)
1734 prop_text_out.text = "R";
1735 else
1736 prop_text_out.text = "U";
1737
1738 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1739
1740 //gdk_gc_unref(draw_context_out->gc);
1741
1742 draw_context_out->current->middle->y = y_out+height/2;
1743 draw_context_out->current->over->y = y_out;
1744 draw_context_out->current->under->y = y_out+height;
1745 draw_context_out->current->status = process_out->state->s;
1746
1747 /* for pid_out : remove previous, Prev = current, new current (default) */
1748 g_free(draw_context_out->previous->modify_under);
1749 g_free(draw_context_out->previous->modify_middle);
1750 g_free(draw_context_out->previous->modify_over);
1751 g_free(draw_context_out->previous->under);
1752 g_free(draw_context_out->previous->middle);
1753 g_free(draw_context_out->previous->over);
1754 g_free(draw_context_out->previous);
1755
1756 draw_context_out->previous = draw_context_out->current;
1757
1758 draw_context_out->current = g_new(DrawInfo,1);
1759 draw_context_out->current->over = g_new(ItemInfo,1);
1760 draw_context_out->current->over->x = -1;
1761 draw_context_out->current->over->y = -1;
1762 draw_context_out->current->middle = g_new(ItemInfo,1);
1763 draw_context_out->current->middle->x = -1;
1764 draw_context_out->current->middle->y = -1;
1765 draw_context_out->current->under = g_new(ItemInfo,1);
1766 draw_context_out->current->under->x = -1;
1767 draw_context_out->current->under->y = -1;
1768 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1769 draw_context_out->current->modify_over->x = -1;
1770 draw_context_out->current->modify_over->y = -1;
1771 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1772 draw_context_out->current->modify_middle->x = -1;
1773 draw_context_out->current->modify_middle->y = -1;
1774 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1775 draw_context_out->current->modify_under->x = -1;
1776 draw_context_out->current->modify_under->y = -1;
1777 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1778
1779 /* Finally, update the drawing context of the pid_in. */
1780
1781 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1782 //draw_context_in->current->modify_over->x = x;
1783 draw_context_in->current->modify_over->y = y_in;
1784 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1785 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1786 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1787 widget = control_flow_data->drawing->drawing_area;
1788 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1789
1790 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1791 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1792
1793 /*if(process_in->state->s == LTTV_STATE_RUN)
1794 {
1795 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1796 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1797 PropertiesBG prop_bg;
1798 prop_bg.color = g_new(GdkColor,1);
1799
1800 prop_bg.color->red = 0xffff;
1801 prop_bg.color->green = 0xffff;
1802 prop_bg.color->blue = 0xffff;
1803
1804 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1805 g_free(prop_bg.color);
1806 gdk_gc_unref(draw_context_in->gc);
1807 }*/
1808
1809 draw_context_in->gc = widget->style->black_gc;
1810
1811 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1812 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1813 PropertiesText prop_text_in;
1814 prop_text_in.foreground = &colorfg_in;
1815 prop_text_in.background = &colorbg_in;
1816 prop_text_in.size = 6;
1817 prop_text_in.position = OVER;
1818
1819 /* foreground of text : status of the process */
1820 if(process_in->state->s == LTTV_STATE_UNNAMED)
1821 {
1822 prop_text_in.foreground->red = 0xffff;
1823 prop_text_in.foreground->green = 0xffff;
1824 prop_text_in.foreground->blue = 0xffff;
1825 }
1826 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1827 {
1828 prop_text_in.foreground->red = 0x0fff;
1829 prop_text_in.foreground->green = 0xffff;
1830 prop_text_in.foreground->blue = 0xfff0;
1831 }
1832 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1833 {
1834 prop_text_in.foreground->red = 0xffff;
1835 prop_text_in.foreground->green = 0xffff;
1836 prop_text_in.foreground->blue = 0x0000;
1837 }
1838 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1839 {
1840 prop_text_in.foreground->red = 0xffff;
1841 prop_text_in.foreground->green = 0x0000;
1842 prop_text_in.foreground->blue = 0xffff;
1843 }
1844 else if(process_in->state->s == LTTV_STATE_WAIT)
1845 {
1846 prop_text_in.foreground->red = 0xffff;
1847 prop_text_in.foreground->green = 0x0000;
1848 prop_text_in.foreground->blue = 0x0000;
1849 }
1850 else if(process_in->state->s == LTTV_STATE_RUN)
1851 {
1852 prop_text_in.foreground->red = 0x0000;
1853 prop_text_in.foreground->green = 0xffff;
1854 prop_text_in.foreground->blue = 0x0000;
1855 }
1856 else
1857 {
1858 prop_text_in.foreground->red = 0xffff;
1859 prop_text_in.foreground->green = 0xffff;
1860 prop_text_in.foreground->blue = 0xffff;
1861 }
1862
1863
1864 /* Print status of the process : U, WF, WC, E, W, R */
1865 if(process_in->state->s == LTTV_STATE_UNNAMED)
1866 prop_text_in.text = "U";
1867 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1868 prop_text_in.text = "WF";
1869 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1870 prop_text_in.text = "WC";
1871 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1872 prop_text_in.text = "E";
1873 else if(process_in->state->s == LTTV_STATE_WAIT)
1874 prop_text_in.text = "W";
1875 else if(process_in->state->s == LTTV_STATE_RUN)
1876 prop_text_in.text = "R";
1877 else
1878 prop_text_in.text = "U";
1879
1880 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1881
1882
1883 if(process_in->state->s == LTTV_STATE_RUN)
1884 {
1885 gchar tmp[255];
1886 prop_text_in.foreground = &colorfg_in;
1887 prop_text_in.background = &colorbg_in;
1888 prop_text_in.foreground->red = 0xffff;
1889 prop_text_in.foreground->green = 0xffff;
1890 prop_text_in.foreground->blue = 0xffff;
1891 prop_text_in.size = 6;
1892 prop_text_in.position = UNDER;
1893
1894 prop_text_in.text = g_new(gchar, 260);
1895 strcpy(prop_text_in.text, "CPU ");
1896 snprintf(tmp, 255, "%u", ltt_tracefile_num(tfc->tf));
1897 strcat(prop_text_in.text, tmp);
1898
1899 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1900 g_free(prop_text_in.text);
1901 }
1902
1903
1904 draw_context_in->current->middle->y = y_in+height/2;
1905 draw_context_in->current->over->y = y_in;
1906 draw_context_in->current->under->y = y_in+height;
1907 draw_context_in->current->status = process_in->state->s;
1908
1909 /* for pid_in : remove previous, Prev = current, new current (default) */
1910 g_free(draw_context_in->previous->modify_under);
1911 g_free(draw_context_in->previous->modify_middle);
1912 g_free(draw_context_in->previous->modify_over);
1913 g_free(draw_context_in->previous->under);
1914 g_free(draw_context_in->previous->middle);
1915 g_free(draw_context_in->previous->over);
1916 g_free(draw_context_in->previous);
1917
1918 draw_context_in->previous = draw_context_in->current;
1919
1920 draw_context_in->current = g_new(DrawInfo,1);
1921 draw_context_in->current->over = g_new(ItemInfo,1);
1922 draw_context_in->current->over->x = -1;
1923 draw_context_in->current->over->y = -1;
1924 draw_context_in->current->middle = g_new(ItemInfo,1);
1925 draw_context_in->current->middle->x = -1;
1926 draw_context_in->current->middle->y = -1;
1927 draw_context_in->current->under = g_new(ItemInfo,1);
1928 draw_context_in->current->under->x = -1;
1929 draw_context_in->current->under->y = -1;
1930 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1931 draw_context_in->current->modify_over->x = -1;
1932 draw_context_in->current->modify_over->y = -1;
1933 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1934 draw_context_in->current->modify_middle->x = -1;
1935 draw_context_in->current->modify_middle->y = -1;
1936 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1937 draw_context_in->current->modify_under->x = -1;
1938 draw_context_in->current->modify_under->y = -1;
1939 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1940
1941 }
1942
1943 return 0;
1944 #endif //0
1945 }
1946
1947 #if 0
1948 static inline PropertiesLine prepare_execmode_line(LttvProcessState *process)
1949 {
1950 PropertiesLine prop_line;
1951 prop_line.line_width = 1;
1952 prop_line.style = GDK_LINE_SOLID;
1953 prop_line.y = OVER;
1954 //GdkColormap *colormap = gdk_colormap_get_system();
1955
1956 /* color of line : execution mode of the process */
1957 if(process->state->t == LTTV_STATE_USER_MODE)
1958 prop_line.color = drawing_colors[COL_USER_MODE];
1959 else if(process->state->t == LTTV_STATE_SYSCALL)
1960 prop_line.color = drawing_colors[COL_SYSCALL];
1961 else if(process->state->t == LTTV_STATE_TRAP)
1962 prop_line.color = drawing_colors[COL_TRAP];
1963 else if(process->state->t == LTTV_STATE_IRQ)
1964 prop_line.color = drawing_colors[COL_IRQ];
1965 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1966 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1967 else
1968 prop_line.color = drawing_colors[COL_WHITE];
1969
1970 //gdk_colormap_alloc_color(colormap,
1971 // prop_line.color,
1972 // FALSE,
1973 // TRUE);
1974
1975 return prop_line;
1976
1977 }
1978 #endif //0
1979
1980
1981 /* before_execmode_hook
1982 *
1983 * This function basically draw lines and icons. Two types of lines are drawn :
1984 * one small (3 pixels?) representing the state of the process and the second
1985 * type is thicker (10 pixels?) representing on which CPU a process is running
1986 * (and this only in running state).
1987 *
1988 * Extremums of the lines :
1989 * x_min : time of the last event context for this process kept in memory.
1990 * x_max : time of the current event.
1991 * y : middle of the process in the process list. The process is found in the
1992 * list, therefore is it's position in pixels.
1993 *
1994 * The choice of lines'color is defined by the context of the last event for this
1995 * process.
1996 */
1997
1998
1999 int before_execmode_hook(void *hook_data, void *call_data)
2000 {
2001 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2002 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2003 ControlFlowData *control_flow_data = events_request->viewer_data;
2004
2005 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2006
2007 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2008
2009 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2010
2011 LttEvent *e;
2012 e = ltt_tracefile_get_event(tfc->tf);
2013
2014 LttTime evtime = ltt_event_time(e);
2015
2016 /* we are in a execmode, before the state update. We must draw the
2017 * items corresponding to the state before it changes : now is the right
2018 * time to do it.
2019 */
2020 /* For the pid */
2021 //LttvProcessState *process = tfs->process;
2022 guint cpu = ltt_tracefile_num(tfc->tf);
2023 LttvProcessState *process = ts->running_process[cpu];
2024 g_assert(process != NULL);
2025
2026 guint pid = process->pid;
2027
2028 /* Well, the process_out existed : we must get it in the process hash
2029 * or add it, and draw its items.
2030 */
2031 /* Add process to process list (if not present) */
2032 guint pl_height = 0;
2033 HashedProcessData *hashed_process_data = NULL;
2034 ProcessList *process_list = control_flow_data->process_list;
2035 LttTime birth = process->creation_time;
2036
2037 if(likely(process_list->current_hash_data[cpu] != NULL)) {
2038 hashed_process_data = process_list->current_hash_data[cpu];
2039 } else {
2040 hashed_process_data = processlist_get_process_data(process_list,
2041 pid,
2042 process->cpu,
2043 &birth,
2044 tfc->t_context->index);
2045 if(unlikely(hashed_process_data == NULL))
2046 {
2047 g_assert(pid == 0 || pid != process->ppid);
2048 ProcessInfo *process_info;
2049 /* Process not present */
2050 Drawing_t *drawing = control_flow_data->drawing;
2051 processlist_add(process_list,
2052 drawing,
2053 pid,
2054 process->cpu,
2055 process->ppid,
2056 &birth,
2057 tfc->t_context->index,
2058 process->name,
2059 &pl_height,
2060 &process_info,
2061 &hashed_process_data);
2062 gtk_widget_set_size_request(drawing->drawing_area,
2063 -1,
2064 pl_height);
2065 gtk_widget_queue_draw(drawing->drawing_area);
2066 }
2067 /* Set the current process */
2068 process_list->current_hash_data[process->cpu] =
2069 hashed_process_data;
2070 }
2071
2072 /* Now, the process is in the state hash and our own process hash.
2073 * We definitely can draw the items related to the ending state.
2074 */
2075
2076 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2077 evtime) > 0))
2078 {
2079 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2080 TimeWindow time_window =
2081 lttvwindow_get_time_window(control_flow_data->tab);
2082
2083 #ifdef EXTRA_CHECK
2084 if(ltt_time_compare(evtime, time_window.start_time) == -1
2085 || ltt_time_compare(evtime, time_window.end_time) == 1)
2086 return;
2087 #endif //EXTRA_CHECK
2088 Drawing_t *drawing = control_flow_data->drawing;
2089 guint width = drawing->width;
2090 guint x;
2091 convert_time_to_pixels(
2092 time_window,
2093 evtime,
2094 width,
2095 &x);
2096
2097 /* Draw collision indicator */
2098 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2099 gdk_draw_point(hashed_process_data->pixmap,
2100 drawing->gc,
2101 x,
2102 (hashed_process_data->height/2)-3);
2103 hashed_process_data->x.middle_marked = TRUE;
2104 }
2105 } else {
2106 TimeWindow time_window =
2107 lttvwindow_get_time_window(control_flow_data->tab);
2108
2109 #ifdef EXTRA_CHECK
2110 if(ltt_time_compare(evtime, time_window.start_time) == -1
2111 || ltt_time_compare(evtime, time_window.end_time) == 1)
2112 return;
2113 #endif //EXTRA_CHECK
2114 Drawing_t *drawing = control_flow_data->drawing;
2115 guint width = drawing->width;
2116 guint x;
2117
2118 convert_time_to_pixels(
2119 time_window,
2120 evtime,
2121 width,
2122 &x);
2123
2124
2125 /* Jump over draw if we are at the same x position */
2126 if(unlikely(x == hashed_process_data->x.middle &&
2127 hashed_process_data->x.middle_used))
2128 {
2129 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2130 /* Draw collision indicator */
2131 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2132 gdk_draw_point(hashed_process_data->pixmap,
2133 drawing->gc,
2134 x,
2135 (hashed_process_data->height/2)-3);
2136 hashed_process_data->x.middle_marked = TRUE;
2137 }
2138 /* jump */
2139 } else {
2140
2141 DrawContext draw_context;
2142 /* Now create the drawing context that will be used to draw
2143 * items related to the last state. */
2144 draw_context.drawable = hashed_process_data->pixmap;
2145 draw_context.gc = drawing->gc;
2146 draw_context.pango_layout = drawing->pango_layout;
2147 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2148 draw_context.drawinfo.end.x = x;
2149
2150 draw_context.drawinfo.y.over = 1;
2151 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2152 draw_context.drawinfo.y.under = hashed_process_data->height;
2153
2154 draw_context.drawinfo.start.offset.over = 0;
2155 draw_context.drawinfo.start.offset.middle = 0;
2156 draw_context.drawinfo.start.offset.under = 0;
2157 draw_context.drawinfo.end.offset.over = 0;
2158 draw_context.drawinfo.end.offset.middle = 0;
2159 draw_context.drawinfo.end.offset.under = 0;
2160
2161 {
2162 /* Draw the line */
2163 PropertiesLine prop_line = prepare_s_e_line(process);
2164 draw_line((void*)&prop_line, (void*)&draw_context);
2165
2166 }
2167 /* become the last x position */
2168 hashed_process_data->x.middle = x;
2169 hashed_process_data->x.middle_used = TRUE;
2170 hashed_process_data->x.middle_marked = FALSE;
2171
2172 /* Calculate the next good time */
2173 convert_pixels_to_time(width, x+1, time_window,
2174 &hashed_process_data->next_good_time);
2175 }
2176 }
2177
2178 return 0;
2179 }
2180
2181 /* after_execmode_hook
2182 *
2183 * The draw after hook is called by the reading API to have a
2184 * particular event drawn on the screen.
2185 * @param hook_data ControlFlowData structure of the viewer.
2186 * @param call_data Event context.
2187 *
2188 * This function adds items to be drawn in a queue for each process.
2189 *
2190 */
2191 #if 0
2192 int after_execmode_hook(void *hook_data, void *call_data)
2193 {
2194 /**************** DOES NOTHING!! *************/
2195 /* hook desactivated in drawing.c */
2196 return 0;
2197
2198
2199 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2200 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2201 ControlFlowData *control_flow_data = events_request->viewer_data;
2202
2203 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2204
2205 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2206
2207 LttEvent *e;
2208 e = ltt_tracefile_get_event(tfc->tf);
2209
2210 LttTime evtime = ltt_event_time(e);
2211
2212 /* Add process to process list (if not present) */
2213 LttvProcessState *process;
2214 LttTime birth;
2215 guint pl_height = 0;
2216 HashedProcessData *hashed_process_data = NULL;
2217
2218 ProcessList *process_list = control_flow_data->process_list;
2219
2220 /* Find process pid_in in the list... */
2221 process = tfs->process;
2222 /* It should exist, because we are after the state update. */
2223 g_assert(process != NULL);
2224
2225 guint pid = process->pid;
2226
2227 birth = process->creation_time;
2228
2229 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL)) {
2230 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
2231 } else {
2232 hashed_process_data = processlist_get_process_data(process_list,
2233 pid,
2234 process->last_cpu_index,
2235 &birth,
2236 tfc->t_context->index);
2237 if(unlikely(hashed_process_data == NULL))
2238 {
2239 g_assert(pid == 0 || pid != process->ppid);
2240 /* Process not present */
2241 Drawing_t *drawing = control_flow_data->drawing;
2242 const gchar *name = g_quark_to_string(process->name);
2243 ProcessInfo *process_info;
2244 processlist_add(process_list,
2245 drawing,
2246 pid,
2247 process->last_cpu_index,
2248 process->ppid,
2249 &birth,
2250 tfc->t_context->index,
2251 name,
2252 &pl_height,
2253 &process_info,
2254 &hashed_process_data);
2255 gtk_widget_set_size_request(drawing->drawing_area,
2256 -1,
2257 pl_height);
2258 gtk_widget_queue_draw(drawing->drawing_area);
2259 }
2260 /* Set the current process */
2261 process_list->current_hash_data[process->last_cpu_index] =
2262 hashed_process_data;
2263 }
2264
2265 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2266 evtime) <= 0))
2267 {
2268 TimeWindow time_window =
2269 lttvwindow_get_time_window(control_flow_data->tab);
2270
2271 #ifdef EXTRA_CHECK
2272 if(ltt_time_compare(evtime, time_window.start_time) == -1
2273 || ltt_time_compare(evtime, time_window.end_time) == 1)
2274 return;
2275 #endif //EXTRA_CHECK
2276 Drawing_t *drawing = control_flow_data->drawing;
2277 guint width = drawing->width;
2278 guint new_x;
2279
2280 convert_time_to_pixels(
2281 time_window,
2282 evtime,
2283 width,
2284 &new_x);
2285
2286 if(hashed_process_data->x.middle != new_x) {
2287 hashed_process_data->x.middle = new_x;
2288 hashed_process_data->x.middle_used = FALSE;
2289 hashed_process_data->x.middle_marked = FALSE;
2290 }
2291 }
2292 return 0;
2293 }
2294 #endif //0
2295
2296
2297
2298 /* before_process_exit_hook
2299 *
2300 * Draw lines for process event.
2301 *
2302 * @param hook_data ControlFlowData structure of the viewer.
2303 * @param call_data Event context.
2304 *
2305 * This function adds items to be drawn in a queue for each process.
2306 *
2307 */
2308
2309
2310 int before_process_exit_hook(void *hook_data, void *call_data)
2311 {
2312 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2313 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2314
2315 ControlFlowData *control_flow_data = events_request->viewer_data;
2316
2317 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2318
2319 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2320
2321 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2322
2323 LttEvent *e;
2324 e = ltt_tracefile_get_event(tfc->tf);
2325
2326 LttTime evtime = ltt_event_time(e);
2327
2328 /* Add process to process list (if not present) */
2329 //LttvProcessState *process = tfs->process;
2330 guint cpu = ltt_tracefile_num(tfc->tf);
2331 LttvProcessState *process = ts->running_process[cpu];
2332 guint pid = process->pid;
2333 LttTime birth;
2334 guint pl_height = 0;
2335 HashedProcessData *hashed_process_data = NULL;
2336
2337 ProcessList *process_list = control_flow_data->process_list;
2338
2339 g_assert(process != NULL);
2340
2341 birth = process->creation_time;
2342
2343 if(likely(process_list->current_hash_data[cpu] != NULL)) {
2344 hashed_process_data = process_list->current_hash_data[cpu];
2345 } else {
2346 hashed_process_data = processlist_get_process_data(process_list,
2347 pid,
2348 process->cpu,
2349 &birth,
2350 tfc->t_context->index);
2351 if(unlikely(hashed_process_data == NULL))
2352 {
2353 g_assert(pid == 0 || pid != process->ppid);
2354 /* Process not present */
2355 Drawing_t *drawing = control_flow_data->drawing;
2356 ProcessInfo *process_info;
2357 processlist_add(process_list,
2358 drawing,
2359 pid,
2360 process->cpu,
2361 process->ppid,
2362 &birth,
2363 tfc->t_context->index,
2364 process->name,
2365 &pl_height,
2366 &process_info,
2367 &hashed_process_data);
2368 gtk_widget_set_size_request(drawing->drawing_area,
2369 -1,
2370 pl_height);
2371 gtk_widget_queue_draw(drawing->drawing_area);
2372 }
2373 }
2374
2375 /* Now, the process is in the state hash and our own process hash.
2376 * We definitely can draw the items related to the ending state.
2377 */
2378
2379 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2380 evtime) > 0))
2381 {
2382 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2383 TimeWindow time_window =
2384 lttvwindow_get_time_window(control_flow_data->tab);
2385
2386 #ifdef EXTRA_CHECK
2387 if(ltt_time_compare(evtime, time_window.start_time) == -1
2388 || ltt_time_compare(evtime, time_window.end_time) == 1)
2389 return;
2390 #endif //EXTRA_CHECK
2391 Drawing_t *drawing = control_flow_data->drawing;
2392 guint width = drawing->width;
2393 guint x;
2394 convert_time_to_pixels(
2395 time_window,
2396 evtime,
2397 width,
2398 &x);
2399
2400 /* Draw collision indicator */
2401 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2402 gdk_draw_point(hashed_process_data->pixmap,
2403 drawing->gc,
2404 x,
2405 (hashed_process_data->height/2)-3);
2406 hashed_process_data->x.middle_marked = TRUE;
2407 }
2408 } else {
2409 TimeWindow time_window =
2410 lttvwindow_get_time_window(control_flow_data->tab);
2411
2412 #ifdef EXTRA_CHECK
2413 if(ltt_time_compare(evtime, time_window.start_time) == -1
2414 || ltt_time_compare(evtime, time_window.end_time) == 1)
2415 return;
2416 #endif //EXTRA_CHECK
2417 Drawing_t *drawing = control_flow_data->drawing;
2418 guint width = drawing->width;
2419 guint x;
2420
2421 convert_time_to_pixels(
2422 time_window,
2423 evtime,
2424 width,
2425 &x);
2426
2427
2428 /* Jump over draw if we are at the same x position */
2429 if(unlikely(x == hashed_process_data->x.middle &&
2430 hashed_process_data->x.middle_used))
2431 {
2432 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2433 /* Draw collision indicator */
2434 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2435 gdk_draw_point(hashed_process_data->pixmap,
2436 drawing->gc,
2437 x,
2438 (hashed_process_data->height/2)-3);
2439 hashed_process_data->x.middle_marked = TRUE;
2440 }
2441 /* jump */
2442 } else {
2443 DrawContext draw_context;
2444
2445 /* Now create the drawing context that will be used to draw
2446 * items related to the last state. */
2447 draw_context.drawable = hashed_process_data->pixmap;
2448 draw_context.gc = drawing->gc;
2449 draw_context.pango_layout = drawing->pango_layout;
2450 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2451 draw_context.drawinfo.end.x = x;
2452
2453 draw_context.drawinfo.y.over = 1;
2454 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2455 draw_context.drawinfo.y.under = hashed_process_data->height;
2456
2457 draw_context.drawinfo.start.offset.over = 0;
2458 draw_context.drawinfo.start.offset.middle = 0;
2459 draw_context.drawinfo.start.offset.under = 0;
2460 draw_context.drawinfo.end.offset.over = 0;
2461 draw_context.drawinfo.end.offset.middle = 0;
2462 draw_context.drawinfo.end.offset.under = 0;
2463
2464 {
2465 /* Draw the line */
2466 PropertiesLine prop_line = prepare_s_e_line(process);
2467 draw_line((void*)&prop_line, (void*)&draw_context);
2468
2469 }
2470 /* become the last x position */
2471 hashed_process_data->x.middle = x;
2472 hashed_process_data->x.middle_used = TRUE;
2473 hashed_process_data->x.middle_marked = FALSE;
2474
2475 /* Calculate the next good time */
2476 convert_pixels_to_time(width, x+1, time_window,
2477 &hashed_process_data->next_good_time);
2478 }
2479 }
2480
2481 return 0;
2482
2483 }
2484
2485
2486
2487 /* before_process_release_hook
2488 *
2489 * Draw lines for process event.
2490 *
2491 * @param hook_data ControlFlowData structure of the viewer.
2492 * @param call_data Event context.
2493 *
2494 * This function adds items to be drawn in a queue for each process.
2495 *
2496 */
2497
2498
2499 int before_process_release_hook(void *hook_data, void *call_data)
2500 {
2501 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2502 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2503
2504 ControlFlowData *control_flow_data = events_request->viewer_data;
2505
2506 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2507
2508 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2509
2510 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2511
2512 LttEvent *e;
2513 e = ltt_tracefile_get_event(tfc->tf);
2514
2515 LttTime evtime = ltt_event_time(e);
2516
2517
2518 guint pid;
2519 {
2520 pid = ltt_event_get_long_unsigned(e, thf->f1);
2521 }
2522
2523 /* Add process to process list (if not present) */
2524 /* Don't care about the process if it's not in the state hash already :
2525 * that means a process that has never done anything in the trace and
2526 * unknown suddently gets destroyed : no state meaningful to show. */
2527 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2528
2529 if(process != NULL) {
2530 LttTime birth;
2531 guint pl_height = 0;
2532 HashedProcessData *hashed_process_data = NULL;
2533
2534 ProcessList *process_list = control_flow_data->process_list;
2535
2536 birth = process->creation_time;
2537
2538 /* Cannot use current process : this event happens on another process,
2539 * action done by the parent. */
2540 hashed_process_data = processlist_get_process_data(process_list,
2541 pid,
2542 process->cpu,
2543 &birth,
2544 tfc->t_context->index);
2545 if(unlikely(hashed_process_data == NULL))
2546 {
2547 g_assert(pid == 0 || pid != process->ppid);
2548 /* Process not present */
2549 Drawing_t *drawing = control_flow_data->drawing;
2550 ProcessInfo *process_info;
2551 processlist_add(process_list,
2552 drawing,
2553 pid,
2554 process->cpu,
2555 process->ppid,
2556 &birth,
2557 tfc->t_context->index,
2558 process->name,
2559 &pl_height,
2560 &process_info,
2561 &hashed_process_data);
2562 gtk_widget_set_size_request(drawing->drawing_area,
2563 -1,
2564 pl_height);
2565 gtk_widget_queue_draw(drawing->drawing_area);
2566 }
2567
2568 /* Now, the process is in the state hash and our own process hash.
2569 * We definitely can draw the items related to the ending state.
2570 */
2571
2572 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2573 evtime) > 0))
2574 {
2575 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2576 TimeWindow time_window =
2577 lttvwindow_get_time_window(control_flow_data->tab);
2578
2579 #ifdef EXTRA_CHECK
2580 if(ltt_time_compare(evtime, time_window.start_time) == -1
2581 || ltt_time_compare(evtime, time_window.end_time) == 1)
2582 return;
2583 #endif //EXTRA_CHECK
2584 Drawing_t *drawing = control_flow_data->drawing;
2585 guint width = drawing->width;
2586 guint x;
2587 convert_time_to_pixels(
2588 time_window,
2589 evtime,
2590 width,
2591 &x);
2592
2593 /* Draw collision indicator */
2594 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2595 gdk_draw_point(hashed_process_data->pixmap,
2596 drawing->gc,
2597 x,
2598 (hashed_process_data->height/2)-3);
2599 hashed_process_data->x.middle_marked = TRUE;
2600 }
2601 } else {
2602 TimeWindow time_window =
2603 lttvwindow_get_time_window(control_flow_data->tab);
2604
2605 #ifdef EXTRA_CHECK
2606 if(ltt_time_compare(evtime, time_window.start_time) == -1
2607 || ltt_time_compare(evtime, time_window.end_time) == 1)
2608 return;
2609 #endif //EXTRA_CHECK
2610 Drawing_t *drawing = control_flow_data->drawing;
2611 guint width = drawing->width;
2612 guint x;
2613
2614 convert_time_to_pixels(
2615 time_window,
2616 evtime,
2617 width,
2618 &x);
2619
2620
2621 /* Jump over draw if we are at the same x position */
2622 if(unlikely(x == hashed_process_data->x.middle &&
2623 hashed_process_data->x.middle_used))
2624 {
2625 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2626 /* Draw collision indicator */
2627 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2628 gdk_draw_point(hashed_process_data->pixmap,
2629 drawing->gc,
2630 x,
2631 (hashed_process_data->height/2)-3);
2632 hashed_process_data->x.middle_marked = TRUE;
2633 }
2634 /* jump */
2635 } else {
2636 DrawContext draw_context;
2637
2638 /* Now create the drawing context that will be used to draw
2639 * items related to the last state. */
2640 draw_context.drawable = hashed_process_data->pixmap;
2641 draw_context.gc = drawing->gc;
2642 draw_context.pango_layout = drawing->pango_layout;
2643 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2644 draw_context.drawinfo.end.x = x;
2645
2646 draw_context.drawinfo.y.over = 1;
2647 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2648 draw_context.drawinfo.y.under = hashed_process_data->height;
2649
2650 draw_context.drawinfo.start.offset.over = 0;
2651 draw_context.drawinfo.start.offset.middle = 0;
2652 draw_context.drawinfo.start.offset.under = 0;
2653 draw_context.drawinfo.end.offset.over = 0;
2654 draw_context.drawinfo.end.offset.middle = 0;
2655 draw_context.drawinfo.end.offset.under = 0;
2656
2657 {
2658 /* Draw the line */
2659 PropertiesLine prop_line = prepare_s_e_line(process);
2660 draw_line((void*)&prop_line, (void*)&draw_context);
2661
2662 }
2663 /* become the last x position */
2664 hashed_process_data->x.middle = x;
2665 hashed_process_data->x.middle_used = TRUE;
2666 hashed_process_data->x.middle_marked = FALSE;
2667
2668 /* Calculate the next good time */
2669 convert_pixels_to_time(width, x+1, time_window,
2670 &hashed_process_data->next_good_time);
2671 }
2672 }
2673 }
2674
2675 return 0;
2676 }
2677
2678
2679
2680
2681
2682
2683
2684
2685 #if 0
2686 /* before_process_hook
2687 *
2688 * Draw lines for process event.
2689 *
2690 * @param hook_data ControlFlowData structure of the viewer.
2691 * @param call_data Event context.
2692 *
2693 * This function adds items to be drawn in a queue for each process.
2694 *
2695 */
2696 int before_process_hook(void *hook_data, void *call_data)
2697 {
2698 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2699 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2700 ControlFlowData *control_flow_data = events_request->viewer_data;
2701
2702 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2703
2704 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2705
2706 LttEvent *e;
2707 e = ltt_tracefile_get_event(tfc->tf);
2708
2709 LttTime evtime = ltt_event_time(e);
2710
2711 guint sub_id;
2712 {
2713 LttField *f = ltt_event_field(e);
2714 LttField *element;
2715 element = ltt_field_member(f,0);
2716 sub_id = ltt_event_get_long_unsigned(e,element);
2717 }
2718
2719 if(sub_id == 3) { /* exit */
2720
2721 /* Add process to process list (if not present) */
2722 LttvProcessState *process = tfs->process;
2723 guint pid = process->pid;
2724 LttTime birth;
2725 guint pl_height = 0;
2726 HashedProcessData *hashed_process_data = NULL;
2727
2728 ProcessList *process_list = control_flow_data->process_list;
2729
2730 g_assert(process != NULL);
2731
2732 birth = process->creation_time;
2733
2734 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2735 hashed_process_data = process_list->current_hash_data[tfc->index];
2736 } else {
2737 hashed_process_data = processlist_get_process_data(process_list,
2738 pid,
2739 process->last_cpu_index,
2740 &birth,
2741 tfc->t_context->index);
2742 if(unlikely(hashed_process_data == NULL))
2743 {
2744 g_assert(pid == 0 || pid != process->ppid);
2745 /* Process not present */
2746 Drawing_t *drawing = control_flow_data->drawing;
2747 const gchar *name = g_quark_to_string(process->name);
2748 ProcessInfo *process_info;
2749 processlist_add(process_list,
2750 drawing,
2751 pid,
2752 process->last_cpu_index,
2753 process->ppid,
2754 &birth,
2755 tfc->t_context->index,
2756 name,
2757 &pl_height,
2758 &process_info,
2759 &hashed_process_data);
2760 gtk_widget_set_size_request(drawing->drawing_area,
2761 -1,
2762 pl_height);
2763 gtk_widget_queue_draw(drawing->drawing_area);
2764 }
2765 }
2766
2767 /* Now, the process is in the state hash and our own process hash.
2768 * We definitely can draw the items related to the ending state.
2769 */
2770
2771 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2772 evtime) > 0))
2773 {
2774 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2775 TimeWindow time_window =
2776 lttvwindow_get_time_window(control_flow_data->tab);
2777
2778 #ifdef EXTRA_CHECK
2779 if(ltt_time_compare(evtime, time_window.start_time) == -1
2780 || ltt_time_compare(evtime, time_window.end_time) == 1)
2781 return;
2782 #endif //EXTRA_CHECK
2783 Drawing_t *drawing = control_flow_data->drawing;
2784 guint width = drawing->width;
2785 guint x;
2786 convert_time_to_pixels(
2787 time_window,
2788 evtime,
2789 width,
2790 &x);
2791
2792 /* Draw collision indicator */
2793 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2794 gdk_draw_point(hashed_process_data->pixmap,
2795 drawing->gc,
2796 x,
2797 (hashed_process_data->height/2)-3);
2798 hashed_process_data->x.middle_marked = TRUE;
2799 }
2800 } else {
2801 TimeWindow time_window =
2802 lttvwindow_get_time_window(control_flow_data->tab);
2803
2804 #ifdef EXTRA_CHECK
2805 if(ltt_time_compare(evtime, time_window.start_time) == -1
2806 || ltt_time_compare(evtime, time_window.end_time) == 1)
2807 return;
2808 #endif //EXTRA_CHECK
2809 Drawing_t *drawing = control_flow_data->drawing;
2810 guint width = drawing->width;
2811 guint x;
2812
2813 convert_time_to_pixels(
2814 time_window,
2815 evtime,
2816 width,
2817 &x);
2818
2819
2820 /* Jump over draw if we are at the same x position */
2821 if(unlikely(x == hashed_process_data->x.middle &&
2822 hashed_process_data->x.middle_used))
2823 {
2824 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2825 /* Draw collision indicator */
2826 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2827 gdk_draw_point(hashed_process_data->pixmap,
2828 drawing->gc,
2829 x,
2830 (hashed_process_data->height/2)-3);
2831 hashed_process_data->x.middle_marked = TRUE;
2832 }
2833 /* jump */
2834 } else {
2835 DrawContext draw_context;
2836
2837 /* Now create the drawing context that will be used to draw
2838 * items related to the last state. */
2839 draw_context.drawable = hashed_process_data->pixmap;
2840 draw_context.gc = drawing->gc;
2841 draw_context.pango_layout = drawing->pango_layout;
2842 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2843 draw_context.drawinfo.end.x = x;
2844
2845 draw_context.drawinfo.y.over = 1;
2846 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2847 draw_context.drawinfo.y.under = hashed_process_data->height;
2848
2849 draw_context.drawinfo.start.offset.over = 0;
2850 draw_context.drawinfo.start.offset.middle = 0;
2851 draw_context.drawinfo.start.offset.under = 0;
2852 draw_context.drawinfo.end.offset.over = 0;
2853 draw_context.drawinfo.end.offset.middle = 0;
2854 draw_context.drawinfo.end.offset.under = 0;
2855
2856 {
2857 /* Draw the line */
2858 PropertiesLine prop_line = prepare_s_e_line(process);
2859 draw_line((void*)&prop_line, (void*)&draw_context);
2860
2861 }
2862 /* become the last x position */
2863 hashed_process_data->x.middle = x;
2864 hashed_process_data->x.middle_used = TRUE;
2865 hashed_process_data->x.middle_marked = FALSE;
2866
2867 /* Calculate the next good time */
2868 convert_pixels_to_time(width, x+1, time_window,
2869 &hashed_process_data->next_good_time);
2870 }
2871 }
2872
2873 } else if(sub_id == 7) /* release */ {
2874
2875 guint pid;
2876 {
2877 LttField *f = ltt_event_field(e);
2878 LttField *element;
2879 element = ltt_field_member(f,1);
2880 pid = ltt_event_get_long_unsigned(e,element);
2881 }
2882
2883 /* Add process to process list (if not present) */
2884 /* Don't care about the process if it's not in the state hash already :
2885 * that means a process that has never done anything in the trace and
2886 * unknown suddently gets destroyed : no state meaningful to show. */
2887 LttvProcessState *process = lttv_state_find_process(tfs, pid);
2888
2889 if(process != NULL) {
2890 LttTime birth;
2891 guint pl_height = 0;
2892 HashedProcessData *hashed_process_data = NULL;
2893
2894 ProcessList *process_list = control_flow_data->process_list;
2895
2896 birth = process->creation_time;
2897
2898 /* Cannot use current process : this event happens on another process,
2899 * action done by the parent. */
2900 hashed_process_data = processlist_get_process_data(process_list,
2901 pid,
2902 process->last_cpu_index,
2903 &birth,
2904 tfc->t_context->index);
2905 if(unlikely(hashed_process_data == NULL))
2906 {
2907 g_assert(pid == 0 || pid != process->ppid);
2908 /* Process not present */
2909 Drawing_t *drawing = control_flow_data->drawing;
2910 ProcessInfo *process_info;
2911 processlist_add(process_list,
2912 drawing,
2913 pid,
2914 process->last_cpu_index,
2915 process->ppid,
2916 &birth,
2917 tfc->t_context->index,
2918 process->name,
2919 &pl_height,
2920 &process_info,
2921 &hashed_process_data);
2922 gtk_widget_set_size_request(drawing->drawing_area,
2923 -1,
2924 pl_height);
2925 gtk_widget_queue_draw(drawing->drawing_area);
2926 }
2927
2928 /* Now, the process is in the state hash and our own process hash.
2929 * We definitely can draw the items related to the ending state.
2930 */
2931
2932 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2933 evtime) > 0))
2934 {
2935 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2936 TimeWindow time_window =
2937 lttvwindow_get_time_window(control_flow_data->tab);
2938
2939 #ifdef EXTRA_CHECK
2940 if(ltt_time_compare(evtime, time_window.start_time) == -1
2941 || ltt_time_compare(evtime, time_window.end_time) == 1)
2942 return;
2943 #endif //EXTRA_CHECK
2944 Drawing_t *drawing = control_flow_data->drawing;
2945 guint width = drawing->width;
2946 guint x;
2947 convert_time_to_pixels(
2948 time_window,
2949 evtime,
2950 width,
2951 &x);
2952
2953 /* Draw collision indicator */
2954 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2955 gdk_draw_point(hashed_process_data->pixmap,
2956 drawing->gc,
2957 x,
2958 (hashed_process_data->height/2)-3);
2959 hashed_process_data->x.middle_marked = TRUE;
2960 }
2961 } else {
2962 TimeWindow time_window =
2963 lttvwindow_get_time_window(control_flow_data->tab);
2964
2965 #ifdef EXTRA_CHECK
2966 if(ltt_time_compare(evtime, time_window.start_time) == -1
2967 || ltt_time_compare(evtime, time_window.end_time) == 1)
2968 return;
2969 #endif //EXTRA_CHECK
2970 Drawing_t *drawing = control_flow_data->drawing;
2971 guint width = drawing->width;
2972 guint x;
2973
2974 convert_time_to_pixels(
2975 time_window,
2976 evtime,
2977 width,
2978 &x);
2979
2980
2981 /* Jump over draw if we are at the same x position */
2982 if(unlikely(x == hashed_process_data->x.middle &&
2983 hashed_process_data->x.middle_used))
2984 {
2985 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2986 /* Draw collision indicator */
2987 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2988 gdk_draw_point(hashed_process_data->pixmap,
2989 drawing->gc,
2990 x,
2991 (hashed_process_data->height/2)-3);
2992 hashed_process_data->x.middle_marked = TRUE;
2993 }
2994 /* jump */
2995 } else {
2996 DrawContext draw_context;
2997
2998 /* Now create the drawing context that will be used to draw
2999 * items related to the last state. */
3000 draw_context.drawable = hashed_process_data->pixmap;
3001 draw_context.gc = drawing->gc;
3002 draw_context.pango_layout = drawing->pango_layout;
3003 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
3004 draw_context.drawinfo.end.x = x;
3005
3006 draw_context.drawinfo.y.over = 1;
3007 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
3008 draw_context.drawinfo.y.under = hashed_process_data->height;
3009
3010 draw_context.drawinfo.start.offset.over = 0;
3011 draw_context.drawinfo.start.offset.middle = 0;
3012 draw_context.drawinfo.start.offset.under = 0;
3013 draw_context.drawinfo.end.offset.over = 0;
3014 draw_context.drawinfo.end.offset.middle = 0;
3015 draw_context.drawinfo.end.offset.under = 0;
3016
3017 {
3018 /* Draw the line */
3019 PropertiesLine prop_line = prepare_s_e_line(process);
3020 draw_line((void*)&prop_line, (void*)&draw_context);
3021
3022 }
3023 /* become the last x position */
3024 hashed_process_data->x.middle = x;
3025 hashed_process_data->x.middle_used = TRUE;
3026 hashed_process_data->x.middle_marked = FALSE;
3027
3028 /* Calculate the next good time */
3029 convert_pixels_to_time(width, x+1, time_window,
3030 &hashed_process_data->next_good_time);
3031 }
3032 }
3033 }
3034
3035 }
3036 return 0;
3037
3038 }
3039
3040 #endif //0
3041
3042
3043
3044 /* after_process_fork_hook
3045 *
3046 * Create the processlist entry for the child process. Put the last
3047 * position in x at the current time value.
3048 *
3049 * @param hook_data ControlFlowData structure of the viewer.
3050 * @param call_data Event context.
3051 *
3052 * This function adds items to be drawn in a queue for each process.
3053 *
3054 */
3055 int after_process_fork_hook(void *hook_data, void *call_data)
3056 {
3057 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3058 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3059 ControlFlowData *control_flow_data = events_request->viewer_data;
3060
3061 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3062
3063 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3064
3065 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3066
3067 LttEvent *e;
3068 e = ltt_tracefile_get_event(tfc->tf);
3069
3070 LttTime evtime = ltt_event_time(e);
3071
3072 guint child_pid;
3073 {
3074 child_pid = ltt_event_get_long_unsigned(e, thf->f2);
3075 }
3076
3077 /* Add process to process list (if not present) */
3078 LttvProcessState *process_child;
3079 LttTime birth;
3080 guint pl_height = 0;
3081 HashedProcessData *hashed_process_data_child = NULL;
3082
3083 ProcessList *process_list = control_flow_data->process_list;
3084
3085 /* Find child in the list... */
3086 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
3087 /* It should exist, because we are after the state update. */
3088 g_assert(process_child != NULL);
3089
3090 birth = process_child->creation_time;
3091
3092 /* Cannot use current process, because this action is done by the parent
3093 * on its child. */
3094 hashed_process_data_child = processlist_get_process_data(process_list,
3095 child_pid,
3096 process_child->cpu,
3097 &birth,
3098 tfc->t_context->index);
3099 if(likely(hashed_process_data_child == NULL))
3100 {
3101 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3102 /* Process not present */
3103 Drawing_t *drawing = control_flow_data->drawing;
3104 ProcessInfo *process_info;
3105 processlist_add(process_list,
3106 drawing,
3107 child_pid,
3108 process_child->cpu,
3109 process_child->ppid,
3110 &birth,
3111 tfc->t_context->index,
3112 process_child->name,
3113 &pl_height,
3114 &process_info,
3115 &hashed_process_data_child);
3116 gtk_widget_set_size_request(drawing->drawing_area,
3117 -1,
3118 pl_height);
3119 gtk_widget_queue_draw(drawing->drawing_area);
3120 }
3121
3122
3123 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3124 evtime) <= 0))
3125 {
3126 TimeWindow time_window =
3127 lttvwindow_get_time_window(control_flow_data->tab);
3128
3129 #ifdef EXTRA_CHECK
3130 if(ltt_time_compare(evtime, time_window.start_time) == -1
3131 || ltt_time_compare(evtime, time_window.end_time) == 1)
3132 return;
3133 #endif //EXTRA_CHECK
3134 Drawing_t *drawing = control_flow_data->drawing;
3135 guint width = drawing->width;
3136 guint new_x;
3137 convert_time_to_pixels(
3138 time_window,
3139 evtime,
3140 width,
3141 &new_x);
3142
3143 if(likely(hashed_process_data_child->x.over != new_x)) {
3144 hashed_process_data_child->x.over = new_x;
3145 hashed_process_data_child->x.over_used = FALSE;
3146 hashed_process_data_child->x.over_marked = FALSE;
3147 }
3148 if(likely(hashed_process_data_child->x.middle != new_x)) {
3149 hashed_process_data_child->x.middle = new_x;
3150 hashed_process_data_child->x.middle_used = FALSE;
3151 hashed_process_data_child->x.middle_marked = FALSE;
3152 }
3153 if(likely(hashed_process_data_child->x.under != new_x)) {
3154 hashed_process_data_child->x.under = new_x;
3155 hashed_process_data_child->x.under_used = FALSE;
3156 hashed_process_data_child->x.under_marked = FALSE;
3157 }
3158 }
3159 return 0;
3160 }
3161
3162
3163
3164 /* after_process_exit_hook
3165 *
3166 * Create the processlist entry for the child process. Put the last
3167 * position in x at the current time value.
3168 *
3169 * @param hook_data ControlFlowData structure of the viewer.
3170 * @param call_data Event context.
3171 *
3172 * This function adds items to be drawn in a queue for each process.
3173 *
3174 */
3175 int after_process_exit_hook(void *hook_data, void *call_data)
3176 {
3177 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3178 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3179 ControlFlowData *control_flow_data = events_request->viewer_data;
3180
3181 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3182
3183 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3184
3185 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3186
3187 LttEvent *e;
3188 e = ltt_tracefile_get_event(tfc->tf);
3189
3190 LttTime evtime = ltt_event_time(e);
3191
3192 /* Add process to process list (if not present) */
3193 //LttvProcessState *process = tfs->process;
3194 guint cpu = ltt_tracefile_num(tfc->tf);
3195 LttvProcessState *process = ts->running_process[cpu];
3196
3197 /* It should exist, because we are after the state update. */
3198 g_assert(process != NULL);
3199
3200 guint pid = process->pid;
3201 LttTime birth;
3202 guint pl_height = 0;
3203 HashedProcessData *hashed_process_data = NULL;
3204
3205 ProcessList *process_list = control_flow_data->process_list;
3206
3207 birth = process->creation_time;
3208
3209 if(likely(process_list->current_hash_data[cpu] != NULL) ){
3210 hashed_process_data = process_list->current_hash_data[cpu];
3211 } else {
3212 hashed_process_data = processlist_get_process_data(process_list,
3213 pid,
3214 process->cpu,
3215 &birth,
3216 tfc->t_context->index);
3217 if(unlikely(hashed_process_data == NULL))
3218 {
3219 g_assert(pid == 0 || pid != process->ppid);
3220 /* Process not present */
3221 Drawing_t *drawing = control_flow_data->drawing;
3222 ProcessInfo *process_info;
3223 processlist_add(process_list,
3224 drawing,
3225 pid,
3226 process->cpu,
3227 process->ppid,
3228 &birth,
3229 tfc->t_context->index,
3230 process->name,
3231 &pl_height,
3232 &process_info,
3233 &hashed_process_data);
3234 gtk_widget_set_size_request(drawing->drawing_area,
3235 -1,
3236 pl_height);
3237 gtk_widget_queue_draw(drawing->drawing_area);
3238 }
3239
3240 /* Set the current process */
3241 process_list->current_hash_data[process->cpu] =
3242 hashed_process_data;
3243 }
3244
3245 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3246 evtime) <= 0))
3247 {
3248 TimeWindow time_window =
3249 lttvwindow_get_time_window(control_flow_data->tab);
3250
3251 #ifdef EXTRA_CHECK
3252 if(ltt_time_compare(evtime, time_window.start_time) == -1
3253 || ltt_time_compare(evtime, time_window.end_time) == 1)
3254 return;
3255 #endif //EXTRA_CHECK
3256 Drawing_t *drawing = control_flow_data->drawing;
3257 guint width = drawing->width;
3258 guint new_x;
3259 convert_time_to_pixels(
3260 time_window,
3261 evtime,
3262 width,
3263 &new_x);
3264 if(unlikely(hashed_process_data->x.middle != new_x)) {
3265 hashed_process_data->x.middle = new_x;
3266 hashed_process_data->x.middle_used = FALSE;
3267 hashed_process_data->x.middle_marked = FALSE;
3268 }
3269 }
3270
3271 return 0;
3272 }
3273
3274
3275 #if 0
3276
3277 /* after_process_hook
3278 *
3279 * Create the processlist entry for the child process. Put the last
3280 * position in x at the current time value.
3281 *
3282 * @param hook_data ControlFlowData structure of the viewer.
3283 * @param call_data Event context.
3284 *
3285 * This function adds items to be drawn in a queue for each process.
3286 *
3287 */
3288 int after_process_hook(void *hook_data, void *call_data)
3289 {
3290 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3291 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3292 ControlFlowData *control_flow_data = events_request->viewer_data;
3293
3294 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3295
3296 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3297
3298 LttEvent *e;
3299 e = ltt_tracefile_get_event(tfc->tf);
3300
3301 LttTime evtime = ltt_event_time(e);
3302
3303 guint sub_id;
3304 guint param1;
3305 {
3306 LttField *f = ltt_event_field(e);
3307 LttField *element;
3308 element = ltt_field_member(f,0);
3309 sub_id = ltt_event_get_long_unsigned(e,element);
3310 element = ltt_field_member(f,1);
3311 param1 = ltt_event_get_long_unsigned(e,element);
3312 }
3313
3314 if(sub_id == 2) { /* fork */
3315
3316 guint child_pid = param1;
3317 /* Add process to process list (if not present) */
3318 LttvProcessState *process_child;
3319 LttTime birth;
3320 guint pl_height = 0;
3321 HashedProcessData *hashed_process_data_child = NULL;
3322
3323 ProcessList *process_list = control_flow_data->process_list;
3324
3325 /* Find child in the list... */
3326 process_child = lttv_state_find_process(tfs, child_pid);
3327 /* It should exist, because we are after the state update. */
3328 g_assert(process_child != NULL);
3329
3330 birth = process_child->creation_time;
3331
3332 /* Cannot use current process, because this action is done by the parent
3333 * on its child. */
3334 hashed_process_data_child = processlist_get_process_data(process_list,
3335 child_pid,
3336 process_child->last_cpu_index,
3337 &birth,
3338 tfc->t_context->index);
3339 if(likely(hashed_process_data_child == NULL))
3340 {
3341 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3342 /* Process not present */
3343 Drawing_t *drawing = control_flow_data->drawing;
3344 const gchar *name = g_quark_to_string(process_child->name);
3345 ProcessInfo *process_info;
3346 processlist_add(process_list,
3347 drawing,
3348 child_pid,
3349 process_child->last_cpu_index,
3350 process_child->ppid,
3351 &birth,
3352 tfc->t_context->index,
3353 name,
3354 &pl_height,
3355 &process_info,
3356 &hashed_process_data_child);
3357 gtk_widget_set_size_request(drawing->drawing_area,
3358 -1,
3359 pl_height);
3360 gtk_widget_queue_draw(drawing->drawing_area);
3361 }
3362
3363
3364 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3365 evtime) <= 0))
3366 {
3367 TimeWindow time_window =
3368 lttvwindow_get_time_window(control_flow_data->tab);
3369
3370 #ifdef EXTRA_CHECK
3371 if(ltt_time_compare(evtime, time_window.start_time) == -1
3372 || ltt_time_compare(evtime, time_window.end_time) == 1)
3373 return;
3374 #endif //EXTRA_CHECK
3375 Drawing_t *drawing = control_flow_data->drawing;
3376 guint width = drawing->width;
3377 guint new_x;
3378 convert_time_to_pixels(
3379 time_window,
3380 evtime,
3381 width,
3382 &new_x);
3383
3384 if(likely(hashed_process_data_child->x.over != new_x)) {
3385 hashed_process_data_child->x.over = new_x;
3386 hashed_process_data_child->x.over_used = FALSE;
3387 hashed_process_data_child->x.over_marked = FALSE;
3388 }
3389 if(likely(hashed_process_data_child->x.middle != new_x)) {
3390 hashed_process_data_child->x.middle = new_x;
3391 hashed_process_data_child->x.middle_used = FALSE;
3392 hashed_process_data_child->x.middle_marked = FALSE;
3393 }
3394 if(likely(hashed_process_data_child->x.under != new_x)) {
3395 hashed_process_data_child->x.under = new_x;
3396 hashed_process_data_child->x.under_used = FALSE;
3397 hashed_process_data_child->x.under_marked = FALSE;
3398 }
3399 }
3400
3401 } else if(sub_id == 3) { /* exit */
3402
3403 /* Add process to process list (if not present) */
3404 LttvProcessState *process = tfs->process;
3405 guint pid = process->pid;
3406 LttTime birth;
3407 guint pl_height = 0;
3408 HashedProcessData *hashed_process_data = NULL;
3409
3410 ProcessList *process_list = control_flow_data->process_list;
3411
3412 /* It should exist, because we are after the state update. */
3413 g_assert(process != NULL);
3414
3415 birth = process->creation_time;
3416
3417 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL) ){
3418 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
3419 } else {
3420 hashed_process_data = processlist_get_process_data(process_list,
3421 pid,
3422 process->last_cpu_index,
3423 &birth,
3424 tfc->t_context->index);
3425 if(unlikely(hashed_process_data == NULL))
3426 {
3427 g_assert(pid == 0 || pid != process->ppid);
3428 /* Process not present */
3429 Drawing_t *drawing = control_flow_data->drawing;
3430 const gchar *name = g_quark_to_string(process->name);
3431 ProcessInfo *process_info;
3432 processlist_add(process_list,
3433 drawing,
3434 pid,
3435 process->last_cpu_index,
3436 process->ppid,
3437 &birth,
3438 tfc->t_context->index,
3439 name,
3440 &pl_height,
3441 &process_info,
3442 &hashed_process_data);
3443 gtk_widget_set_size_request(drawing->drawing_area,
3444 -1,
3445 pl_height);
3446 gtk_widget_queue_draw(drawing->drawing_area);
3447 }
3448
3449 /* Set the current process */
3450 process_list->current_hash_data[process->last_cpu_index] =
3451 hashed_process_data;
3452 }
3453
3454 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3455 evtime) <= 0))
3456 {
3457 TimeWindow time_window =
3458 lttvwindow_get_time_window(control_flow_data->tab);
3459
3460 #ifdef EXTRA_CHECK
3461 if(ltt_time_compare(evtime, time_window.start_time) == -1
3462 || ltt_time_compare(evtime, time_window.end_time) == 1)
3463 return;
3464 #endif //EXTRA_CHECK
3465 Drawing_t *drawing = control_flow_data->drawing;
3466 guint width = drawing->width;
3467 guint new_x;
3468 convert_time_to_pixels(
3469 time_window,
3470 evtime,
3471 width,
3472 &new_x);
3473 if(unlikely(hashed_process_data->x.middle != new_x)) {
3474 hashed_process_data->x.middle = new_x;
3475 hashed_process_data->x.middle_used = FALSE;
3476 hashed_process_data->x.middle_marked = FALSE;
3477 }
3478 }
3479
3480 }
3481 return 0;
3482
3483 }
3484 #endif //0
3485
3486 /* Get the filename of the process to print */
3487 int after_fs_exec_hook(void *hook_data, void *call_data)
3488 {
3489 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3490 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3491 ControlFlowData *control_flow_data = events_request->viewer_data;
3492
3493 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3494
3495 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3496
3497 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3498
3499 guint cpu = ltt_tracefile_num(tfc->tf);
3500 LttvProcessState *process = ts->running_process[cpu];
3501 g_assert(process != NULL);
3502
3503 guint pid = process->pid;
3504
3505 /* Well, the process_out existed : we must get it in the process hash
3506 * or add it, and draw its items.
3507 */
3508 /* Add process to process list (if not present) */
3509 guint pl_height = 0;
3510 HashedProcessData *hashed_process_data = NULL;
3511 ProcessList *process_list = control_flow_data->process_list;
3512 LttTime birth = process->creation_time;
3513
3514 if(likely(process_list->current_hash_data[cpu] != NULL)) {
3515 hashed_process_data = process_list->current_hash_data[cpu];
3516 } else {
3517 hashed_process_data = processlist_get_process_data(process_list,
3518 pid,
3519 process->cpu,
3520 &birth,
3521 tfc->t_context->index);
3522 if(unlikely(hashed_process_data == NULL))
3523 {
3524 g_assert(pid == 0 || pid != process->ppid);
3525 ProcessInfo *process_info;
3526 /* Process not present */
3527 Drawing_t *drawing = control_flow_data->drawing;
3528 processlist_add(process_list,
3529 drawing,
3530 pid,
3531 process->cpu,
3532 process->ppid,
3533 &birth,
3534 tfc->t_context->index,
3535 process->name,
3536 &pl_height,
3537 &process_info,
3538 &hashed_process_data);
3539 gtk_widget_set_size_request(drawing->drawing_area,
3540 -1,
3541 pl_height);
3542 gtk_widget_queue_draw(drawing->drawing_area);
3543 }
3544 /* Set the current process */
3545 process_list->current_hash_data[process->cpu] =
3546 hashed_process_data;
3547 }
3548
3549 processlist_set_name(process_list, process->name, hashed_process_data);
3550
3551 return 0;
3552
3553 }
3554
3555
3556
3557
3558 gint update_time_window_hook(void *hook_data, void *call_data)
3559 {
3560 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3561 Drawing_t *drawing = control_flow_data->drawing;
3562 ProcessList *process_list = control_flow_data->process_list;
3563
3564 const TimeWindowNotifyData *time_window_nofify_data =
3565 ((const TimeWindowNotifyData *)call_data);
3566
3567 TimeWindow *old_time_window =
3568 time_window_nofify_data->old_time_window;
3569 TimeWindow *new_time_window =
3570 time_window_nofify_data->new_time_window;
3571
3572 /* Update the ruler */
3573 drawing_update_ruler(control_flow_data->drawing,
3574 new_time_window);
3575
3576
3577 /* Two cases : zoom in/out or scrolling */
3578
3579 /* In order to make sure we can reuse the old drawing, the scale must
3580 * be the same and the new time interval being partly located in the
3581 * currently shown time interval. (reuse is only for scrolling)
3582 */
3583
3584 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3585 old_time_window->start_time.tv_sec,
3586 old_time_window->start_time.tv_nsec,
3587 old_time_window->time_width.tv_sec,
3588 old_time_window->time_width.tv_nsec);
3589
3590 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3591 new_time_window->start_time.tv_sec,
3592 new_time_window->start_time.tv_nsec,
3593 new_time_window->time_width.tv_sec,
3594 new_time_window->time_width.tv_nsec);
3595
3596 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
3597 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
3598 {
3599 /* Same scale (scrolling) */
3600 g_info("scrolling");
3601 LttTime *ns = &new_time_window->start_time;
3602 LttTime *nw = &new_time_window->time_width;
3603 LttTime *os = &old_time_window->start_time;
3604 LttTime *ow = &old_time_window->time_width;
3605 LttTime old_end = old_time_window->end_time;
3606 LttTime new_end = new_time_window->end_time;
3607 //if(ns<os+w<ns+w)
3608 //if(ns<os+w && os+w<ns+w)
3609 //if(ns<old_end && os<ns)
3610 if(ltt_time_compare(*ns, old_end) == -1
3611 && ltt_time_compare(*os, *ns) == -1)
3612 {
3613 g_info("scrolling near right");
3614 /* Scroll right, keep right part of the screen */
3615 guint x = 0;
3616 guint width = control_flow_data->drawing->width;
3617 convert_time_to_pixels(
3618 *old_time_window,
3619 *ns,
3620 width,
3621 &x);
3622
3623 /* Copy old data to new location */
3624 copy_pixmap_region(process_list,
3625 NULL,
3626 control_flow_data->drawing->drawing_area->style->black_gc,
3627 NULL,
3628 x, 0,
3629 0, 0,
3630 control_flow_data->drawing->width-x+SAFETY, -1);
3631
3632 if(drawing->damage_begin == drawing->damage_end)
3633 drawing->damage_begin = control_flow_data->drawing->width-x;
3634 else
3635 drawing->damage_begin = 0;
3636
3637 drawing->damage_end = control_flow_data->drawing->width;
3638
3639 /* Clear the data request background, but not SAFETY */
3640 rectangle_pixmap(process_list,
3641 control_flow_data->drawing->drawing_area->style->black_gc,
3642 TRUE,
3643 drawing->damage_begin+SAFETY, 0,
3644 drawing->damage_end - drawing->damage_begin, // do not overlap
3645 -1);
3646 gtk_widget_queue_draw(drawing->drawing_area);
3647 //gtk_widget_queue_draw_area (drawing->drawing_area,
3648 // 0,0,
3649 // control_flow_data->drawing->width,
3650 // control_flow_data->drawing->height);
3651
3652 /* Get new data for the rest. */
3653 drawing_data_request(control_flow_data->drawing,
3654 drawing->damage_begin, 0,
3655 drawing->damage_end - drawing->damage_begin,
3656 control_flow_data->drawing->height);
3657 } else {
3658 //if(ns<os<ns+w)
3659 //if(ns<os && os<ns+w)
3660 //if(ns<os && os<new_end)
3661 if(ltt_time_compare(*ns,*os) == -1
3662 && ltt_time_compare(*os,new_end) == -1)
3663 {
3664 g_info("scrolling near left");
3665 /* Scroll left, keep left part of the screen */
3666 guint x = 0;
3667 guint width = control_flow_data->drawing->width;
3668 convert_time_to_pixels(
3669 *new_time_window,
3670 *os,
3671 width,
3672 &x);
3673
3674 /* Copy old data to new location */
3675 copy_pixmap_region (process_list,
3676 NULL,
3677 control_flow_data->drawing->drawing_area->style->black_gc,
3678 NULL,
3679 0, 0,
3680 x, 0,
3681 -1, -1);
3682
3683 if(drawing->damage_begin == drawing->damage_end)
3684 drawing->damage_end = x;
3685 else
3686 drawing->damage_end =
3687 control_flow_data->drawing->width;
3688
3689 drawing->damage_begin = 0;
3690
3691 rectangle_pixmap (process_list,
3692 control_flow_data->drawing->drawing_area->style->black_gc,
3693 TRUE,
3694 drawing->damage_begin, 0,
3695 drawing->damage_end - drawing->damage_begin, // do not overlap
3696 -1);
3697
3698 gtk_widget_queue_draw(drawing->drawing_area);
3699 //gtk_widget_queue_draw_area (drawing->drawing_area,
3700 // 0,0,
3701 // control_flow_data->drawing->width,
3702 // control_flow_data->drawing->height);
3703
3704
3705 /* Get new data for the rest. */
3706 drawing_data_request(control_flow_data->drawing,
3707 drawing->damage_begin, 0,
3708 drawing->damage_end - drawing->damage_begin,
3709 control_flow_data->drawing->height);
3710
3711 } else {
3712 if(ltt_time_compare(*ns,*os) == 0)
3713 {
3714 g_info("not scrolling");
3715 } else {
3716 g_info("scrolling far");
3717 /* Cannot reuse any part of the screen : far jump */
3718
3719
3720 rectangle_pixmap (process_list,
3721 control_flow_data->drawing->drawing_area->style->black_gc,
3722 TRUE,
3723 0, 0,
3724 control_flow_data->drawing->width+SAFETY, // do not overlap
3725 -1);
3726
3727 //gtk_widget_queue_draw_area (drawing->drawing_area,
3728 // 0,0,
3729 // control_flow_data->drawing->width,
3730 // control_flow_data->drawing->height);
3731 gtk_widget_queue_draw(drawing->drawing_area);
3732
3733 drawing->damage_begin = 0;
3734 drawing->damage_end = control_flow_data->drawing->width;
3735
3736 drawing_data_request(control_flow_data->drawing,
3737 0, 0,
3738 control_flow_data->drawing->width,
3739 control_flow_data->drawing->height);
3740
3741 }
3742 }
3743 }
3744 } else {
3745 /* Different scale (zoom) */
3746 g_info("zoom");
3747
3748 rectangle_pixmap (process_list,
3749 control_flow_data->drawing->drawing_area->style->black_gc,
3750 TRUE,
3751 0, 0,
3752 control_flow_data->drawing->width+SAFETY, // do not overlap
3753 -1);
3754
3755 //gtk_widget_queue_draw_area (drawing->drawing_area,
3756 // 0,0,
3757 // control_flow_data->drawing->width,
3758 // control_flow_data->drawing->height);
3759 gtk_widget_queue_draw(drawing->drawing_area);
3760
3761 drawing->damage_begin = 0;
3762 drawing->damage_end = control_flow_data->drawing->width;
3763
3764 drawing_data_request(control_flow_data->drawing,
3765 0, 0,
3766 control_flow_data->drawing->width,
3767 control_flow_data->drawing->height);
3768 }
3769
3770
3771
3772 return 0;
3773 }
3774
3775 gint traceset_notify(void *hook_data, void *call_data)
3776 {
3777 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3778 Drawing_t *drawing = control_flow_data->drawing;
3779
3780
3781 drawing_clear(control_flow_data->drawing);
3782 processlist_clear(control_flow_data->process_list);
3783 gtk_widget_set_size_request(
3784 control_flow_data->drawing->drawing_area,
3785 -1, processlist_get_height(control_flow_data->process_list));
3786 redraw_notify(control_flow_data, NULL);
3787
3788 request_background_data(control_flow_data);
3789
3790 return FALSE;
3791 }
3792
3793 gint redraw_notify(void *hook_data, void *call_data)
3794 {
3795 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3796 Drawing_t *drawing = control_flow_data->drawing;
3797 GtkWidget *widget = drawing->drawing_area;
3798
3799 drawing->damage_begin = 0;
3800 drawing->damage_end = drawing->width;
3801
3802 /* fun feature, to be separated someday... */
3803 drawing_clear(control_flow_data->drawing);
3804 processlist_clear(control_flow_data->process_list);
3805 gtk_widget_set_size_request(
3806 control_flow_data->drawing->drawing_area,
3807 -1, processlist_get_height(control_flow_data->process_list));
3808 // Clear the images
3809 rectangle_pixmap (control_flow_data->process_list,
3810 widget->style->black_gc,
3811 TRUE,
3812 0, 0,
3813 drawing->alloc_width,
3814 -1);
3815
3816 gtk_widget_queue_draw(drawing->drawing_area);
3817
3818 if(drawing->damage_begin < drawing->damage_end)
3819 {
3820 drawing_data_request(drawing,
3821 drawing->damage_begin,
3822 0,
3823 drawing->damage_end-drawing->damage_begin,
3824 drawing->height);
3825 }
3826
3827 //gtk_widget_queue_draw_area(drawing->drawing_area,
3828 // 0,0,
3829 // drawing->width,
3830 // drawing->height);
3831 return FALSE;
3832
3833 }
3834
3835
3836 gint continue_notify(void *hook_data, void *call_data)
3837 {
3838 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3839 Drawing_t *drawing = control_flow_data->drawing;
3840
3841 //g_assert(widget->allocation.width == drawing->damage_end);
3842
3843 if(drawing->damage_begin < drawing->damage_end)
3844 {
3845 drawing_data_request(drawing,
3846 drawing->damage_begin,
3847 0,
3848 drawing->damage_end-drawing->damage_begin,
3849 drawing->height);
3850 }
3851
3852 return FALSE;
3853 }
3854
3855
3856 gint update_current_time_hook(void *hook_data, void *call_data)
3857 {
3858 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
3859 Drawing_t *drawing = control_flow_data->drawing;
3860
3861 LttTime current_time = *((LttTime*)call_data);
3862
3863 TimeWindow time_window =
3864 lttvwindow_get_time_window(control_flow_data->tab);
3865
3866 LttTime time_begin = time_window.start_time;
3867 LttTime width = time_window.time_width;
3868 LttTime half_width;
3869 {
3870 guint64 time_ll = ltt_time_to_uint64(width);
3871 time_ll = time_ll >> 1; /* divide by two */
3872 half_width = ltt_time_from_uint64(time_ll);
3873 }
3874 LttTime time_end = ltt_time_add(time_begin, width);
3875
3876 LttvTracesetContext * tsc =
3877 lttvwindow_get_traceset_context(control_flow_data->tab);
3878
3879 LttTime trace_start = tsc->time_span.start_time;
3880 LttTime trace_end = tsc->time_span.end_time;
3881
3882 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
3883 current_time.tv_nsec);
3884
3885
3886
3887 /* If current time is inside time interval, just move the highlight
3888 * bar */
3889
3890 /* Else, we have to change the time interval. We have to tell it
3891 * to the main window. */
3892 /* The time interval change will take care of placing the current
3893 * time at the center of the visible area, or nearest possible if we are
3894 * at one end of the trace. */
3895
3896
3897 if(ltt_time_compare(current_time, time_begin) < 0)
3898 {
3899 TimeWindow new_time_window;
3900
3901 if(ltt_time_compare(current_time,
3902 ltt_time_add(trace_start,half_width)) < 0)
3903 time_begin = trace_start;
3904 else
3905 time_begin = ltt_time_sub(current_time,half_width);
3906
3907 new_time_window.start_time = time_begin;
3908 new_time_window.time_width = width;
3909 new_time_window.time_width_double = ltt_time_to_double(width);
3910 new_time_window.end_time = ltt_time_add(time_begin, width);
3911
3912 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3913 }
3914 else if(ltt_time_compare(current_time, time_end) > 0)
3915 {
3916 TimeWindow new_time_window;
3917
3918 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
3919 time_begin = ltt_time_sub(trace_end,width);
3920 else
3921 time_begin = ltt_time_sub(current_time,half_width);
3922
3923 new_time_window.start_time = time_begin;
3924 new_time_window.time_width = width;
3925 new_time_window.time_width_double = ltt_time_to_double(width);
3926 new_time_window.end_time = ltt_time_add(time_begin, width);
3927
3928 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3929
3930 }
3931 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
3932
3933
3934 return 0;
3935 }
3936
3937 typedef struct _ClosureData {
3938 EventsRequest *events_request;
3939 LttvTracesetState *tss;
3940 LttTime end_time;
3941 guint x_end;
3942 } ClosureData;
3943
3944
3945 void draw_closure(gpointer key, gpointer value, gpointer user_data)
3946 {
3947 ProcessInfo *process_info = (ProcessInfo*)key;
3948 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
3949 ClosureData *closure_data = (ClosureData*)user_data;
3950
3951 EventsRequest *events_request = closure_data->events_request;
3952 ControlFlowData *control_flow_data = events_request->viewer_data;
3953
3954 LttvTracesetState *tss = closure_data->tss;
3955 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
3956
3957 LttTime evtime = closure_data->end_time;
3958
3959 {
3960 /* For the process */
3961 /* First, check if the current process is in the state computation
3962 * process list. If it is there, that means we must add it right now and
3963 * draw items from the beginning of the read for it. If it is not
3964 * present, it's a new process and it was not present : it will
3965 * be added after the state update. */
3966 #ifdef EXTRA_CHECK
3967 g_assert(lttv_traceset_number(tsc->ts) > 0);
3968 #endif //EXTRA_CHECK
3969 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
3970 LttvTraceState *ts = (LttvTraceState*)tc;
3971
3972 #if 0
3973 //FIXME : optimize data structures.
3974 LttvTracefileState *tfs;
3975 LttvTracefileContext *tfc;
3976 guint i;
3977 for(i=0;i<tc->tracefiles->len;i++) {
3978 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
3979 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
3980 && ltt_tracefile_num(tfc->tf) == process_info->cpu)
3981 break;
3982
3983 }
3984 g_assert(i<tc->tracefiles->len);
3985 tfs = LTTV_TRACEFILE_STATE(tfc);
3986 #endif //0
3987 // LttvTracefileState *tfs =
3988 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3989 // tracefiles[process_info->cpu];
3990
3991 LttvProcessState *process;
3992 process = lttv_state_find_process(ts, process_info->cpu,
3993 process_info->pid);
3994
3995 if(unlikely(process != NULL)) {
3996
3997 /* Only draw for processes that are currently in the trace states */
3998
3999 ProcessList *process_list = control_flow_data->process_list;
4000 #ifdef EXTRA_CHECK
4001 /* Should be alike when background info is ready */
4002 if(control_flow_data->background_info_waiting==0)
4003 g_assert(ltt_time_compare(process->creation_time,
4004 process_info->birth) == 0);
4005 #endif //EXTRA_CHECK
4006
4007 /* Now, the process is in the state hash and our own process hash.
4008 * We definitely can draw the items related to the ending state.
4009 */
4010
4011 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
4012 evtime) <= 0))
4013 {
4014 TimeWindow time_window =
4015 lttvwindow_get_time_window(control_flow_data->tab);
4016
4017 #ifdef EXTRA_CHECK
4018 if(ltt_time_compare(evtime, time_window.start_time) == -1
4019 || ltt_time_compare(evtime, time_window.end_time) == 1)
4020 return;
4021 #endif //EXTRA_CHECK
4022 Drawing_t *drawing = control_flow_data->drawing;
4023 guint width = drawing->width;
4024
4025 guint x = closure_data->x_end;
4026
4027 DrawContext draw_context;
4028
4029 /* Now create the drawing context that will be used to draw
4030 * items related to the last state. */
4031 draw_context.drawable = hashed_process_data->pixmap;
4032 draw_context.gc = drawing->gc;
4033 draw_context.pango_layout = drawing->pango_layout;
4034 draw_context.drawinfo.end.x = x;
4035
4036 draw_context.drawinfo.y.over = 1;
4037 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
4038 draw_context.drawinfo.y.under = hashed_process_data->height;
4039
4040 draw_context.drawinfo.start.offset.over = 0;
4041 draw_context.drawinfo.start.offset.middle = 0;
4042 draw_context.drawinfo.start.offset.under = 0;
4043 draw_context.drawinfo.end.offset.over = 0;
4044 draw_context.drawinfo.end.offset.middle = 0;
4045 draw_context.drawinfo.end.offset.under = 0;
4046 #if 0
4047 /* Jump over draw if we are at the same x position */
4048 if(x == hashed_process_data->x.over)
4049 {
4050 /* jump */
4051 } else {
4052 draw_context.drawinfo.start.x = hashed_process_data->x.over;
4053 /* Draw the line */
4054 PropertiesLine prop_line = prepare_execmode_line(process);
4055 draw_line((void*)&prop_line, (void*)&draw_context);
4056
4057 hashed_process_data->x.over = x;
4058 }
4059 #endif //0
4060
4061 if(unlikely(x == hashed_process_data->x.middle &&
4062 hashed_process_data->x.middle_used)) {
4063 #if 0 /* do not mark closure : not missing information */
4064 if(hashed_process_data->x.middle_marked == FALSE) {
4065 /* Draw collision indicator */
4066 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
4067 gdk_draw_point(drawing->pixmap,
4068 drawing->gc,
4069 x,
4070 y+(height/2)-3);
4071 hashed_process_data->x.middle_marked = TRUE;
4072 }
4073 #endif //0
4074 /* Jump */
4075 } else {
4076 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
4077 /* Draw the line */
4078 PropertiesLine prop_line = prepare_s_e_line(process);
4079 draw_line((void*)&prop_line, (void*)&draw_context);
4080
4081 /* become the last x position */
4082 if(likely(x != hashed_process_data->x.middle)) {
4083 hashed_process_data->x.middle = x;
4084 /* but don't use the pixel */
4085 hashed_process_data->x.middle_used = FALSE;
4086
4087 /* Calculate the next good time */
4088 convert_pixels_to_time(width, x+1, time_window,
4089 &hashed_process_data->next_good_time);
4090 }
4091 }
4092 }
4093 }
4094 }
4095 return;
4096 }
4097
4098 int before_chunk(void *hook_data, void *call_data)
4099 {
4100 EventsRequest *events_request = (EventsRequest*)hook_data;
4101 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4102 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
4103 #if 0
4104 /* Desactivate sort */
4105 gtk_tree_sortable_set_sort_column_id(
4106 GTK_TREE_SORTABLE(cfd->process_list->list_store),
4107 TRACE_COLUMN,
4108 GTK_SORT_ASCENDING);
4109 #endif //0
4110 drawing_chunk_begin(events_request, tss);
4111
4112 return 0;
4113 }
4114
4115 int before_request(void *hook_data, void *call_data)
4116 {
4117 EventsRequest *events_request = (EventsRequest*)hook_data;
4118 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4119
4120 drawing_data_request_begin(events_request, tss);
4121
4122 return 0;
4123 }
4124
4125
4126 /*
4127 * after request is necessary in addition of after chunk in order to draw
4128 * lines until the end of the screen. after chunk just draws lines until
4129 * the last event.
4130 *
4131 * for each process
4132 * draw closing line
4133 * expose
4134 */
4135 int after_request(void *hook_data, void *call_data)
4136 {
4137 EventsRequest *events_request = (EventsRequest*)hook_data;
4138 ControlFlowData *control_flow_data = events_request->viewer_data;
4139 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4140
4141 ProcessList *process_list = control_flow_data->process_list;
4142 LttTime end_time = events_request->end_time;
4143
4144 ClosureData closure_data;
4145 closure_data.events_request = (EventsRequest*)hook_data;
4146 closure_data.tss = tss;
4147 closure_data.end_time = end_time;
4148
4149 TimeWindow time_window =
4150 lttvwindow_get_time_window(control_flow_data->tab);
4151 guint width = control_flow_data->drawing->width;
4152 convert_time_to_pixels(
4153 time_window,
4154 end_time,
4155 width,
4156 &closure_data.x_end);
4157
4158
4159 /* Draw last items */
4160 g_hash_table_foreach(process_list->process_hash, draw_closure,
4161 (void*)&closure_data);
4162
4163
4164 /* Request expose */
4165 drawing_request_expose(events_request, tss, end_time);
4166 return 0;
4167 }
4168
4169 /*
4170 * for each process
4171 * draw closing line
4172 * expose
4173 */
4174 int after_chunk(void *hook_data, void *call_data)
4175 {
4176 EventsRequest *events_request = (EventsRequest*)hook_data;
4177 ControlFlowData *control_flow_data = events_request->viewer_data;
4178 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4179 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
4180 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
4181 LttTime end_time;
4182
4183 ProcessList *process_list = control_flow_data->process_list;
4184
4185 g_free(process_list->current_hash_data);
4186 process_list->current_hash_data = NULL;
4187
4188 if(tfc != NULL)
4189 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
4190 else /* end of traceset, or position now out of request : end */
4191 end_time = events_request->end_time;
4192
4193 ClosureData closure_data;
4194 closure_data.events_request = (EventsRequest*)hook_data;
4195 closure_data.tss = tss;
4196 closure_data.end_time = end_time;
4197
4198 TimeWindow time_window =
4199 lttvwindow_get_time_window(control_flow_data->tab);
4200 guint width = control_flow_data->drawing->width;
4201 convert_time_to_pixels(
4202 time_window,
4203 end_time,
4204 width,
4205 &closure_data.x_end);
4206
4207 /* Draw last items */
4208 g_hash_table_foreach(process_list->process_hash, draw_closure,
4209 (void*)&closure_data);
4210 #if 0
4211 /* Reactivate sort */
4212 gtk_tree_sortable_set_sort_column_id(
4213 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
4214 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
4215 GTK_SORT_ASCENDING);
4216
4217 update_index_to_pixmap(control_flow_data->process_list);
4218 /* Request a full expose : drawing scrambled */
4219 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
4220 #endif //0
4221 /* Request expose (updates damages zone also) */
4222 drawing_request_expose(events_request, tss, end_time);
4223
4224 return 0;
4225 }
4226
This page took 0.111218 seconds and 5 git commands to generate.