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