remove files unneeded for lttv
[lttv.git] / 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>
43ed82b5 59#include <inttypes.h>
9e01e6d4 60
61//#include <pango/pango.h>
62
63#include <ltt/event.h>
64#include <ltt/time.h>
9e01e6d4 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
3d27be8a 82#define STATE_LINE_WIDTH 6
9e01e6d4 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{
67f72973 95 ControlFlowData *resourceview_data = (ControlFlowData *)hook_data;
9e01e6d4 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
43ed82b5 624int before_execmode_hook_irq(void *hook_data, void *call_data);
625int before_execmode_hook_soft_irq(void *hook_data, void *call_data);
626int before_execmode_hook_trap(void *hook_data, void *call_data);
627
58a9b31b 628/* before_execmode_hook
629 *
630 * This function basically draw lines and icons. Two types of lines are drawn :
631 * one small (3 pixels?) representing the state of the process and the second
632 * type is thicker (10 pixels?) representing on which CPU a process is running
633 * (and this only in running state).
634 *
635 * Extremums of the lines :
636 * x_min : time of the last event context for this process kept in memory.
637 * x_max : time of the current event.
638 * y : middle of the process in the process list. The process is found in the
639 * list, therefore is it's position in pixels.
640 *
641 * The choice of lines'color is defined by the context of the last event for this
642 * process.
643 */
9e01e6d4 644
598026ba 645int before_execmode_hook(void *hook_data, void *call_data)
646{
dd455fb8 647 LttvTraceHook *th = (LttvTraceHook*)hook_data;
648 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 649 ControlFlowData *resourceview_data = events_request->viewer_data;
598026ba 650
651 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
652
653 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
654 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
655
656 LttEvent *e;
657 e = ltt_tracefile_get_event(tfc->tf);
658
659 LttTime evtime = ltt_event_time(e);
660
8743690d 661 before_execmode_hook_irq(hook_data, call_data);
0305fe77 662 before_execmode_hook_soft_irq(hook_data, call_data);
38726a78 663 before_execmode_hook_trap(hook_data, call_data);
8743690d 664
598026ba 665 /* we are in a execmode, before the state update. We must draw the
666 * items corresponding to the state before it changes : now is the right
667 * time to do it.
668 */
669 /* For the pid */
598026ba 670 guint cpu = tfs->cpu;
67f72973 671
598026ba 672 guint trace_num = ts->parent.index;
673 LttvProcessState *process = ts->running_process[cpu];
674 g_assert(process != NULL);
675
598026ba 676 /* Well, the process_out existed : we must get it in the process hash
677 * or add it, and draw its items.
678 */
679 /* Add process to process list (if not present) */
680 guint pl_height = 0;
681 HashedResourceData *hashed_process_data = NULL;
67f72973 682 ProcessList *process_list = resourceview_data->process_list;
683
598026ba 684 LttTime birth = process->creation_time;
685
686 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
687 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
688 } else {
67f72973 689 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
690
598026ba 691 /* Set the current process */
692 process_list->current_hash_data[trace_num][process->cpu] =
693 hashed_process_data;
694 }
695
696 /* Now, the process is in the state hash and our own process hash.
697 * We definitely can draw the items related to the ending state.
698 */
699
700 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
701 evtime) > 0))
702 {
703 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
704 TimeWindow time_window =
67f72973 705 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 706
707#ifdef EXTRA_CHECK
708 if(ltt_time_compare(evtime, time_window.start_time) == -1
709 || ltt_time_compare(evtime, time_window.end_time) == 1)
710 return;
711#endif //EXTRA_CHECK
67f72973 712 Drawing_t *drawing = resourceview_data->drawing;
598026ba 713 guint width = drawing->width;
714 guint x;
715 convert_time_to_pixels(
716 time_window,
717 evtime,
718 width,
719 &x);
720
721 /* Draw collision indicator */
722 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
723 gdk_draw_point(hashed_process_data->pixmap,
724 drawing->gc,
725 x,
726 COLLISION_POSITION(hashed_process_data->height));
727 hashed_process_data->x.middle_marked = TRUE;
728 }
d3d99fde 729 }
730 else {
598026ba 731 TimeWindow time_window =
67f72973 732 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 733
734#ifdef EXTRA_CHECK
735 if(ltt_time_compare(evtime, time_window.start_time) == -1
736 || ltt_time_compare(evtime, time_window.end_time) == 1)
737 return;
738#endif //EXTRA_CHECK
67f72973 739 Drawing_t *drawing = resourceview_data->drawing;
598026ba 740 guint width = drawing->width;
741 guint x;
742
743 convert_time_to_pixels(
744 time_window,
745 evtime,
746 width,
747 &x);
748
749
750 /* Jump over draw if we are at the same x position */
751 if(unlikely(x == hashed_process_data->x.middle &&
752 hashed_process_data->x.middle_used))
753 {
754 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
755 /* Draw collision indicator */
756 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
757 gdk_draw_point(hashed_process_data->pixmap,
758 drawing->gc,
759 x,
760 COLLISION_POSITION(hashed_process_data->height));
761 hashed_process_data->x.middle_marked = TRUE;
762 }
763 /* jump */
d3d99fde 764 }
765 else {
598026ba 766
767 DrawContext draw_context;
768 /* Now create the drawing context that will be used to draw
769 * items related to the last state. */
770 draw_context.drawable = hashed_process_data->pixmap;
771 draw_context.gc = drawing->gc;
772 draw_context.pango_layout = drawing->pango_layout;
773 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
774 draw_context.drawinfo.end.x = x;
775
776 draw_context.drawinfo.y.over = 1;
777 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
778 draw_context.drawinfo.y.under = hashed_process_data->height;
779
780 draw_context.drawinfo.start.offset.over = 0;
781 draw_context.drawinfo.start.offset.middle = 0;
782 draw_context.drawinfo.start.offset.under = 0;
783 draw_context.drawinfo.end.offset.over = 0;
784 draw_context.drawinfo.end.offset.middle = 0;
785 draw_context.drawinfo.end.offset.under = 0;
786
787 {
788 /* Draw the line */
789 PropertiesLine prop_line;
d3d99fde 790 prop_line.line_width = STATE_LINE_WIDTH;
791 prop_line.style = GDK_LINE_SOLID;
792 prop_line.y = MIDDLE;
793 cpu_set_line_color(&prop_line, tfs->cpu_state);
598026ba 794 draw_line((void*)&prop_line, (void*)&draw_context);
795 }
796 /* become the last x position */
797 hashed_process_data->x.middle = x;
798 hashed_process_data->x.middle_used = TRUE;
799 hashed_process_data->x.middle_marked = FALSE;
800
801 /* Calculate the next good time */
802 convert_pixels_to_time(width, x+1, time_window,
803 &hashed_process_data->next_good_time);
804 }
805 }
806
807 return 0;
808}
9e01e6d4 809
8743690d 810int before_execmode_hook_irq(void *hook_data, void *call_data)
811{
dd455fb8 812 LttvTraceHook *th = (LttvTraceHook*)hook_data;
813 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 814 ControlFlowData *resourceview_data = events_request->viewer_data;
8743690d 815
816 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
817
818 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
819 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 820 struct marker_info *minfo;
8743690d 821
822 LttEvent *e;
823 e = ltt_tracefile_get_event(tfc->tf);
824
825 LttTime evtime = ltt_event_time(e);
826
ca5c76ed 827 LttTrace *trace = tfc->t_context->t;
828
8743690d 829 /* we are in a execmode, before the state update. We must draw the
830 * items corresponding to the state before it changes : now is the right
831 * time to do it.
832 */
833 /* For the pid */
834
835 guint64 irq;
836 guint cpu = tfs->cpu;
837
750eb11a 838 /*
839 * Check for LTT_CHANNEL_KERNEL channel name and event ID
840 * corresponding to LTT_EVENT_IRQ_ENTRY or LTT_EVENT_IRQ_EXIT.
841 */
842 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
843 return 0;
844 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
845 g_assert(minfo != NULL);
846 if (minfo->name == LTT_EVENT_IRQ_ENTRY) {
ca5c76ed 847 irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
750eb11a 848 } else if (minfo->name == LTT_EVENT_IRQ_EXIT) {
55a35306 849 gint len = ts->cpu_states[cpu].irq_stack->len;
850 if(len) {
851 irq = g_array_index(ts->cpu_states[cpu].irq_stack, gint, len-1);
852 }
853 else {
854 return 0;
855 }
750eb11a 856 } else
8743690d 857 return 0;
8743690d 858
8743690d 859 guint trace_num = ts->parent.index;
860
8743690d 861 /* Well, the process_out existed : we must get it in the process hash
862 * or add it, and draw its items.
863 */
864 /* Add process to process list (if not present) */
865 guint pl_height = 0;
866 HashedResourceData *hashed_process_data = NULL;
67f72973 867 ProcessList *process_list = resourceview_data->process_list;
868
869 hashed_process_data = resourcelist_obtain_irq(resourceview_data, trace_num, irq);
671c625b 870 // TODO: fix this, it's ugly and slow:
871 GQuark name;
872 {
873 gchar *str;
43ed82b5 874 str = g_strdup_printf("IRQ %" PRIu64 " [%s]", irq, (char*)g_quark_to_string(ts->irq_names[irq]));
671c625b 875 name = g_quark_from_string(str);
876 g_free(str);
877 }
878 gtk_tree_store_set(resourceview_data->process_list->list_store, &hashed_process_data->y_iter, NAME_COLUMN, g_quark_to_string(name), -1);
8743690d 879
880 /* Now, the process is in the state hash and our own process hash.
881 * We definitely can draw the items related to the ending state.
882 */
883
884 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
885 evtime) > 0))
886 {
887 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
888 TimeWindow time_window =
67f72973 889 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 890
891#ifdef EXTRA_CHECK
892 if(ltt_time_compare(evtime, time_window.start_time) == -1
893 || ltt_time_compare(evtime, time_window.end_time) == 1)
894 return;
895#endif //EXTRA_CHECK
67f72973 896 Drawing_t *drawing = resourceview_data->drawing;
8743690d 897 guint width = drawing->width;
898 guint x;
899 convert_time_to_pixels(
900 time_window,
901 evtime,
902 width,
903 &x);
904
905 /* Draw collision indicator */
906 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
907 gdk_draw_point(hashed_process_data->pixmap,
908 drawing->gc,
909 x,
910 COLLISION_POSITION(hashed_process_data->height));
911 hashed_process_data->x.middle_marked = TRUE;
912 }
913 }
914 else {
915 TimeWindow time_window =
67f72973 916 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 917
918#ifdef EXTRA_CHECK
919 if(ltt_time_compare(evtime, time_window.start_time) == -1
920 || ltt_time_compare(evtime, time_window.end_time) == 1)
921 return;
922#endif //EXTRA_CHECK
67f72973 923 Drawing_t *drawing = resourceview_data->drawing;
8743690d 924 guint width = drawing->width;
925 guint x;
926
927 convert_time_to_pixels(
928 time_window,
929 evtime,
930 width,
931 &x);
932
933
934 /* Jump over draw if we are at the same x position */
935 if(unlikely(x == hashed_process_data->x.middle &&
936 hashed_process_data->x.middle_used))
937 {
938 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
939 /* Draw collision indicator */
940 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
941 gdk_draw_point(hashed_process_data->pixmap,
942 drawing->gc,
943 x,
944 COLLISION_POSITION(hashed_process_data->height));
945 hashed_process_data->x.middle_marked = TRUE;
946 }
947 /* jump */
948 }
949 else {
950
951 DrawContext draw_context;
952 /* Now create the drawing context that will be used to draw
953 * items related to the last state. */
954 draw_context.drawable = hashed_process_data->pixmap;
955 draw_context.gc = drawing->gc;
956 draw_context.pango_layout = drawing->pango_layout;
957 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
958 draw_context.drawinfo.end.x = x;
959
960 draw_context.drawinfo.y.over = 1;
961 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
962 draw_context.drawinfo.y.under = hashed_process_data->height;
963
964 draw_context.drawinfo.start.offset.over = 0;
965 draw_context.drawinfo.start.offset.middle = 0;
966 draw_context.drawinfo.start.offset.under = 0;
967 draw_context.drawinfo.end.offset.over = 0;
968 draw_context.drawinfo.end.offset.middle = 0;
969 draw_context.drawinfo.end.offset.under = 0;
970
971 {
972 /* Draw the line */
973 PropertiesLine prop_line;
974 prop_line.line_width = STATE_LINE_WIDTH;
975 prop_line.style = GDK_LINE_SOLID;
976 prop_line.y = MIDDLE;
977 irq_set_line_color(&prop_line, &ts->irq_states[irq]);
978 draw_line((void*)&prop_line, (void*)&draw_context);
979 }
980 /* become the last x position */
981 hashed_process_data->x.middle = x;
982 hashed_process_data->x.middle_used = TRUE;
983 hashed_process_data->x.middle_marked = FALSE;
984
985 /* Calculate the next good time */
986 convert_pixels_to_time(width, x+1, time_window,
987 &hashed_process_data->next_good_time);
988 }
989 }
990
991 return 0;
992}
993
0305fe77 994int before_execmode_hook_soft_irq(void *hook_data, void *call_data)
995{
996 LttvTraceHook *th = (LttvTraceHook*)hook_data;
997 EventsRequest *events_request = (EventsRequest*)th->hook_data;
998 ControlFlowData *resourceview_data = events_request->viewer_data;
999
1000 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1001
1002 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1003 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 1004 struct marker_info *minfo;
0305fe77 1005
1006 LttEvent *e;
1007 e = ltt_tracefile_get_event(tfc->tf);
1008
1009 LttTime evtime = ltt_event_time(e);
1010
1011 LttTrace *trace = tfc->t_context->t;
1012
1013 /* we are in a execmode, before the state update. We must draw the
1014 * items corresponding to the state before it changes : now is the right
1015 * time to do it.
1016 */
1017 /* For the pid */
1018
1019 guint64 softirq;
1020 guint cpu = tfs->cpu;
1021
750eb11a 1022 /*
1023 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1024 * corresponding to LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY
1025 * or LTT_EVENT_SOFT_IRQ_EXIT.
1026 */
1027 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1028 return 0;
1029 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1030 g_assert(minfo != NULL);
1031 if (minfo->name == LTT_EVENT_SOFT_IRQ_RAISE
1032 || minfo->name == LTT_EVENT_SOFT_IRQ_ENTRY) {
0305fe77 1033 softirq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
750eb11a 1034 } else if (minfo->name == LTT_EVENT_SOFT_IRQ_EXIT) {
16e4e89b 1035 gint len = ts->cpu_states[cpu].softirq_stack->len;
1036 if(len) {
1037 softirq = g_array_index(ts->cpu_states[cpu].softirq_stack, gint, len-1);
1038 }
1039 else {
1040 return 0;
1041 }
750eb11a 1042 } else
0305fe77 1043 return 0;
0305fe77 1044
1045 guint trace_num = ts->parent.index;
1046
1047 /* Well, the process_out existed : we must get it in the process hash
1048 * or add it, and draw its items.
1049 */
1050 /* Add process to process list (if not present) */
1051 guint pl_height = 0;
1052 HashedResourceData *hashed_process_data = NULL;
1053 ProcessList *process_list = resourceview_data->process_list;
1054
1055 hashed_process_data = resourcelist_obtain_soft_irq(resourceview_data, trace_num, softirq);
1056
1057 /* Now, the process is in the state hash and our own process hash.
1058 * We definitely can draw the items related to the ending state.
1059 */
1060
1061 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1062 evtime) > 0))
1063 {
1064 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1065 TimeWindow time_window =
1066 lttvwindow_get_time_window(resourceview_data->tab);
1067
1068#ifdef EXTRA_CHECK
1069 if(ltt_time_compare(evtime, time_window.start_time) == -1
1070 || ltt_time_compare(evtime, time_window.end_time) == 1)
1071 return;
1072#endif //EXTRA_CHECK
1073 Drawing_t *drawing = resourceview_data->drawing;
1074 guint width = drawing->width;
1075 guint x;
1076 convert_time_to_pixels(
1077 time_window,
1078 evtime,
1079 width,
1080 &x);
1081
1082 /* Draw collision indicator */
1083 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1084 gdk_draw_point(hashed_process_data->pixmap,
1085 drawing->gc,
1086 x,
1087 COLLISION_POSITION(hashed_process_data->height));
1088 hashed_process_data->x.middle_marked = TRUE;
1089 }
1090 }
1091 else {
1092 TimeWindow time_window =
1093 lttvwindow_get_time_window(resourceview_data->tab);
1094
1095#ifdef EXTRA_CHECK
1096 if(ltt_time_compare(evtime, time_window.start_time) == -1
1097 || ltt_time_compare(evtime, time_window.end_time) == 1)
1098 return;
1099#endif //EXTRA_CHECK
1100 Drawing_t *drawing = resourceview_data->drawing;
1101 guint width = drawing->width;
1102 guint x;
1103
1104 convert_time_to_pixels(
1105 time_window,
1106 evtime,
1107 width,
1108 &x);
1109
1110
1111 /* Jump over draw if we are at the same x position */
1112 if(unlikely(x == hashed_process_data->x.middle &&
1113 hashed_process_data->x.middle_used))
1114 {
1115 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1116 /* Draw collision indicator */
1117 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1118 gdk_draw_point(hashed_process_data->pixmap,
1119 drawing->gc,
1120 x,
1121 COLLISION_POSITION(hashed_process_data->height));
1122 hashed_process_data->x.middle_marked = TRUE;
1123 }
1124 /* jump */
1125 }
1126 else {
1127
1128 DrawContext draw_context;
1129 /* Now create the drawing context that will be used to draw
1130 * items related to the last state. */
1131 draw_context.drawable = hashed_process_data->pixmap;
1132 draw_context.gc = drawing->gc;
1133 draw_context.pango_layout = drawing->pango_layout;
1134 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1135 draw_context.drawinfo.end.x = x;
1136
1137 draw_context.drawinfo.y.over = 1;
1138 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1139 draw_context.drawinfo.y.under = hashed_process_data->height;
1140
1141 draw_context.drawinfo.start.offset.over = 0;
1142 draw_context.drawinfo.start.offset.middle = 0;
1143 draw_context.drawinfo.start.offset.under = 0;
1144 draw_context.drawinfo.end.offset.over = 0;
1145 draw_context.drawinfo.end.offset.middle = 0;
1146 draw_context.drawinfo.end.offset.under = 0;
1147
1148 {
1149 /* Draw the line */
1150 PropertiesLine prop_line;
1151 prop_line.line_width = STATE_LINE_WIDTH;
1152 prop_line.style = GDK_LINE_SOLID;
1153 prop_line.y = MIDDLE;
1154 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[softirq]);
1155 draw_line((void*)&prop_line, (void*)&draw_context);
1156 }
1157 /* become the last x position */
1158 hashed_process_data->x.middle = x;
1159 hashed_process_data->x.middle_used = TRUE;
1160 hashed_process_data->x.middle_marked = FALSE;
1161
1162 /* Calculate the next good time */
1163 convert_pixels_to_time(width, x+1, time_window,
1164 &hashed_process_data->next_good_time);
1165 }
1166 }
1167
1168 return 0;
1169}
1170
38726a78 1171int before_execmode_hook_trap(void *hook_data, void *call_data)
1172{
1173 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1174 EventsRequest *events_request = (EventsRequest*)th->hook_data;
1175 ControlFlowData *resourceview_data = events_request->viewer_data;
1176
1177 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1178
1179 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1180 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
750eb11a 1181 struct marker_info *minfo;
38726a78 1182
1183 LttEvent *e;
1184 e = ltt_tracefile_get_event(tfc->tf);
1185
1186 LttTime evtime = ltt_event_time(e);
1187
1188 LttTrace *trace = tfc->t_context->t;
1189
1190 /* we are in a execmode, before the state update. We must draw the
1191 * items corresponding to the state before it changes : now is the right
1192 * time to do it.
1193 */
1194 /* For the pid */
1195
1196 guint64 trap;
1197 guint cpu = tfs->cpu;
1198
750eb11a 1199 /*
1200 * Check for LTT_CHANNEL_KERNEL channel name and event ID
4e9bbbd3 1201 * corresponding to LTT_EVENT_TRAP/PAGE_FAULT_ENTRY or
1202 * LTT_EVENT_TRAP/PAGE_FAULT_EXIT.
750eb11a 1203 */
1204 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1205 return 0;
1206 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1207 g_assert(minfo != NULL);
4e9bbbd3 1208 if (minfo->name == LTT_EVENT_TRAP_ENTRY
1209 || minfo->name == LTT_EVENT_PAGE_FAULT_ENTRY
1210 || minfo->name == LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY) {
38726a78 1211 trap = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
4e9bbbd3 1212 } else if (minfo->name == LTT_EVENT_TRAP_EXIT
1213 || minfo->name == LTT_EVENT_PAGE_FAULT_EXIT
1214 || minfo->name == LTT_EVENT_PAGE_FAULT_NOSEM_EXIT) {
16e4e89b 1215 gint len = ts->cpu_states[cpu].trap_stack->len;
1216 if(len) {
1217 trap = g_array_index(ts->cpu_states[cpu].trap_stack, gint, len-1);
1218 }
1219 else {
1220 return 0;
1221 }
750eb11a 1222 } else
38726a78 1223 return 0;
38726a78 1224
1225 guint trace_num = ts->parent.index;
1226
1227 /* Well, the process_out existed : we must get it in the process hash
1228 * or add it, and draw its items.
1229 */
1230 /* Add process to process list (if not present) */
1231 guint pl_height = 0;
1232 HashedResourceData *hashed_process_data = NULL;
1233 ProcessList *process_list = resourceview_data->process_list;
1234
1235 hashed_process_data = resourcelist_obtain_trap(resourceview_data, trace_num, trap);
1236
1237 /* Now, the process is in the state hash and our own process hash.
1238 * We definitely can draw the items related to the ending state.
1239 */
1240
1241 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1242 evtime) > 0))
1243 {
1244 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
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 convert_time_to_pixels(
1257 time_window,
1258 evtime,
1259 width,
1260 &x);
1261
1262 /* Draw collision indicator */
1263 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1264 gdk_draw_point(hashed_process_data->pixmap,
1265 drawing->gc,
1266 x,
1267 COLLISION_POSITION(hashed_process_data->height));
1268 hashed_process_data->x.middle_marked = TRUE;
1269 }
1270 }
1271 else {
1272 TimeWindow time_window =
1273 lttvwindow_get_time_window(resourceview_data->tab);
1274
1275#ifdef EXTRA_CHECK
1276 if(ltt_time_compare(evtime, time_window.start_time) == -1
1277 || ltt_time_compare(evtime, time_window.end_time) == 1)
1278 return;
1279#endif //EXTRA_CHECK
1280 Drawing_t *drawing = resourceview_data->drawing;
1281 guint width = drawing->width;
1282 guint x;
1283
1284 convert_time_to_pixels(
1285 time_window,
1286 evtime,
1287 width,
1288 &x);
1289
1290
1291 /* Jump over draw if we are at the same x position */
1292 if(unlikely(x == hashed_process_data->x.middle &&
1293 hashed_process_data->x.middle_used))
1294 {
1295 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1296 /* Draw collision indicator */
1297 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1298 gdk_draw_point(hashed_process_data->pixmap,
1299 drawing->gc,
1300 x,
1301 COLLISION_POSITION(hashed_process_data->height));
1302 hashed_process_data->x.middle_marked = TRUE;
1303 }
1304 /* jump */
1305 }
1306 else {
1307
1308 DrawContext draw_context;
1309 /* Now create the drawing context that will be used to draw
1310 * items related to the last state. */
1311 draw_context.drawable = hashed_process_data->pixmap;
1312 draw_context.gc = drawing->gc;
1313 draw_context.pango_layout = drawing->pango_layout;
1314 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1315 draw_context.drawinfo.end.x = x;
1316
1317 draw_context.drawinfo.y.over = 1;
1318 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1319 draw_context.drawinfo.y.under = hashed_process_data->height;
1320
1321 draw_context.drawinfo.start.offset.over = 0;
1322 draw_context.drawinfo.start.offset.middle = 0;
1323 draw_context.drawinfo.start.offset.under = 0;
1324 draw_context.drawinfo.end.offset.over = 0;
1325 draw_context.drawinfo.end.offset.middle = 0;
1326 draw_context.drawinfo.end.offset.under = 0;
1327
1328 {
1329 /* Draw the line */
1330 PropertiesLine prop_line;
1331 prop_line.line_width = STATE_LINE_WIDTH;
1332 prop_line.style = GDK_LINE_SOLID;
1333 prop_line.y = MIDDLE;
1334 trap_set_line_color(&prop_line, &ts->trap_states[trap]);
1335 draw_line((void*)&prop_line, (void*)&draw_context);
1336 }
1337 /* become the last x position */
1338 hashed_process_data->x.middle = x;
1339 hashed_process_data->x.middle_used = TRUE;
1340 hashed_process_data->x.middle_marked = FALSE;
1341
1342 /* Calculate the next good time */
1343 convert_pixels_to_time(width, x+1, time_window,
1344 &hashed_process_data->next_good_time);
1345 }
1346 }
1347
1348 return 0;
1349}
1350
0305fe77 1351
20d16f82 1352int before_bdev_event_hook(void *hook_data, void *call_data)
1353{
dd455fb8 1354 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1355 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 1356 ControlFlowData *resourceview_data = events_request->viewer_data;
20d16f82 1357
1358 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1359
1360 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1361 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1362
1363 LttEvent *e;
1364 e = ltt_tracefile_get_event(tfc->tf);
1365
1366 LttTime evtime = ltt_event_time(e);
1367
20d16f82 1368 /* we are in a execmode, before the state update. We must draw the
1369 * items corresponding to the state before it changes : now is the right
1370 * time to do it.
1371 */
1372 /* For the pid */
1373
1374 guint cpu = tfs->cpu;
ca5c76ed 1375 guint8 major = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1376 guint8 minor = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
1377 guint oper = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
20d16f82 1378 gint devcode_gint = MKDEV(major,minor);
1379
20d16f82 1380 guint trace_num = ts->parent.index;
1381
1382 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
23e59a12 1383 /* the result of the lookup might be NULL. that's ok, the rest of the function
1384 should understand it was not found and that its state is unknown */
20d16f82 1385
20d16f82 1386 /* Well, the process_out existed : we must get it in the process hash
1387 * or add it, and draw its items.
1388 */
1389 /* Add process to process list (if not present) */
1390 guint pl_height = 0;
1391 HashedResourceData *hashed_process_data = NULL;
67f72973 1392 ProcessList *process_list = resourceview_data->process_list;
20d16f82 1393// LttTime birth = process->creation_time;
1394
1395// if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1396// hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1397// } else {
67f72973 1398 hashed_process_data = resourcelist_obtain_bdev(resourceview_data, trace_num, devcode_gint);
1399 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
20d16f82 1400// hashed_process_data = processlist_get_process_data(process_list,
1401// pid,
1402// process->cpu,
1403// &birth,
1404// trace_num);
67f72973 1405//
20d16f82 1406 /* Set the current process */
1407// process_list->current_hash_data[trace_num][process->cpu] =
1408// hashed_process_data;
1409// }
1410
1411 /* Now, the process is in the state hash and our own process hash.
1412 * We definitely can draw the items related to the ending state.
1413 */
1414
1415 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1416 evtime) > 0))
1417 {
1418 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
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 convert_time_to_pixels(
1431 time_window,
1432 evtime,
1433 width,
1434 &x);
1435
1436 /* Draw collision indicator */
1437 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1438 gdk_draw_point(hashed_process_data->pixmap,
1439 drawing->gc,
1440 x,
1441 COLLISION_POSITION(hashed_process_data->height));
1442 hashed_process_data->x.middle_marked = TRUE;
1443 }
1444 }
1445 else {
1446 TimeWindow time_window =
67f72973 1447 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1448
1449#ifdef EXTRA_CHECK
1450 if(ltt_time_compare(evtime, time_window.start_time) == -1
1451 || ltt_time_compare(evtime, time_window.end_time) == 1)
1452 return;
1453#endif //EXTRA_CHECK
67f72973 1454 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1455 guint width = drawing->width;
1456 guint x;
1457
1458 convert_time_to_pixels(
1459 time_window,
1460 evtime,
1461 width,
1462 &x);
1463
1464
1465 /* Jump over draw if we are at the same x position */
1466 if(unlikely(x == hashed_process_data->x.middle &&
1467 hashed_process_data->x.middle_used))
1468 {
1469 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1470 /* Draw collision indicator */
1471 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1472 gdk_draw_point(hashed_process_data->pixmap,
1473 drawing->gc,
1474 x,
1475 COLLISION_POSITION(hashed_process_data->height));
1476 hashed_process_data->x.middle_marked = TRUE;
1477 }
1478 /* jump */
1479 }
1480 else {
1481
1482 DrawContext draw_context;
1483 /* Now create the drawing context that will be used to draw
1484 * items related to the last state. */
1485 draw_context.drawable = hashed_process_data->pixmap;
1486 draw_context.gc = drawing->gc;
1487 draw_context.pango_layout = drawing->pango_layout;
1488 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1489 draw_context.drawinfo.end.x = x;
1490
1491 draw_context.drawinfo.y.over = 1;
1492 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1493 draw_context.drawinfo.y.under = hashed_process_data->height;
1494
1495 draw_context.drawinfo.start.offset.over = 0;
1496 draw_context.drawinfo.start.offset.middle = 0;
1497 draw_context.drawinfo.start.offset.under = 0;
1498 draw_context.drawinfo.end.offset.over = 0;
1499 draw_context.drawinfo.end.offset.middle = 0;
1500 draw_context.drawinfo.end.offset.under = 0;
1501
1502 {
1503 /* Draw the line */
1504 PropertiesLine prop_line;
1505 prop_line.line_width = STATE_LINE_WIDTH;
1506 prop_line.style = GDK_LINE_SOLID;
1507 prop_line.y = MIDDLE;
1508 bdev_set_line_color(&prop_line, bdev);
1509 draw_line((void*)&prop_line, (void*)&draw_context);
1510 }
1511 /* become the last x position */
1512 hashed_process_data->x.middle = x;
1513 hashed_process_data->x.middle_used = TRUE;
1514 hashed_process_data->x.middle_marked = FALSE;
1515
1516 /* Calculate the next good time */
1517 convert_pixels_to_time(width, x+1, time_window,
1518 &hashed_process_data->next_good_time);
1519 }
1520 }
1521
1522 return 0;
1523}
1524
9e01e6d4 1525gint update_time_window_hook(void *hook_data, void *call_data)
1526{
67f72973 1527 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1528 Drawing_t *drawing = resourceview_data->drawing;
1529 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1530
1531 const TimeWindowNotifyData *time_window_nofify_data =
1532 ((const TimeWindowNotifyData *)call_data);
1533
1534 TimeWindow *old_time_window =
1535 time_window_nofify_data->old_time_window;
1536 TimeWindow *new_time_window =
1537 time_window_nofify_data->new_time_window;
1538
1539 /* Update the ruler */
67f72973 1540 drawing_update_ruler(resourceview_data->drawing,
9e01e6d4 1541 new_time_window);
1542
1543
1544 /* Two cases : zoom in/out or scrolling */
1545
1546 /* In order to make sure we can reuse the old drawing, the scale must
1547 * be the same and the new time interval being partly located in the
1548 * currently shown time interval. (reuse is only for scrolling)
1549 */
1550
1551 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1552 old_time_window->start_time.tv_sec,
1553 old_time_window->start_time.tv_nsec,
1554 old_time_window->time_width.tv_sec,
1555 old_time_window->time_width.tv_nsec);
1556
1557 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1558 new_time_window->start_time.tv_sec,
1559 new_time_window->start_time.tv_nsec,
1560 new_time_window->time_width.tv_sec,
1561 new_time_window->time_width.tv_nsec);
1562
1563 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1564 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1565 {
1566 /* Same scale (scrolling) */
1567 g_info("scrolling");
1568 LttTime *ns = &new_time_window->start_time;
1569 LttTime *nw = &new_time_window->time_width;
1570 LttTime *os = &old_time_window->start_time;
1571 LttTime *ow = &old_time_window->time_width;
1572 LttTime old_end = old_time_window->end_time;
1573 LttTime new_end = new_time_window->end_time;
1574 //if(ns<os+w<ns+w)
1575 //if(ns<os+w && os+w<ns+w)
1576 //if(ns<old_end && os<ns)
1577 if(ltt_time_compare(*ns, old_end) == -1
1578 && ltt_time_compare(*os, *ns) == -1)
1579 {
1580 g_info("scrolling near right");
1581 /* Scroll right, keep right part of the screen */
1582 guint x = 0;
67f72973 1583 guint width = resourceview_data->drawing->width;
9e01e6d4 1584 convert_time_to_pixels(
1585 *old_time_window,
1586 *ns,
1587 width,
1588 &x);
1589
1590 /* Copy old data to new location */
1591 copy_pixmap_region(process_list,
1592 NULL,
67f72973 1593 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1594 NULL,
1595 x, 0,
1596 0, 0,
67f72973 1597 resourceview_data->drawing->width-x+SAFETY, -1);
9e01e6d4 1598
1599 if(drawing->damage_begin == drawing->damage_end)
67f72973 1600 drawing->damage_begin = resourceview_data->drawing->width-x;
9e01e6d4 1601 else
1602 drawing->damage_begin = 0;
1603
67f72973 1604 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1605
1606 /* Clear the data request background, but not SAFETY */
1607 rectangle_pixmap(process_list,
67f72973 1608 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1609 TRUE,
1610 drawing->damage_begin+SAFETY, 0,
1611 drawing->damage_end - drawing->damage_begin, // do not overlap
1612 -1);
1613 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1614
1615 /* Get new data for the rest. */
67f72973 1616 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1617 drawing->damage_begin, 0,
1618 drawing->damage_end - drawing->damage_begin,
67f72973 1619 resourceview_data->drawing->height);
9e01e6d4 1620 } else {
9e01e6d4 1621 if(ltt_time_compare(*ns,*os) == -1
1622 && ltt_time_compare(*os,new_end) == -1)
1623 {
1624 g_info("scrolling near left");
1625 /* Scroll left, keep left part of the screen */
1626 guint x = 0;
67f72973 1627 guint width = resourceview_data->drawing->width;
9e01e6d4 1628 convert_time_to_pixels(
1629 *new_time_window,
1630 *os,
1631 width,
1632 &x);
1633
1634 /* Copy old data to new location */
1635 copy_pixmap_region (process_list,
1636 NULL,
67f72973 1637 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1638 NULL,
1639 0, 0,
1640 x, 0,
1641 -1, -1);
1642
1643 if(drawing->damage_begin == drawing->damage_end)
1644 drawing->damage_end = x;
1645 else
1646 drawing->damage_end =
67f72973 1647 resourceview_data->drawing->width;
9e01e6d4 1648
1649 drawing->damage_begin = 0;
1650
1651 rectangle_pixmap (process_list,
67f72973 1652 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1653 TRUE,
1654 drawing->damage_begin, 0,
1655 drawing->damage_end - drawing->damage_begin, // do not overlap
1656 -1);
1657
1658 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1659
1660 /* Get new data for the rest. */
67f72973 1661 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1662 drawing->damage_begin, 0,
1663 drawing->damage_end - drawing->damage_begin,
67f72973 1664 resourceview_data->drawing->height);
9e01e6d4 1665
1666 } else {
1667 if(ltt_time_compare(*ns,*os) == 0)
1668 {
1669 g_info("not scrolling");
1670 } else {
1671 g_info("scrolling far");
1672 /* Cannot reuse any part of the screen : far jump */
1673
1674
1675 rectangle_pixmap (process_list,
67f72973 1676 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1677 TRUE,
1678 0, 0,
67f72973 1679 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1680 -1);
1681
9e01e6d4 1682 gtk_widget_queue_draw(drawing->drawing_area);
1683
1684 drawing->damage_begin = 0;
67f72973 1685 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1686
67f72973 1687 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1688 0, 0,
67f72973 1689 resourceview_data->drawing->width,
1690 resourceview_data->drawing->height);
9e01e6d4 1691
1692 }
1693 }
1694 }
1695 } else {
1696 /* Different scale (zoom) */
1697 g_info("zoom");
1698
1699 rectangle_pixmap (process_list,
67f72973 1700 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1701 TRUE,
1702 0, 0,
67f72973 1703 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1704 -1);
1705
9e01e6d4 1706 gtk_widget_queue_draw(drawing->drawing_area);
1707
1708 drawing->damage_begin = 0;
67f72973 1709 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1710
67f72973 1711 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1712 0, 0,
67f72973 1713 resourceview_data->drawing->width,
1714 resourceview_data->drawing->height);
9e01e6d4 1715 }
1716
1717 /* Update directly when scrolling */
67f72973 1718 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1719 TRUE);
1720
1721 return 0;
1722}
1723
1724gint traceset_notify(void *hook_data, void *call_data)
1725{
67f72973 1726 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1727 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1728
1729 if(unlikely(drawing->gc == NULL)) {
1730 return FALSE;
1731 }
1732 if(drawing->dotted_gc == NULL) {
1733 return FALSE;
1734 }
1735
67f72973 1736 drawing_clear(resourceview_data->drawing);
1737 processlist_clear(resourceview_data->process_list);
9e01e6d4 1738 gtk_widget_set_size_request(
67f72973 1739 resourceview_data->drawing->drawing_area,
1740 -1, processlist_get_height(resourceview_data->process_list));
1741 redraw_notify(resourceview_data, NULL);
9e01e6d4 1742
67f72973 1743 request_background_data(resourceview_data);
9e01e6d4 1744
1745 return FALSE;
1746}
1747
1748gint redraw_notify(void *hook_data, void *call_data)
1749{
67f72973 1750 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1751 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1752 GtkWidget *widget = drawing->drawing_area;
1753
1754 drawing->damage_begin = 0;
1755 drawing->damage_end = drawing->width;
1756
1757 /* fun feature, to be separated someday... */
67f72973 1758 drawing_clear(resourceview_data->drawing);
1759 processlist_clear(resourceview_data->process_list);
9e01e6d4 1760 gtk_widget_set_size_request(
67f72973 1761 resourceview_data->drawing->drawing_area,
1762 -1, processlist_get_height(resourceview_data->process_list));
9e01e6d4 1763 // Clear the images
67f72973 1764 rectangle_pixmap (resourceview_data->process_list,
9e01e6d4 1765 widget->style->black_gc,
1766 TRUE,
1767 0, 0,
1768 drawing->alloc_width,
1769 -1);
1770
1771 gtk_widget_queue_draw(drawing->drawing_area);
1772
1773 if(drawing->damage_begin < drawing->damage_end)
1774 {
1775 drawing_data_request(drawing,
1776 drawing->damage_begin,
1777 0,
1778 drawing->damage_end-drawing->damage_begin,
1779 drawing->height);
1780 }
1781
9e01e6d4 1782 return FALSE;
1783
1784}
1785
1786
1787gint continue_notify(void *hook_data, void *call_data)
1788{
67f72973 1789 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1790 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1791
1792 if(drawing->damage_begin < drawing->damage_end)
1793 {
1794 drawing_data_request(drawing,
1795 drawing->damage_begin,
1796 0,
1797 drawing->damage_end-drawing->damage_begin,
1798 drawing->height);
1799 }
1800
1801 return FALSE;
1802}
1803
1804
1805gint update_current_time_hook(void *hook_data, void *call_data)
1806{
67f72973 1807 ControlFlowData *resourceview_data = (ControlFlowData*)hook_data;
1808 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1809
1810 LttTime current_time = *((LttTime*)call_data);
1811
1812 TimeWindow time_window =
67f72973 1813 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 1814
1815 LttTime time_begin = time_window.start_time;
1816 LttTime width = time_window.time_width;
1817 LttTime half_width;
1818 {
1819 guint64 time_ll = ltt_time_to_uint64(width);
1820 time_ll = time_ll >> 1; /* divide by two */
1821 half_width = ltt_time_from_uint64(time_ll);
1822 }
1823 LttTime time_end = ltt_time_add(time_begin, width);
1824
1825 LttvTracesetContext * tsc =
67f72973 1826 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 1827
1828 LttTime trace_start = tsc->time_span.start_time;
1829 LttTime trace_end = tsc->time_span.end_time;
1830
1831 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1832 current_time.tv_nsec);
9e01e6d4 1833
1834 /* If current time is inside time interval, just move the highlight
1835 * bar */
1836
1837 /* Else, we have to change the time interval. We have to tell it
1838 * to the main window. */
1839 /* The time interval change will take care of placing the current
1840 * time at the center of the visible area, or nearest possible if we are
1841 * at one end of the trace. */
1842
1843
1844 if(ltt_time_compare(current_time, time_begin) < 0)
1845 {
1846 TimeWindow new_time_window;
1847
1848 if(ltt_time_compare(current_time,
1849 ltt_time_add(trace_start,half_width)) < 0)
1850 time_begin = trace_start;
1851 else
1852 time_begin = ltt_time_sub(current_time,half_width);
1853
1854 new_time_window.start_time = time_begin;
1855 new_time_window.time_width = width;
1856 new_time_window.time_width_double = ltt_time_to_double(width);
1857 new_time_window.end_time = ltt_time_add(time_begin, width);
1858
67f72973 1859 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1860 }
1861 else if(ltt_time_compare(current_time, time_end) > 0)
1862 {
1863 TimeWindow new_time_window;
1864
1865 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1866 time_begin = ltt_time_sub(trace_end,width);
1867 else
1868 time_begin = ltt_time_sub(current_time,half_width);
1869
1870 new_time_window.start_time = time_begin;
1871 new_time_window.time_width = width;
1872 new_time_window.time_width_double = ltt_time_to_double(width);
1873 new_time_window.end_time = ltt_time_add(time_begin, width);
1874
67f72973 1875 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1876
1877 }
67f72973 1878 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 1879
1880 /* Update directly when scrolling */
67f72973 1881 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1882 TRUE);
1883
1884 return 0;
1885}
1886
1887typedef struct _ClosureData {
1888 EventsRequest *events_request;
1889 LttvTracesetState *tss;
1890 LttTime end_time;
1891 guint x_end;
1892} ClosureData;
1893
58a9b31b 1894/* Draw line until end of the screen */
9e01e6d4 1895
1896void draw_closure(gpointer key, gpointer value, gpointer user_data)
1897{
67f72973 1898 ResourceUniqueNumeric *process_info = (ResourceUniqueNumeric*)key;
44ffb95f 1899 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1900 ClosureData *closure_data = (ClosureData*)user_data;
1901
1902 EventsRequest *events_request = closure_data->events_request;
67f72973 1903 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 1904
1905 LttvTracesetState *tss = closure_data->tss;
1906 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1907
1908 LttTime evtime = closure_data->end_time;
1909
1910 gboolean dodraw = TRUE;
1911
67f72973 1912 if(hashed_process_data->type == RV_RESOURCE_MACHINE)
1913 return;
1914
44ffb95f 1915 {
1916 /* For the process */
1917 /* First, check if the current process is in the state computation
1918 * process list. If it is there, that means we must add it right now and
1919 * draw items from the beginning of the read for it. If it is not
1920 * present, it's a new process and it was not present : it will
1921 * be added after the state update. */
1922#ifdef EXTRA_CHECK
1923 g_assert(lttv_traceset_number(tsc->ts) > 0);
1924#endif //EXTRA_CHECK
1925 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1926 LttvTraceState *ts = (LttvTraceState*)tc;
1927
67f72973 1928 /* Only draw for processes that are currently in the trace states */
44ffb95f 1929
67f72973 1930 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 1931#ifdef EXTRA_CHECK
67f72973 1932 /* Should be alike when background info is ready */
1933 if(resourceview_data->background_info_waiting==0)
44ffb95f 1934 g_assert(ltt_time_compare(process->creation_time,
1935 process_info->birth) == 0);
1936#endif //EXTRA_CHECK
1937
67f72973 1938 /* Now, the process is in the state hash and our own process hash.
1939 * We definitely can draw the items related to the ending state.
1940 */
1941
1942 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1943 evtime) <= 0))
1944 {
1945 TimeWindow time_window =
1946 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 1947
1948#ifdef EXTRA_CHECK
67f72973 1949 if(ltt_time_compare(evtime, time_window.start_time) == -1
1950 || ltt_time_compare(evtime, time_window.end_time) == 1)
1951 return;
44ffb95f 1952#endif //EXTRA_CHECK
67f72973 1953 Drawing_t *drawing = resourceview_data->drawing;
1954 guint width = drawing->width;
1955
1956 guint x = closure_data->x_end;
1957
1958 DrawContext draw_context;
1959
1960 /* Now create the drawing context that will be used to draw
1961 * items related to the last state. */
1962 draw_context.drawable = hashed_process_data->pixmap;
1963 draw_context.gc = drawing->gc;
1964 draw_context.pango_layout = drawing->pango_layout;
1965 draw_context.drawinfo.end.x = x;
1966
1967 draw_context.drawinfo.y.over = 1;
1968 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1969 draw_context.drawinfo.y.under = hashed_process_data->height;
1970
1971 draw_context.drawinfo.start.offset.over = 0;
1972 draw_context.drawinfo.start.offset.middle = 0;
1973 draw_context.drawinfo.start.offset.under = 0;
1974 draw_context.drawinfo.end.offset.over = 0;
1975 draw_context.drawinfo.end.offset.middle = 0;
1976 draw_context.drawinfo.end.offset.under = 0;
44ffb95f 1977#if 0
67f72973 1978 /* Jump over draw if we are at the same x position */
1979 if(x == hashed_process_data->x.over)
1980 {
1981 /* jump */
1982 } else {
1983 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1984 /* Draw the line */
1985 PropertiesLine prop_line = prepare_execmode_line(process);
1986 draw_line((void*)&prop_line, (void*)&draw_context);
44ffb95f 1987
67f72973 1988 hashed_process_data->x.over = x;
1989 }
44ffb95f 1990#endif //0
1991
67f72973 1992 if(unlikely(x == hashed_process_data->x.middle &&
1993 hashed_process_data->x.middle_used)) {
44ffb95f 1994#if 0 /* do not mark closure : not missing information */
67f72973 1995 if(hashed_process_data->x.middle_marked == FALSE) {
1996 /* Draw collision indicator */
1997 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1998 gdk_draw_point(drawing->pixmap,
1999 drawing->gc,
2000 x,
2001 y+(height/2)-3);
2002 hashed_process_data->x.middle_marked = TRUE;
2003 }
44ffb95f 2004#endif //0
67f72973 2005 /* Jump */
2006 } else {
2007 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2008 /* Draw the line */
2009 if(dodraw) {
2010 PropertiesLine prop_line;
2011 prop_line.line_width = STATE_LINE_WIDTH;
2012 prop_line.style = GDK_LINE_SOLID;
2013 prop_line.y = MIDDLE;
2014 if(hashed_process_data->type == RV_RESOURCE_CPU)
2015 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
2016 else if(hashed_process_data->type == RV_RESOURCE_IRQ)
2017 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
0305fe77 2018 else if(hashed_process_data->type == RV_RESOURCE_SOFT_IRQ)
2019 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[process_info->id]);
38726a78 2020 else if(hashed_process_data->type == RV_RESOURCE_TRAP)
2021 trap_set_line_color(&prop_line, &ts->trap_states[process_info->id]);
67f72973 2022 else if(hashed_process_data->type == RV_RESOURCE_BDEV) {
2023 gint devcode_gint = process_info->id;
2024 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
2025 // the lookup may return null; bdev_set_line_color must act appropriately
2026 bdev_set_line_color(&prop_line, bdev);
44ffb95f 2027 }
67f72973 2028
2029 draw_line((void*)&prop_line, (void*)&draw_context);
2030 }
44ffb95f 2031
67f72973 2032 /* become the last x position */
2033 if(likely(x != hashed_process_data->x.middle)) {
2034 hashed_process_data->x.middle = x;
2035 /* but don't use the pixel */
2036 hashed_process_data->x.middle_used = FALSE;
44ffb95f 2037
67f72973 2038 /* Calculate the next good time */
2039 convert_pixels_to_time(width, x+1, time_window,
2040 &hashed_process_data->next_good_time);
44ffb95f 2041 }
2042 }
67f72973 2043 }
44ffb95f 2044 }
9e01e6d4 2045}
2046
2047int before_chunk(void *hook_data, void *call_data)
2048{
2049 EventsRequest *events_request = (EventsRequest*)hook_data;
2050 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2051 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
2052#if 0
67f72973 2053 /* Deactivate sort */
9e01e6d4 2054 gtk_tree_sortable_set_sort_column_id(
2055 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2056 TRACE_COLUMN,
2057 GTK_SORT_ASCENDING);
2058#endif //0
2059 drawing_chunk_begin(events_request, tss);
2060
2061 return 0;
2062}
2063
d389bc8d 2064/* before_request
2065 *
2066 * This gets executed just before an events request is executed
2067 */
2068
9e01e6d4 2069int before_request(void *hook_data, void *call_data)
2070{
2071 EventsRequest *events_request = (EventsRequest*)hook_data;
2072 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2073
2074 drawing_data_request_begin(events_request, tss);
2075
2076 return 0;
2077}
2078
2079
2080/*
2081 * after request is necessary in addition of after chunk in order to draw
2082 * lines until the end of the screen. after chunk just draws lines until
2083 * the last event.
2084 *
2085 * for each process
2086 * draw closing line
2087 * expose
2088 */
2089int after_request(void *hook_data, void *call_data)
2090{
67f72973 2091 guint i;
2092 EventsRequest *events_request = (EventsRequest*)hook_data;
2093 ControlFlowData *resourceview_data = events_request->viewer_data;
2094 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2095
2096 ProcessList *process_list = resourceview_data->process_list;
2097 LttTime end_time = events_request->end_time;
2098
2099 ClosureData closure_data;
2100 closure_data.events_request = (EventsRequest*)hook_data;
2101 closure_data.tss = tss;
2102 closure_data.end_time = end_time;
2103
2104 TimeWindow time_window =
2105 lttvwindow_get_time_window(resourceview_data->tab);
2106 guint width = resourceview_data->drawing->width;
2107 convert_time_to_pixels(
2108 time_window,
2109 end_time,
2110 width,
2111 &closure_data.x_end);
2112
2113
2114 /* Draw last items */
2115 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2116 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2117 (void*)&closure_data);
2118 }
2119
2120 /* Request expose */
2121 drawing_request_expose(events_request, tss, end_time);
9e01e6d4 2122 return 0;
2123}
2124
2125/*
2126 * for each process
2127 * draw closing line
2128 * expose
2129 */
2130int after_chunk(void *hook_data, void *call_data)
2131{
2132 EventsRequest *events_request = (EventsRequest*)hook_data;
67f72973 2133 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2134 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2135 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
2136 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2137 LttTime end_time;
2138
67f72973 2139 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2140 guint i;
2141 LttvTraceset *traceset = tsc->ts;
2142 guint nb_trace = lttv_traceset_number(traceset);
2143
2144 /* Only execute when called for the first trace's events request */
43ed82b5 2145 if(!process_list->current_hash_data)
2146 return 0;
9e01e6d4 2147
2148 for(i = 0 ; i < nb_trace ; i++) {
2149 g_free(process_list->current_hash_data[i]);
2150 }
2151 g_free(process_list->current_hash_data);
2152 process_list->current_hash_data = NULL;
2153
2154 if(tfc != NULL)
2155 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2156 else /* end of traceset, or position now out of request : end */
2157 end_time = events_request->end_time;
2158
2159 ClosureData closure_data;
2160 closure_data.events_request = (EventsRequest*)hook_data;
2161 closure_data.tss = tss;
2162 closure_data.end_time = end_time;
2163
2164 TimeWindow time_window =
67f72973 2165 lttvwindow_get_time_window(resourceview_data->tab);
2166 guint width = resourceview_data->drawing->width;
9e01e6d4 2167 convert_time_to_pixels(
2168 time_window,
2169 end_time,
2170 width,
2171 &closure_data.x_end);
2172
2173 /* Draw last items */
67f72973 2174 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2175 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2176 (void*)&closure_data);
67f72973 2177 }
9e01e6d4 2178#if 0
2179 /* Reactivate sort */
2180 gtk_tree_sortable_set_sort_column_id(
67f72973 2181 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2182 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2183 GTK_SORT_ASCENDING);
2184
67f72973 2185 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2186 /* Request a full expose : drawing scrambled */
67f72973 2187 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2188#endif //0
2189 /* Request expose (updates damages zone also) */
2190 drawing_request_expose(events_request, tss, end_time);
2191
2192 return 0;
2193}
2194
2195/* after_statedump_end
2196 *
2197 * @param hook_data ControlFlowData structure of the viewer.
2198 * @param call_data Event context.
2199 *
2200 * This function adds items to be drawn in a queue for each process.
2201 *
2202 */
2203int before_statedump_end(void *hook_data, void *call_data)
2204{
67f72973 2205 gint i;
2206
dd455fb8 2207 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2208 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 2209 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2210
2211 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2212
2213 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2214
2215 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2216
2217 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
67f72973 2218 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2219
2220 LttEvent *e;
2221 e = ltt_tracefile_get_event(tfc->tf);
2222
67f72973 2223 LttvFilter *filter = resourceview_data->filter;
9e01e6d4 2224 if(filter != NULL && filter->head != NULL)
2225 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2226 tfc->t_context->t,tfc,NULL,NULL))
2227 return FALSE;
2228
2229 LttTime evtime = ltt_event_time(e);
2230
2231 ClosureData closure_data;
2232 closure_data.events_request = events_request;
2233 closure_data.tss = tss;
2234 closure_data.end_time = evtime;
2235
2236 TimeWindow time_window =
67f72973 2237 lttvwindow_get_time_window(resourceview_data->tab);
2238 guint width = resourceview_data->drawing->width;
9e01e6d4 2239 convert_time_to_pixels(
2240 time_window,
2241 evtime,
2242 width,
2243 &closure_data.x_end);
2244
2245 /* Draw last items */
67f72973 2246
2247 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2248 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2249 (void*)&closure_data);
67f72973 2250 }
9e01e6d4 2251#if 0
2252 /* Reactivate sort */
2253 gtk_tree_sortable_set_sort_column_id(
67f72973 2254 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2255 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2256 GTK_SORT_ASCENDING);
2257
67f72973 2258 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2259 /* Request a full expose : drawing scrambled */
67f72973 2260 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2261#endif //0
2262 /* Request expose (updates damages zone also) */
2263 drawing_request_expose(events_request, tss, evtime);
2264
2265 return 0;
2266}
This page took 0.131908 seconds and 4 git commands to generate.