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