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