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