update quickstart and flight
[lttv.git] / trunk / lttv / 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>
9e01e6d4 64#include <ltt/trace.h>
65
66#include <lttv/lttv.h>
67#include <lttv/hook.h>
68#include <lttv/state.h>
69#include <lttvwindow/lttvwindow.h>
70#include <lttvwindow/lttvwindowtraces.h>
71#include <lttvwindow/support.h>
72
73
74#include "eventhooks.h"
75#include "cfv.h"
76#include "processlist.h"
77#include "drawing.h"
78
79
80#define MAX_PATH_LEN 256
3d27be8a 81#define STATE_LINE_WIDTH 6
9e01e6d4 82#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
83
84extern GSList *g_legend_list;
85
86
87/* Action to do when background computation completed.
88 *
89 * Wait for all the awaited computations to be over.
90 */
91
92static gint background_ready(void *hook_data, void *call_data)
93{
67f72973 94 ControlFlowData *resourceview_data = (ControlFlowData *)hook_data;
9e01e6d4 95 LttvTrace *trace = (LttvTrace*)call_data;
96
67f72973 97 resourceview_data->background_info_waiting--;
9e01e6d4 98
67f72973 99 if(resourceview_data->background_info_waiting == 0) {
9e01e6d4 100 g_message("control flow viewer : background computation data ready.");
101
67f72973 102 drawing_clear(resourceview_data->drawing);
103 processlist_clear(resourceview_data->process_list);
9e01e6d4 104 gtk_widget_set_size_request(
67f72973 105 resourceview_data->drawing->drawing_area,
106 -1, processlist_get_height(resourceview_data->process_list));
107 redraw_notify(resourceview_data, NULL);
9e01e6d4 108 }
109
110 return 0;
111}
112
113
114/* Request background computation. Verify if it is in progress or ready first.
115 * Only for each trace in the tab's traceset.
116 */
67f72973 117static void request_background_data(ControlFlowData *resourceview_data)
9e01e6d4 118{
119 LttvTracesetContext * tsc =
67f72973 120 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 121 gint num_traces = lttv_traceset_number(tsc->ts);
122 gint i;
123 LttvTrace *trace;
124 LttvTraceState *tstate;
125
126 LttvHooks *background_ready_hook =
127 lttv_hooks_new();
67f72973 128 lttv_hooks_add(background_ready_hook, background_ready, resourceview_data,
9e01e6d4 129 LTTV_PRIO_DEFAULT);
67f72973 130 resourceview_data->background_info_waiting = 0;
9e01e6d4 131
132 for(i=0;i<num_traces;i++) {
133 trace = lttv_traceset_get(tsc->ts, i);
134 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
135
136 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
137 && !tstate->has_precomputed_states) {
138
139 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
140 trace) == FALSE) {
141 /* We first remove requests that could have been done for the same
142 * information. Happens when two viewers ask for it before servicing
143 * starts.
144 */
145 if(!lttvwindowtraces_background_request_find(trace, "state"))
146 lttvwindowtraces_background_request_queue(
67f72973 147 main_window_get_widget(resourceview_data->tab), trace, "state");
148 lttvwindowtraces_background_notify_queue(resourceview_data,
9e01e6d4 149 trace,
150 ltt_time_infinite,
151 NULL,
152 background_ready_hook);
67f72973 153 resourceview_data->background_info_waiting++;
9e01e6d4 154 } else { /* in progress */
155
67f72973 156 lttvwindowtraces_background_notify_current(resourceview_data,
9e01e6d4 157 trace,
158 ltt_time_infinite,
159 NULL,
160 background_ready_hook);
67f72973 161 resourceview_data->background_info_waiting++;
9e01e6d4 162 }
163 } else {
164 /* Data ready. By its nature, this viewer doesn't need to have
165 * its data ready hook called there, because a background
166 * request is always linked with a redraw.
167 */
168 }
9e01e6d4 169 }
170
171 lttv_hooks_destroy(background_ready_hook);
172}
173
174
9e01e6d4 175/**
176 * Event Viewer's constructor hook
177 *
178 * This constructor is given as a parameter to the menuitem and toolbar button
179 * registration. It creates the list.
180 * @param tab A pointer to the parent tab.
181 * @return The widget created.
182 */
183GtkWidget *
58a9b31b 184h_resourceview(LttvPlugin *plugin)
9e01e6d4 185{
186 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
187 Tab *tab = ptab->tab;
188 g_info("h_guicontrolflow, %p", tab);
67f72973 189 ControlFlowData *resourceview_data = resourceview(ptab);
9e01e6d4 190
67f72973 191 resourceview_data->tab = tab;
9e01e6d4 192
193 // Unreg done in the GuiControlFlow_Destructor
194 lttvwindow_register_traceset_notify(tab,
195 traceset_notify,
67f72973 196 resourceview_data);
9e01e6d4 197
198 lttvwindow_register_time_window_notify(tab,
199 update_time_window_hook,
67f72973 200 resourceview_data);
9e01e6d4 201 lttvwindow_register_current_time_notify(tab,
202 update_current_time_hook,
67f72973 203 resourceview_data);
9e01e6d4 204 lttvwindow_register_redraw_notify(tab,
205 redraw_notify,
67f72973 206 resourceview_data);
9e01e6d4 207 lttvwindow_register_continue_notify(tab,
208 continue_notify,
67f72973 209 resourceview_data);
210 request_background_data(resourceview_data);
9e01e6d4 211
212
67f72973 213 return guicontrolflow_get_widget(resourceview_data) ;
9e01e6d4 214
215}
216
217void legend_destructor(GtkWindow *legend)
218{
219 g_legend_list = g_slist_remove(g_legend_list, legend);
220}
221
222/* Create a popup legend */
223GtkWidget *
224h_legend(LttvPlugin *plugin)
225{
226 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
227 Tab *tab = ptab->tab;
228 g_info("h_legend, %p", tab);
229
230 GtkWindow *legend = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
231
232 g_legend_list = g_slist_append(
233 g_legend_list,
234 legend);
235
236 g_object_set_data_full(
237 G_OBJECT(legend),
238 "legend",
239 legend,
240 (GDestroyNotify)legend_destructor);
241
242 gtk_window_set_title(legend, "Control Flow View Legend");
243
244 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(legend), "lttv-color-list.png");
245
9e01e6d4 246 gtk_container_add(GTK_CONTAINER(legend), GTK_WIDGET(pixmap));
247
248 gtk_widget_show(GTK_WIDGET(pixmap));
249 gtk_widget_show(GTK_WIDGET(legend));
250
251
252 return NULL; /* This is a popup window */
253}
254
255
256int event_selected_hook(void *hook_data, void *call_data)
257{
67f72973 258 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
9e01e6d4 259 guint *event_number = (guint*) call_data;
260
261 g_debug("DEBUG : event selected by main window : %u", *event_number);
262
263 return 0;
264}
265
d3d99fde 266static void cpu_set_line_color(PropertiesLine *prop_line, LttvCPUState *s)
598026ba 267{
1b171947 268 GQuark present_state;
269
270 if(s->mode_stack->len == 0)
271 present_state = LTTV_CPU_UNKNOWN;
272 else
273 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
d3d99fde 274
201fcc15 275 if(present_state == LTTV_CPU_IDLE) {
598026ba 276 prop_line->color = drawing_colors_cpu[COL_CPU_IDLE];
277 }
278 else if(present_state == LTTV_CPU_BUSY) {
279 prop_line->color = drawing_colors_cpu[COL_CPU_BUSY];
280 }
281 else if(present_state == LTTV_CPU_IRQ) {
282 prop_line->color = drawing_colors_cpu[COL_CPU_IRQ];
283 }
d34141ca 284 else if(present_state == LTTV_CPU_SOFT_IRQ) {
285 prop_line->color = drawing_colors_cpu[COL_CPU_SOFT_IRQ];
286 }
d3d99fde 287 else if(present_state == LTTV_CPU_TRAP) {
288 prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
201fcc15 289 } else {
290 prop_line->color = drawing_colors_cpu[COL_CPU_UNKNOWN];
d3d99fde 291 }
598026ba 292}
9e01e6d4 293
8743690d 294static void irq_set_line_color(PropertiesLine *prop_line, LttvIRQState *s)
295{
1b171947 296 GQuark present_state;
297 if(s->mode_stack->len == 0)
298 present_state = LTTV_IRQ_UNKNOWN;
299 else
300 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
8743690d 301
1b171947 302 if(present_state == LTTV_IRQ_IDLE) {
8743690d 303 prop_line->color = drawing_colors_irq[COL_IRQ_IDLE];
304 }
305 else if(present_state == LTTV_IRQ_BUSY) {
306 prop_line->color = drawing_colors_irq[COL_IRQ_BUSY];
307 }
1b171947 308 else {
309 prop_line->color = drawing_colors_irq[COL_IRQ_UNKNOWN];
310 }
8743690d 311}
312
0305fe77 313static void soft_irq_set_line_color(PropertiesLine *prop_line, LttvSoftIRQState *s)
314{
315 GQuark present_state;
67c73bb3 316 if(s->running)
0305fe77 317 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_BUSY];
67c73bb3 318 else if(s->pending)
319 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_PENDING];
320 else
321 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_IDLE];
0305fe77 322}
323
38726a78 324static void trap_set_line_color(PropertiesLine *prop_line, LttvTrapState *s)
325{
326 GQuark present_state;
327 if(s->running == 0)
328 prop_line->color = drawing_colors_trap[COL_TRAP_IDLE];
329 else
330 prop_line->color = drawing_colors_trap[COL_TRAP_BUSY];
331}
332
20d16f82 333static void bdev_set_line_color(PropertiesLine *prop_line, LttvBdevState *s)
334{
1b171947 335 GQuark present_state;
23e59a12 336 if(s == 0 || s->mode_stack->len == 0)
1b171947 337 present_state = LTTV_BDEV_UNKNOWN;
338 else
339 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
20d16f82 340
1b171947 341 if(present_state == LTTV_BDEV_IDLE) {
20d16f82 342 prop_line->color = drawing_colors_bdev[COL_BDEV_IDLE];
343 }
344 else if(present_state == LTTV_BDEV_BUSY_READING) {
345 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_READING];
346 }
347 else if(present_state == LTTV_BDEV_BUSY_WRITING) {
348 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_WRITING];
349 }
1b171947 350 else {
351 prop_line->color = drawing_colors_bdev[COL_BDEV_UNKNOWN];
352 }
20d16f82 353}
354
9e01e6d4 355/* before_schedchange_hook
356 *
357 * This function basically draw lines and icons. Two types of lines are drawn :
358 * one small (3 pixels?) representing the state of the process and the second
359 * type is thicker (10 pixels?) representing on which CPU a process is running
360 * (and this only in running state).
361 *
362 * Extremums of the lines :
363 * x_min : time of the last event context for this process kept in memory.
364 * x_max : time of the current event.
365 * y : middle of the process in the process list. The process is found in the
366 * list, therefore is it's position in pixels.
367 *
368 * The choice of lines'color is defined by the context of the last event for this
369 * process.
370 */
371
372
373int before_schedchange_hook(void *hook_data, void *call_data)
374{
dd455fb8 375 LttvTraceHook *th = (LttvTraceHook*)hook_data;
376 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 377 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 378
379 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
380
381 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
382 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
383
384 LttEvent *e;
385 e = ltt_tracefile_get_event(tfc->tf);
386 gint target_pid_saved = tfc->target_pid;
387
388 LttTime evtime = ltt_event_time(e);
67f72973 389 LttvFilter *filter = resourceview_data->filter;
58a9b31b 390
9e01e6d4 391 /* we are in a schedchange, before the state update. We must draw the
392 * items corresponding to the state before it changes : now is the right
393 * time to do it.
394 */
395
396 guint pid_out;
397 guint pid_in;
ca5c76ed 398 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
399 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
67f72973 400// TODO: can't we reenable this? pmf
44ffb95f 401// if(pid_in != 0 && pid_out != 0) {
402// /* not a transition to/from idle */
403// return 0;
404// }
c4e6f4dc 405
9e01e6d4 406 tfc->target_pid = pid_out;
58a9b31b 407
67f72973 408 guint cpu = tfs->cpu;
9e01e6d4 409
67f72973 410 guint trace_num = ts->parent.index;
411 /* Add process to process list (if not present) */
412 guint pl_height = 0;
413 HashedResourceData *hashed_process_data = NULL;
414 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 415
67f72973 416 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
417
418 /* Now, the process is in the state hash and our own process hash.
419 * We definitely can draw the items related to the ending state.
420 */
421
422 if(ltt_time_compare(hashed_process_data->next_good_time,
423 evtime) > 0)
424 {
425 if(hashed_process_data->x.middle_marked == FALSE) {
426
427 TimeWindow time_window =
428 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 429#ifdef EXTRA_CHECK
67f72973 430 if(ltt_time_compare(evtime, time_window.start_time) == -1
431 || ltt_time_compare(evtime, time_window.end_time) == 1)
432 return;
9e01e6d4 433#endif //EXTRA_CHECK
67f72973 434 Drawing_t *drawing = resourceview_data->drawing;
435 guint width = drawing->width;
436 guint x;
437 convert_time_to_pixels(
438 time_window,
439 evtime,
440 width,
441 &x);
442
443 /* Draw collision indicator */
444 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
445 gdk_draw_point(hashed_process_data->pixmap,
446 drawing->gc,
447 x,
448 COLLISION_POSITION(hashed_process_data->height));
449 hashed_process_data->x.middle_marked = TRUE;
450 }
451 } else {
452 TimeWindow time_window =
453 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 454#ifdef EXTRA_CHECK
67f72973 455 if(ltt_time_compare(evtime, time_window.start_time) == -1
9e01e6d4 456 || ltt_time_compare(evtime, time_window.end_time) == 1)
67f72973 457 return;
9e01e6d4 458#endif //EXTRA_CHECK
67f72973 459 Drawing_t *drawing = resourceview_data->drawing;
460 guint width = drawing->width;
461 guint x;
462 convert_time_to_pixels(
463 time_window,
464 evtime,
465 width,
466 &x);
9e01e6d4 467
67f72973 468 /* Jump over draw if we are at the same x position */
469 if(x == hashed_process_data->x.middle &&
470 hashed_process_data->x.middle_used)
471 {
472 if(hashed_process_data->x.middle_marked == FALSE) {
473 /* Draw collision indicator */
474 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
475 gdk_draw_point(hashed_process_data->pixmap,
476 drawing->gc,
477 x,
478 COLLISION_POSITION(hashed_process_data->height));
479 hashed_process_data->x.middle_marked = TRUE;
58a9b31b 480 }
67f72973 481 /* jump */
482 } else {
483 DrawContext draw_context;
9e01e6d4 484
67f72973 485 /* Now create the drawing context that will be used to draw
486 * items related to the last state. */
487 draw_context.drawable = hashed_process_data->pixmap;
488 draw_context.gc = drawing->gc;
489 draw_context.pango_layout = drawing->pango_layout;
490 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
491 draw_context.drawinfo.end.x = x;
9e01e6d4 492
67f72973 493 draw_context.drawinfo.y.over = 1;
494 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
495 draw_context.drawinfo.y.under = hashed_process_data->height;
9e01e6d4 496
67f72973 497 draw_context.drawinfo.start.offset.over = 0;
498 draw_context.drawinfo.start.offset.middle = 0;
499 draw_context.drawinfo.start.offset.under = 0;
500 draw_context.drawinfo.end.offset.over = 0;
501 draw_context.drawinfo.end.offset.middle = 0;
502 draw_context.drawinfo.end.offset.under = 0;
9e01e6d4 503
67f72973 504 {
505 /* Draw the line */
506 //PropertiesLine prop_line = prepare_s_e_line(process);
507 PropertiesLine prop_line;
508 prop_line.line_width = STATE_LINE_WIDTH;
509 prop_line.style = GDK_LINE_SOLID;
510 prop_line.y = MIDDLE;
511 cpu_set_line_color(&prop_line, tfs->cpu_state);
512 draw_line((void*)&prop_line, (void*)&draw_context);
9e01e6d4 513
67f72973 514 }
515 /* become the last x position */
516 hashed_process_data->x.middle = x;
517 hashed_process_data->x.middle_used = TRUE;
518 hashed_process_data->x.middle_marked = FALSE;
9e01e6d4 519
67f72973 520 /* Calculate the next good time */
521 convert_pixels_to_time(width, x+1, time_window,
522 &hashed_process_data->next_good_time);
523 }
9e01e6d4 524 }
525
67f72973 526 return 0;
9e01e6d4 527}
528
58a9b31b 529/* after_schedchange_hook
530 *
531 * The draw after hook is called by the reading API to have a
532 * particular event drawn on the screen.
533 * @param hook_data ControlFlowData structure of the viewer.
534 * @param call_data Event context.
535 *
536 * This function adds items to be drawn in a queue for each process.
537 *
538 */
539int after_schedchange_hook(void *hook_data, void *call_data)
9e01e6d4 540{
dd455fb8 541 LttvTraceHook *th = (LttvTraceHook*)hook_data;
542 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 543 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 544 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
44ffb95f 545 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
44ffb95f 546 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
44ffb95f 547 LttEvent *e;
67f72973 548
44ffb95f 549 e = ltt_tracefile_get_event(tfc->tf);
550
67f72973 551 LttvFilter *filter = resourceview_data->filter;
44ffb95f 552 if(filter != NULL && filter->head != NULL)
553 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
554 tfc->t_context->t,tfc,NULL,NULL))
555 return FALSE;
556
557 LttTime evtime = ltt_event_time(e);
558
44ffb95f 559 /* Add process to process list (if not present) */
560 LttvProcessState *process_in;
561 LttTime birth;
562 guint pl_height = 0;
563 HashedResourceData *hashed_process_data_in = NULL;
564
67f72973 565 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 566
567 guint pid_in;
568 {
569 guint pid_out;
ca5c76ed 570 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
571 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
44ffb95f 572 }
573
574
575 /* Find process pid_in in the list... */
576 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
577 //process_in = tfs->process;
578 guint cpu = tfs->cpu;
44ffb95f 579 guint trace_num = ts->parent.index;
580 process_in = ts->running_process[cpu];
581 /* It should exist, because we are after the state update. */
582#ifdef EXTRA_CHECK
583 g_assert(process_in != NULL);
584#endif //EXTRA_CHECK
585 birth = process_in->creation_time;
586
67f72973 587 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
588 hashed_process_data_in = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
589
44ffb95f 590 /* Set the current process */
591 process_list->current_hash_data[trace_num][process_in->cpu] =
592 hashed_process_data_in;
593
594 if(ltt_time_compare(hashed_process_data_in->next_good_time,
595 evtime) <= 0)
596 {
597 TimeWindow time_window =
67f72973 598 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 599
600#ifdef EXTRA_CHECK
601 if(ltt_time_compare(evtime, time_window.start_time) == -1
602 || ltt_time_compare(evtime, time_window.end_time) == 1)
603 return;
604#endif //EXTRA_CHECK
67f72973 605 Drawing_t *drawing = resourceview_data->drawing;
44ffb95f 606 guint width = drawing->width;
607 guint new_x;
608
609 convert_time_to_pixels(
610 time_window,
611 evtime,
612 width,
613 &new_x);
614
615 if(hashed_process_data_in->x.middle != new_x) {
616 hashed_process_data_in->x.middle = new_x;
617 hashed_process_data_in->x.middle_used = FALSE;
618 hashed_process_data_in->x.middle_marked = FALSE;
619 }
620 }
58a9b31b 621 return 0;
622}
9e01e6d4 623
58a9b31b 624/* before_execmode_hook
625 *
626 * This function basically draw lines and icons. Two types of lines are drawn :
627 * one small (3 pixels?) representing the state of the process and the second
628 * type is thicker (10 pixels?) representing on which CPU a process is running
629 * (and this only in running state).
630 *
631 * Extremums of the lines :
632 * x_min : time of the last event context for this process kept in memory.
633 * x_max : time of the current event.
634 * y : middle of the process in the process list. The process is found in the
635 * list, therefore is it's position in pixels.
636 *
637 * The choice of lines'color is defined by the context of the last event for this
638 * process.
639 */
9e01e6d4 640
598026ba 641int before_execmode_hook(void *hook_data, void *call_data)
642{
dd455fb8 643 LttvTraceHook *th = (LttvTraceHook*)hook_data;
644 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 645 ControlFlowData *resourceview_data = events_request->viewer_data;
598026ba 646
647 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
648
649 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
650 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
651
652 LttEvent *e;
653 e = ltt_tracefile_get_event(tfc->tf);
654
655 LttTime evtime = ltt_event_time(e);
656
8743690d 657 before_execmode_hook_irq(hook_data, call_data);
0305fe77 658 before_execmode_hook_soft_irq(hook_data, call_data);
38726a78 659 before_execmode_hook_trap(hook_data, call_data);
8743690d 660
598026ba 661 /* we are in a execmode, before the state update. We must draw the
662 * items corresponding to the state before it changes : now is the right
663 * time to do it.
664 */
665 /* For the pid */
598026ba 666 guint cpu = tfs->cpu;
67f72973 667
598026ba 668 guint trace_num = ts->parent.index;
669 LttvProcessState *process = ts->running_process[cpu];
670 g_assert(process != NULL);
671
598026ba 672 /* Well, the process_out existed : we must get it in the process hash
673 * or add it, and draw its items.
674 */
675 /* Add process to process list (if not present) */
676 guint pl_height = 0;
677 HashedResourceData *hashed_process_data = NULL;
67f72973 678 ProcessList *process_list = resourceview_data->process_list;
679
598026ba 680 LttTime birth = process->creation_time;
681
682 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
683 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
684 } else {
67f72973 685 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
686
598026ba 687 /* Set the current process */
688 process_list->current_hash_data[trace_num][process->cpu] =
689 hashed_process_data;
690 }
691
692 /* Now, the process is in the state hash and our own process hash.
693 * We definitely can draw the items related to the ending state.
694 */
695
696 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
697 evtime) > 0))
698 {
699 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
700 TimeWindow time_window =
67f72973 701 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 702
703#ifdef EXTRA_CHECK
704 if(ltt_time_compare(evtime, time_window.start_time) == -1
705 || ltt_time_compare(evtime, time_window.end_time) == 1)
706 return;
707#endif //EXTRA_CHECK
67f72973 708 Drawing_t *drawing = resourceview_data->drawing;
598026ba 709 guint width = drawing->width;
710 guint x;
711 convert_time_to_pixels(
712 time_window,
713 evtime,
714 width,
715 &x);
716
717 /* Draw collision indicator */
718 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
719 gdk_draw_point(hashed_process_data->pixmap,
720 drawing->gc,
721 x,
722 COLLISION_POSITION(hashed_process_data->height));
723 hashed_process_data->x.middle_marked = TRUE;
724 }
d3d99fde 725 }
726 else {
598026ba 727 TimeWindow time_window =
67f72973 728 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 729
730#ifdef EXTRA_CHECK
731 if(ltt_time_compare(evtime, time_window.start_time) == -1
732 || ltt_time_compare(evtime, time_window.end_time) == 1)
733 return;
734#endif //EXTRA_CHECK
67f72973 735 Drawing_t *drawing = resourceview_data->drawing;
598026ba 736 guint width = drawing->width;
737 guint x;
738
739 convert_time_to_pixels(
740 time_window,
741 evtime,
742 width,
743 &x);
744
745
746 /* Jump over draw if we are at the same x position */
747 if(unlikely(x == hashed_process_data->x.middle &&
748 hashed_process_data->x.middle_used))
749 {
750 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
751 /* Draw collision indicator */
752 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
753 gdk_draw_point(hashed_process_data->pixmap,
754 drawing->gc,
755 x,
756 COLLISION_POSITION(hashed_process_data->height));
757 hashed_process_data->x.middle_marked = TRUE;
758 }
759 /* jump */
d3d99fde 760 }
761 else {
598026ba 762
763 DrawContext draw_context;
764 /* Now create the drawing context that will be used to draw
765 * items related to the last state. */
766 draw_context.drawable = hashed_process_data->pixmap;
767 draw_context.gc = drawing->gc;
768 draw_context.pango_layout = drawing->pango_layout;
769 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
770 draw_context.drawinfo.end.x = x;
771
772 draw_context.drawinfo.y.over = 1;
773 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
774 draw_context.drawinfo.y.under = hashed_process_data->height;
775
776 draw_context.drawinfo.start.offset.over = 0;
777 draw_context.drawinfo.start.offset.middle = 0;
778 draw_context.drawinfo.start.offset.under = 0;
779 draw_context.drawinfo.end.offset.over = 0;
780 draw_context.drawinfo.end.offset.middle = 0;
781 draw_context.drawinfo.end.offset.under = 0;
782
783 {
784 /* Draw the line */
785 PropertiesLine prop_line;
d3d99fde 786 prop_line.line_width = STATE_LINE_WIDTH;
787 prop_line.style = GDK_LINE_SOLID;
788 prop_line.y = MIDDLE;
789 cpu_set_line_color(&prop_line, tfs->cpu_state);
598026ba 790 draw_line((void*)&prop_line, (void*)&draw_context);
791 }
792 /* become the last x position */
793 hashed_process_data->x.middle = x;
794 hashed_process_data->x.middle_used = TRUE;
795 hashed_process_data->x.middle_marked = FALSE;
796
797 /* Calculate the next good time */
798 convert_pixels_to_time(width, x+1, time_window,
799 &hashed_process_data->next_good_time);
800 }
801 }
802
803 return 0;
804}
9e01e6d4 805
8743690d 806int before_execmode_hook_irq(void *hook_data, void *call_data)
807{
dd455fb8 808 LttvTraceHook *th = (LttvTraceHook*)hook_data;
809 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 810 ControlFlowData *resourceview_data = events_request->viewer_data;
8743690d 811
812 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
813
814 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
815 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 816 struct marker_info *minfo;
8743690d 817
818 LttEvent *e;
819 e = ltt_tracefile_get_event(tfc->tf);
820
821 LttTime evtime = ltt_event_time(e);
822
ca5c76ed 823 LttTrace *trace = tfc->t_context->t;
824
8743690d 825 /* we are in a execmode, before the state update. We must draw the
826 * items corresponding to the state before it changes : now is the right
827 * time to do it.
828 */
829 /* For the pid */
830
831 guint64 irq;
832 guint cpu = tfs->cpu;
833
750eb11a 834 /*
835 * Check for LTT_CHANNEL_KERNEL channel name and event ID
836 * corresponding to LTT_EVENT_IRQ_ENTRY or LTT_EVENT_IRQ_EXIT.
837 */
838 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
839 return 0;
840 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
841 g_assert(minfo != NULL);
842 if (minfo->name == LTT_EVENT_IRQ_ENTRY) {
ca5c76ed 843 irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
750eb11a 844 } else if (minfo->name == LTT_EVENT_IRQ_EXIT) {
8743690d 845 irq = ts->cpu_states[cpu].last_irq;
750eb11a 846 } else
8743690d 847 return 0;
8743690d 848
8743690d 849 guint trace_num = ts->parent.index;
850
8743690d 851 /* Well, the process_out existed : we must get it in the process hash
852 * or add it, and draw its items.
853 */
854 /* Add process to process list (if not present) */
855 guint pl_height = 0;
856 HashedResourceData *hashed_process_data = NULL;
67f72973 857 ProcessList *process_list = resourceview_data->process_list;
858
859 hashed_process_data = resourcelist_obtain_irq(resourceview_data, trace_num, irq);
671c625b 860 // TODO: fix this, it's ugly and slow:
861 GQuark name;
862 {
863 gchar *str;
864 str = g_strdup_printf("IRQ %llu [%s]", irq, (char*)g_quark_to_string(ts->irq_names[irq]));
865 name = g_quark_from_string(str);
866 g_free(str);
867 }
868 gtk_tree_store_set(resourceview_data->process_list->list_store, &hashed_process_data->y_iter, NAME_COLUMN, g_quark_to_string(name), -1);
8743690d 869
870 /* Now, the process is in the state hash and our own process hash.
871 * We definitely can draw the items related to the ending state.
872 */
873
874 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
875 evtime) > 0))
876 {
877 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
878 TimeWindow time_window =
67f72973 879 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 880
881#ifdef EXTRA_CHECK
882 if(ltt_time_compare(evtime, time_window.start_time) == -1
883 || ltt_time_compare(evtime, time_window.end_time) == 1)
884 return;
885#endif //EXTRA_CHECK
67f72973 886 Drawing_t *drawing = resourceview_data->drawing;
8743690d 887 guint width = drawing->width;
888 guint x;
889 convert_time_to_pixels(
890 time_window,
891 evtime,
892 width,
893 &x);
894
895 /* Draw collision indicator */
896 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
897 gdk_draw_point(hashed_process_data->pixmap,
898 drawing->gc,
899 x,
900 COLLISION_POSITION(hashed_process_data->height));
901 hashed_process_data->x.middle_marked = TRUE;
902 }
903 }
904 else {
905 TimeWindow time_window =
67f72973 906 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 907
908#ifdef EXTRA_CHECK
909 if(ltt_time_compare(evtime, time_window.start_time) == -1
910 || ltt_time_compare(evtime, time_window.end_time) == 1)
911 return;
912#endif //EXTRA_CHECK
67f72973 913 Drawing_t *drawing = resourceview_data->drawing;
8743690d 914 guint width = drawing->width;
915 guint x;
916
917 convert_time_to_pixels(
918 time_window,
919 evtime,
920 width,
921 &x);
922
923
924 /* Jump over draw if we are at the same x position */
925 if(unlikely(x == hashed_process_data->x.middle &&
926 hashed_process_data->x.middle_used))
927 {
928 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
929 /* Draw collision indicator */
930 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
931 gdk_draw_point(hashed_process_data->pixmap,
932 drawing->gc,
933 x,
934 COLLISION_POSITION(hashed_process_data->height));
935 hashed_process_data->x.middle_marked = TRUE;
936 }
937 /* jump */
938 }
939 else {
940
941 DrawContext draw_context;
942 /* Now create the drawing context that will be used to draw
943 * items related to the last state. */
944 draw_context.drawable = hashed_process_data->pixmap;
945 draw_context.gc = drawing->gc;
946 draw_context.pango_layout = drawing->pango_layout;
947 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
948 draw_context.drawinfo.end.x = x;
949
950 draw_context.drawinfo.y.over = 1;
951 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
952 draw_context.drawinfo.y.under = hashed_process_data->height;
953
954 draw_context.drawinfo.start.offset.over = 0;
955 draw_context.drawinfo.start.offset.middle = 0;
956 draw_context.drawinfo.start.offset.under = 0;
957 draw_context.drawinfo.end.offset.over = 0;
958 draw_context.drawinfo.end.offset.middle = 0;
959 draw_context.drawinfo.end.offset.under = 0;
960
961 {
962 /* Draw the line */
963 PropertiesLine prop_line;
964 prop_line.line_width = STATE_LINE_WIDTH;
965 prop_line.style = GDK_LINE_SOLID;
966 prop_line.y = MIDDLE;
967 irq_set_line_color(&prop_line, &ts->irq_states[irq]);
968 draw_line((void*)&prop_line, (void*)&draw_context);
969 }
970 /* become the last x position */
971 hashed_process_data->x.middle = x;
972 hashed_process_data->x.middle_used = TRUE;
973 hashed_process_data->x.middle_marked = FALSE;
974
975 /* Calculate the next good time */
976 convert_pixels_to_time(width, x+1, time_window,
977 &hashed_process_data->next_good_time);
978 }
979 }
980
981 return 0;
982}
983
0305fe77 984int before_execmode_hook_soft_irq(void *hook_data, void *call_data)
985{
986 LttvTraceHook *th = (LttvTraceHook*)hook_data;
987 EventsRequest *events_request = (EventsRequest*)th->hook_data;
988 ControlFlowData *resourceview_data = events_request->viewer_data;
989
990 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
991
992 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
993 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 994 struct marker_info *minfo;
0305fe77 995
996 LttEvent *e;
997 e = ltt_tracefile_get_event(tfc->tf);
998
999 LttTime evtime = ltt_event_time(e);
1000
1001 LttTrace *trace = tfc->t_context->t;
1002
1003 /* we are in a execmode, before the state update. We must draw the
1004 * items corresponding to the state before it changes : now is the right
1005 * time to do it.
1006 */
1007 /* For the pid */
1008
1009 guint64 softirq;
1010 guint cpu = tfs->cpu;
1011
750eb11a 1012 /*
1013 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1014 * corresponding to LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY
1015 * or LTT_EVENT_SOFT_IRQ_EXIT.
1016 */
1017 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1018 return 0;
1019 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1020 g_assert(minfo != NULL);
1021 if (minfo->name == LTT_EVENT_SOFT_IRQ_RAISE
1022 || minfo->name == LTT_EVENT_SOFT_IRQ_ENTRY) {
0305fe77 1023 softirq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
750eb11a 1024 } else if (minfo->name == LTT_EVENT_SOFT_IRQ_EXIT) {
0305fe77 1025 softirq = ts->cpu_states[cpu].last_soft_irq;
750eb11a 1026 } else
0305fe77 1027 return 0;
0305fe77 1028
1029 guint trace_num = ts->parent.index;
1030
1031 /* Well, the process_out existed : we must get it in the process hash
1032 * or add it, and draw its items.
1033 */
1034 /* Add process to process list (if not present) */
1035 guint pl_height = 0;
1036 HashedResourceData *hashed_process_data = NULL;
1037 ProcessList *process_list = resourceview_data->process_list;
1038
1039 hashed_process_data = resourcelist_obtain_soft_irq(resourceview_data, trace_num, softirq);
1040
1041 /* Now, the process is in the state hash and our own process hash.
1042 * We definitely can draw the items related to the ending state.
1043 */
1044
1045 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1046 evtime) > 0))
1047 {
1048 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1049 TimeWindow time_window =
1050 lttvwindow_get_time_window(resourceview_data->tab);
1051
1052#ifdef EXTRA_CHECK
1053 if(ltt_time_compare(evtime, time_window.start_time) == -1
1054 || ltt_time_compare(evtime, time_window.end_time) == 1)
1055 return;
1056#endif //EXTRA_CHECK
1057 Drawing_t *drawing = resourceview_data->drawing;
1058 guint width = drawing->width;
1059 guint x;
1060 convert_time_to_pixels(
1061 time_window,
1062 evtime,
1063 width,
1064 &x);
1065
1066 /* Draw collision indicator */
1067 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1068 gdk_draw_point(hashed_process_data->pixmap,
1069 drawing->gc,
1070 x,
1071 COLLISION_POSITION(hashed_process_data->height));
1072 hashed_process_data->x.middle_marked = TRUE;
1073 }
1074 }
1075 else {
1076 TimeWindow time_window =
1077 lttvwindow_get_time_window(resourceview_data->tab);
1078
1079#ifdef EXTRA_CHECK
1080 if(ltt_time_compare(evtime, time_window.start_time) == -1
1081 || ltt_time_compare(evtime, time_window.end_time) == 1)
1082 return;
1083#endif //EXTRA_CHECK
1084 Drawing_t *drawing = resourceview_data->drawing;
1085 guint width = drawing->width;
1086 guint x;
1087
1088 convert_time_to_pixels(
1089 time_window,
1090 evtime,
1091 width,
1092 &x);
1093
1094
1095 /* Jump over draw if we are at the same x position */
1096 if(unlikely(x == hashed_process_data->x.middle &&
1097 hashed_process_data->x.middle_used))
1098 {
1099 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1100 /* Draw collision indicator */
1101 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1102 gdk_draw_point(hashed_process_data->pixmap,
1103 drawing->gc,
1104 x,
1105 COLLISION_POSITION(hashed_process_data->height));
1106 hashed_process_data->x.middle_marked = TRUE;
1107 }
1108 /* jump */
1109 }
1110 else {
1111
1112 DrawContext draw_context;
1113 /* Now create the drawing context that will be used to draw
1114 * items related to the last state. */
1115 draw_context.drawable = hashed_process_data->pixmap;
1116 draw_context.gc = drawing->gc;
1117 draw_context.pango_layout = drawing->pango_layout;
1118 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1119 draw_context.drawinfo.end.x = x;
1120
1121 draw_context.drawinfo.y.over = 1;
1122 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1123 draw_context.drawinfo.y.under = hashed_process_data->height;
1124
1125 draw_context.drawinfo.start.offset.over = 0;
1126 draw_context.drawinfo.start.offset.middle = 0;
1127 draw_context.drawinfo.start.offset.under = 0;
1128 draw_context.drawinfo.end.offset.over = 0;
1129 draw_context.drawinfo.end.offset.middle = 0;
1130 draw_context.drawinfo.end.offset.under = 0;
1131
1132 {
1133 /* Draw the line */
1134 PropertiesLine prop_line;
1135 prop_line.line_width = STATE_LINE_WIDTH;
1136 prop_line.style = GDK_LINE_SOLID;
1137 prop_line.y = MIDDLE;
1138 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[softirq]);
1139 draw_line((void*)&prop_line, (void*)&draw_context);
1140 }
1141 /* become the last x position */
1142 hashed_process_data->x.middle = x;
1143 hashed_process_data->x.middle_used = TRUE;
1144 hashed_process_data->x.middle_marked = FALSE;
1145
1146 /* Calculate the next good time */
1147 convert_pixels_to_time(width, x+1, time_window,
1148 &hashed_process_data->next_good_time);
1149 }
1150 }
1151
1152 return 0;
1153}
1154
38726a78 1155int before_execmode_hook_trap(void *hook_data, void *call_data)
1156{
1157 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1158 EventsRequest *events_request = (EventsRequest*)th->hook_data;
1159 ControlFlowData *resourceview_data = events_request->viewer_data;
1160
1161 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1162
1163 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1164 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 1165 struct marker_info *minfo;
38726a78 1166
1167 LttEvent *e;
1168 e = ltt_tracefile_get_event(tfc->tf);
1169
1170 LttTime evtime = ltt_event_time(e);
1171
1172 LttTrace *trace = tfc->t_context->t;
1173
1174 /* we are in a execmode, before the state update. We must draw the
1175 * items corresponding to the state before it changes : now is the right
1176 * time to do it.
1177 */
1178 /* For the pid */
1179
1180 guint64 trap;
1181 guint cpu = tfs->cpu;
1182
750eb11a 1183 /*
1184 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1185 * corresponding to LTT_EVENT_TRAP_ENTRY or LTT_EVENT_TRAP_EXIT.
1186 */
1187 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1188 return 0;
1189 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1190 g_assert(minfo != NULL);
1191 if (minfo->name == LTT_EVENT_TRAP_ENTRY) {
38726a78 1192 trap = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
750eb11a 1193 } else if (minfo->name == LTT_EVENT_TRAP_EXIT) {
38726a78 1194 trap = ts->cpu_states[cpu].last_trap;
750eb11a 1195 } else
38726a78 1196 return 0;
38726a78 1197
1198 guint trace_num = ts->parent.index;
1199
1200 /* Well, the process_out existed : we must get it in the process hash
1201 * or add it, and draw its items.
1202 */
1203 /* Add process to process list (if not present) */
1204 guint pl_height = 0;
1205 HashedResourceData *hashed_process_data = NULL;
1206 ProcessList *process_list = resourceview_data->process_list;
1207
1208 hashed_process_data = resourcelist_obtain_trap(resourceview_data, trace_num, trap);
1209
1210 /* Now, the process is in the state hash and our own process hash.
1211 * We definitely can draw the items related to the ending state.
1212 */
1213
1214 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1215 evtime) > 0))
1216 {
1217 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1218 TimeWindow time_window =
1219 lttvwindow_get_time_window(resourceview_data->tab);
1220
1221#ifdef EXTRA_CHECK
1222 if(ltt_time_compare(evtime, time_window.start_time) == -1
1223 || ltt_time_compare(evtime, time_window.end_time) == 1)
1224 return;
1225#endif //EXTRA_CHECK
1226 Drawing_t *drawing = resourceview_data->drawing;
1227 guint width = drawing->width;
1228 guint x;
1229 convert_time_to_pixels(
1230 time_window,
1231 evtime,
1232 width,
1233 &x);
1234
1235 /* Draw collision indicator */
1236 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1237 gdk_draw_point(hashed_process_data->pixmap,
1238 drawing->gc,
1239 x,
1240 COLLISION_POSITION(hashed_process_data->height));
1241 hashed_process_data->x.middle_marked = TRUE;
1242 }
1243 }
1244 else {
1245 TimeWindow time_window =
1246 lttvwindow_get_time_window(resourceview_data->tab);
1247
1248#ifdef EXTRA_CHECK
1249 if(ltt_time_compare(evtime, time_window.start_time) == -1
1250 || ltt_time_compare(evtime, time_window.end_time) == 1)
1251 return;
1252#endif //EXTRA_CHECK
1253 Drawing_t *drawing = resourceview_data->drawing;
1254 guint width = drawing->width;
1255 guint x;
1256
1257 convert_time_to_pixels(
1258 time_window,
1259 evtime,
1260 width,
1261 &x);
1262
1263
1264 /* Jump over draw if we are at the same x position */
1265 if(unlikely(x == hashed_process_data->x.middle &&
1266 hashed_process_data->x.middle_used))
1267 {
1268 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1269 /* Draw collision indicator */
1270 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1271 gdk_draw_point(hashed_process_data->pixmap,
1272 drawing->gc,
1273 x,
1274 COLLISION_POSITION(hashed_process_data->height));
1275 hashed_process_data->x.middle_marked = TRUE;
1276 }
1277 /* jump */
1278 }
1279 else {
1280
1281 DrawContext draw_context;
1282 /* Now create the drawing context that will be used to draw
1283 * items related to the last state. */
1284 draw_context.drawable = hashed_process_data->pixmap;
1285 draw_context.gc = drawing->gc;
1286 draw_context.pango_layout = drawing->pango_layout;
1287 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1288 draw_context.drawinfo.end.x = x;
1289
1290 draw_context.drawinfo.y.over = 1;
1291 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1292 draw_context.drawinfo.y.under = hashed_process_data->height;
1293
1294 draw_context.drawinfo.start.offset.over = 0;
1295 draw_context.drawinfo.start.offset.middle = 0;
1296 draw_context.drawinfo.start.offset.under = 0;
1297 draw_context.drawinfo.end.offset.over = 0;
1298 draw_context.drawinfo.end.offset.middle = 0;
1299 draw_context.drawinfo.end.offset.under = 0;
1300
1301 {
1302 /* Draw the line */
1303 PropertiesLine prop_line;
1304 prop_line.line_width = STATE_LINE_WIDTH;
1305 prop_line.style = GDK_LINE_SOLID;
1306 prop_line.y = MIDDLE;
1307 trap_set_line_color(&prop_line, &ts->trap_states[trap]);
1308 draw_line((void*)&prop_line, (void*)&draw_context);
1309 }
1310 /* become the last x position */
1311 hashed_process_data->x.middle = x;
1312 hashed_process_data->x.middle_used = TRUE;
1313 hashed_process_data->x.middle_marked = FALSE;
1314
1315 /* Calculate the next good time */
1316 convert_pixels_to_time(width, x+1, time_window,
1317 &hashed_process_data->next_good_time);
1318 }
1319 }
1320
1321 return 0;
1322}
1323
0305fe77 1324
20d16f82 1325int before_bdev_event_hook(void *hook_data, void *call_data)
1326{
dd455fb8 1327 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1328 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 1329 ControlFlowData *resourceview_data = events_request->viewer_data;
20d16f82 1330
1331 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1332
1333 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1334 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1335
1336 LttEvent *e;
1337 e = ltt_tracefile_get_event(tfc->tf);
1338
1339 LttTime evtime = ltt_event_time(e);
1340
20d16f82 1341 /* we are in a execmode, before the state update. We must draw the
1342 * items corresponding to the state before it changes : now is the right
1343 * time to do it.
1344 */
1345 /* For the pid */
1346
1347 guint cpu = tfs->cpu;
ca5c76ed 1348 guint8 major = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1349 guint8 minor = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
1350 guint oper = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
20d16f82 1351 gint devcode_gint = MKDEV(major,minor);
1352
20d16f82 1353 guint trace_num = ts->parent.index;
1354
1355 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
23e59a12 1356 /* the result of the lookup might be NULL. that's ok, the rest of the function
1357 should understand it was not found and that its state is unknown */
20d16f82 1358
20d16f82 1359 /* Well, the process_out existed : we must get it in the process hash
1360 * or add it, and draw its items.
1361 */
1362 /* Add process to process list (if not present) */
1363 guint pl_height = 0;
1364 HashedResourceData *hashed_process_data = NULL;
67f72973 1365 ProcessList *process_list = resourceview_data->process_list;
20d16f82 1366// LttTime birth = process->creation_time;
1367
1368// if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1369// hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1370// } else {
67f72973 1371 hashed_process_data = resourcelist_obtain_bdev(resourceview_data, trace_num, devcode_gint);
1372 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
20d16f82 1373// hashed_process_data = processlist_get_process_data(process_list,
1374// pid,
1375// process->cpu,
1376// &birth,
1377// trace_num);
67f72973 1378//
20d16f82 1379 /* Set the current process */
1380// process_list->current_hash_data[trace_num][process->cpu] =
1381// hashed_process_data;
1382// }
1383
1384 /* Now, the process is in the state hash and our own process hash.
1385 * We definitely can draw the items related to the ending state.
1386 */
1387
1388 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1389 evtime) > 0))
1390 {
1391 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1392 TimeWindow time_window =
67f72973 1393 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1394
1395#ifdef EXTRA_CHECK
1396 if(ltt_time_compare(evtime, time_window.start_time) == -1
1397 || ltt_time_compare(evtime, time_window.end_time) == 1)
1398 return;
1399#endif //EXTRA_CHECK
67f72973 1400 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1401 guint width = drawing->width;
1402 guint x;
1403 convert_time_to_pixels(
1404 time_window,
1405 evtime,
1406 width,
1407 &x);
1408
1409 /* Draw collision indicator */
1410 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1411 gdk_draw_point(hashed_process_data->pixmap,
1412 drawing->gc,
1413 x,
1414 COLLISION_POSITION(hashed_process_data->height));
1415 hashed_process_data->x.middle_marked = TRUE;
1416 }
1417 }
1418 else {
1419 TimeWindow time_window =
67f72973 1420 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1421
1422#ifdef EXTRA_CHECK
1423 if(ltt_time_compare(evtime, time_window.start_time) == -1
1424 || ltt_time_compare(evtime, time_window.end_time) == 1)
1425 return;
1426#endif //EXTRA_CHECK
67f72973 1427 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1428 guint width = drawing->width;
1429 guint x;
1430
1431 convert_time_to_pixels(
1432 time_window,
1433 evtime,
1434 width,
1435 &x);
1436
1437
1438 /* Jump over draw if we are at the same x position */
1439 if(unlikely(x == hashed_process_data->x.middle &&
1440 hashed_process_data->x.middle_used))
1441 {
1442 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1443 /* Draw collision indicator */
1444 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1445 gdk_draw_point(hashed_process_data->pixmap,
1446 drawing->gc,
1447 x,
1448 COLLISION_POSITION(hashed_process_data->height));
1449 hashed_process_data->x.middle_marked = TRUE;
1450 }
1451 /* jump */
1452 }
1453 else {
1454
1455 DrawContext draw_context;
1456 /* Now create the drawing context that will be used to draw
1457 * items related to the last state. */
1458 draw_context.drawable = hashed_process_data->pixmap;
1459 draw_context.gc = drawing->gc;
1460 draw_context.pango_layout = drawing->pango_layout;
1461 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1462 draw_context.drawinfo.end.x = x;
1463
1464 draw_context.drawinfo.y.over = 1;
1465 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1466 draw_context.drawinfo.y.under = hashed_process_data->height;
1467
1468 draw_context.drawinfo.start.offset.over = 0;
1469 draw_context.drawinfo.start.offset.middle = 0;
1470 draw_context.drawinfo.start.offset.under = 0;
1471 draw_context.drawinfo.end.offset.over = 0;
1472 draw_context.drawinfo.end.offset.middle = 0;
1473 draw_context.drawinfo.end.offset.under = 0;
1474
1475 {
1476 /* Draw the line */
1477 PropertiesLine prop_line;
1478 prop_line.line_width = STATE_LINE_WIDTH;
1479 prop_line.style = GDK_LINE_SOLID;
1480 prop_line.y = MIDDLE;
1481 bdev_set_line_color(&prop_line, bdev);
1482 draw_line((void*)&prop_line, (void*)&draw_context);
1483 }
1484 /* become the last x position */
1485 hashed_process_data->x.middle = x;
1486 hashed_process_data->x.middle_used = TRUE;
1487 hashed_process_data->x.middle_marked = FALSE;
1488
1489 /* Calculate the next good time */
1490 convert_pixels_to_time(width, x+1, time_window,
1491 &hashed_process_data->next_good_time);
1492 }
1493 }
1494
1495 return 0;
1496}
1497
9e01e6d4 1498gint update_time_window_hook(void *hook_data, void *call_data)
1499{
67f72973 1500 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1501 Drawing_t *drawing = resourceview_data->drawing;
1502 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1503
1504 const TimeWindowNotifyData *time_window_nofify_data =
1505 ((const TimeWindowNotifyData *)call_data);
1506
1507 TimeWindow *old_time_window =
1508 time_window_nofify_data->old_time_window;
1509 TimeWindow *new_time_window =
1510 time_window_nofify_data->new_time_window;
1511
1512 /* Update the ruler */
67f72973 1513 drawing_update_ruler(resourceview_data->drawing,
9e01e6d4 1514 new_time_window);
1515
1516
1517 /* Two cases : zoom in/out or scrolling */
1518
1519 /* In order to make sure we can reuse the old drawing, the scale must
1520 * be the same and the new time interval being partly located in the
1521 * currently shown time interval. (reuse is only for scrolling)
1522 */
1523
1524 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1525 old_time_window->start_time.tv_sec,
1526 old_time_window->start_time.tv_nsec,
1527 old_time_window->time_width.tv_sec,
1528 old_time_window->time_width.tv_nsec);
1529
1530 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1531 new_time_window->start_time.tv_sec,
1532 new_time_window->start_time.tv_nsec,
1533 new_time_window->time_width.tv_sec,
1534 new_time_window->time_width.tv_nsec);
1535
1536 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1537 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1538 {
1539 /* Same scale (scrolling) */
1540 g_info("scrolling");
1541 LttTime *ns = &new_time_window->start_time;
1542 LttTime *nw = &new_time_window->time_width;
1543 LttTime *os = &old_time_window->start_time;
1544 LttTime *ow = &old_time_window->time_width;
1545 LttTime old_end = old_time_window->end_time;
1546 LttTime new_end = new_time_window->end_time;
1547 //if(ns<os+w<ns+w)
1548 //if(ns<os+w && os+w<ns+w)
1549 //if(ns<old_end && os<ns)
1550 if(ltt_time_compare(*ns, old_end) == -1
1551 && ltt_time_compare(*os, *ns) == -1)
1552 {
1553 g_info("scrolling near right");
1554 /* Scroll right, keep right part of the screen */
1555 guint x = 0;
67f72973 1556 guint width = resourceview_data->drawing->width;
9e01e6d4 1557 convert_time_to_pixels(
1558 *old_time_window,
1559 *ns,
1560 width,
1561 &x);
1562
1563 /* Copy old data to new location */
1564 copy_pixmap_region(process_list,
1565 NULL,
67f72973 1566 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1567 NULL,
1568 x, 0,
1569 0, 0,
67f72973 1570 resourceview_data->drawing->width-x+SAFETY, -1);
9e01e6d4 1571
1572 if(drawing->damage_begin == drawing->damage_end)
67f72973 1573 drawing->damage_begin = resourceview_data->drawing->width-x;
9e01e6d4 1574 else
1575 drawing->damage_begin = 0;
1576
67f72973 1577 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1578
1579 /* Clear the data request background, but not SAFETY */
1580 rectangle_pixmap(process_list,
67f72973 1581 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1582 TRUE,
1583 drawing->damage_begin+SAFETY, 0,
1584 drawing->damage_end - drawing->damage_begin, // do not overlap
1585 -1);
1586 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1587
1588 /* Get new data for the rest. */
67f72973 1589 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1590 drawing->damage_begin, 0,
1591 drawing->damage_end - drawing->damage_begin,
67f72973 1592 resourceview_data->drawing->height);
9e01e6d4 1593 } else {
9e01e6d4 1594 if(ltt_time_compare(*ns,*os) == -1
1595 && ltt_time_compare(*os,new_end) == -1)
1596 {
1597 g_info("scrolling near left");
1598 /* Scroll left, keep left part of the screen */
1599 guint x = 0;
67f72973 1600 guint width = resourceview_data->drawing->width;
9e01e6d4 1601 convert_time_to_pixels(
1602 *new_time_window,
1603 *os,
1604 width,
1605 &x);
1606
1607 /* Copy old data to new location */
1608 copy_pixmap_region (process_list,
1609 NULL,
67f72973 1610 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1611 NULL,
1612 0, 0,
1613 x, 0,
1614 -1, -1);
1615
1616 if(drawing->damage_begin == drawing->damage_end)
1617 drawing->damage_end = x;
1618 else
1619 drawing->damage_end =
67f72973 1620 resourceview_data->drawing->width;
9e01e6d4 1621
1622 drawing->damage_begin = 0;
1623
1624 rectangle_pixmap (process_list,
67f72973 1625 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1626 TRUE,
1627 drawing->damage_begin, 0,
1628 drawing->damage_end - drawing->damage_begin, // do not overlap
1629 -1);
1630
1631 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1632
1633 /* Get new data for the rest. */
67f72973 1634 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1635 drawing->damage_begin, 0,
1636 drawing->damage_end - drawing->damage_begin,
67f72973 1637 resourceview_data->drawing->height);
9e01e6d4 1638
1639 } else {
1640 if(ltt_time_compare(*ns,*os) == 0)
1641 {
1642 g_info("not scrolling");
1643 } else {
1644 g_info("scrolling far");
1645 /* Cannot reuse any part of the screen : far jump */
1646
1647
1648 rectangle_pixmap (process_list,
67f72973 1649 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1650 TRUE,
1651 0, 0,
67f72973 1652 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1653 -1);
1654
9e01e6d4 1655 gtk_widget_queue_draw(drawing->drawing_area);
1656
1657 drawing->damage_begin = 0;
67f72973 1658 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1659
67f72973 1660 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1661 0, 0,
67f72973 1662 resourceview_data->drawing->width,
1663 resourceview_data->drawing->height);
9e01e6d4 1664
1665 }
1666 }
1667 }
1668 } else {
1669 /* Different scale (zoom) */
1670 g_info("zoom");
1671
1672 rectangle_pixmap (process_list,
67f72973 1673 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1674 TRUE,
1675 0, 0,
67f72973 1676 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1677 -1);
1678
9e01e6d4 1679 gtk_widget_queue_draw(drawing->drawing_area);
1680
1681 drawing->damage_begin = 0;
67f72973 1682 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1683
67f72973 1684 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1685 0, 0,
67f72973 1686 resourceview_data->drawing->width,
1687 resourceview_data->drawing->height);
9e01e6d4 1688 }
1689
1690 /* Update directly when scrolling */
67f72973 1691 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1692 TRUE);
1693
1694 return 0;
1695}
1696
1697gint traceset_notify(void *hook_data, void *call_data)
1698{
67f72973 1699 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1700 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1701
1702 if(unlikely(drawing->gc == NULL)) {
1703 return FALSE;
1704 }
1705 if(drawing->dotted_gc == NULL) {
1706 return FALSE;
1707 }
1708
67f72973 1709 drawing_clear(resourceview_data->drawing);
1710 processlist_clear(resourceview_data->process_list);
9e01e6d4 1711 gtk_widget_set_size_request(
67f72973 1712 resourceview_data->drawing->drawing_area,
1713 -1, processlist_get_height(resourceview_data->process_list));
1714 redraw_notify(resourceview_data, NULL);
9e01e6d4 1715
67f72973 1716 request_background_data(resourceview_data);
9e01e6d4 1717
1718 return FALSE;
1719}
1720
1721gint redraw_notify(void *hook_data, void *call_data)
1722{
67f72973 1723 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1724 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1725 GtkWidget *widget = drawing->drawing_area;
1726
1727 drawing->damage_begin = 0;
1728 drawing->damage_end = drawing->width;
1729
1730 /* fun feature, to be separated someday... */
67f72973 1731 drawing_clear(resourceview_data->drawing);
1732 processlist_clear(resourceview_data->process_list);
9e01e6d4 1733 gtk_widget_set_size_request(
67f72973 1734 resourceview_data->drawing->drawing_area,
1735 -1, processlist_get_height(resourceview_data->process_list));
9e01e6d4 1736 // Clear the images
67f72973 1737 rectangle_pixmap (resourceview_data->process_list,
9e01e6d4 1738 widget->style->black_gc,
1739 TRUE,
1740 0, 0,
1741 drawing->alloc_width,
1742 -1);
1743
1744 gtk_widget_queue_draw(drawing->drawing_area);
1745
1746 if(drawing->damage_begin < drawing->damage_end)
1747 {
1748 drawing_data_request(drawing,
1749 drawing->damage_begin,
1750 0,
1751 drawing->damage_end-drawing->damage_begin,
1752 drawing->height);
1753 }
1754
9e01e6d4 1755 return FALSE;
1756
1757}
1758
1759
1760gint continue_notify(void *hook_data, void *call_data)
1761{
67f72973 1762 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1763 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1764
1765 if(drawing->damage_begin < drawing->damage_end)
1766 {
1767 drawing_data_request(drawing,
1768 drawing->damage_begin,
1769 0,
1770 drawing->damage_end-drawing->damage_begin,
1771 drawing->height);
1772 }
1773
1774 return FALSE;
1775}
1776
1777
1778gint update_current_time_hook(void *hook_data, void *call_data)
1779{
67f72973 1780 ControlFlowData *resourceview_data = (ControlFlowData*)hook_data;
1781 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1782
1783 LttTime current_time = *((LttTime*)call_data);
1784
1785 TimeWindow time_window =
67f72973 1786 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 1787
1788 LttTime time_begin = time_window.start_time;
1789 LttTime width = time_window.time_width;
1790 LttTime half_width;
1791 {
1792 guint64 time_ll = ltt_time_to_uint64(width);
1793 time_ll = time_ll >> 1; /* divide by two */
1794 half_width = ltt_time_from_uint64(time_ll);
1795 }
1796 LttTime time_end = ltt_time_add(time_begin, width);
1797
1798 LttvTracesetContext * tsc =
67f72973 1799 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 1800
1801 LttTime trace_start = tsc->time_span.start_time;
1802 LttTime trace_end = tsc->time_span.end_time;
1803
1804 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1805 current_time.tv_nsec);
9e01e6d4 1806
1807 /* If current time is inside time interval, just move the highlight
1808 * bar */
1809
1810 /* Else, we have to change the time interval. We have to tell it
1811 * to the main window. */
1812 /* The time interval change will take care of placing the current
1813 * time at the center of the visible area, or nearest possible if we are
1814 * at one end of the trace. */
1815
1816
1817 if(ltt_time_compare(current_time, time_begin) < 0)
1818 {
1819 TimeWindow new_time_window;
1820
1821 if(ltt_time_compare(current_time,
1822 ltt_time_add(trace_start,half_width)) < 0)
1823 time_begin = trace_start;
1824 else
1825 time_begin = ltt_time_sub(current_time,half_width);
1826
1827 new_time_window.start_time = time_begin;
1828 new_time_window.time_width = width;
1829 new_time_window.time_width_double = ltt_time_to_double(width);
1830 new_time_window.end_time = ltt_time_add(time_begin, width);
1831
67f72973 1832 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1833 }
1834 else if(ltt_time_compare(current_time, time_end) > 0)
1835 {
1836 TimeWindow new_time_window;
1837
1838 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1839 time_begin = ltt_time_sub(trace_end,width);
1840 else
1841 time_begin = ltt_time_sub(current_time,half_width);
1842
1843 new_time_window.start_time = time_begin;
1844 new_time_window.time_width = width;
1845 new_time_window.time_width_double = ltt_time_to_double(width);
1846 new_time_window.end_time = ltt_time_add(time_begin, width);
1847
67f72973 1848 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1849
1850 }
67f72973 1851 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 1852
1853 /* Update directly when scrolling */
67f72973 1854 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1855 TRUE);
1856
1857 return 0;
1858}
1859
1860typedef struct _ClosureData {
1861 EventsRequest *events_request;
1862 LttvTracesetState *tss;
1863 LttTime end_time;
1864 guint x_end;
1865} ClosureData;
1866
58a9b31b 1867/* Draw line until end of the screen */
9e01e6d4 1868
1869void draw_closure(gpointer key, gpointer value, gpointer user_data)
1870{
67f72973 1871 ResourceUniqueNumeric *process_info = (ResourceUniqueNumeric*)key;
44ffb95f 1872 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1873 ClosureData *closure_data = (ClosureData*)user_data;
1874
1875 EventsRequest *events_request = closure_data->events_request;
67f72973 1876 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 1877
1878 LttvTracesetState *tss = closure_data->tss;
1879 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1880
1881 LttTime evtime = closure_data->end_time;
1882
1883 gboolean dodraw = TRUE;
1884
67f72973 1885 if(hashed_process_data->type == RV_RESOURCE_MACHINE)
1886 return;
1887
44ffb95f 1888 {
1889 /* For the process */
1890 /* First, check if the current process is in the state computation
1891 * process list. If it is there, that means we must add it right now and
1892 * draw items from the beginning of the read for it. If it is not
1893 * present, it's a new process and it was not present : it will
1894 * be added after the state update. */
1895#ifdef EXTRA_CHECK
1896 g_assert(lttv_traceset_number(tsc->ts) > 0);
1897#endif //EXTRA_CHECK
1898 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1899 LttvTraceState *ts = (LttvTraceState*)tc;
1900
67f72973 1901 /* Only draw for processes that are currently in the trace states */
44ffb95f 1902
67f72973 1903 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 1904#ifdef EXTRA_CHECK
67f72973 1905 /* Should be alike when background info is ready */
1906 if(resourceview_data->background_info_waiting==0)
44ffb95f 1907 g_assert(ltt_time_compare(process->creation_time,
1908 process_info->birth) == 0);
1909#endif //EXTRA_CHECK
1910
67f72973 1911 /* Now, the process is in the state hash and our own process hash.
1912 * We definitely can draw the items related to the ending state.
1913 */
1914
1915 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1916 evtime) <= 0))
1917 {
1918 TimeWindow time_window =
1919 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 1920
1921#ifdef EXTRA_CHECK
67f72973 1922 if(ltt_time_compare(evtime, time_window.start_time) == -1
1923 || ltt_time_compare(evtime, time_window.end_time) == 1)
1924 return;
44ffb95f 1925#endif //EXTRA_CHECK
67f72973 1926 Drawing_t *drawing = resourceview_data->drawing;
1927 guint width = drawing->width;
1928
1929 guint x = closure_data->x_end;
1930
1931 DrawContext draw_context;
1932
1933 /* Now create the drawing context that will be used to draw
1934 * items related to the last state. */
1935 draw_context.drawable = hashed_process_data->pixmap;
1936 draw_context.gc = drawing->gc;
1937 draw_context.pango_layout = drawing->pango_layout;
1938 draw_context.drawinfo.end.x = x;
1939
1940 draw_context.drawinfo.y.over = 1;
1941 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1942 draw_context.drawinfo.y.under = hashed_process_data->height;
1943
1944 draw_context.drawinfo.start.offset.over = 0;
1945 draw_context.drawinfo.start.offset.middle = 0;
1946 draw_context.drawinfo.start.offset.under = 0;
1947 draw_context.drawinfo.end.offset.over = 0;
1948 draw_context.drawinfo.end.offset.middle = 0;
1949 draw_context.drawinfo.end.offset.under = 0;
44ffb95f 1950#if 0
67f72973 1951 /* Jump over draw if we are at the same x position */
1952 if(x == hashed_process_data->x.over)
1953 {
1954 /* jump */
1955 } else {
1956 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1957 /* Draw the line */
1958 PropertiesLine prop_line = prepare_execmode_line(process);
1959 draw_line((void*)&prop_line, (void*)&draw_context);
44ffb95f 1960
67f72973 1961 hashed_process_data->x.over = x;
1962 }
44ffb95f 1963#endif //0
1964
67f72973 1965 if(unlikely(x == hashed_process_data->x.middle &&
1966 hashed_process_data->x.middle_used)) {
44ffb95f 1967#if 0 /* do not mark closure : not missing information */
67f72973 1968 if(hashed_process_data->x.middle_marked == FALSE) {
1969 /* Draw collision indicator */
1970 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1971 gdk_draw_point(drawing->pixmap,
1972 drawing->gc,
1973 x,
1974 y+(height/2)-3);
1975 hashed_process_data->x.middle_marked = TRUE;
1976 }
44ffb95f 1977#endif //0
67f72973 1978 /* Jump */
1979 } else {
1980 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1981 /* Draw the line */
1982 if(dodraw) {
1983 PropertiesLine prop_line;
1984 prop_line.line_width = STATE_LINE_WIDTH;
1985 prop_line.style = GDK_LINE_SOLID;
1986 prop_line.y = MIDDLE;
1987 if(hashed_process_data->type == RV_RESOURCE_CPU)
1988 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
1989 else if(hashed_process_data->type == RV_RESOURCE_IRQ)
1990 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
0305fe77 1991 else if(hashed_process_data->type == RV_RESOURCE_SOFT_IRQ)
1992 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[process_info->id]);
38726a78 1993 else if(hashed_process_data->type == RV_RESOURCE_TRAP)
1994 trap_set_line_color(&prop_line, &ts->trap_states[process_info->id]);
67f72973 1995 else if(hashed_process_data->type == RV_RESOURCE_BDEV) {
1996 gint devcode_gint = process_info->id;
1997 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1998 // the lookup may return null; bdev_set_line_color must act appropriately
1999 bdev_set_line_color(&prop_line, bdev);
44ffb95f 2000 }
67f72973 2001
2002 draw_line((void*)&prop_line, (void*)&draw_context);
2003 }
44ffb95f 2004
67f72973 2005 /* become the last x position */
2006 if(likely(x != hashed_process_data->x.middle)) {
2007 hashed_process_data->x.middle = x;
2008 /* but don't use the pixel */
2009 hashed_process_data->x.middle_used = FALSE;
44ffb95f 2010
67f72973 2011 /* Calculate the next good time */
2012 convert_pixels_to_time(width, x+1, time_window,
2013 &hashed_process_data->next_good_time);
44ffb95f 2014 }
2015 }
67f72973 2016 }
44ffb95f 2017 }
9e01e6d4 2018}
2019
2020int before_chunk(void *hook_data, void *call_data)
2021{
2022 EventsRequest *events_request = (EventsRequest*)hook_data;
2023 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2024 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
2025#if 0
67f72973 2026 /* Deactivate sort */
9e01e6d4 2027 gtk_tree_sortable_set_sort_column_id(
2028 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2029 TRACE_COLUMN,
2030 GTK_SORT_ASCENDING);
2031#endif //0
2032 drawing_chunk_begin(events_request, tss);
2033
2034 return 0;
2035}
2036
d389bc8d 2037/* before_request
2038 *
2039 * This gets executed just before an events request is executed
2040 */
2041
9e01e6d4 2042int before_request(void *hook_data, void *call_data)
2043{
2044 EventsRequest *events_request = (EventsRequest*)hook_data;
2045 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2046
2047 drawing_data_request_begin(events_request, tss);
2048
2049 return 0;
2050}
2051
2052
2053/*
2054 * after request is necessary in addition of after chunk in order to draw
2055 * lines until the end of the screen. after chunk just draws lines until
2056 * the last event.
2057 *
2058 * for each process
2059 * draw closing line
2060 * expose
2061 */
2062int after_request(void *hook_data, void *call_data)
2063{
67f72973 2064 guint i;
2065 EventsRequest *events_request = (EventsRequest*)hook_data;
2066 ControlFlowData *resourceview_data = events_request->viewer_data;
2067 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2068
2069 ProcessList *process_list = resourceview_data->process_list;
2070 LttTime end_time = events_request->end_time;
2071
2072 ClosureData closure_data;
2073 closure_data.events_request = (EventsRequest*)hook_data;
2074 closure_data.tss = tss;
2075 closure_data.end_time = end_time;
2076
2077 TimeWindow time_window =
2078 lttvwindow_get_time_window(resourceview_data->tab);
2079 guint width = resourceview_data->drawing->width;
2080 convert_time_to_pixels(
2081 time_window,
2082 end_time,
2083 width,
2084 &closure_data.x_end);
2085
2086
2087 /* Draw last items */
2088 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2089 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2090 (void*)&closure_data);
2091 }
2092
2093 /* Request expose */
2094 drawing_request_expose(events_request, tss, end_time);
9e01e6d4 2095 return 0;
2096}
2097
2098/*
2099 * for each process
2100 * draw closing line
2101 * expose
2102 */
2103int after_chunk(void *hook_data, void *call_data)
2104{
2105 EventsRequest *events_request = (EventsRequest*)hook_data;
67f72973 2106 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2107 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2108 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
2109 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2110 LttTime end_time;
2111
67f72973 2112 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2113 guint i;
2114 LttvTraceset *traceset = tsc->ts;
2115 guint nb_trace = lttv_traceset_number(traceset);
2116
2117 /* Only execute when called for the first trace's events request */
2118 if(!process_list->current_hash_data) return;
2119
2120 for(i = 0 ; i < nb_trace ; i++) {
2121 g_free(process_list->current_hash_data[i]);
2122 }
2123 g_free(process_list->current_hash_data);
2124 process_list->current_hash_data = NULL;
2125
2126 if(tfc != NULL)
2127 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2128 else /* end of traceset, or position now out of request : end */
2129 end_time = events_request->end_time;
2130
2131 ClosureData closure_data;
2132 closure_data.events_request = (EventsRequest*)hook_data;
2133 closure_data.tss = tss;
2134 closure_data.end_time = end_time;
2135
2136 TimeWindow time_window =
67f72973 2137 lttvwindow_get_time_window(resourceview_data->tab);
2138 guint width = resourceview_data->drawing->width;
9e01e6d4 2139 convert_time_to_pixels(
2140 time_window,
2141 end_time,
2142 width,
2143 &closure_data.x_end);
2144
2145 /* Draw last items */
67f72973 2146 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2147 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2148 (void*)&closure_data);
67f72973 2149 }
9e01e6d4 2150#if 0
2151 /* Reactivate sort */
2152 gtk_tree_sortable_set_sort_column_id(
67f72973 2153 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2154 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2155 GTK_SORT_ASCENDING);
2156
67f72973 2157 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2158 /* Request a full expose : drawing scrambled */
67f72973 2159 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2160#endif //0
2161 /* Request expose (updates damages zone also) */
2162 drawing_request_expose(events_request, tss, end_time);
2163
2164 return 0;
2165}
2166
2167/* after_statedump_end
2168 *
2169 * @param hook_data ControlFlowData structure of the viewer.
2170 * @param call_data Event context.
2171 *
2172 * This function adds items to be drawn in a queue for each process.
2173 *
2174 */
2175int before_statedump_end(void *hook_data, void *call_data)
2176{
67f72973 2177 gint i;
2178
dd455fb8 2179 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2180 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 2181 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2182
2183 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2184
2185 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2186
2187 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2188
2189 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
67f72973 2190 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2191
2192 LttEvent *e;
2193 e = ltt_tracefile_get_event(tfc->tf);
2194
67f72973 2195 LttvFilter *filter = resourceview_data->filter;
9e01e6d4 2196 if(filter != NULL && filter->head != NULL)
2197 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2198 tfc->t_context->t,tfc,NULL,NULL))
2199 return FALSE;
2200
2201 LttTime evtime = ltt_event_time(e);
2202
2203 ClosureData closure_data;
2204 closure_data.events_request = events_request;
2205 closure_data.tss = tss;
2206 closure_data.end_time = evtime;
2207
2208 TimeWindow time_window =
67f72973 2209 lttvwindow_get_time_window(resourceview_data->tab);
2210 guint width = resourceview_data->drawing->width;
9e01e6d4 2211 convert_time_to_pixels(
2212 time_window,
2213 evtime,
2214 width,
2215 &closure_data.x_end);
2216
2217 /* Draw last items */
67f72973 2218
2219 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2220 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2221 (void*)&closure_data);
67f72973 2222 }
9e01e6d4 2223#if 0
2224 /* Reactivate sort */
2225 gtk_tree_sortable_set_sort_column_id(
67f72973 2226 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2227 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2228 GTK_SORT_ASCENDING);
2229
67f72973 2230 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2231 /* Request a full expose : drawing scrambled */
67f72973 2232 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2233#endif //0
2234 /* Request expose (updates damages zone also) */
2235 drawing_request_expose(events_request, tss, evtime);
2236
2237 return 0;
2238}
This page took 0.131223 seconds and 4 git commands to generate.