likely/unlikely branch prediction
[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
382 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
383
384 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
385
386 LttEvent *e;
387 e = tfc->e;
388
389 LttTime evtime = ltt_event_time(e);
390
391 /* we are in a schedchange, before the state update. We must draw the
392 * items corresponding to the state before it changes : now is the right
393 * time to do it.
394 */
395
396 guint pid_out;
397 guint pid_in;
398 {
399 LttField *f = ltt_event_field(e);
400 LttField *element;
401 element = ltt_field_member(f,0);
402 pid_out = ltt_event_get_long_unsigned(e,element);
403 element = ltt_field_member(f,1);
404 pid_in = ltt_event_get_long_unsigned(e,element);
405 g_debug("out : %u in : %u", pid_out, pid_in);
406 }
407
408 {
409 /* For the pid_out */
410 /* First, check if the current process is in the state computation
411 * process list. If it is there, that means we must add it right now and
412 * draw items from the beginning of the read for it. If it is not
413 * present, it's a new process and it was not present : it will
414 * be added after the state update. */
415 LttvProcessState *process;
416 /* unknown state, bad current pid */
417 if(tfs->process->pid != pid_out)
418 process = lttv_state_find_process(tfs, pid_out);
419 else
420 process = tfs->process;
421
422 if(process != NULL) {
423 /* Well, the process_out existed : we must get it in the process hash
424 * or add it, and draw its items.
425 */
426 /* Add process to process list (if not present) */
427 guint y = 0, height = 0, pl_height = 0;
428 HashedProcessData *hashed_process_data = NULL;
429 ProcessList *process_list = control_flow_data->process_list;
430 LttTime birth = process->creation_time;
431
432 hashed_process_data = processlist_get_process_data(process_list,
433 pid_out,
434 process->last_cpu_index,
435 &birth,
436 tfc->t_context->index);
437 if(hashed_process_data == NULL)
438 {
439 g_assert(pid_out == 0 || pid_out != process->ppid);
440 const gchar *name = g_quark_to_string(process->name);
441 /* Process not present */
442 ProcessInfo *process_info;
443 processlist_add(process_list,
444 pid_out,
445 process->last_cpu_index,
446 process->ppid,
447 &birth,
448 tfc->t_context->index,
449 name,
450 &pl_height,
451 &process_info,
452 &hashed_process_data);
453 processlist_get_pixels_from_data(process_list,
454 hashed_process_data,
455 &y,
456 &height);
457 drawing_insert_square( control_flow_data->drawing, y, height);
458 }
459
460 /* Now, the process is in the state hash and our own process hash.
461 * We definitely can draw the items related to the ending state.
462 */
463
464 /* Check if the x position is unset. In can have been left unset by
465 * a draw closure from a after chunk hook. This should never happen,
466 * because it must be set by before chunk hook to the damage_begin
467 * value.
468 */
469 g_assert(hashed_process_data->x.middle != -1);
470 if(ltt_time_compare(hashed_process_data->next_good_time,
471 evtime) > 0)
472 {
473 if(hashed_process_data->x.middle_marked == FALSE) {
474 processlist_get_pixels_from_data(process_list,
475 hashed_process_data,
476 &y,
477 &height);
478
479 TimeWindow time_window =
480 lttvwindow_get_time_window(control_flow_data->tab);
481 #ifdef EXTRA_CHECK
482 if(ltt_time_compare(evtime, time_window.start_time) == -1
483 || ltt_time_compare(evtime, time_window.end_time) == 1)
484 return;
485 #endif //EXTRA_CHECK
486 Drawing_t *drawing = control_flow_data->drawing;
487 guint width = drawing->width;
488 guint x;
489 convert_time_to_pixels(
490 time_window,
491 evtime,
492 width,
493 &x);
494
495 /* Draw collision indicator */
496 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
497 gdk_draw_point(drawing->pixmap,
498 drawing->gc,
499 x,
500 y+(height/2)-3);
501 hashed_process_data->x.middle_marked = TRUE;
502 }
503 } else {
504 processlist_get_pixels_from_data(process_list,
505 hashed_process_data,
506 &y,
507 &height);
508
509
510 TimeWindow time_window =
511 lttvwindow_get_time_window(control_flow_data->tab);
512 #ifdef EXTRA_CHECK
513 if(ltt_time_compare(evtime, time_window.start_time) == -1
514 || ltt_time_compare(evtime, time_window.end_time) == 1)
515 return;
516 #endif //EXTRA_CHECK
517 Drawing_t *drawing = control_flow_data->drawing;
518 guint width = drawing->width;
519 guint x;
520 convert_time_to_pixels(
521 time_window,
522 evtime,
523 width,
524 &x);
525
526
527 /* Jump over draw if we are at the same x position */
528 if(x == hashed_process_data->x.middle &&
529 hashed_process_data->x.middle_used)
530 {
531 if(hashed_process_data->x.middle_marked == FALSE) {
532 /* Draw collision indicator */
533 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
534 gdk_draw_point(drawing->pixmap,
535 drawing->gc,
536 x,
537 y+(height/2)-3);
538 hashed_process_data->x.middle_marked = TRUE;
539 }
540 /* jump */
541 } else {
542 DrawContext draw_context;
543
544 /* Now create the drawing context that will be used to draw
545 * items related to the last state. */
546 draw_context.drawable = drawing->pixmap;
547 draw_context.gc = drawing->gc;
548 draw_context.pango_layout = drawing->pango_layout;
549 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
550 draw_context.drawinfo.end.x = x;
551
552 draw_context.drawinfo.y.over = y+1;
553 draw_context.drawinfo.y.middle = y+(height/2);
554 draw_context.drawinfo.y.under = y+height;
555
556 draw_context.drawinfo.start.offset.over = 0;
557 draw_context.drawinfo.start.offset.middle = 0;
558 draw_context.drawinfo.start.offset.under = 0;
559 draw_context.drawinfo.end.offset.over = 0;
560 draw_context.drawinfo.end.offset.middle = 0;
561 draw_context.drawinfo.end.offset.under = 0;
562
563 {
564 /* Draw the line */
565 PropertiesLine prop_line = prepare_s_e_line(process);
566 draw_line((void*)&prop_line, (void*)&draw_context);
567
568 }
569 /* become the last x position */
570 hashed_process_data->x.middle = x;
571 hashed_process_data->x.middle_used = TRUE;
572 hashed_process_data->x.middle_marked = FALSE;
573
574 /* Calculate the next good time */
575 convert_pixels_to_time(width, x+1, time_window,
576 &hashed_process_data->next_good_time);
577 }
578 }
579 }
580 }
581
582 {
583 /* For the pid_in */
584 /* First, check if the current process is in the state computation
585 * process list. If it is there, that means we must add it right now and
586 * draw items from the beginning of the read for it. If it is not
587 * present, it's a new process and it was not present : it will
588 * be added after the state update. */
589 LttvProcessState *process;
590 process = lttv_state_find_process(tfs, pid_in);
591
592 if(process != NULL) {
593 /* Well, the process_out existed : we must get it in the process hash
594 * or add it, and draw its items.
595 */
596 /* Add process to process list (if not present) */
597 guint y = 0, height = 0, pl_height = 0;
598 HashedProcessData *hashed_process_data = NULL;
599 ProcessList *process_list = control_flow_data->process_list;
600 LttTime birth = process->creation_time;
601
602 hashed_process_data = processlist_get_process_data(process_list,
603 pid_in,
604 process->last_cpu_index,
605 &birth,
606 tfc->t_context->index);
607 if(hashed_process_data == NULL)
608 {
609 g_assert(pid_in == 0 || pid_in != process->ppid);
610 const gchar *name = g_quark_to_string(process->name);
611 /* Process not present */
612 ProcessInfo *process_info;
613 processlist_add(process_list,
614 pid_in,
615 process->last_cpu_index,
616 process->ppid,
617 &birth,
618 tfc->t_context->index,
619 name,
620 &pl_height,
621 &process_info,
622 &hashed_process_data);
623 processlist_get_pixels_from_data(process_list,
624 hashed_process_data,
625 &y,
626 &height);
627 drawing_insert_square( control_flow_data->drawing, y, height);
628 }
629 //We could set the current process and hash here, but will be done
630 //by after schedchange hook
631
632 /* Now, the process is in the state hash and our own process hash.
633 * We definitely can draw the items related to the ending state.
634 */
635
636 /* Check if the x position is unset. In can have been left unset by
637 * a draw closure from a after chunk hook. This should never happen,
638 * because it must be set by before chunk hook to the damage_begin
639 * value.
640 */
641 g_assert(hashed_process_data->x.middle != -1);
642
643 if(ltt_time_compare(hashed_process_data->next_good_time,
644 evtime) > 0)
645 {
646 if(hashed_process_data->x.middle_marked == FALSE) {
647
648 processlist_get_pixels_from_data(process_list,
649 hashed_process_data,
650 &y,
651 &height);
652 TimeWindow time_window =
653 lttvwindow_get_time_window(control_flow_data->tab);
654 #ifdef EXTRA_CHECK
655 if(ltt_time_compare(evtime, time_window.start_time) == -1
656 || ltt_time_compare(evtime, time_window.end_time) == 1)
657 return;
658 #endif //EXTRA_CHECK
659 Drawing_t *drawing = control_flow_data->drawing;
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 Drawing_t *drawing = control_flow_data->drawing;
689 guint width = drawing->width;
690 guint x;
691
692 convert_time_to_pixels(
693 time_window,
694 evtime,
695 width,
696 &x);
697
698
699 /* Jump over draw if we are at the same x position */
700 if(x == hashed_process_data->x.middle &&
701 hashed_process_data->x.middle_used)
702 {
703 if(hashed_process_data->x.middle_marked == FALSE) {
704 /* Draw collision indicator */
705 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
706 gdk_draw_point(drawing->pixmap,
707 drawing->gc,
708 x,
709 y+(height/2)-3);
710 hashed_process_data->x.middle_marked = TRUE;
711 }
712 /* jump */
713 } else {
714 DrawContext draw_context;
715
716 /* Now create the drawing context that will be used to draw
717 * items related to the last state. */
718 draw_context.drawable = drawing->pixmap;
719 draw_context.gc = drawing->gc;
720 draw_context.pango_layout = drawing->pango_layout;
721 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
722 draw_context.drawinfo.end.x = x;
723
724 draw_context.drawinfo.y.over = y+1;
725 draw_context.drawinfo.y.middle = y+(height/2);
726 draw_context.drawinfo.y.under = y+height;
727
728 draw_context.drawinfo.start.offset.over = 0;
729 draw_context.drawinfo.start.offset.middle = 0;
730 draw_context.drawinfo.start.offset.under = 0;
731 draw_context.drawinfo.end.offset.over = 0;
732 draw_context.drawinfo.end.offset.middle = 0;
733 draw_context.drawinfo.end.offset.under = 0;
734
735 {
736 /* Draw the line */
737 PropertiesLine prop_line = prepare_s_e_line(process);
738 draw_line((void*)&prop_line, (void*)&draw_context);
739 }
740
741
742 /* become the last x position */
743 hashed_process_data->x.middle = x;
744 hashed_process_data->x.middle_used = TRUE;
745 hashed_process_data->x.middle_marked = FALSE;
746
747 /* Calculate the next good time */
748 convert_pixels_to_time(width, x+1, time_window,
749 &hashed_process_data->next_good_time);
750 }
751 }
752 }
753 }
754 return 0;
755
756
757 #if 0
758 EventsRequest *events_request = (EventsRequest*)hook_data;
759 ControlFlowData *control_flow_data =
760 (ControlFlowData*)events_request->viewer_data;
761 Tab *tab = control_flow_data->tab;
762
763 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
764
765 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
766 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
767
768 LttEvent *e;
769 e = tfc->e;
770
771 LttTime evtime = ltt_event_time(e);
772 TimeWindow time_window =
773 lttvwindow_get_time_window(tab);
774
775 LttTime time_window.end_time = time_window.time_window.end_time;
776
777 //if(time < time_beg || time > time_end) return;
778 if(ltt_time_compare(evtime, time_window.start_time) == -1
779 || ltt_time_compare(evtime, time_window.end_time) == 1)
780 return;
781
782 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
783 {
784 g_debug("schedchange!");
785
786 /* Add process to process list (if not present) and get drawing "y" from
787 * process position */
788 guint pid_out, pid_in;
789 LttvProcessState *process_out, *process_in;
790 LttTime birth;
791 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
792
793 ProcessList *process_list = control_flow_data->process_list;
794
795
796 LttField *f = ltt_event_field(e);
797 LttField *element;
798 element = ltt_field_member(f,0);
799 pid_out = ltt_event_get_long_unsigned(e,element);
800 element = ltt_field_member(f,1);
801 pid_in = ltt_event_get_long_unsigned(e,element);
802 g_debug("out : %u in : %u", pid_out, pid_in);
803
804
805 /* Find process pid_out in the list... */
806 process_out = lttv_state_find_process(tfs, pid_out);
807 if(process_out == NULL) return 0;
808 g_debug("out : %s",g_quark_to_string(process_out->state->s));
809
810 birth = process_out->creation_time;
811 const gchar *name = g_quark_to_string(process_out->name);
812 HashedProcessData *hashed_process_data_out = NULL;
813
814 if(processlist_get_process_pixels(process_list,
815 pid_out,
816 &birth,
817 tfc->t_context->index,
818 &y_out,
819 &height,
820 &hashed_process_data_out) == 1)
821 {
822 /* Process not present */
823 processlist_add(process_list,
824 pid_out,
825 &birth,
826 tfc->t_context->index,
827 name,
828 &pl_height,
829 &hashed_process_data_out);
830 g_assert(processlist_get_process_pixels(process_list,
831 pid_out,
832 &birth,
833 tfc->t_context->index,
834 &y_out,
835 &height,
836 &hashed_process_data_out)==0);
837 drawing_insert_square( control_flow_data->drawing, y_out, height);
838 }
839 //g_free(name);
840
841 /* Find process pid_in in the list... */
842 process_in = lttv_state_find_process(tfs, pid_in);
843 if(process_in == NULL) return 0;
844 g_debug("in : %s",g_quark_to_string(process_in->state->s));
845
846 birth = process_in->creation_time;
847 name = g_quark_to_string(process_in->name);
848 HashedProcessData *hashed_process_data_in = NULL;
849
850 if(processlist_get_process_pixels(process_list,
851 pid_in,
852 &birth,
853 tfc->t_context->index,
854 &y_in,
855 &height,
856 &hashed_process_data_in) == 1)
857 {
858 /* Process not present */
859 processlist_add(process_list,
860 pid_in,
861 &birth,
862 tfc->t_context->index,
863 name,
864 &pl_height,
865 &hashed_process_data_in);
866 processlist_get_process_pixels(process_list,
867 pid_in,
868 &birth,
869 tfc->t_context->index,
870 &y_in,
871 &height,
872 &hashed_process_data_in);
873
874 drawing_insert_square( control_flow_data->drawing, y_in, height);
875 }
876 //g_free(name);
877
878
879 /* Find pixels corresponding to time of the event. If the time does
880 * not fit in the window, show a warning, not supposed to happend. */
881 guint x = 0;
882 guint width = control_flow_data->drawing->width;
883
884 LttTime time = ltt_event_time(e);
885
886 LttTime window_end = time_window.time_window.end_time;
887
888 convert_time_to_pixels(
889 time_window,
890 time,
891 width,
892 &x);
893 //assert(x <= width);
894 //
895 /* draw what represents the event for outgoing process. */
896
897 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
898 draw_context_out->current->modify_over->x = x;
899 draw_context_out->current->modify_under->x = x;
900 draw_context_out->current->modify_over->y = y_out;
901 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
902 draw_context_out->drawable = control_flow_data->drawing->pixmap;
903 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
904 GtkWidget *widget = control_flow_data->drawing->drawing_area;
905 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
906 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
907 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
908 //draw_context_out->gc = widget->style->black_gc;
909
910 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
911 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
912
913 /* Draw the line/background of the out process */
914 if(draw_context_out->previous->middle->x == -1)
915 {
916 draw_context_out->previous->over->x =
917 control_flow_data->drawing->damage_begin;
918 draw_context_out->previous->middle->x =
919 control_flow_data->drawing->damage_begin;
920 draw_context_out->previous->under->x =
921 control_flow_data->drawing->damage_begin;
922
923 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
924 }
925
926 draw_context_out->current->middle->x = x;
927 draw_context_out->current->over->x = x;
928 draw_context_out->current->under->x = x;
929 draw_context_out->current->middle->y = y_out + height/2;
930 draw_context_out->current->over->y = y_out;
931 draw_context_out->current->under->y = y_out + height;
932 draw_context_out->previous->middle->y = y_out + height/2;
933 draw_context_out->previous->over->y = y_out;
934 draw_context_out->previous->under->y = y_out + height;
935
936 draw_context_out->drawable = control_flow_data->drawing->pixmap;
937 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
938
939 if(process_out->state->s == LTTV_STATE_RUN)
940 {
941 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
942 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
943 draw_context_out->gc = control_flow_data->drawing->gc;
944
945 PropertiesBG prop_bg;
946 prop_bg.color = g_new(GdkColor,1);
947
948 switch(tfc->index) {
949 case 0:
950 prop_bg.color->red = 0x1515;
951 prop_bg.color->green = 0x1515;
952 prop_bg.color->blue = 0x8c8c;
953 break;
954 case 1:
955 prop_bg.color->red = 0x4e4e;
956 prop_bg.color->green = 0xa9a9;
957 prop_bg.color->blue = 0xa4a4;
958 break;
959 case 2:
960 prop_bg.color->red = 0x7a7a;
961 prop_bg.color->green = 0x4a4a;
962 prop_bg.color->blue = 0x8b8b;
963 break;
964 case 3:
965 prop_bg.color->red = 0x8080;
966 prop_bg.color->green = 0x7777;
967 prop_bg.color->blue = 0x4747;
968 break;
969 default:
970 prop_bg.color->red = 0xe7e7;
971 prop_bg.color->green = 0xe7e7;
972 prop_bg.color->blue = 0xe7e7;
973 }
974
975 g_debug("calling from draw_event");
976 draw_bg((void*)&prop_bg, (void*)draw_context_out);
977 g_free(prop_bg.color);
978 //gdk_gc_unref(draw_context_out->gc);
979 }
980
981 draw_context_out->gc = widget->style->black_gc;
982
983 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
984 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
985 PropertiesText prop_text_out;
986 prop_text_out.foreground = &colorfg_out;
987 prop_text_out.background = &colorbg_out;
988 prop_text_out.size = 6;
989 prop_text_out.position = OVER;
990
991 /* color of text : status of the process */
992 if(process_out->state->s == LTTV_STATE_UNNAMED)
993 {
994 prop_text_out.foreground->red = 0xffff;
995 prop_text_out.foreground->green = 0xffff;
996 prop_text_out.foreground->blue = 0xffff;
997 }
998 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
999 {
1000 prop_text_out.foreground->red = 0x0fff;
1001 prop_text_out.foreground->green = 0xffff;
1002 prop_text_out.foreground->blue = 0xfff0;
1003 }
1004 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1005 {
1006 prop_text_out.foreground->red = 0xffff;
1007 prop_text_out.foreground->green = 0xffff;
1008 prop_text_out.foreground->blue = 0x0000;
1009 }
1010 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1011 {
1012 prop_text_out.foreground->red = 0xffff;
1013 prop_text_out.foreground->green = 0x0000;
1014 prop_text_out.foreground->blue = 0xffff;
1015 }
1016 else if(process_out->state->s == LTTV_STATE_WAIT)
1017 {
1018 prop_text_out.foreground->red = 0xffff;
1019 prop_text_out.foreground->green = 0x0000;
1020 prop_text_out.foreground->blue = 0x0000;
1021 }
1022 else if(process_out->state->s == LTTV_STATE_RUN)
1023 {
1024 prop_text_out.foreground->red = 0x0000;
1025 prop_text_out.foreground->green = 0xffff;
1026 prop_text_out.foreground->blue = 0x0000;
1027 }
1028 else
1029 {
1030 prop_text_out.foreground->red = 0xffff;
1031 prop_text_out.foreground->green = 0xffff;
1032 prop_text_out.foreground->blue = 0xffff;
1033 }
1034
1035
1036 /* Print status of the process : U, WF, WC, E, W, R */
1037 if(process_out->state->s == LTTV_STATE_UNNAMED)
1038 prop_text_out.text = "U->";
1039 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1040 prop_text_out.text = "WF->";
1041 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1042 prop_text_out.text = "WC->";
1043 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1044 prop_text_out.text = "E->";
1045 else if(process_out->state->s == LTTV_STATE_WAIT)
1046 prop_text_out.text = "W->";
1047 else if(process_out->state->s == LTTV_STATE_RUN)
1048 prop_text_out.text = "R->";
1049 else
1050 prop_text_out.text = "U";
1051
1052 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1053 //gdk_gc_unref(draw_context_out->gc);
1054
1055 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1056 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1057 draw_context_out->gc = control_flow_data->drawing->gc;
1058
1059 PropertiesLine prop_line_out;
1060 prop_line_out.color = g_new(GdkColor,1);
1061 prop_line_out.line_width = 2;
1062 prop_line_out.style = GDK_LINE_SOLID;
1063 prop_line_out.position = MIDDLE;
1064
1065 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
1066
1067 /* color of line : status of the process */
1068 if(process_out->state->s == LTTV_STATE_UNNAMED)
1069 {
1070 prop_line_out.color->red = 0xffff;
1071 prop_line_out.color->green = 0xffff;
1072 prop_line_out.color->blue = 0xffff;
1073 }
1074 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1075 {
1076 prop_line_out.color->red = 0x0fff;
1077 prop_line_out.color->green = 0xffff;
1078 prop_line_out.color->blue = 0xfff0;
1079 }
1080 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1081 {
1082 prop_line_out.color->red = 0xffff;
1083 prop_line_out.color->green = 0xffff;
1084 prop_line_out.color->blue = 0x0000;
1085 }
1086 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1087 {
1088 prop_line_out.color->red = 0xffff;
1089 prop_line_out.color->green = 0x0000;
1090 prop_line_out.color->blue = 0xffff;
1091 }
1092 else if(process_out->state->s == LTTV_STATE_WAIT)
1093 {
1094 prop_line_out.color->red = 0xffff;
1095 prop_line_out.color->green = 0x0000;
1096 prop_line_out.color->blue = 0x0000;
1097 }
1098 else if(process_out->state->s == LTTV_STATE_RUN)
1099 {
1100 prop_line_out.color->red = 0x0000;
1101 prop_line_out.color->green = 0xffff;
1102 prop_line_out.color->blue = 0x0000;
1103 }
1104 else
1105 {
1106 prop_line_out.color->red = 0xffff;
1107 prop_line_out.color->green = 0xffff;
1108 prop_line_out.color->blue = 0xffff;
1109 }
1110
1111 draw_line((void*)&prop_line_out, (void*)draw_context_out);
1112 g_free(prop_line_out.color);
1113 //gdk_gc_unref(draw_context_out->gc);
1114 /* Note : finishing line will have to be added when trace read over. */
1115
1116 /* Finally, update the drawing context of the pid_in. */
1117
1118 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1119 draw_context_in->current->modify_over->x = x;
1120 draw_context_in->current->modify_under->x = x;
1121 draw_context_in->current->modify_over->y = y_in;
1122 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1123 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1124 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1125 widget = control_flow_data->drawing->drawing_area;
1126 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1127 //draw_context_in->gc = widget->style->black_gc;
1128 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1129 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1130
1131 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1132 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1133
1134 /* Draw the line/bg of the in process */
1135 if(draw_context_in->previous->middle->x == -1)
1136 {
1137 draw_context_in->previous->over->x =
1138 control_flow_data->drawing->damage_begin;
1139 draw_context_in->previous->middle->x =
1140 control_flow_data->drawing->damage_begin;
1141 draw_context_in->previous->under->x =
1142 control_flow_data->drawing->damage_begin;
1143
1144 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
1145
1146 }
1147
1148 draw_context_in->current->middle->x = x;
1149 draw_context_in->current->over->x = x;
1150 draw_context_in->current->under->x = x;
1151 draw_context_in->current->middle->y = y_in + height/2;
1152 draw_context_in->current->over->y = y_in;
1153 draw_context_in->current->under->y = y_in + height;
1154 draw_context_in->previous->middle->y = y_in + height/2;
1155 draw_context_in->previous->over->y = y_in;
1156 draw_context_in->previous->under->y = y_in + height;
1157
1158 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1159 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1160
1161
1162 if(process_in->state->s == LTTV_STATE_RUN)
1163 {
1164 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1165 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1166 draw_context_in->gc = control_flow_data->drawing->gc;
1167
1168 PropertiesBG prop_bg;
1169 prop_bg.color = g_new(GdkColor,1);
1170
1171 switch(tfc->index) {
1172 case 0:
1173 prop_bg.color->red = 0x1515;
1174 prop_bg.color->green = 0x1515;
1175 prop_bg.color->blue = 0x8c8c;
1176 break;
1177 case 1:
1178 prop_bg.color->red = 0x4e4e;
1179 prop_bg.color->green = 0xa9a9;
1180 prop_bg.color->blue = 0xa4a4;
1181 break;
1182 case 2:
1183 prop_bg.color->red = 0x7a7a;
1184 prop_bg.color->green = 0x4a4a;
1185 prop_bg.color->blue = 0x8b8b;
1186 break;
1187 case 3:
1188 prop_bg.color->red = 0x8080;
1189 prop_bg.color->green = 0x7777;
1190 prop_bg.color->blue = 0x4747;
1191 break;
1192 default:
1193 prop_bg.color->red = 0xe7e7;
1194 prop_bg.color->green = 0xe7e7;
1195 prop_bg.color->blue = 0xe7e7;
1196 }
1197
1198
1199 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1200 g_free(prop_bg.color);
1201 //gdk_gc_unref(draw_context_in->gc);
1202 }
1203
1204 draw_context_in->gc = widget->style->black_gc;
1205
1206 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1207 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1208 PropertiesText prop_text_in;
1209 prop_text_in.foreground = &colorfg_in;
1210 prop_text_in.background = &colorbg_in;
1211 prop_text_in.size = 6;
1212 prop_text_in.position = OVER;
1213
1214 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1215 /* foreground of text : status of the process */
1216 if(process_in->state->s == LTTV_STATE_UNNAMED)
1217 {
1218 prop_text_in.foreground->red = 0xffff;
1219 prop_text_in.foreground->green = 0xffff;
1220 prop_text_in.foreground->blue = 0xffff;
1221 }
1222 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1223 {
1224 prop_text_in.foreground->red = 0x0fff;
1225 prop_text_in.foreground->green = 0xffff;
1226 prop_text_in.foreground->blue = 0xfff0;
1227 }
1228 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1229 {
1230 prop_text_in.foreground->red = 0xffff;
1231 prop_text_in.foreground->green = 0xffff;
1232 prop_text_in.foreground->blue = 0x0000;
1233 }
1234 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1235 {
1236 prop_text_in.foreground->red = 0xffff;
1237 prop_text_in.foreground->green = 0x0000;
1238 prop_text_in.foreground->blue = 0xffff;
1239 }
1240 else if(process_in->state->s == LTTV_STATE_WAIT)
1241 {
1242 prop_text_in.foreground->red = 0xffff;
1243 prop_text_in.foreground->green = 0x0000;
1244 prop_text_in.foreground->blue = 0x0000;
1245 }
1246 else if(process_in->state->s == LTTV_STATE_RUN)
1247 {
1248 prop_text_in.foreground->red = 0x0000;
1249 prop_text_in.foreground->green = 0xffff;
1250 prop_text_in.foreground->blue = 0x0000;
1251 }
1252 else
1253 {
1254 prop_text_in.foreground->red = 0xffff;
1255 prop_text_in.foreground->green = 0xffff;
1256 prop_text_in.foreground->blue = 0xffff;
1257 }
1258
1259
1260
1261 /* Print status of the process : U, WF, WC, E, W, R */
1262 if(process_in->state->s == LTTV_STATE_UNNAMED)
1263 prop_text_in.text = "U->";
1264 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1265 prop_text_in.text = "WF->";
1266 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1267 prop_text_in.text = "WC->";
1268 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1269 prop_text_in.text = "E->";
1270 else if(process_in->state->s == LTTV_STATE_WAIT)
1271 prop_text_in.text = "W->";
1272 else if(process_in->state->s == LTTV_STATE_RUN)
1273 prop_text_in.text = "R->";
1274 else
1275 prop_text_in.text = "U";
1276
1277 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1278 //gdk_gc_unref(draw_context_in->gc);
1279
1280 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1281 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1282 draw_context_in->gc = control_flow_data->drawing->gc;
1283
1284 PropertiesLine prop_line_in;
1285 prop_line_in.color = g_new(GdkColor,1);
1286 prop_line_in.line_width = 2;
1287 prop_line_in.style = GDK_LINE_SOLID;
1288 prop_line_in.position = MIDDLE;
1289
1290 /* color of line : status of the process */
1291 if(process_in->state->s == LTTV_STATE_UNNAMED)
1292 {
1293 prop_line_in.color->red = 0xffff;
1294 prop_line_in.color->green = 0xffff;
1295 prop_line_in.color->blue = 0xffff;
1296 }
1297 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1298 {
1299 prop_line_in.color->red = 0x0fff;
1300 prop_line_in.color->green = 0xffff;
1301 prop_line_in.color->blue = 0xfff0;
1302 }
1303 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1304 {
1305 prop_line_in.color->red = 0xffff;
1306 prop_line_in.color->green = 0xffff;
1307 prop_line_in.color->blue = 0x0000;
1308 }
1309 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1310 {
1311 prop_line_in.color->red = 0xffff;
1312 prop_line_in.color->green = 0x0000;
1313 prop_line_in.color->blue = 0xffff;
1314 }
1315 else if(process_in->state->s == LTTV_STATE_WAIT)
1316 {
1317 prop_line_in.color->red = 0xffff;
1318 prop_line_in.color->green = 0x0000;
1319 prop_line_in.color->blue = 0x0000;
1320 }
1321 else if(process_in->state->s == LTTV_STATE_RUN)
1322 {
1323 prop_line_in.color->red = 0x0000;
1324 prop_line_in.color->green = 0xffff;
1325 prop_line_in.color->blue = 0x0000;
1326 }
1327 else
1328 {
1329 prop_line_in.color->red = 0xffff;
1330 prop_line_in.color->green = 0xffff;
1331 prop_line_in.color->blue = 0xffff;
1332 }
1333
1334 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1335 g_free(prop_line_in.color);
1336 //gdk_gc_unref(draw_context_in->gc);
1337 }
1338
1339 return 0;
1340 #endif //0
1341
1342
1343
1344 /* Text dump */
1345 #ifdef DONTSHOW
1346 GString *string = g_string_new("");;
1347 gboolean field_names = TRUE, state = TRUE;
1348
1349 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1350 g_string_append_printf(string,"\n");
1351
1352 if(state) {
1353 g_string_append_printf(string, " %s",
1354 g_quark_to_string(tfs->process->state->s));
1355 }
1356
1357 g_info("%s",string->str);
1358
1359 g_string_free(string, TRUE);
1360
1361 /* End of text dump */
1362 #endif //DONTSHOW
1363
1364 }
1365
1366 /* after_schedchange_hook
1367 *
1368 * The draw after hook is called by the reading API to have a
1369 * particular event drawn on the screen.
1370 * @param hook_data ControlFlowData structure of the viewer.
1371 * @param call_data Event context.
1372 *
1373 * This function adds items to be drawn in a queue for each process.
1374 *
1375 */
1376 int after_schedchange_hook(void *hook_data, void *call_data)
1377 {
1378 EventsRequest *events_request = (EventsRequest*)hook_data;
1379 ControlFlowData *control_flow_data = events_request->viewer_data;
1380
1381 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1382
1383 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
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 Drawing_t *drawing = control_flow_data->drawing;
1467 guint width = 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
1995 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1996
1997 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1998
1999 LttEvent *e;
2000 e = tfc->e;
2001
2002 LttTime evtime = ltt_event_time(e);
2003
2004 /* we are in a execmode, before the state update. We must draw the
2005 * items corresponding to the state before it changes : now is the right
2006 * time to do it.
2007 */
2008 /* For the pid */
2009 LttvProcessState *process = tfs->process;
2010 g_assert(process != NULL);
2011
2012 guint pid = process->pid;
2013
2014 /* Well, the process_out existed : we must get it in the process hash
2015 * or add it, and draw its items.
2016 */
2017 /* Add process to process list (if not present) */
2018 guint y = 0, height = 0, pl_height = 0;
2019 HashedProcessData *hashed_process_data = NULL;
2020 ProcessList *process_list = control_flow_data->process_list;
2021 LttTime birth = process->creation_time;
2022
2023 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2024 hashed_process_data = process_list->current_hash_data[tfc->index];
2025 } else {
2026 hashed_process_data = processlist_get_process_data(process_list,
2027 pid,
2028 process->last_cpu_index,
2029 &birth,
2030 tfc->t_context->index);
2031 if(unlikely(hashed_process_data == NULL))
2032 {
2033 g_assert(pid == 0 || pid != process->ppid);
2034 ProcessInfo *process_info;
2035 /* Process not present */
2036 const gchar *name = g_quark_to_string(process->name);
2037 processlist_add(process_list,
2038 pid,
2039 process->last_cpu_index,
2040 process->ppid,
2041 &birth,
2042 tfc->t_context->index,
2043 name,
2044 &pl_height,
2045 &process_info,
2046 &hashed_process_data);
2047 processlist_get_pixels_from_data(process_list,
2048 hashed_process_data,
2049 &y,
2050 &height);
2051 drawing_insert_square( control_flow_data->drawing, y, height);
2052 }
2053 /* Set the current process */
2054 process_list->current_hash_data[process->last_cpu_index] =
2055 hashed_process_data;
2056 }
2057
2058 /* Now, the process is in the state hash and our own process hash.
2059 * We definitely can draw the items related to the ending state.
2060 */
2061
2062 /* Check if the x position is unset. In can have been left unset by
2063 * a draw closure from a after chunk hook. This should never happen,
2064 * because it must be set by before chunk hook to the damage_begin
2065 * value.
2066 */
2067 g_assert(hashed_process_data->x.over != -1);
2068
2069 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2070 evtime) > 0))
2071 {
2072 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2073 processlist_get_pixels_from_data(process_list,
2074 hashed_process_data,
2075 &y,
2076 &height);
2077 TimeWindow time_window =
2078 lttvwindow_get_time_window(control_flow_data->tab);
2079
2080 #ifdef EXTRA_CHECK
2081 if(ltt_time_compare(evtime, time_window.start_time) == -1
2082 || ltt_time_compare(evtime, time_window.end_time) == 1)
2083 return;
2084 #endif //EXTRA_CHECK
2085 Drawing_t *drawing = control_flow_data->drawing;
2086 guint width = drawing->width;
2087 guint x;
2088 convert_time_to_pixels(
2089 time_window,
2090 evtime,
2091 width,
2092 &x);
2093
2094 /* Draw collision indicator */
2095 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2096 gdk_draw_point(drawing->pixmap,
2097 drawing->gc,
2098 x,
2099 y+(height/2)-3);
2100 hashed_process_data->x.middle_marked = TRUE;
2101 }
2102 } else {
2103 processlist_get_pixels_from_data(process_list,
2104 hashed_process_data,
2105 &y,
2106 &height);
2107 TimeWindow time_window =
2108 lttvwindow_get_time_window(control_flow_data->tab);
2109
2110 #ifdef EXTRA_CHECK
2111 if(ltt_time_compare(evtime, time_window.start_time) == -1
2112 || ltt_time_compare(evtime, time_window.end_time) == 1)
2113 return;
2114 #endif //EXTRA_CHECK
2115 Drawing_t *drawing = control_flow_data->drawing;
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(unlikely(x == hashed_process_data->x.middle &&
2128 hashed_process_data->x.middle_used))
2129 {
2130 if(unlikely(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
2207 LttEvent *e;
2208 e = tfc->e;
2209
2210 LttTime evtime = ltt_event_time(e);
2211
2212 /* Add process to process list (if not present) */
2213 LttvProcessState *process;
2214 LttTime birth;
2215 guint y = 0, height = 0, pl_height = 0;
2216 HashedProcessData *hashed_process_data = NULL;
2217
2218 ProcessList *process_list = control_flow_data->process_list;
2219
2220 /* Find process pid_in in the list... */
2221 process = tfs->process;
2222 /* It should exist, because we are after the state update. */
2223 g_assert(process != NULL);
2224
2225 guint pid = process->pid;
2226
2227 birth = process->creation_time;
2228
2229 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2230 hashed_process_data = process_list->current_hash_data[tfc->index];
2231 } else {
2232 hashed_process_data = processlist_get_process_data(process_list,
2233 pid,
2234 process->last_cpu_index,
2235 &birth,
2236 tfc->t_context->index);
2237 if(unlikely(hashed_process_data == NULL))
2238 {
2239 g_assert(pid == 0 || pid != process->ppid);
2240 /* Process not present */
2241 const gchar *name = g_quark_to_string(process->name);
2242 ProcessInfo *process_info;
2243 processlist_add(process_list,
2244 pid,
2245 process->last_cpu_index,
2246 process->ppid,
2247 &birth,
2248 tfc->t_context->index,
2249 name,
2250 &pl_height,
2251 &process_info,
2252 &hashed_process_data);
2253 processlist_get_pixels_from_data(process_list,
2254 hashed_process_data,
2255 &y,
2256 &height);
2257 drawing_insert_square( control_flow_data->drawing, y, height);
2258 }
2259 /* Set the current process */
2260 process_list->current_hash_data[process->last_cpu_index] =
2261 hashed_process_data;
2262 }
2263
2264 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2265 evtime) <= 0))
2266 {
2267 #if 0
2268 processlist_get_pixels_from_data(process_list,
2269 hashed_process_data,
2270 &y,
2271 &height);
2272 #endif //0
2273 TimeWindow time_window =
2274 lttvwindow_get_time_window(control_flow_data->tab);
2275
2276 #ifdef EXTRA_CHECK
2277 if(ltt_time_compare(evtime, time_window.start_time) == -1
2278 || ltt_time_compare(evtime, time_window.end_time) == 1)
2279 return;
2280 #endif //EXTRA_CHECK
2281 Drawing_t *drawing = control_flow_data->drawing;
2282 guint width = 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
2317 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2318
2319 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2320
2321 LttEvent *e;
2322 e = tfc->e;
2323
2324 LttTime evtime = ltt_event_time(e);
2325
2326 guint sub_id;
2327 {
2328 LttField *f = ltt_event_field(e);
2329 LttField *element;
2330 element = ltt_field_member(f,0);
2331 sub_id = ltt_event_get_long_unsigned(e,element);
2332 }
2333
2334 if(sub_id == 3) { /* exit */
2335
2336 /* Add process to process list (if not present) */
2337 LttvProcessState *process = tfs->process;
2338 guint pid = process->pid;
2339 LttTime birth;
2340 guint y = 0, height = 0, pl_height = 0;
2341 HashedProcessData *hashed_process_data = NULL;
2342
2343 ProcessList *process_list = control_flow_data->process_list;
2344
2345 g_assert(process != NULL);
2346
2347 birth = process->creation_time;
2348
2349 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2350 hashed_process_data = process_list->current_hash_data[tfc->index];
2351 } else {
2352 hashed_process_data = processlist_get_process_data(process_list,
2353 pid,
2354 process->last_cpu_index,
2355 &birth,
2356 tfc->t_context->index);
2357 if(unlikely(hashed_process_data == NULL))
2358 {
2359 g_assert(pid == 0 || pid != process->ppid);
2360 /* Process not present */
2361 const gchar *name = g_quark_to_string(process->name);
2362 ProcessInfo *process_info;
2363 processlist_add(process_list,
2364 pid,
2365 process->last_cpu_index,
2366 process->ppid,
2367 &birth,
2368 tfc->t_context->index,
2369 name,
2370 &pl_height,
2371 &process_info,
2372 &hashed_process_data);
2373 processlist_get_pixels_from_data(process_list,
2374 hashed_process_data,
2375 &y,
2376 &height);
2377 drawing_insert_square( control_flow_data->drawing, y, height);
2378 }
2379 }
2380
2381 /* Now, the process is in the state hash and our own process hash.
2382 * We definitely can draw the items related to the ending state.
2383 */
2384
2385 /* Check if the x position is unset. In can have been left unset by
2386 * a draw closure from a after chunk hook. This should never happen,
2387 * because it must be set by before chunk hook to the damage_begin
2388 * value.
2389 */
2390 g_assert(hashed_process_data->x.over != -1);
2391
2392 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2393 evtime) > 0))
2394 {
2395 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2396 processlist_get_pixels_from_data(process_list,
2397 hashed_process_data,
2398 &y,
2399 &height);
2400 TimeWindow time_window =
2401 lttvwindow_get_time_window(control_flow_data->tab);
2402
2403 #ifdef EXTRA_CHECK
2404 if(ltt_time_compare(evtime, time_window.start_time) == -1
2405 || ltt_time_compare(evtime, time_window.end_time) == 1)
2406 return;
2407 #endif //EXTRA_CHECK
2408 Drawing_t *drawing = control_flow_data->drawing;
2409 guint width = drawing->width;
2410 guint x;
2411 convert_time_to_pixels(
2412 time_window,
2413 evtime,
2414 width,
2415 &x);
2416
2417 /* Draw collision indicator */
2418 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2419 gdk_draw_point(drawing->pixmap,
2420 drawing->gc,
2421 x,
2422 y+(height/2)-3);
2423 hashed_process_data->x.middle_marked = TRUE;
2424 }
2425 } else {
2426 processlist_get_pixels_from_data(process_list,
2427 hashed_process_data,
2428 &y,
2429 &height);
2430 TimeWindow time_window =
2431 lttvwindow_get_time_window(control_flow_data->tab);
2432
2433 #ifdef EXTRA_CHECK
2434 if(ltt_time_compare(evtime, time_window.start_time) == -1
2435 || ltt_time_compare(evtime, time_window.end_time) == 1)
2436 return;
2437 #endif //EXTRA_CHECK
2438 Drawing_t *drawing = control_flow_data->drawing;
2439 guint width = drawing->width;
2440 guint x;
2441
2442 convert_time_to_pixels(
2443 time_window,
2444 evtime,
2445 width,
2446 &x);
2447
2448
2449 /* Jump over draw if we are at the same x position */
2450 if(unlikely(x == hashed_process_data->x.middle &&
2451 hashed_process_data->x.middle_used))
2452 {
2453 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2454 /* Draw collision indicator */
2455 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2456 gdk_draw_point(drawing->pixmap,
2457 drawing->gc,
2458 x,
2459 y+(height/2)-3);
2460 hashed_process_data->x.middle_marked = TRUE;
2461 }
2462 /* jump */
2463 } else {
2464 DrawContext draw_context;
2465
2466 /* Now create the drawing context that will be used to draw
2467 * items related to the last state. */
2468 draw_context.drawable = drawing->pixmap;
2469 draw_context.gc = drawing->gc;
2470 draw_context.pango_layout = drawing->pango_layout;
2471 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2472 draw_context.drawinfo.end.x = x;
2473
2474 draw_context.drawinfo.y.over = y+1;
2475 draw_context.drawinfo.y.middle = y+(height/2);
2476 draw_context.drawinfo.y.under = y+height;
2477
2478 draw_context.drawinfo.start.offset.over = 0;
2479 draw_context.drawinfo.start.offset.middle = 0;
2480 draw_context.drawinfo.start.offset.under = 0;
2481 draw_context.drawinfo.end.offset.over = 0;
2482 draw_context.drawinfo.end.offset.middle = 0;
2483 draw_context.drawinfo.end.offset.under = 0;
2484
2485 {
2486 /* Draw the line */
2487 PropertiesLine prop_line = prepare_s_e_line(process);
2488 draw_line((void*)&prop_line, (void*)&draw_context);
2489
2490 }
2491 /* become the last x position */
2492 hashed_process_data->x.middle = x;
2493 hashed_process_data->x.middle_used = TRUE;
2494 hashed_process_data->x.middle_marked = FALSE;
2495
2496 /* Calculate the next good time */
2497 convert_pixels_to_time(width, x+1, time_window,
2498 &hashed_process_data->next_good_time);
2499 }
2500 }
2501
2502 }
2503 return 0;
2504
2505 }
2506
2507
2508
2509
2510
2511
2512 /* after_process_hook
2513 *
2514 * Create the processlist entry for the child process. Put the last
2515 * position in x at the current time value.
2516 *
2517 * @param hook_data ControlFlowData structure of the viewer.
2518 * @param call_data Event context.
2519 *
2520 * This function adds items to be drawn in a queue for each process.
2521 *
2522 */
2523 int after_process_hook(void *hook_data, void *call_data)
2524 {
2525 EventsRequest *events_request = (EventsRequest*)hook_data;
2526 ControlFlowData *control_flow_data = events_request->viewer_data;
2527
2528 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2529
2530 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2531
2532 LttEvent *e;
2533 e = tfc->e;
2534
2535 LttTime evtime = ltt_event_time(e);
2536
2537 guint sub_id;
2538 guint param1;
2539 {
2540 LttField *f = ltt_event_field(e);
2541 LttField *element;
2542 element = ltt_field_member(f,0);
2543 sub_id = ltt_event_get_long_unsigned(e,element);
2544 element = ltt_field_member(f,1);
2545 param1 = ltt_event_get_long_unsigned(e,element);
2546 }
2547
2548 if(sub_id == 2) { /* fork */
2549
2550 guint child_pid = param1;
2551 /* Add process to process list (if not present) */
2552 LttvProcessState *process_child;
2553 LttTime birth;
2554 guint y_child = 0, height = 0, pl_height = 0;
2555 HashedProcessData *hashed_process_data_child = NULL;
2556
2557 ProcessList *process_list = control_flow_data->process_list;
2558
2559 /* Find child in the list... */
2560 process_child = lttv_state_find_process(tfs, child_pid);
2561 /* It should exist, because we are after the state update. */
2562 g_assert(process_child != NULL);
2563
2564 birth = process_child->creation_time;
2565
2566 hashed_process_data_child = processlist_get_process_data(process_list,
2567 child_pid,
2568 process_child->last_cpu_index,
2569 &birth,
2570 tfc->t_context->index);
2571 if(likely(hashed_process_data_child == NULL))
2572 {
2573 g_assert(child_pid == 0 || child_pid != process_child->ppid);
2574 /* Process not present */
2575 const gchar *name = g_quark_to_string(process_child->name);
2576 ProcessInfo *process_info;
2577 processlist_add(process_list,
2578 child_pid,
2579 process_child->last_cpu_index,
2580 process_child->ppid,
2581 &birth,
2582 tfc->t_context->index,
2583 name,
2584 &pl_height,
2585 &process_info,
2586 &hashed_process_data_child);
2587 processlist_get_pixels_from_data(process_list,
2588 hashed_process_data_child,
2589 &y_child,
2590 &height);
2591 drawing_insert_square( control_flow_data->drawing, y_child, height);
2592 }
2593
2594
2595 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
2596 evtime) <= 0))
2597 {
2598 #if 0
2599 processlist_get_pixels_from_data(process_list,
2600 hashed_process_data_child,
2601 &y_child,
2602 &height);
2603 #endif //0
2604 TimeWindow time_window =
2605 lttvwindow_get_time_window(control_flow_data->tab);
2606
2607 #ifdef EXTRA_CHECK
2608 if(ltt_time_compare(evtime, time_window.start_time) == -1
2609 || ltt_time_compare(evtime, time_window.end_time) == 1)
2610 return;
2611 #endif //EXTRA_CHECK
2612 Drawing_t *drawing = control_flow_data->drawing;
2613 guint width = drawing->width;
2614 guint new_x;
2615 convert_time_to_pixels(
2616 time_window,
2617 evtime,
2618 width,
2619 &new_x);
2620
2621 if(likely(hashed_process_data_child->x.over != new_x)) {
2622 hashed_process_data_child->x.over = new_x;
2623 hashed_process_data_child->x.over_used = FALSE;
2624 hashed_process_data_child->x.over_marked = FALSE;
2625 }
2626 if(likely(hashed_process_data_child->x.middle != new_x)) {
2627 hashed_process_data_child->x.middle = new_x;
2628 hashed_process_data_child->x.middle_used = FALSE;
2629 hashed_process_data_child->x.middle_marked = FALSE;
2630 }
2631 if(likely(hashed_process_data_child->x.under != new_x)) {
2632 hashed_process_data_child->x.under = new_x;
2633 hashed_process_data_child->x.under_used = FALSE;
2634 hashed_process_data_child->x.under_marked = FALSE;
2635 }
2636 }
2637
2638 } else if(sub_id == 3) { /* exit */
2639
2640 /* Add process to process list (if not present) */
2641 LttvProcessState *process = tfs->process;
2642 guint pid = process->pid;
2643 LttTime birth;
2644 guint y = 0, height = 0, pl_height = 0;
2645 HashedProcessData *hashed_process_data = NULL;
2646
2647 ProcessList *process_list = control_flow_data->process_list;
2648
2649 /* It should exist, because we are after the state update. */
2650 g_assert(process != NULL);
2651
2652 birth = process->creation_time;
2653
2654 if(likely(process_list->current_hash_data[tfc->index] != NULL) ){
2655 hashed_process_data = process_list->current_hash_data[tfc->index];
2656 } else {
2657 hashed_process_data = processlist_get_process_data(process_list,
2658 pid,
2659 process->last_cpu_index,
2660 &birth,
2661 tfc->t_context->index);
2662 if(unlikely(hashed_process_data == NULL))
2663 {
2664 g_assert(pid == 0 || pid != process->ppid);
2665 /* Process not present */
2666 const gchar *name = g_quark_to_string(process->name);
2667 ProcessInfo *process_info;
2668 processlist_add(process_list,
2669 pid,
2670 process->last_cpu_index,
2671 process->ppid,
2672 &birth,
2673 tfc->t_context->index,
2674 name,
2675 &pl_height,
2676 &process_info,
2677 &hashed_process_data);
2678 processlist_get_pixels_from_data(process_list,
2679 hashed_process_data,
2680 &y,
2681 &height);
2682 drawing_insert_square( control_flow_data->drawing, y, height);
2683 }
2684
2685 /* Set the current process */
2686 process_list->current_hash_data[process->last_cpu_index] =
2687 hashed_process_data;
2688 }
2689
2690 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2691 evtime) <= 0))
2692 {
2693 #if 0
2694 processlist_get_pixels_from_data(process_list,
2695 hashed_process_data,
2696 &y,
2697 &height);
2698 #endif //0
2699 TimeWindow time_window =
2700 lttvwindow_get_time_window(control_flow_data->tab);
2701
2702 #ifdef EXTRA_CHECK
2703 if(ltt_time_compare(evtime, time_window.start_time) == -1
2704 || ltt_time_compare(evtime, time_window.end_time) == 1)
2705 return;
2706 #endif //EXTRA_CHECK
2707 Drawing_t *drawing = control_flow_data->drawing;
2708 guint width = drawing->width;
2709 guint new_x;
2710 convert_time_to_pixels(
2711 time_window,
2712 evtime,
2713 width,
2714 &new_x);
2715 if(unlikely(hashed_process_data->x.middle != new_x)) {
2716 hashed_process_data->x.middle = new_x;
2717 hashed_process_data->x.middle_used = FALSE;
2718 hashed_process_data->x.middle_marked = FALSE;
2719 }
2720 }
2721
2722 }
2723 return 0;
2724
2725 }
2726
2727
2728 gint update_time_window_hook(void *hook_data, void *call_data)
2729 {
2730 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2731 Drawing_t *drawing = control_flow_data->drawing;
2732
2733 const TimeWindowNotifyData *time_window_nofify_data =
2734 ((const TimeWindowNotifyData *)call_data);
2735
2736 TimeWindow *old_time_window =
2737 time_window_nofify_data->old_time_window;
2738 TimeWindow *new_time_window =
2739 time_window_nofify_data->new_time_window;
2740
2741 /* Update the ruler */
2742 drawing_update_ruler(control_flow_data->drawing,
2743 new_time_window);
2744
2745
2746 /* Two cases : zoom in/out or scrolling */
2747
2748 /* In order to make sure we can reuse the old drawing, the scale must
2749 * be the same and the new time interval being partly located in the
2750 * currently shown time interval. (reuse is only for scrolling)
2751 */
2752
2753 g_info("Old time window HOOK : %u, %u to %u, %u",
2754 old_time_window->start_time.tv_sec,
2755 old_time_window->start_time.tv_nsec,
2756 old_time_window->time_width.tv_sec,
2757 old_time_window->time_width.tv_nsec);
2758
2759 g_info("New time window HOOK : %u, %u to %u, %u",
2760 new_time_window->start_time.tv_sec,
2761 new_time_window->start_time.tv_nsec,
2762 new_time_window->time_width.tv_sec,
2763 new_time_window->time_width.tv_nsec);
2764
2765 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2766 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
2767 {
2768 /* Same scale (scrolling) */
2769 g_info("scrolling");
2770 LttTime *ns = &new_time_window->start_time;
2771 LttTime *nw = &new_time_window->time_width;
2772 LttTime *os = &old_time_window->start_time;
2773 LttTime *ow = &old_time_window->time_width;
2774 LttTime old_end = old_time_window->end_time;
2775 LttTime new_end = new_time_window->end_time;
2776 //if(ns<os+w<ns+w)
2777 //if(ns<os+w && os+w<ns+w)
2778 //if(ns<old_end && os<ns)
2779 if(ltt_time_compare(*ns, old_end) == -1
2780 && ltt_time_compare(*os, *ns) == -1)
2781 {
2782 g_info("scrolling near right");
2783 /* Scroll right, keep right part of the screen */
2784 guint x = 0;
2785 guint width = control_flow_data->drawing->width;
2786 convert_time_to_pixels(
2787 *old_time_window,
2788 *ns,
2789 width,
2790 &x);
2791
2792 /* Copy old data to new location */
2793 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2794 control_flow_data->drawing->drawing_area->style->black_gc,
2795 control_flow_data->drawing->pixmap,
2796 x, 0,
2797 0, 0,
2798 control_flow_data->drawing->width-x+SAFETY, -1);
2799
2800 if(drawing->damage_begin == drawing->damage_end)
2801 drawing->damage_begin = control_flow_data->drawing->width-x;
2802 else
2803 drawing->damage_begin = 0;
2804
2805 drawing->damage_end = control_flow_data->drawing->width;
2806
2807 /* Clear the data request background, but not SAFETY */
2808 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2809 //control_flow_data->drawing->drawing_area->style->black_gc,
2810 control_flow_data->drawing->drawing_area->style->black_gc,
2811 TRUE,
2812 drawing->damage_begin+SAFETY, 0,
2813 drawing->damage_end - drawing->damage_begin, // do not overlap
2814 control_flow_data->drawing->height);
2815
2816 gtk_widget_queue_draw_area (drawing->drawing_area,
2817 0,0,
2818 control_flow_data->drawing->width,
2819 control_flow_data->drawing->height);
2820
2821 /* Get new data for the rest. */
2822 drawing_data_request(control_flow_data->drawing,
2823 &control_flow_data->drawing->pixmap,
2824 drawing->damage_begin, 0,
2825 drawing->damage_end - drawing->damage_begin,
2826 control_flow_data->drawing->height);
2827 } else {
2828 //if(ns<os<ns+w)
2829 //if(ns<os && os<ns+w)
2830 //if(ns<os && os<new_end)
2831 if(ltt_time_compare(*ns,*os) == -1
2832 && ltt_time_compare(*os,new_end) == -1)
2833 {
2834 g_info("scrolling near left");
2835 /* Scroll left, keep left part of the screen */
2836 guint x = 0;
2837 guint width = control_flow_data->drawing->width;
2838 convert_time_to_pixels(
2839 *new_time_window,
2840 *os,
2841 width,
2842 &x);
2843
2844
2845 /* Copy old data to new location */
2846 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2847 control_flow_data->drawing->drawing_area->style->black_gc,
2848 control_flow_data->drawing->pixmap,
2849 0, 0,
2850 x, 0,
2851 -1, -1);
2852
2853 if(drawing->damage_begin == drawing->damage_end)
2854 drawing->damage_end = x;
2855 else
2856 drawing->damage_end =
2857 control_flow_data->drawing->width;
2858
2859 drawing->damage_begin = 0;
2860
2861 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2862 control_flow_data->drawing->drawing_area->style->black_gc,
2863 TRUE,
2864 drawing->damage_begin, 0,
2865 drawing->damage_end - drawing->damage_begin, // do not overlap
2866 control_flow_data->drawing->height);
2867
2868 gtk_widget_queue_draw_area (drawing->drawing_area,
2869 0,0,
2870 control_flow_data->drawing->width,
2871 control_flow_data->drawing->height);
2872
2873
2874 /* Get new data for the rest. */
2875 drawing_data_request(control_flow_data->drawing,
2876 &control_flow_data->drawing->pixmap,
2877 drawing->damage_begin, 0,
2878 drawing->damage_end - drawing->damage_begin,
2879 control_flow_data->drawing->height);
2880
2881 } else {
2882 if(ltt_time_compare(*ns,*os) == 0)
2883 {
2884 g_info("not scrolling");
2885 } else {
2886 g_info("scrolling far");
2887 /* Cannot reuse any part of the screen : far jump */
2888
2889
2890 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2891 control_flow_data->drawing->drawing_area->style->black_gc,
2892 TRUE,
2893 0, 0,
2894 control_flow_data->drawing->width+SAFETY, // do not overlap
2895 control_flow_data->drawing->height);
2896
2897 gtk_widget_queue_draw_area (drawing->drawing_area,
2898 0,0,
2899 control_flow_data->drawing->width,
2900 control_flow_data->drawing->height);
2901
2902 drawing->damage_begin = 0;
2903 drawing->damage_end = control_flow_data->drawing->width;
2904
2905 drawing_data_request(control_flow_data->drawing,
2906 &control_flow_data->drawing->pixmap,
2907 0, 0,
2908 control_flow_data->drawing->width,
2909 control_flow_data->drawing->height);
2910
2911 }
2912 }
2913 }
2914 } else {
2915 /* Different scale (zoom) */
2916 g_info("zoom");
2917
2918 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2919 control_flow_data->drawing->drawing_area->style->black_gc,
2920 TRUE,
2921 0, 0,
2922 control_flow_data->drawing->width+SAFETY, // do not overlap
2923 control_flow_data->drawing->height);
2924
2925 gtk_widget_queue_draw_area (drawing->drawing_area,
2926 0,0,
2927 control_flow_data->drawing->width,
2928 control_flow_data->drawing->height);
2929
2930 drawing->damage_begin = 0;
2931 drawing->damage_end = control_flow_data->drawing->width;
2932
2933 drawing_data_request(control_flow_data->drawing,
2934 &control_flow_data->drawing->pixmap,
2935 0, 0,
2936 control_flow_data->drawing->width,
2937 control_flow_data->drawing->height);
2938 }
2939
2940
2941
2942 return 0;
2943 }
2944
2945 gint traceset_notify(void *hook_data, void *call_data)
2946 {
2947 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2948 Drawing_t *drawing = control_flow_data->drawing;
2949 GtkWidget *widget = drawing->drawing_area;
2950
2951
2952 drawing_clear(control_flow_data->drawing);
2953 processlist_clear(control_flow_data->process_list);
2954 redraw_notify(control_flow_data, NULL);
2955
2956 request_background_data(control_flow_data);
2957 #if 0
2958 drawing->damage_begin = 0;
2959 drawing->damage_end = drawing->width;
2960 if(drawing->damage_begin < drawing->damage_end)
2961 {
2962 drawing_data_request(drawing,
2963 &drawing->pixmap,
2964 drawing->damage_begin,
2965 0,
2966 drawing->damage_end-drawing->damage_begin,
2967 drawing->height);
2968 }
2969
2970 gtk_widget_queue_draw_area(drawing->drawing_area,
2971 0,0,
2972 drawing->width,
2973 drawing->height);
2974 #endif //0
2975
2976 return FALSE;
2977 }
2978
2979 gint redraw_notify(void *hook_data, void *call_data)
2980 {
2981 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2982 Drawing_t *drawing = control_flow_data->drawing;
2983 GtkWidget *widget = drawing->drawing_area;
2984
2985 drawing->damage_begin = 0;
2986 drawing->damage_end = drawing->width;
2987
2988 /* fun feature, to be separated someday... */
2989 drawing_clear(control_flow_data->drawing);
2990 processlist_clear(control_flow_data->process_list);
2991
2992 // Clear the image
2993 gdk_draw_rectangle (drawing->pixmap,
2994 widget->style->black_gc,
2995 TRUE,
2996 0, 0,
2997 drawing->width+SAFETY,
2998 drawing->height);
2999
3000
3001 if(drawing->damage_begin < drawing->damage_end)
3002 {
3003 drawing_data_request(drawing,
3004 &drawing->pixmap,
3005 drawing->damage_begin,
3006 0,
3007 drawing->damage_end-drawing->damage_begin,
3008 drawing->height);
3009 }
3010
3011 gtk_widget_queue_draw_area(drawing->drawing_area,
3012 0,0,
3013 drawing->width,
3014 drawing->height);
3015 return FALSE;
3016
3017 }
3018
3019
3020 gint continue_notify(void *hook_data, void *call_data)
3021 {
3022 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3023 Drawing_t *drawing = control_flow_data->drawing;
3024 GtkWidget *widget = drawing->drawing_area;
3025
3026 //g_assert(widget->allocation.width == drawing->damage_end);
3027
3028 if(drawing->damage_begin < drawing->damage_end)
3029 {
3030 drawing_data_request(drawing,
3031 &drawing->pixmap,
3032 drawing->damage_begin,
3033 0,
3034 drawing->damage_end-drawing->damage_begin,
3035 drawing->height);
3036 }
3037
3038 return FALSE;
3039 }
3040
3041
3042 gint update_current_time_hook(void *hook_data, void *call_data)
3043 {
3044 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
3045 Drawing_t *drawing = control_flow_data->drawing;
3046
3047 LttTime current_time = *((LttTime*)call_data);
3048
3049 TimeWindow time_window =
3050 lttvwindow_get_time_window(control_flow_data->tab);
3051
3052 LttTime time_begin = time_window.start_time;
3053 LttTime width = time_window.time_width;
3054 LttTime half_width;
3055 {
3056 guint64 time_ll = ltt_time_to_uint64(width);
3057 time_ll = time_ll >> 1; /* divide by two */
3058 half_width = ltt_time_from_uint64(time_ll);
3059 }
3060 LttTime time_end = ltt_time_add(time_begin, width);
3061
3062 LttvTracesetContext * tsc =
3063 lttvwindow_get_traceset_context(control_flow_data->tab);
3064
3065 LttTime trace_start = tsc->time_span.start_time;
3066 LttTime trace_end = tsc->time_span.end_time;
3067
3068 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
3069 current_time.tv_nsec);
3070
3071
3072
3073 /* If current time is inside time interval, just move the highlight
3074 * bar */
3075
3076 /* Else, we have to change the time interval. We have to tell it
3077 * to the main window. */
3078 /* The time interval change will take care of placing the current
3079 * time at the center of the visible area, or nearest possible if we are
3080 * at one end of the trace. */
3081
3082
3083 if(ltt_time_compare(current_time, time_begin) == -1)
3084 {
3085 TimeWindow new_time_window;
3086
3087 if(ltt_time_compare(current_time,
3088 ltt_time_add(trace_start,half_width)) == -1)
3089 time_begin = trace_start;
3090 else
3091 time_begin = ltt_time_sub(current_time,half_width);
3092
3093 new_time_window.start_time = time_begin;
3094 new_time_window.time_width = width;
3095 new_time_window.time_width_double = ltt_time_to_double(width);
3096 new_time_window.end_time = ltt_time_add(time_begin, width);
3097
3098 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3099 }
3100 else if(ltt_time_compare(current_time, time_end) == 1)
3101 {
3102 TimeWindow new_time_window;
3103
3104 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
3105 time_begin = ltt_time_sub(trace_end,width);
3106 else
3107 time_begin = ltt_time_sub(current_time,half_width);
3108
3109 new_time_window.start_time = time_begin;
3110 new_time_window.time_width = width;
3111 new_time_window.time_width_double = ltt_time_to_double(width);
3112 new_time_window.end_time = ltt_time_add(time_begin, width);
3113
3114 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3115
3116 }
3117 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
3118 gtk_widget_queue_draw_area(drawing->drawing_area,
3119 0,0,
3120 drawing->width,
3121 drawing->height);
3122
3123 return 0;
3124 }
3125
3126 typedef struct _ClosureData {
3127 EventsRequest *events_request;
3128 LttvTracesetState *tss;
3129 LttTime end_time;
3130 guint x_end;
3131 } ClosureData;
3132
3133
3134 void draw_closure(gpointer key, gpointer value, gpointer user_data)
3135 {
3136 ProcessInfo *process_info = (ProcessInfo*)key;
3137 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
3138 ClosureData *closure_data = (ClosureData*)user_data;
3139
3140 EventsRequest *events_request = closure_data->events_request;
3141 ControlFlowData *control_flow_data = events_request->viewer_data;
3142
3143 LttvTracesetState *tss = closure_data->tss;
3144 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
3145
3146 LttTime evtime = closure_data->end_time;
3147
3148 {
3149 /* For the process */
3150 /* First, check if the current process is in the state computation
3151 * process list. If it is there, that means we must add it right now and
3152 * draw items from the beginning of the read for it. If it is not
3153 * present, it's a new process and it was not present : it will
3154 * be added after the state update. */
3155 #ifdef EXTRA_CHECK
3156 g_assert(lttv_traceset_number(tsc->ts) > 0);
3157 #endif //EXTRA_CHECK
3158 /* tracefiles[0] is ok here, because we draw for every PID, and
3159 * assume CPU 0 for PID 0 //FIXME */
3160 LttvTracefileState *tfs =
3161 (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
3162
3163 LttvProcessState *process;
3164 process = lttv_state_find_process(tfs,
3165 process_info->pid);
3166
3167 if(unlikely(process != NULL)) {
3168
3169 /* Only draw for processes that are currently in the trace states */
3170
3171 guint y = 0, height = 0, pl_height = 0;
3172 ProcessList *process_list = control_flow_data->process_list;
3173 LttTime birth = process_info->birth;
3174 #ifdef EXTRA_CHECK
3175 /* Should be alike when background info is ready */
3176 if(control_flow_data->background_info_waiting==0)
3177 g_assert(ltt_time_compare(process->creation_time,
3178 process_info->birth) == 0);
3179 #endif //EXTRA_CHECK
3180 /* process HAS to be present */
3181 processlist_get_pixels_from_data(process_list,
3182 hashed_process_data,
3183 &y,
3184 &height);
3185
3186 /* Now, the process is in the state hash and our own process hash.
3187 * We definitely can draw the items related to the ending state.
3188 */
3189
3190 /* Check if the x position is unset. In can have been left unset by
3191 * a draw closure from a after chunk hook. This should never happen,
3192 * because it must be set by before chunk hook to the damage_begin
3193 * value.
3194 */
3195 g_assert(hashed_process_data->x.over != -1);
3196
3197 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3198 evtime) <= 0))
3199 {
3200 TimeWindow time_window =
3201 lttvwindow_get_time_window(control_flow_data->tab);
3202
3203 #ifdef EXTRA_CHECK
3204 if(ltt_time_compare(evtime, time_window.start_time) == -1
3205 || ltt_time_compare(evtime, time_window.end_time) == 1)
3206 return;
3207 #endif //EXTRA_CHECK
3208 Drawing_t *drawing = control_flow_data->drawing;
3209 guint width = drawing->width;
3210
3211 guint x = closure_data->x_end;
3212
3213 DrawContext draw_context;
3214
3215 /* Now create the drawing context that will be used to draw
3216 * items related to the last state. */
3217 draw_context.drawable = drawing->pixmap;
3218 draw_context.gc = drawing->gc;
3219 draw_context.pango_layout = drawing->pango_layout;
3220 draw_context.drawinfo.end.x = x;
3221
3222 draw_context.drawinfo.y.over = y+1;
3223 draw_context.drawinfo.y.middle = y+(height/2);
3224 draw_context.drawinfo.y.under = y+height;
3225
3226 draw_context.drawinfo.start.offset.over = 0;
3227 draw_context.drawinfo.start.offset.middle = 0;
3228 draw_context.drawinfo.start.offset.under = 0;
3229 draw_context.drawinfo.end.offset.over = 0;
3230 draw_context.drawinfo.end.offset.middle = 0;
3231 draw_context.drawinfo.end.offset.under = 0;
3232 #if 0
3233 /* Jump over draw if we are at the same x position */
3234 if(x == hashed_process_data->x.over)
3235 {
3236 /* jump */
3237 } else {
3238 draw_context.drawinfo.start.x = hashed_process_data->x.over;
3239 /* Draw the line */
3240 PropertiesLine prop_line = prepare_execmode_line(process);
3241 draw_line((void*)&prop_line, (void*)&draw_context);
3242
3243 hashed_process_data->x.over = x;
3244 }
3245 #endif //0
3246
3247 if(unlikely(x == hashed_process_data->x.middle &&
3248 hashed_process_data->x.middle_used)) {
3249 #if 0 /* do not mark closure : not missing information */
3250 if(hashed_process_data->x.middle_marked == FALSE) {
3251 /* Draw collision indicator */
3252 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
3253 gdk_draw_point(drawing->pixmap,
3254 drawing->gc,
3255 x,
3256 y+(height/2)-3);
3257 hashed_process_data->x.middle_marked = TRUE;
3258 }
3259 #endif //0
3260 /* Jump */
3261 } else {
3262 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
3263 /* Draw the line */
3264 PropertiesLine prop_line = prepare_s_e_line(process);
3265 draw_line((void*)&prop_line, (void*)&draw_context);
3266
3267 /* become the last x position */
3268 if(likely(x != hashed_process_data->x.middle)) {
3269 hashed_process_data->x.middle = x;
3270 /* but don't use the pixel */
3271 hashed_process_data->x.middle_used = FALSE;
3272
3273 /* Calculate the next good time */
3274 convert_pixels_to_time(width, x+1, time_window,
3275 &hashed_process_data->next_good_time);
3276 }
3277 }
3278 }
3279 }
3280 }
3281 return;
3282 }
3283
3284 int before_chunk(void *hook_data, void *call_data)
3285 {
3286 EventsRequest *events_request = (EventsRequest*)hook_data;
3287 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3288
3289 drawing_chunk_begin(events_request, tss);
3290
3291 return 0;
3292 }
3293
3294 int before_request(void *hook_data, void *call_data)
3295 {
3296 EventsRequest *events_request = (EventsRequest*)hook_data;
3297 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3298
3299 drawing_data_request_begin(events_request, tss);
3300
3301 return 0;
3302 }
3303
3304
3305 /*
3306 * after request is necessary in addition of after chunk in order to draw
3307 * lines until the end of the screen. after chunk just draws lines until
3308 * the last event.
3309 *
3310 * for each process
3311 * draw closing line
3312 * expose
3313 */
3314 int after_request(void *hook_data, void *call_data)
3315 {
3316 EventsRequest *events_request = (EventsRequest*)hook_data;
3317 ControlFlowData *control_flow_data = events_request->viewer_data;
3318 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3319 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
3320
3321 ProcessList *process_list = control_flow_data->process_list;
3322 LttTime end_time = events_request->end_time;
3323
3324 ClosureData closure_data;
3325 closure_data.events_request = (EventsRequest*)hook_data;
3326 closure_data.tss = tss;
3327 closure_data.end_time = end_time;
3328
3329 TimeWindow time_window =
3330 lttvwindow_get_time_window(control_flow_data->tab);
3331 guint width = control_flow_data->drawing->width;
3332 convert_time_to_pixels(
3333 time_window,
3334 end_time,
3335 width,
3336 &closure_data.x_end);
3337
3338
3339 /* Draw last items */
3340 g_hash_table_foreach(process_list->process_hash, draw_closure,
3341 (void*)&closure_data);
3342
3343 /* Request expose */
3344 drawing_request_expose(events_request, tss, end_time);
3345 return 0;
3346 }
3347
3348 /*
3349 * for each process
3350 * draw closing line
3351 * expose
3352 */
3353 int after_chunk(void *hook_data, void *call_data)
3354 {
3355 EventsRequest *events_request = (EventsRequest*)hook_data;
3356 ControlFlowData *control_flow_data = events_request->viewer_data;
3357 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3358 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
3359 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
3360 LttTime end_time;
3361
3362 ProcessList *process_list = control_flow_data->process_list;
3363
3364 g_free(process_list->current_hash_data);
3365 process_list->current_hash_data = NULL;
3366
3367 if(tfc != NULL)
3368 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
3369 else /* end of traceset, or position now out of request : end */
3370 end_time = events_request->end_time;
3371
3372 ClosureData closure_data;
3373 closure_data.events_request = (EventsRequest*)hook_data;
3374 closure_data.tss = tss;
3375 closure_data.end_time = end_time;
3376
3377 TimeWindow time_window =
3378 lttvwindow_get_time_window(control_flow_data->tab);
3379 guint width = control_flow_data->drawing->width;
3380 convert_time_to_pixels(
3381 time_window,
3382 end_time,
3383 width,
3384 &closure_data.x_end);
3385
3386 /* Draw last items */
3387 g_hash_table_foreach(process_list->process_hash, draw_closure,
3388 (void*)&closure_data);
3389
3390 /* Request expose */
3391 drawing_request_expose(events_request, tss, end_time);
3392
3393 return 0;
3394 }
3395
This page took 0.107736 seconds and 4 git commands to generate.