remove a big chunk of unused code
[lttv.git] / ltt / branches / poly / lttv / modules / gui / resourceview / eventhooks.c
CommitLineData
9e01e6d4 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
85extern 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
93static 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 */
118static 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 */
187GtkWidget *
58a9b31b 188h_resourceview(LttvPlugin *plugin)
9e01e6d4 189{
190 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
191 Tab *tab = ptab->tab;
192 g_info("h_guicontrolflow, %p", tab);
58a9b31b 193 ControlFlowData *control_flow_data = resourceview(ptab);
9e01e6d4 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
221void legend_destructor(GtkWindow *legend)
222{
223 g_legend_list = g_slist_remove(g_legend_list, legend);
224}
225
226/* Create a popup legend */
227GtkWidget *
228h_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
263int 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 */
274static 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;
9e01e6d4 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
d3d99fde 320static void cpu_set_line_color(PropertiesLine *prop_line, LttvCPUState *s)
598026ba 321{
d3d99fde 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) {
598026ba 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 }
d3d99fde 336 else if(present_state == LTTV_CPU_TRAP) {
337 prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
338 }
598026ba 339}
9e01e6d4 340
8743690d 341static 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
9e01e6d4 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
374int before_schedchange_hook(void *hook_data, void *call_data)
8743690d 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
382int before_schedchange_hook_cpu(void *hook_data, void *call_data)
9e01e6d4 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
58a9b31b 400 GQuark cpuq;
401
9e01e6d4 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;
58a9b31b 409 pid_out = ltt_event_get_long_unsigned(e, thf->f1);
410 pid_in = ltt_event_get_long_unsigned(e, thf->f2);
44ffb95f 411// if(pid_in != 0 && pid_out != 0) {
412// /* not a transition to/from idle */
413// return 0;
414// }
c4e6f4dc 415
9e01e6d4 416 tfc->target_pid = pid_out;
58a9b31b 417// if(!filter || !filter->head ||
418// lttv_filter_tree_parse(filter->head,e,tfc->tf,
419// tfc->t_context->t,tfc,NULL,NULL)) {
9e01e6d4 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;
44ffb95f 427 {
428 gchar *cpustr;
429 cpustr = g_strdup_printf("CPU%u", cpu);
430 cpuq = g_quark_from_string(cpustr);
431 g_free(cpustr);
432 }
58a9b31b 433
9e01e6d4 434 guint trace_num = ts->parent.index;
58a9b31b 435// LttvProcessState *process = ts->running_process[cpu];
9e01e6d4 436 /* unknown state, bad current pid */
58a9b31b 437// if(process->pid != pid_out)
438// process = lttv_state_find_process(ts,
439// tfs->cpu, pid_out);
9e01e6d4 440
58a9b31b 441// if(process != NULL) {
9e01e6d4 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;
58a9b31b 447 HashedResourceData *hashed_process_data = NULL;
9e01e6d4 448 ProcessList *process_list = control_flow_data->process_list;
58a9b31b 449// LttTime birth = process->creation_time;
9e01e6d4 450
58a9b31b 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);
9e01e6d4 457 if(hashed_process_data == NULL)
458 {
58a9b31b 459// g_assert(pid_out == 0 || pid_out != process->ppid);
9e01e6d4 460 /* Process not present */
58a9b31b 461 ResourceInfo *process_info;
9e01e6d4 462 Drawing_t *drawing = control_flow_data->drawing;
c4e6f4dc 463 resourcelist_add(process_list,
9e01e6d4 464 drawing,
58a9b31b 465 trace_num,
466 cpuq, //process->name,
44ffb95f 467 0, //cpu
468 cpu,
9e01e6d4 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 */
58a9b31b 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;
d3d99fde 573 cpu_set_line_color(&prop_line, tfs->cpu_state);
9e01e6d4 574 draw_line((void*)&prop_line, (void*)&draw_context);
9e01e6d4 575
58a9b31b 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;
9e01e6d4 581
58a9b31b 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;
9e01e6d4 759
9e01e6d4 760
9e01e6d4 761
9e01e6d4 762
58a9b31b 763 /* Text dump */
764#ifdef DONTSHOW
765 GString *string = g_string_new("");;
766 gboolean field_names = TRUE, state = TRUE;
9e01e6d4 767
58a9b31b 768 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
769 g_string_append_printf(string,"\n");
9e01e6d4 770
58a9b31b 771 if(state) {
772 g_string_append_printf(string, " %s",
773 g_quark_to_string(tfs->process->state->s));
9e01e6d4 774 }
775
58a9b31b 776 g_info("%s",string->str);
9e01e6d4 777
58a9b31b 778 g_string_free(string, TRUE);
779
780 /* End of text dump */
781#endif //DONTSHOW
9e01e6d4 782
783}
784
58a9b31b 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 */
795int after_schedchange_hook(void *hook_data, void *call_data)
9e01e6d4 796{
44ffb95f 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 }
58a9b31b 911 return 0;
912}
9e01e6d4 913
58a9b31b 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 */
9e01e6d4 930
598026ba 931int 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
8743690d 949 before_execmode_hook_irq(hook_data, call_data);
950
598026ba 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
58a9b31b 968// guint pid = process->pid;
598026ba 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;
d3d99fde 994 resourcelist_add(process_list,
598026ba 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 }
d3d99fde 1046 }
1047 else {
598026ba 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 */
d3d99fde 1081 }
1082 else {
598026ba 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;
d3d99fde 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);
598026ba 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}
9e01e6d4 1126
8743690d 1127int 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
9e01e6d4 1338gint update_time_window_hook(void *hook_data, void *call_data)
1339{
1340 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1341 Drawing_t *drawing = control_flow_data->drawing;
1342 ProcessList *process_list = control_flow_data->process_list;
1343
1344 const TimeWindowNotifyData *time_window_nofify_data =
1345 ((const TimeWindowNotifyData *)call_data);
1346
1347 TimeWindow *old_time_window =
1348 time_window_nofify_data->old_time_window;
1349 TimeWindow *new_time_window =
1350 time_window_nofify_data->new_time_window;
1351
1352 /* Update the ruler */
1353 drawing_update_ruler(control_flow_data->drawing,
1354 new_time_window);
1355
1356
1357 /* Two cases : zoom in/out or scrolling */
1358
1359 /* In order to make sure we can reuse the old drawing, the scale must
1360 * be the same and the new time interval being partly located in the
1361 * currently shown time interval. (reuse is only for scrolling)
1362 */
1363
1364 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1365 old_time_window->start_time.tv_sec,
1366 old_time_window->start_time.tv_nsec,
1367 old_time_window->time_width.tv_sec,
1368 old_time_window->time_width.tv_nsec);
1369
1370 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1371 new_time_window->start_time.tv_sec,
1372 new_time_window->start_time.tv_nsec,
1373 new_time_window->time_width.tv_sec,
1374 new_time_window->time_width.tv_nsec);
1375
1376 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1377 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1378 {
1379 /* Same scale (scrolling) */
1380 g_info("scrolling");
1381 LttTime *ns = &new_time_window->start_time;
1382 LttTime *nw = &new_time_window->time_width;
1383 LttTime *os = &old_time_window->start_time;
1384 LttTime *ow = &old_time_window->time_width;
1385 LttTime old_end = old_time_window->end_time;
1386 LttTime new_end = new_time_window->end_time;
1387 //if(ns<os+w<ns+w)
1388 //if(ns<os+w && os+w<ns+w)
1389 //if(ns<old_end && os<ns)
1390 if(ltt_time_compare(*ns, old_end) == -1
1391 && ltt_time_compare(*os, *ns) == -1)
1392 {
1393 g_info("scrolling near right");
1394 /* Scroll right, keep right part of the screen */
1395 guint x = 0;
1396 guint width = control_flow_data->drawing->width;
1397 convert_time_to_pixels(
1398 *old_time_window,
1399 *ns,
1400 width,
1401 &x);
1402
1403 /* Copy old data to new location */
1404 copy_pixmap_region(process_list,
1405 NULL,
1406 control_flow_data->drawing->drawing_area->style->black_gc,
1407 NULL,
1408 x, 0,
1409 0, 0,
1410 control_flow_data->drawing->width-x+SAFETY, -1);
1411
1412 if(drawing->damage_begin == drawing->damage_end)
1413 drawing->damage_begin = control_flow_data->drawing->width-x;
1414 else
1415 drawing->damage_begin = 0;
1416
1417 drawing->damage_end = control_flow_data->drawing->width;
1418
1419 /* Clear the data request background, but not SAFETY */
1420 rectangle_pixmap(process_list,
1421 control_flow_data->drawing->drawing_area->style->black_gc,
1422 TRUE,
1423 drawing->damage_begin+SAFETY, 0,
1424 drawing->damage_end - drawing->damage_begin, // do not overlap
1425 -1);
1426 gtk_widget_queue_draw(drawing->drawing_area);
1427 //gtk_widget_queue_draw_area (drawing->drawing_area,
1428 // 0,0,
1429 // control_flow_data->drawing->width,
1430 // control_flow_data->drawing->height);
1431
1432 /* Get new data for the rest. */
1433 drawing_data_request(control_flow_data->drawing,
1434 drawing->damage_begin, 0,
1435 drawing->damage_end - drawing->damage_begin,
1436 control_flow_data->drawing->height);
1437 } else {
1438 //if(ns<os<ns+w)
1439 //if(ns<os && os<ns+w)
1440 //if(ns<os && os<new_end)
1441 if(ltt_time_compare(*ns,*os) == -1
1442 && ltt_time_compare(*os,new_end) == -1)
1443 {
1444 g_info("scrolling near left");
1445 /* Scroll left, keep left part of the screen */
1446 guint x = 0;
1447 guint width = control_flow_data->drawing->width;
1448 convert_time_to_pixels(
1449 *new_time_window,
1450 *os,
1451 width,
1452 &x);
1453
1454 /* Copy old data to new location */
1455 copy_pixmap_region (process_list,
1456 NULL,
1457 control_flow_data->drawing->drawing_area->style->black_gc,
1458 NULL,
1459 0, 0,
1460 x, 0,
1461 -1, -1);
1462
1463 if(drawing->damage_begin == drawing->damage_end)
1464 drawing->damage_end = x;
1465 else
1466 drawing->damage_end =
1467 control_flow_data->drawing->width;
1468
1469 drawing->damage_begin = 0;
1470
1471 rectangle_pixmap (process_list,
1472 control_flow_data->drawing->drawing_area->style->black_gc,
1473 TRUE,
1474 drawing->damage_begin, 0,
1475 drawing->damage_end - drawing->damage_begin, // do not overlap
1476 -1);
1477
1478 gtk_widget_queue_draw(drawing->drawing_area);
1479 //gtk_widget_queue_draw_area (drawing->drawing_area,
1480 // 0,0,
1481 // control_flow_data->drawing->width,
1482 // control_flow_data->drawing->height);
1483
1484
1485 /* Get new data for the rest. */
1486 drawing_data_request(control_flow_data->drawing,
1487 drawing->damage_begin, 0,
1488 drawing->damage_end - drawing->damage_begin,
1489 control_flow_data->drawing->height);
1490
1491 } else {
1492 if(ltt_time_compare(*ns,*os) == 0)
1493 {
1494 g_info("not scrolling");
1495 } else {
1496 g_info("scrolling far");
1497 /* Cannot reuse any part of the screen : far jump */
1498
1499
1500 rectangle_pixmap (process_list,
1501 control_flow_data->drawing->drawing_area->style->black_gc,
1502 TRUE,
1503 0, 0,
1504 control_flow_data->drawing->width+SAFETY, // do not overlap
1505 -1);
1506
1507 //gtk_widget_queue_draw_area (drawing->drawing_area,
1508 // 0,0,
1509 // control_flow_data->drawing->width,
1510 // control_flow_data->drawing->height);
1511 gtk_widget_queue_draw(drawing->drawing_area);
1512
1513 drawing->damage_begin = 0;
1514 drawing->damage_end = control_flow_data->drawing->width;
1515
1516 drawing_data_request(control_flow_data->drawing,
1517 0, 0,
1518 control_flow_data->drawing->width,
1519 control_flow_data->drawing->height);
1520
1521 }
1522 }
1523 }
1524 } else {
1525 /* Different scale (zoom) */
1526 g_info("zoom");
1527
1528 rectangle_pixmap (process_list,
1529 control_flow_data->drawing->drawing_area->style->black_gc,
1530 TRUE,
1531 0, 0,
1532 control_flow_data->drawing->width+SAFETY, // do not overlap
1533 -1);
1534
1535 //gtk_widget_queue_draw_area (drawing->drawing_area,
1536 // 0,0,
1537 // control_flow_data->drawing->width,
1538 // control_flow_data->drawing->height);
1539 gtk_widget_queue_draw(drawing->drawing_area);
1540
1541 drawing->damage_begin = 0;
1542 drawing->damage_end = control_flow_data->drawing->width;
1543
1544 drawing_data_request(control_flow_data->drawing,
1545 0, 0,
1546 control_flow_data->drawing->width,
1547 control_flow_data->drawing->height);
1548 }
1549
1550 /* Update directly when scrolling */
1551 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1552 TRUE);
1553
1554 return 0;
1555}
1556
1557gint traceset_notify(void *hook_data, void *call_data)
1558{
1559 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1560 Drawing_t *drawing = control_flow_data->drawing;
1561
1562 if(unlikely(drawing->gc == NULL)) {
1563 return FALSE;
1564 }
1565 if(drawing->dotted_gc == NULL) {
1566 return FALSE;
1567 }
1568
1569 drawing_clear(control_flow_data->drawing);
1570 processlist_clear(control_flow_data->process_list);
1571 gtk_widget_set_size_request(
1572 control_flow_data->drawing->drawing_area,
1573 -1, processlist_get_height(control_flow_data->process_list));
1574 redraw_notify(control_flow_data, NULL);
1575
1576 request_background_data(control_flow_data);
1577
1578 return FALSE;
1579}
1580
1581gint redraw_notify(void *hook_data, void *call_data)
1582{
1583 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1584 Drawing_t *drawing = control_flow_data->drawing;
1585 GtkWidget *widget = drawing->drawing_area;
1586
1587 drawing->damage_begin = 0;
1588 drawing->damage_end = drawing->width;
1589
1590 /* fun feature, to be separated someday... */
1591 drawing_clear(control_flow_data->drawing);
1592 processlist_clear(control_flow_data->process_list);
1593 gtk_widget_set_size_request(
1594 control_flow_data->drawing->drawing_area,
1595 -1, processlist_get_height(control_flow_data->process_list));
1596 // Clear the images
1597 rectangle_pixmap (control_flow_data->process_list,
1598 widget->style->black_gc,
1599 TRUE,
1600 0, 0,
1601 drawing->alloc_width,
1602 -1);
1603
1604 gtk_widget_queue_draw(drawing->drawing_area);
1605
1606 if(drawing->damage_begin < drawing->damage_end)
1607 {
1608 drawing_data_request(drawing,
1609 drawing->damage_begin,
1610 0,
1611 drawing->damage_end-drawing->damage_begin,
1612 drawing->height);
1613 }
1614
1615 //gtk_widget_queue_draw_area(drawing->drawing_area,
1616 // 0,0,
1617 // drawing->width,
1618 // drawing->height);
1619 return FALSE;
1620
1621}
1622
1623
1624gint continue_notify(void *hook_data, void *call_data)
1625{
1626 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1627 Drawing_t *drawing = control_flow_data->drawing;
1628
1629 //g_assert(widget->allocation.width == drawing->damage_end);
1630
1631 if(drawing->damage_begin < drawing->damage_end)
1632 {
1633 drawing_data_request(drawing,
1634 drawing->damage_begin,
1635 0,
1636 drawing->damage_end-drawing->damage_begin,
1637 drawing->height);
1638 }
1639
1640 return FALSE;
1641}
1642
1643
1644gint update_current_time_hook(void *hook_data, void *call_data)
1645{
1646 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
1647 Drawing_t *drawing = control_flow_data->drawing;
1648
1649 LttTime current_time = *((LttTime*)call_data);
1650
1651 TimeWindow time_window =
1652 lttvwindow_get_time_window(control_flow_data->tab);
1653
1654 LttTime time_begin = time_window.start_time;
1655 LttTime width = time_window.time_width;
1656 LttTime half_width;
1657 {
1658 guint64 time_ll = ltt_time_to_uint64(width);
1659 time_ll = time_ll >> 1; /* divide by two */
1660 half_width = ltt_time_from_uint64(time_ll);
1661 }
1662 LttTime time_end = ltt_time_add(time_begin, width);
1663
1664 LttvTracesetContext * tsc =
1665 lttvwindow_get_traceset_context(control_flow_data->tab);
1666
1667 LttTime trace_start = tsc->time_span.start_time;
1668 LttTime trace_end = tsc->time_span.end_time;
1669
1670 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1671 current_time.tv_nsec);
1672
1673
1674
1675 /* If current time is inside time interval, just move the highlight
1676 * bar */
1677
1678 /* Else, we have to change the time interval. We have to tell it
1679 * to the main window. */
1680 /* The time interval change will take care of placing the current
1681 * time at the center of the visible area, or nearest possible if we are
1682 * at one end of the trace. */
1683
1684
1685 if(ltt_time_compare(current_time, time_begin) < 0)
1686 {
1687 TimeWindow new_time_window;
1688
1689 if(ltt_time_compare(current_time,
1690 ltt_time_add(trace_start,half_width)) < 0)
1691 time_begin = trace_start;
1692 else
1693 time_begin = ltt_time_sub(current_time,half_width);
1694
1695 new_time_window.start_time = time_begin;
1696 new_time_window.time_width = width;
1697 new_time_window.time_width_double = ltt_time_to_double(width);
1698 new_time_window.end_time = ltt_time_add(time_begin, width);
1699
1700 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
1701 }
1702 else if(ltt_time_compare(current_time, time_end) > 0)
1703 {
1704 TimeWindow new_time_window;
1705
1706 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1707 time_begin = ltt_time_sub(trace_end,width);
1708 else
1709 time_begin = ltt_time_sub(current_time,half_width);
1710
1711 new_time_window.start_time = time_begin;
1712 new_time_window.time_width = width;
1713 new_time_window.time_width_double = ltt_time_to_double(width);
1714 new_time_window.end_time = ltt_time_add(time_begin, width);
1715
1716 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
1717
1718 }
1719 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
1720
1721 /* Update directly when scrolling */
1722 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1723 TRUE);
1724
1725 return 0;
1726}
1727
1728typedef struct _ClosureData {
1729 EventsRequest *events_request;
1730 LttvTracesetState *tss;
1731 LttTime end_time;
1732 guint x_end;
1733} ClosureData;
1734
58a9b31b 1735/* Draw line until end of the screen */
9e01e6d4 1736
1737void draw_closure(gpointer key, gpointer value, gpointer user_data)
1738{
44ffb95f 1739 ResourceInfo *process_info = (ResourceInfo*)key;
1740 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1741 ClosureData *closure_data = (ClosureData*)user_data;
1742
1743 EventsRequest *events_request = closure_data->events_request;
1744 ControlFlowData *control_flow_data = events_request->viewer_data;
1745
1746 LttvTracesetState *tss = closure_data->tss;
1747 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1748
1749 LttTime evtime = closure_data->end_time;
1750
1751 gboolean dodraw = TRUE;
1752
1753 {
1754 /* For the process */
1755 /* First, check if the current process is in the state computation
1756 * process list. If it is there, that means we must add it right now and
1757 * draw items from the beginning of the read for it. If it is not
1758 * present, it's a new process and it was not present : it will
1759 * be added after the state update. */
1760#ifdef EXTRA_CHECK
1761 g_assert(lttv_traceset_number(tsc->ts) > 0);
1762#endif //EXTRA_CHECK
1763 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1764 LttvTraceState *ts = (LttvTraceState*)tc;
1765
1766#if 0
1767 //FIXME : optimize data structures.
1768 LttvTracefileState *tfs;
1769 LttvTracefileContext *tfc;
1770 guint i;
1771 for(i=0;i<tc->tracefiles->len;i++) {
1772 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
1773 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
1774 && tfs->cpu == process_info->cpu)
1775 break;
1776
1777 }
1778 g_assert(i<tc->tracefiles->len);
1779 tfs = LTTV_TRACEFILE_STATE(tfc);
1780#endif //0
1781 // LttvTracefileState *tfs =
1782 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
1783 // tracefiles[process_info->cpu];
1784
58a9b31b 1785// LttvProcessState *process;
1786// process = lttv_state_find_process(ts, process_info->cpu,
1787// process_info->pid);
44ffb95f 1788
58a9b31b 1789// if(unlikely(process != NULL)) {
44ffb95f 1790
58a9b31b 1791// LttvFilter *filter = control_flow_data->filter;
1792// if(filter != NULL && filter->head != NULL)
1793// if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
1794// tc->t,NULL,process,tc))
1795// dodraw = FALSE;
44ffb95f 1796
1797 /* Only draw for processes that are currently in the trace states */
1798
1799 ProcessList *process_list = control_flow_data->process_list;
1800#ifdef EXTRA_CHECK
1801 /* Should be alike when background info is ready */
1802 if(control_flow_data->background_info_waiting==0)
1803 g_assert(ltt_time_compare(process->creation_time,
1804 process_info->birth) == 0);
1805#endif //EXTRA_CHECK
1806
1807 /* Now, the process is in the state hash and our own process hash.
1808 * We definitely can draw the items related to the ending state.
1809 */
1810
1811 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1812 evtime) <= 0))
1813 {
1814 TimeWindow time_window =
1815 lttvwindow_get_time_window(control_flow_data->tab);
1816
1817#ifdef EXTRA_CHECK
1818 if(ltt_time_compare(evtime, time_window.start_time) == -1
1819 || ltt_time_compare(evtime, time_window.end_time) == 1)
1820 return;
1821#endif //EXTRA_CHECK
1822 Drawing_t *drawing = control_flow_data->drawing;
1823 guint width = drawing->width;
1824
1825 guint x = closure_data->x_end;
1826
1827 DrawContext draw_context;
1828
1829 /* Now create the drawing context that will be used to draw
1830 * items related to the last state. */
1831 draw_context.drawable = hashed_process_data->pixmap;
1832 draw_context.gc = drawing->gc;
1833 draw_context.pango_layout = drawing->pango_layout;
1834 draw_context.drawinfo.end.x = x;
1835
1836 draw_context.drawinfo.y.over = 1;
1837 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1838 draw_context.drawinfo.y.under = hashed_process_data->height;
1839
1840 draw_context.drawinfo.start.offset.over = 0;
1841 draw_context.drawinfo.start.offset.middle = 0;
1842 draw_context.drawinfo.start.offset.under = 0;
1843 draw_context.drawinfo.end.offset.over = 0;
1844 draw_context.drawinfo.end.offset.middle = 0;
1845 draw_context.drawinfo.end.offset.under = 0;
1846#if 0
1847 /* Jump over draw if we are at the same x position */
1848 if(x == hashed_process_data->x.over)
1849 {
1850 /* jump */
1851 } else {
1852 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1853 /* Draw the line */
1854 PropertiesLine prop_line = prepare_execmode_line(process);
1855 draw_line((void*)&prop_line, (void*)&draw_context);
1856
1857 hashed_process_data->x.over = x;
1858 }
1859#endif //0
1860
1861 if(unlikely(x == hashed_process_data->x.middle &&
1862 hashed_process_data->x.middle_used)) {
1863#if 0 /* do not mark closure : not missing information */
1864 if(hashed_process_data->x.middle_marked == FALSE) {
1865 /* Draw collision indicator */
1866 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1867 gdk_draw_point(drawing->pixmap,
1868 drawing->gc,
1869 x,
1870 y+(height/2)-3);
1871 hashed_process_data->x.middle_marked = TRUE;
1872 }
1873#endif //0
1874 /* Jump */
1875 } else {
1876 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1877 /* Draw the line */
1878 if(dodraw) {
44ffb95f 1879 PropertiesLine prop_line;
1880 prop_line.line_width = STATE_LINE_WIDTH;
1881 prop_line.style = GDK_LINE_SOLID;
1882 prop_line.y = MIDDLE;
8743690d 1883 if(process_info->type == 0)
1884 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
1885 else if(process_info->type == 1)
1886 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
44ffb95f 1887
1888 draw_line((void*)&prop_line, (void*)&draw_context);
1889 }
1890
1891 /* become the last x position */
1892 if(likely(x != hashed_process_data->x.middle)) {
1893 hashed_process_data->x.middle = x;
1894 /* but don't use the pixel */
1895 hashed_process_data->x.middle_used = FALSE;
1896
1897 /* Calculate the next good time */
1898 convert_pixels_to_time(width, x+1, time_window,
1899 &hashed_process_data->next_good_time);
1900 }
1901 }
1902 }
58a9b31b 1903// }
44ffb95f 1904 }
9e01e6d4 1905 return;
1906}
1907
1908int before_chunk(void *hook_data, void *call_data)
1909{
1910 EventsRequest *events_request = (EventsRequest*)hook_data;
1911 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1912 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
1913#if 0
1914 /* Desactivate sort */
1915 gtk_tree_sortable_set_sort_column_id(
1916 GTK_TREE_SORTABLE(cfd->process_list->list_store),
1917 TRACE_COLUMN,
1918 GTK_SORT_ASCENDING);
1919#endif //0
1920 drawing_chunk_begin(events_request, tss);
1921
1922 return 0;
1923}
1924
1925int before_request(void *hook_data, void *call_data)
1926{
1927 EventsRequest *events_request = (EventsRequest*)hook_data;
1928 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1929
1930 drawing_data_request_begin(events_request, tss);
1931
1932 return 0;
1933}
1934
1935
1936/*
1937 * after request is necessary in addition of after chunk in order to draw
1938 * lines until the end of the screen. after chunk just draws lines until
1939 * the last event.
1940 *
1941 * for each process
1942 * draw closing line
1943 * expose
1944 */
58a9b31b 1945// TODO pmf: reenable this
9e01e6d4 1946int after_request(void *hook_data, void *call_data)
1947{
58a9b31b 1948// EventsRequest *events_request = (EventsRequest*)hook_data;
1949// ControlFlowData *control_flow_data = events_request->viewer_data;
1950// LttvTracesetState *tss = (LttvTracesetState*)call_data;
1951//
1952// ProcessList *process_list = control_flow_data->process_list;
1953// LttTime end_time = events_request->end_time;
1954//
1955// ClosureData closure_data;
1956// closure_data.events_request = (EventsRequest*)hook_data;
1957// closure_data.tss = tss;
1958// closure_data.end_time = end_time;
1959//
1960// TimeWindow time_window =
1961// lttvwindow_get_time_window(control_flow_data->tab);
1962// guint width = control_flow_data->drawing->width;
1963// convert_time_to_pixels(
1964// time_window,
1965// end_time,
1966// width,
1967// &closure_data.x_end);
1968//
1969//
1970// /* Draw last items */
1971// g_hash_table_foreach(process_list->process_hash, draw_closure,
1972// (void*)&closure_data);
1973//
1974//
1975// /* Request expose */
1976// drawing_request_expose(events_request, tss, end_time);
9e01e6d4 1977 return 0;
1978}
1979
1980/*
1981 * for each process
1982 * draw closing line
1983 * expose
1984 */
1985int after_chunk(void *hook_data, void *call_data)
1986{
1987 EventsRequest *events_request = (EventsRequest*)hook_data;
1988 ControlFlowData *control_flow_data = events_request->viewer_data;
1989 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1990 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
1991 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
1992 LttTime end_time;
1993
1994 ProcessList *process_list = control_flow_data->process_list;
1995 guint i;
1996 LttvTraceset *traceset = tsc->ts;
1997 guint nb_trace = lttv_traceset_number(traceset);
1998
1999 /* Only execute when called for the first trace's events request */
2000 if(!process_list->current_hash_data) return;
2001
2002 for(i = 0 ; i < nb_trace ; i++) {
2003 g_free(process_list->current_hash_data[i]);
2004 }
2005 g_free(process_list->current_hash_data);
2006 process_list->current_hash_data = NULL;
2007
2008 if(tfc != NULL)
2009 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2010 else /* end of traceset, or position now out of request : end */
2011 end_time = events_request->end_time;
2012
2013 ClosureData closure_data;
2014 closure_data.events_request = (EventsRequest*)hook_data;
2015 closure_data.tss = tss;
2016 closure_data.end_time = end_time;
2017
2018 TimeWindow time_window =
2019 lttvwindow_get_time_window(control_flow_data->tab);
2020 guint width = control_flow_data->drawing->width;
2021 convert_time_to_pixels(
2022 time_window,
2023 end_time,
2024 width,
2025 &closure_data.x_end);
2026
2027 /* Draw last items */
2028 g_hash_table_foreach(process_list->process_hash, draw_closure,
2029 (void*)&closure_data);
2030#if 0
2031 /* Reactivate sort */
2032 gtk_tree_sortable_set_sort_column_id(
2033 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2034 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2035 GTK_SORT_ASCENDING);
2036
2037 update_index_to_pixmap(control_flow_data->process_list);
2038 /* Request a full expose : drawing scrambled */
2039 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2040#endif //0
2041 /* Request expose (updates damages zone also) */
2042 drawing_request_expose(events_request, tss, end_time);
2043
2044 return 0;
2045}
2046
2047/* after_statedump_end
2048 *
2049 * @param hook_data ControlFlowData structure of the viewer.
2050 * @param call_data Event context.
2051 *
2052 * This function adds items to be drawn in a queue for each process.
2053 *
2054 */
2055int before_statedump_end(void *hook_data, void *call_data)
2056{
2057 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2058 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2059 ControlFlowData *control_flow_data = events_request->viewer_data;
2060
2061 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2062
2063 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2064
2065 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2066
2067 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
2068 ProcessList *process_list = control_flow_data->process_list;
2069
2070 LttEvent *e;
2071 e = ltt_tracefile_get_event(tfc->tf);
2072
2073 LttvFilter *filter = control_flow_data->filter;
2074 if(filter != NULL && filter->head != NULL)
2075 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2076 tfc->t_context->t,tfc,NULL,NULL))
2077 return FALSE;
2078
2079 LttTime evtime = ltt_event_time(e);
2080
2081 ClosureData closure_data;
2082 closure_data.events_request = events_request;
2083 closure_data.tss = tss;
2084 closure_data.end_time = evtime;
2085
2086 TimeWindow time_window =
2087 lttvwindow_get_time_window(control_flow_data->tab);
2088 guint width = control_flow_data->drawing->width;
2089 convert_time_to_pixels(
2090 time_window,
2091 evtime,
2092 width,
2093 &closure_data.x_end);
2094
2095 /* Draw last items */
2096 g_hash_table_foreach(process_list->process_hash, draw_closure,
2097 (void*)&closure_data);
2098#if 0
2099 /* Reactivate sort */
2100 gtk_tree_sortable_set_sort_column_id(
2101 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2102 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2103 GTK_SORT_ASCENDING);
2104
2105 update_index_to_pixmap(control_flow_data->process_list);
2106 /* Request a full expose : drawing scrambled */
2107 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2108#endif //0
2109 /* Request expose (updates damages zone also) */
2110 drawing_request_expose(events_request, tss, evtime);
2111
2112 return 0;
2113}
This page took 0.109908 seconds and 4 git commands to generate.