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