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