sync frequency of all traces with the first loaded
[lttv.git] / ltt / branches / poly / lttv / modules / gui / resourceview / eventhooks.c
CommitLineData
9e01e6d4 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
25/* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
31 *
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
34 *
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
51
52//#define PANGO_ENABLE_BACKEND
53#include <gtk/gtk.h>
54#include <gdk/gdk.h>
55#include <glib.h>
56#include <assert.h>
57#include <string.h>
58#include <stdio.h>
59
60//#include <pango/pango.h>
61
62#include <ltt/event.h>
63#include <ltt/time.h>
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
81#define STATE_LINE_WIDTH 4
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 }
d3d99fde 284 else if(present_state == LTTV_CPU_TRAP) {
285 prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
201fcc15 286 } else {
287 prop_line->color = drawing_colors_cpu[COL_CPU_UNKNOWN];
d3d99fde 288 }
598026ba 289}
9e01e6d4 290
8743690d 291static void irq_set_line_color(PropertiesLine *prop_line, LttvIRQState *s)
292{
1b171947 293 GQuark present_state;
294 if(s->mode_stack->len == 0)
295 present_state = LTTV_IRQ_UNKNOWN;
296 else
297 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
8743690d 298
1b171947 299 if(present_state == LTTV_IRQ_IDLE) {
8743690d 300 prop_line->color = drawing_colors_irq[COL_IRQ_IDLE];
301 }
302 else if(present_state == LTTV_IRQ_BUSY) {
303 prop_line->color = drawing_colors_irq[COL_IRQ_BUSY];
304 }
1b171947 305 else {
306 prop_line->color = drawing_colors_irq[COL_IRQ_UNKNOWN];
307 }
8743690d 308}
309
0305fe77 310static void soft_irq_set_line_color(PropertiesLine *prop_line, LttvSoftIRQState *s)
311{
312 GQuark present_state;
313 if(s->running == 0)
314 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_IDLE];
315 else
316 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_BUSY];
317}
318
20d16f82 319static void bdev_set_line_color(PropertiesLine *prop_line, LttvBdevState *s)
320{
1b171947 321 GQuark present_state;
23e59a12 322 if(s == 0 || s->mode_stack->len == 0)
1b171947 323 present_state = LTTV_BDEV_UNKNOWN;
324 else
325 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
20d16f82 326
1b171947 327 if(present_state == LTTV_BDEV_IDLE) {
20d16f82 328 prop_line->color = drawing_colors_bdev[COL_BDEV_IDLE];
329 }
330 else if(present_state == LTTV_BDEV_BUSY_READING) {
331 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_READING];
332 }
333 else if(present_state == LTTV_BDEV_BUSY_WRITING) {
334 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_WRITING];
335 }
1b171947 336 else {
337 prop_line->color = drawing_colors_bdev[COL_BDEV_UNKNOWN];
338 }
20d16f82 339}
340
9e01e6d4 341/* before_schedchange_hook
342 *
343 * This function basically draw lines and icons. Two types of lines are drawn :
344 * one small (3 pixels?) representing the state of the process and the second
345 * type is thicker (10 pixels?) representing on which CPU a process is running
346 * (and this only in running state).
347 *
348 * Extremums of the lines :
349 * x_min : time of the last event context for this process kept in memory.
350 * x_max : time of the current event.
351 * y : middle of the process in the process list. The process is found in the
352 * list, therefore is it's position in pixels.
353 *
354 * The choice of lines'color is defined by the context of the last event for this
355 * process.
356 */
357
358
359int before_schedchange_hook(void *hook_data, void *call_data)
360{
dd455fb8 361 LttvTraceHook *th = (LttvTraceHook*)hook_data;
362 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 363 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 364
365 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
366
367 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
368 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
369
370 LttEvent *e;
371 e = ltt_tracefile_get_event(tfc->tf);
372 gint target_pid_saved = tfc->target_pid;
373
374 LttTime evtime = ltt_event_time(e);
67f72973 375 LttvFilter *filter = resourceview_data->filter;
58a9b31b 376
9e01e6d4 377 /* we are in a schedchange, before the state update. We must draw the
378 * items corresponding to the state before it changes : now is the right
379 * time to do it.
380 */
381
382 guint pid_out;
383 guint pid_in;
ca5c76ed 384 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
385 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
67f72973 386// TODO: can't we reenable this? pmf
44ffb95f 387// if(pid_in != 0 && pid_out != 0) {
388// /* not a transition to/from idle */
389// return 0;
390// }
c4e6f4dc 391
9e01e6d4 392 tfc->target_pid = pid_out;
58a9b31b 393
67f72973 394 guint cpu = tfs->cpu;
9e01e6d4 395
67f72973 396 guint trace_num = ts->parent.index;
397 /* Add process to process list (if not present) */
398 guint pl_height = 0;
399 HashedResourceData *hashed_process_data = NULL;
400 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 401
67f72973 402 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
403
404 /* Now, the process is in the state hash and our own process hash.
405 * We definitely can draw the items related to the ending state.
406 */
407
408 if(ltt_time_compare(hashed_process_data->next_good_time,
409 evtime) > 0)
410 {
411 if(hashed_process_data->x.middle_marked == FALSE) {
412
413 TimeWindow time_window =
414 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 415#ifdef EXTRA_CHECK
67f72973 416 if(ltt_time_compare(evtime, time_window.start_time) == -1
417 || ltt_time_compare(evtime, time_window.end_time) == 1)
418 return;
9e01e6d4 419#endif //EXTRA_CHECK
67f72973 420 Drawing_t *drawing = resourceview_data->drawing;
421 guint width = drawing->width;
422 guint x;
423 convert_time_to_pixels(
424 time_window,
425 evtime,
426 width,
427 &x);
428
429 /* Draw collision indicator */
430 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
431 gdk_draw_point(hashed_process_data->pixmap,
432 drawing->gc,
433 x,
434 COLLISION_POSITION(hashed_process_data->height));
435 hashed_process_data->x.middle_marked = TRUE;
436 }
437 } else {
438 TimeWindow time_window =
439 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 440#ifdef EXTRA_CHECK
67f72973 441 if(ltt_time_compare(evtime, time_window.start_time) == -1
9e01e6d4 442 || ltt_time_compare(evtime, time_window.end_time) == 1)
67f72973 443 return;
9e01e6d4 444#endif //EXTRA_CHECK
67f72973 445 Drawing_t *drawing = resourceview_data->drawing;
446 guint width = drawing->width;
447 guint x;
448 convert_time_to_pixels(
449 time_window,
450 evtime,
451 width,
452 &x);
9e01e6d4 453
67f72973 454 /* Jump over draw if we are at the same x position */
455 if(x == hashed_process_data->x.middle &&
456 hashed_process_data->x.middle_used)
457 {
458 if(hashed_process_data->x.middle_marked == FALSE) {
459 /* Draw collision indicator */
460 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
461 gdk_draw_point(hashed_process_data->pixmap,
462 drawing->gc,
463 x,
464 COLLISION_POSITION(hashed_process_data->height));
465 hashed_process_data->x.middle_marked = TRUE;
58a9b31b 466 }
67f72973 467 /* jump */
468 } else {
469 DrawContext draw_context;
9e01e6d4 470
67f72973 471 /* Now create the drawing context that will be used to draw
472 * items related to the last state. */
473 draw_context.drawable = hashed_process_data->pixmap;
474 draw_context.gc = drawing->gc;
475 draw_context.pango_layout = drawing->pango_layout;
476 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
477 draw_context.drawinfo.end.x = x;
9e01e6d4 478
67f72973 479 draw_context.drawinfo.y.over = 1;
480 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
481 draw_context.drawinfo.y.under = hashed_process_data->height;
9e01e6d4 482
67f72973 483 draw_context.drawinfo.start.offset.over = 0;
484 draw_context.drawinfo.start.offset.middle = 0;
485 draw_context.drawinfo.start.offset.under = 0;
486 draw_context.drawinfo.end.offset.over = 0;
487 draw_context.drawinfo.end.offset.middle = 0;
488 draw_context.drawinfo.end.offset.under = 0;
9e01e6d4 489
67f72973 490 {
491 /* Draw the line */
492 //PropertiesLine prop_line = prepare_s_e_line(process);
493 PropertiesLine prop_line;
494 prop_line.line_width = STATE_LINE_WIDTH;
495 prop_line.style = GDK_LINE_SOLID;
496 prop_line.y = MIDDLE;
497 cpu_set_line_color(&prop_line, tfs->cpu_state);
498 draw_line((void*)&prop_line, (void*)&draw_context);
9e01e6d4 499
67f72973 500 }
501 /* become the last x position */
502 hashed_process_data->x.middle = x;
503 hashed_process_data->x.middle_used = TRUE;
504 hashed_process_data->x.middle_marked = FALSE;
9e01e6d4 505
67f72973 506 /* Calculate the next good time */
507 convert_pixels_to_time(width, x+1, time_window,
508 &hashed_process_data->next_good_time);
509 }
9e01e6d4 510 }
511
67f72973 512 return 0;
9e01e6d4 513}
514
58a9b31b 515/* after_schedchange_hook
516 *
517 * The draw after hook is called by the reading API to have a
518 * particular event drawn on the screen.
519 * @param hook_data ControlFlowData structure of the viewer.
520 * @param call_data Event context.
521 *
522 * This function adds items to be drawn in a queue for each process.
523 *
524 */
525int after_schedchange_hook(void *hook_data, void *call_data)
9e01e6d4 526{
dd455fb8 527 LttvTraceHook *th = (LttvTraceHook*)hook_data;
528 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 529 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 530 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
44ffb95f 531 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
44ffb95f 532 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
44ffb95f 533 LttEvent *e;
67f72973 534
44ffb95f 535 e = ltt_tracefile_get_event(tfc->tf);
536
67f72973 537 LttvFilter *filter = resourceview_data->filter;
44ffb95f 538 if(filter != NULL && filter->head != NULL)
539 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
540 tfc->t_context->t,tfc,NULL,NULL))
541 return FALSE;
542
543 LttTime evtime = ltt_event_time(e);
544
44ffb95f 545 /* Add process to process list (if not present) */
546 LttvProcessState *process_in;
547 LttTime birth;
548 guint pl_height = 0;
549 HashedResourceData *hashed_process_data_in = NULL;
550
67f72973 551 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 552
553 guint pid_in;
554 {
555 guint pid_out;
ca5c76ed 556 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
557 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
44ffb95f 558 }
559
560
561 /* Find process pid_in in the list... */
562 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
563 //process_in = tfs->process;
564 guint cpu = tfs->cpu;
44ffb95f 565 guint trace_num = ts->parent.index;
566 process_in = ts->running_process[cpu];
567 /* It should exist, because we are after the state update. */
568#ifdef EXTRA_CHECK
569 g_assert(process_in != NULL);
570#endif //EXTRA_CHECK
571 birth = process_in->creation_time;
572
67f72973 573 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
574 hashed_process_data_in = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
575
44ffb95f 576 /* Set the current process */
577 process_list->current_hash_data[trace_num][process_in->cpu] =
578 hashed_process_data_in;
579
580 if(ltt_time_compare(hashed_process_data_in->next_good_time,
581 evtime) <= 0)
582 {
583 TimeWindow time_window =
67f72973 584 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 585
586#ifdef EXTRA_CHECK
587 if(ltt_time_compare(evtime, time_window.start_time) == -1
588 || ltt_time_compare(evtime, time_window.end_time) == 1)
589 return;
590#endif //EXTRA_CHECK
67f72973 591 Drawing_t *drawing = resourceview_data->drawing;
44ffb95f 592 guint width = drawing->width;
593 guint new_x;
594
595 convert_time_to_pixels(
596 time_window,
597 evtime,
598 width,
599 &new_x);
600
601 if(hashed_process_data_in->x.middle != new_x) {
602 hashed_process_data_in->x.middle = new_x;
603 hashed_process_data_in->x.middle_used = FALSE;
604 hashed_process_data_in->x.middle_marked = FALSE;
605 }
606 }
58a9b31b 607 return 0;
608}
9e01e6d4 609
58a9b31b 610/* before_execmode_hook
611 *
612 * This function basically draw lines and icons. Two types of lines are drawn :
613 * one small (3 pixels?) representing the state of the process and the second
614 * type is thicker (10 pixels?) representing on which CPU a process is running
615 * (and this only in running state).
616 *
617 * Extremums of the lines :
618 * x_min : time of the last event context for this process kept in memory.
619 * x_max : time of the current event.
620 * y : middle of the process in the process list. The process is found in the
621 * list, therefore is it's position in pixels.
622 *
623 * The choice of lines'color is defined by the context of the last event for this
624 * process.
625 */
9e01e6d4 626
598026ba 627int before_execmode_hook(void *hook_data, void *call_data)
628{
dd455fb8 629 LttvTraceHook *th = (LttvTraceHook*)hook_data;
630 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 631 ControlFlowData *resourceview_data = events_request->viewer_data;
598026ba 632
633 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
634
635 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
636 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
637
638 LttEvent *e;
639 e = ltt_tracefile_get_event(tfc->tf);
640
641 LttTime evtime = ltt_event_time(e);
642
8743690d 643 before_execmode_hook_irq(hook_data, call_data);
0305fe77 644 before_execmode_hook_soft_irq(hook_data, call_data);
8743690d 645
598026ba 646 /* we are in a execmode, before the state update. We must draw the
647 * items corresponding to the state before it changes : now is the right
648 * time to do it.
649 */
650 /* For the pid */
598026ba 651 guint cpu = tfs->cpu;
67f72973 652
598026ba 653 guint trace_num = ts->parent.index;
654 LttvProcessState *process = ts->running_process[cpu];
655 g_assert(process != NULL);
656
598026ba 657 /* Well, the process_out existed : we must get it in the process hash
658 * or add it, and draw its items.
659 */
660 /* Add process to process list (if not present) */
661 guint pl_height = 0;
662 HashedResourceData *hashed_process_data = NULL;
67f72973 663 ProcessList *process_list = resourceview_data->process_list;
664
598026ba 665 LttTime birth = process->creation_time;
666
667 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
668 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
669 } else {
67f72973 670 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
671
598026ba 672 /* Set the current process */
673 process_list->current_hash_data[trace_num][process->cpu] =
674 hashed_process_data;
675 }
676
677 /* Now, the process is in the state hash and our own process hash.
678 * We definitely can draw the items related to the ending state.
679 */
680
681 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
682 evtime) > 0))
683 {
684 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
685 TimeWindow time_window =
67f72973 686 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 687
688#ifdef EXTRA_CHECK
689 if(ltt_time_compare(evtime, time_window.start_time) == -1
690 || ltt_time_compare(evtime, time_window.end_time) == 1)
691 return;
692#endif //EXTRA_CHECK
67f72973 693 Drawing_t *drawing = resourceview_data->drawing;
598026ba 694 guint width = drawing->width;
695 guint x;
696 convert_time_to_pixels(
697 time_window,
698 evtime,
699 width,
700 &x);
701
702 /* Draw collision indicator */
703 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
704 gdk_draw_point(hashed_process_data->pixmap,
705 drawing->gc,
706 x,
707 COLLISION_POSITION(hashed_process_data->height));
708 hashed_process_data->x.middle_marked = TRUE;
709 }
d3d99fde 710 }
711 else {
598026ba 712 TimeWindow time_window =
67f72973 713 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 714
715#ifdef EXTRA_CHECK
716 if(ltt_time_compare(evtime, time_window.start_time) == -1
717 || ltt_time_compare(evtime, time_window.end_time) == 1)
718 return;
719#endif //EXTRA_CHECK
67f72973 720 Drawing_t *drawing = resourceview_data->drawing;
598026ba 721 guint width = drawing->width;
722 guint x;
723
724 convert_time_to_pixels(
725 time_window,
726 evtime,
727 width,
728 &x);
729
730
731 /* Jump over draw if we are at the same x position */
732 if(unlikely(x == hashed_process_data->x.middle &&
733 hashed_process_data->x.middle_used))
734 {
735 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
736 /* Draw collision indicator */
737 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
738 gdk_draw_point(hashed_process_data->pixmap,
739 drawing->gc,
740 x,
741 COLLISION_POSITION(hashed_process_data->height));
742 hashed_process_data->x.middle_marked = TRUE;
743 }
744 /* jump */
d3d99fde 745 }
746 else {
598026ba 747
748 DrawContext draw_context;
749 /* Now create the drawing context that will be used to draw
750 * items related to the last state. */
751 draw_context.drawable = hashed_process_data->pixmap;
752 draw_context.gc = drawing->gc;
753 draw_context.pango_layout = drawing->pango_layout;
754 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
755 draw_context.drawinfo.end.x = x;
756
757 draw_context.drawinfo.y.over = 1;
758 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
759 draw_context.drawinfo.y.under = hashed_process_data->height;
760
761 draw_context.drawinfo.start.offset.over = 0;
762 draw_context.drawinfo.start.offset.middle = 0;
763 draw_context.drawinfo.start.offset.under = 0;
764 draw_context.drawinfo.end.offset.over = 0;
765 draw_context.drawinfo.end.offset.middle = 0;
766 draw_context.drawinfo.end.offset.under = 0;
767
768 {
769 /* Draw the line */
770 PropertiesLine prop_line;
d3d99fde 771 prop_line.line_width = STATE_LINE_WIDTH;
772 prop_line.style = GDK_LINE_SOLID;
773 prop_line.y = MIDDLE;
774 cpu_set_line_color(&prop_line, tfs->cpu_state);
598026ba 775 draw_line((void*)&prop_line, (void*)&draw_context);
776 }
777 /* become the last x position */
778 hashed_process_data->x.middle = x;
779 hashed_process_data->x.middle_used = TRUE;
780 hashed_process_data->x.middle_marked = FALSE;
781
782 /* Calculate the next good time */
783 convert_pixels_to_time(width, x+1, time_window,
784 &hashed_process_data->next_good_time);
785 }
786 }
787
788 return 0;
789}
9e01e6d4 790
8743690d 791int before_execmode_hook_irq(void *hook_data, void *call_data)
792{
dd455fb8 793 LttvTraceHook *th = (LttvTraceHook*)hook_data;
794 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 795 ControlFlowData *resourceview_data = events_request->viewer_data;
8743690d 796
797 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
798
799 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
800 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
801
802 LttEvent *e;
803 e = ltt_tracefile_get_event(tfc->tf);
804
805 LttTime evtime = ltt_event_time(e);
806
ca5c76ed 807 LttTrace *trace = tfc->t_context->t;
808
8743690d 809 /* we are in a execmode, before the state update. We must draw the
810 * items corresponding to the state before it changes : now is the right
811 * time to do it.
812 */
813 /* For the pid */
814
815 guint64 irq;
816 guint cpu = tfs->cpu;
817
ca5c76ed 818 guint16 ev_id_entry = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY)));
819 guint16 ev_id_exit = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT)));
820 if(ev_id_entry == e->event_id) {
821 irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
8743690d 822 }
ca5c76ed 823 else if(ev_id_exit == e->event_id) {
8743690d 824 irq = ts->cpu_states[cpu].last_irq;
825 }
826 else {
827 return 0;
828 }
829
8743690d 830 guint trace_num = ts->parent.index;
831
8743690d 832 /* Well, the process_out existed : we must get it in the process hash
833 * or add it, and draw its items.
834 */
835 /* Add process to process list (if not present) */
836 guint pl_height = 0;
837 HashedResourceData *hashed_process_data = NULL;
67f72973 838 ProcessList *process_list = resourceview_data->process_list;
839
840 hashed_process_data = resourcelist_obtain_irq(resourceview_data, trace_num, irq);
671c625b 841 // TODO: fix this, it's ugly and slow:
842 GQuark name;
843 {
844 gchar *str;
845 str = g_strdup_printf("IRQ %llu [%s]", irq, (char*)g_quark_to_string(ts->irq_names[irq]));
846 name = g_quark_from_string(str);
847 g_free(str);
848 }
849 gtk_tree_store_set(resourceview_data->process_list->list_store, &hashed_process_data->y_iter, NAME_COLUMN, g_quark_to_string(name), -1);
8743690d 850
851 /* Now, the process is in the state hash and our own process hash.
852 * We definitely can draw the items related to the ending state.
853 */
854
855 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
856 evtime) > 0))
857 {
858 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
859 TimeWindow time_window =
67f72973 860 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 861
862#ifdef EXTRA_CHECK
863 if(ltt_time_compare(evtime, time_window.start_time) == -1
864 || ltt_time_compare(evtime, time_window.end_time) == 1)
865 return;
866#endif //EXTRA_CHECK
67f72973 867 Drawing_t *drawing = resourceview_data->drawing;
8743690d 868 guint width = drawing->width;
869 guint x;
870 convert_time_to_pixels(
871 time_window,
872 evtime,
873 width,
874 &x);
875
876 /* Draw collision indicator */
877 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
878 gdk_draw_point(hashed_process_data->pixmap,
879 drawing->gc,
880 x,
881 COLLISION_POSITION(hashed_process_data->height));
882 hashed_process_data->x.middle_marked = TRUE;
883 }
884 }
885 else {
886 TimeWindow time_window =
67f72973 887 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 888
889#ifdef EXTRA_CHECK
890 if(ltt_time_compare(evtime, time_window.start_time) == -1
891 || ltt_time_compare(evtime, time_window.end_time) == 1)
892 return;
893#endif //EXTRA_CHECK
67f72973 894 Drawing_t *drawing = resourceview_data->drawing;
8743690d 895 guint width = drawing->width;
896 guint x;
897
898 convert_time_to_pixels(
899 time_window,
900 evtime,
901 width,
902 &x);
903
904
905 /* Jump over draw if we are at the same x position */
906 if(unlikely(x == hashed_process_data->x.middle &&
907 hashed_process_data->x.middle_used))
908 {
909 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
910 /* Draw collision indicator */
911 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
912 gdk_draw_point(hashed_process_data->pixmap,
913 drawing->gc,
914 x,
915 COLLISION_POSITION(hashed_process_data->height));
916 hashed_process_data->x.middle_marked = TRUE;
917 }
918 /* jump */
919 }
920 else {
921
922 DrawContext draw_context;
923 /* Now create the drawing context that will be used to draw
924 * items related to the last state. */
925 draw_context.drawable = hashed_process_data->pixmap;
926 draw_context.gc = drawing->gc;
927 draw_context.pango_layout = drawing->pango_layout;
928 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
929 draw_context.drawinfo.end.x = x;
930
931 draw_context.drawinfo.y.over = 1;
932 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
933 draw_context.drawinfo.y.under = hashed_process_data->height;
934
935 draw_context.drawinfo.start.offset.over = 0;
936 draw_context.drawinfo.start.offset.middle = 0;
937 draw_context.drawinfo.start.offset.under = 0;
938 draw_context.drawinfo.end.offset.over = 0;
939 draw_context.drawinfo.end.offset.middle = 0;
940 draw_context.drawinfo.end.offset.under = 0;
941
942 {
943 /* Draw the line */
944 PropertiesLine prop_line;
945 prop_line.line_width = STATE_LINE_WIDTH;
946 prop_line.style = GDK_LINE_SOLID;
947 prop_line.y = MIDDLE;
948 irq_set_line_color(&prop_line, &ts->irq_states[irq]);
949 draw_line((void*)&prop_line, (void*)&draw_context);
950 }
951 /* become the last x position */
952 hashed_process_data->x.middle = x;
953 hashed_process_data->x.middle_used = TRUE;
954 hashed_process_data->x.middle_marked = FALSE;
955
956 /* Calculate the next good time */
957 convert_pixels_to_time(width, x+1, time_window,
958 &hashed_process_data->next_good_time);
959 }
960 }
961
962 return 0;
963}
964
0305fe77 965int before_execmode_hook_soft_irq(void *hook_data, void *call_data)
966{
967 LttvTraceHook *th = (LttvTraceHook*)hook_data;
968 EventsRequest *events_request = (EventsRequest*)th->hook_data;
969 ControlFlowData *resourceview_data = events_request->viewer_data;
970
971 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
972
973 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
974 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
975
976 LttEvent *e;
977 e = ltt_tracefile_get_event(tfc->tf);
978
979 LttTime evtime = ltt_event_time(e);
980
981 LttTrace *trace = tfc->t_context->t;
982
983 /* we are in a execmode, before the state update. We must draw the
984 * items corresponding to the state before it changes : now is the right
985 * time to do it.
986 */
987 /* For the pid */
988
989 guint64 softirq;
990 guint cpu = tfs->cpu;
991
992 guint16 ev_id_entry = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY)));
993 guint16 ev_id_exit = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT)));
994 if(ev_id_entry == e->event_id) {
995 softirq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
996 }
997 else if(ev_id_exit == e->event_id) {
998 softirq = ts->cpu_states[cpu].last_soft_irq;
999 }
1000 else {
1001 return 0;
1002 }
1003
1004 guint trace_num = ts->parent.index;
1005
1006 /* Well, the process_out existed : we must get it in the process hash
1007 * or add it, and draw its items.
1008 */
1009 /* Add process to process list (if not present) */
1010 guint pl_height = 0;
1011 HashedResourceData *hashed_process_data = NULL;
1012 ProcessList *process_list = resourceview_data->process_list;
1013
1014 hashed_process_data = resourcelist_obtain_soft_irq(resourceview_data, trace_num, softirq);
1015
1016 /* Now, the process is in the state hash and our own process hash.
1017 * We definitely can draw the items related to the ending state.
1018 */
1019
1020 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1021 evtime) > 0))
1022 {
1023 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1024 TimeWindow time_window =
1025 lttvwindow_get_time_window(resourceview_data->tab);
1026
1027#ifdef EXTRA_CHECK
1028 if(ltt_time_compare(evtime, time_window.start_time) == -1
1029 || ltt_time_compare(evtime, time_window.end_time) == 1)
1030 return;
1031#endif //EXTRA_CHECK
1032 Drawing_t *drawing = resourceview_data->drawing;
1033 guint width = drawing->width;
1034 guint x;
1035 convert_time_to_pixels(
1036 time_window,
1037 evtime,
1038 width,
1039 &x);
1040
1041 /* Draw collision indicator */
1042 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1043 gdk_draw_point(hashed_process_data->pixmap,
1044 drawing->gc,
1045 x,
1046 COLLISION_POSITION(hashed_process_data->height));
1047 hashed_process_data->x.middle_marked = TRUE;
1048 }
1049 }
1050 else {
1051 TimeWindow time_window =
1052 lttvwindow_get_time_window(resourceview_data->tab);
1053
1054#ifdef EXTRA_CHECK
1055 if(ltt_time_compare(evtime, time_window.start_time) == -1
1056 || ltt_time_compare(evtime, time_window.end_time) == 1)
1057 return;
1058#endif //EXTRA_CHECK
1059 Drawing_t *drawing = resourceview_data->drawing;
1060 guint width = drawing->width;
1061 guint x;
1062
1063 convert_time_to_pixels(
1064 time_window,
1065 evtime,
1066 width,
1067 &x);
1068
1069
1070 /* Jump over draw if we are at the same x position */
1071 if(unlikely(x == hashed_process_data->x.middle &&
1072 hashed_process_data->x.middle_used))
1073 {
1074 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1075 /* Draw collision indicator */
1076 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1077 gdk_draw_point(hashed_process_data->pixmap,
1078 drawing->gc,
1079 x,
1080 COLLISION_POSITION(hashed_process_data->height));
1081 hashed_process_data->x.middle_marked = TRUE;
1082 }
1083 /* jump */
1084 }
1085 else {
1086
1087 DrawContext draw_context;
1088 /* Now create the drawing context that will be used to draw
1089 * items related to the last state. */
1090 draw_context.drawable = hashed_process_data->pixmap;
1091 draw_context.gc = drawing->gc;
1092 draw_context.pango_layout = drawing->pango_layout;
1093 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1094 draw_context.drawinfo.end.x = x;
1095
1096 draw_context.drawinfo.y.over = 1;
1097 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1098 draw_context.drawinfo.y.under = hashed_process_data->height;
1099
1100 draw_context.drawinfo.start.offset.over = 0;
1101 draw_context.drawinfo.start.offset.middle = 0;
1102 draw_context.drawinfo.start.offset.under = 0;
1103 draw_context.drawinfo.end.offset.over = 0;
1104 draw_context.drawinfo.end.offset.middle = 0;
1105 draw_context.drawinfo.end.offset.under = 0;
1106
1107 {
1108 /* Draw the line */
1109 PropertiesLine prop_line;
1110 prop_line.line_width = STATE_LINE_WIDTH;
1111 prop_line.style = GDK_LINE_SOLID;
1112 prop_line.y = MIDDLE;
1113 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[softirq]);
1114 draw_line((void*)&prop_line, (void*)&draw_context);
1115 }
1116 /* become the last x position */
1117 hashed_process_data->x.middle = x;
1118 hashed_process_data->x.middle_used = TRUE;
1119 hashed_process_data->x.middle_marked = FALSE;
1120
1121 /* Calculate the next good time */
1122 convert_pixels_to_time(width, x+1, time_window,
1123 &hashed_process_data->next_good_time);
1124 }
1125 }
1126
1127 return 0;
1128}
1129
1130
20d16f82 1131int before_bdev_event_hook(void *hook_data, void *call_data)
1132{
dd455fb8 1133 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1134 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 1135 ControlFlowData *resourceview_data = events_request->viewer_data;
20d16f82 1136
1137 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1138
1139 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1140 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1141
1142 LttEvent *e;
1143 e = ltt_tracefile_get_event(tfc->tf);
1144
1145 LttTime evtime = ltt_event_time(e);
1146
20d16f82 1147 /* we are in a execmode, before the state update. We must draw the
1148 * items corresponding to the state before it changes : now is the right
1149 * time to do it.
1150 */
1151 /* For the pid */
1152
1153 guint cpu = tfs->cpu;
ca5c76ed 1154 guint8 major = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1155 guint8 minor = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
1156 guint oper = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
20d16f82 1157 gint devcode_gint = MKDEV(major,minor);
1158
20d16f82 1159 guint trace_num = ts->parent.index;
1160
1161 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
23e59a12 1162 /* the result of the lookup might be NULL. that's ok, the rest of the function
1163 should understand it was not found and that its state is unknown */
20d16f82 1164
20d16f82 1165 /* Well, the process_out existed : we must get it in the process hash
1166 * or add it, and draw its items.
1167 */
1168 /* Add process to process list (if not present) */
1169 guint pl_height = 0;
1170 HashedResourceData *hashed_process_data = NULL;
67f72973 1171 ProcessList *process_list = resourceview_data->process_list;
20d16f82 1172// LttTime birth = process->creation_time;
1173
1174// if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1175// hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1176// } else {
67f72973 1177 hashed_process_data = resourcelist_obtain_bdev(resourceview_data, trace_num, devcode_gint);
1178 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
20d16f82 1179// hashed_process_data = processlist_get_process_data(process_list,
1180// pid,
1181// process->cpu,
1182// &birth,
1183// trace_num);
67f72973 1184//
20d16f82 1185 /* Set the current process */
1186// process_list->current_hash_data[trace_num][process->cpu] =
1187// hashed_process_data;
1188// }
1189
1190 /* Now, the process is in the state hash and our own process hash.
1191 * We definitely can draw the items related to the ending state.
1192 */
1193
1194 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1195 evtime) > 0))
1196 {
1197 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1198 TimeWindow time_window =
67f72973 1199 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1200
1201#ifdef EXTRA_CHECK
1202 if(ltt_time_compare(evtime, time_window.start_time) == -1
1203 || ltt_time_compare(evtime, time_window.end_time) == 1)
1204 return;
1205#endif //EXTRA_CHECK
67f72973 1206 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1207 guint width = drawing->width;
1208 guint x;
1209 convert_time_to_pixels(
1210 time_window,
1211 evtime,
1212 width,
1213 &x);
1214
1215 /* Draw collision indicator */
1216 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1217 gdk_draw_point(hashed_process_data->pixmap,
1218 drawing->gc,
1219 x,
1220 COLLISION_POSITION(hashed_process_data->height));
1221 hashed_process_data->x.middle_marked = TRUE;
1222 }
1223 }
1224 else {
1225 TimeWindow time_window =
67f72973 1226 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1227
1228#ifdef EXTRA_CHECK
1229 if(ltt_time_compare(evtime, time_window.start_time) == -1
1230 || ltt_time_compare(evtime, time_window.end_time) == 1)
1231 return;
1232#endif //EXTRA_CHECK
67f72973 1233 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1234 guint width = drawing->width;
1235 guint x;
1236
1237 convert_time_to_pixels(
1238 time_window,
1239 evtime,
1240 width,
1241 &x);
1242
1243
1244 /* Jump over draw if we are at the same x position */
1245 if(unlikely(x == hashed_process_data->x.middle &&
1246 hashed_process_data->x.middle_used))
1247 {
1248 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1249 /* Draw collision indicator */
1250 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1251 gdk_draw_point(hashed_process_data->pixmap,
1252 drawing->gc,
1253 x,
1254 COLLISION_POSITION(hashed_process_data->height));
1255 hashed_process_data->x.middle_marked = TRUE;
1256 }
1257 /* jump */
1258 }
1259 else {
1260
1261 DrawContext draw_context;
1262 /* Now create the drawing context that will be used to draw
1263 * items related to the last state. */
1264 draw_context.drawable = hashed_process_data->pixmap;
1265 draw_context.gc = drawing->gc;
1266 draw_context.pango_layout = drawing->pango_layout;
1267 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1268 draw_context.drawinfo.end.x = x;
1269
1270 draw_context.drawinfo.y.over = 1;
1271 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1272 draw_context.drawinfo.y.under = hashed_process_data->height;
1273
1274 draw_context.drawinfo.start.offset.over = 0;
1275 draw_context.drawinfo.start.offset.middle = 0;
1276 draw_context.drawinfo.start.offset.under = 0;
1277 draw_context.drawinfo.end.offset.over = 0;
1278 draw_context.drawinfo.end.offset.middle = 0;
1279 draw_context.drawinfo.end.offset.under = 0;
1280
1281 {
1282 /* Draw the line */
1283 PropertiesLine prop_line;
1284 prop_line.line_width = STATE_LINE_WIDTH;
1285 prop_line.style = GDK_LINE_SOLID;
1286 prop_line.y = MIDDLE;
1287 bdev_set_line_color(&prop_line, bdev);
1288 draw_line((void*)&prop_line, (void*)&draw_context);
1289 }
1290 /* become the last x position */
1291 hashed_process_data->x.middle = x;
1292 hashed_process_data->x.middle_used = TRUE;
1293 hashed_process_data->x.middle_marked = FALSE;
1294
1295 /* Calculate the next good time */
1296 convert_pixels_to_time(width, x+1, time_window,
1297 &hashed_process_data->next_good_time);
1298 }
1299 }
1300
1301 return 0;
1302}
1303
9e01e6d4 1304gint update_time_window_hook(void *hook_data, void *call_data)
1305{
67f72973 1306 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1307 Drawing_t *drawing = resourceview_data->drawing;
1308 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1309
1310 const TimeWindowNotifyData *time_window_nofify_data =
1311 ((const TimeWindowNotifyData *)call_data);
1312
1313 TimeWindow *old_time_window =
1314 time_window_nofify_data->old_time_window;
1315 TimeWindow *new_time_window =
1316 time_window_nofify_data->new_time_window;
1317
1318 /* Update the ruler */
67f72973 1319 drawing_update_ruler(resourceview_data->drawing,
9e01e6d4 1320 new_time_window);
1321
1322
1323 /* Two cases : zoom in/out or scrolling */
1324
1325 /* In order to make sure we can reuse the old drawing, the scale must
1326 * be the same and the new time interval being partly located in the
1327 * currently shown time interval. (reuse is only for scrolling)
1328 */
1329
1330 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1331 old_time_window->start_time.tv_sec,
1332 old_time_window->start_time.tv_nsec,
1333 old_time_window->time_width.tv_sec,
1334 old_time_window->time_width.tv_nsec);
1335
1336 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1337 new_time_window->start_time.tv_sec,
1338 new_time_window->start_time.tv_nsec,
1339 new_time_window->time_width.tv_sec,
1340 new_time_window->time_width.tv_nsec);
1341
1342 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1343 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1344 {
1345 /* Same scale (scrolling) */
1346 g_info("scrolling");
1347 LttTime *ns = &new_time_window->start_time;
1348 LttTime *nw = &new_time_window->time_width;
1349 LttTime *os = &old_time_window->start_time;
1350 LttTime *ow = &old_time_window->time_width;
1351 LttTime old_end = old_time_window->end_time;
1352 LttTime new_end = new_time_window->end_time;
1353 //if(ns<os+w<ns+w)
1354 //if(ns<os+w && os+w<ns+w)
1355 //if(ns<old_end && os<ns)
1356 if(ltt_time_compare(*ns, old_end) == -1
1357 && ltt_time_compare(*os, *ns) == -1)
1358 {
1359 g_info("scrolling near right");
1360 /* Scroll right, keep right part of the screen */
1361 guint x = 0;
67f72973 1362 guint width = resourceview_data->drawing->width;
9e01e6d4 1363 convert_time_to_pixels(
1364 *old_time_window,
1365 *ns,
1366 width,
1367 &x);
1368
1369 /* Copy old data to new location */
1370 copy_pixmap_region(process_list,
1371 NULL,
67f72973 1372 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1373 NULL,
1374 x, 0,
1375 0, 0,
67f72973 1376 resourceview_data->drawing->width-x+SAFETY, -1);
9e01e6d4 1377
1378 if(drawing->damage_begin == drawing->damage_end)
67f72973 1379 drawing->damage_begin = resourceview_data->drawing->width-x;
9e01e6d4 1380 else
1381 drawing->damage_begin = 0;
1382
67f72973 1383 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1384
1385 /* Clear the data request background, but not SAFETY */
1386 rectangle_pixmap(process_list,
67f72973 1387 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1388 TRUE,
1389 drawing->damage_begin+SAFETY, 0,
1390 drawing->damage_end - drawing->damage_begin, // do not overlap
1391 -1);
1392 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1393
1394 /* Get new data for the rest. */
67f72973 1395 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1396 drawing->damage_begin, 0,
1397 drawing->damage_end - drawing->damage_begin,
67f72973 1398 resourceview_data->drawing->height);
9e01e6d4 1399 } else {
9e01e6d4 1400 if(ltt_time_compare(*ns,*os) == -1
1401 && ltt_time_compare(*os,new_end) == -1)
1402 {
1403 g_info("scrolling near left");
1404 /* Scroll left, keep left part of the screen */
1405 guint x = 0;
67f72973 1406 guint width = resourceview_data->drawing->width;
9e01e6d4 1407 convert_time_to_pixels(
1408 *new_time_window,
1409 *os,
1410 width,
1411 &x);
1412
1413 /* Copy old data to new location */
1414 copy_pixmap_region (process_list,
1415 NULL,
67f72973 1416 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1417 NULL,
1418 0, 0,
1419 x, 0,
1420 -1, -1);
1421
1422 if(drawing->damage_begin == drawing->damage_end)
1423 drawing->damage_end = x;
1424 else
1425 drawing->damage_end =
67f72973 1426 resourceview_data->drawing->width;
9e01e6d4 1427
1428 drawing->damage_begin = 0;
1429
1430 rectangle_pixmap (process_list,
67f72973 1431 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1432 TRUE,
1433 drawing->damage_begin, 0,
1434 drawing->damage_end - drawing->damage_begin, // do not overlap
1435 -1);
1436
1437 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1438
1439 /* Get new data for the rest. */
67f72973 1440 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1441 drawing->damage_begin, 0,
1442 drawing->damage_end - drawing->damage_begin,
67f72973 1443 resourceview_data->drawing->height);
9e01e6d4 1444
1445 } else {
1446 if(ltt_time_compare(*ns,*os) == 0)
1447 {
1448 g_info("not scrolling");
1449 } else {
1450 g_info("scrolling far");
1451 /* Cannot reuse any part of the screen : far jump */
1452
1453
1454 rectangle_pixmap (process_list,
67f72973 1455 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1456 TRUE,
1457 0, 0,
67f72973 1458 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1459 -1);
1460
9e01e6d4 1461 gtk_widget_queue_draw(drawing->drawing_area);
1462
1463 drawing->damage_begin = 0;
67f72973 1464 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1465
67f72973 1466 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1467 0, 0,
67f72973 1468 resourceview_data->drawing->width,
1469 resourceview_data->drawing->height);
9e01e6d4 1470
1471 }
1472 }
1473 }
1474 } else {
1475 /* Different scale (zoom) */
1476 g_info("zoom");
1477
1478 rectangle_pixmap (process_list,
67f72973 1479 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1480 TRUE,
1481 0, 0,
67f72973 1482 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1483 -1);
1484
9e01e6d4 1485 gtk_widget_queue_draw(drawing->drawing_area);
1486
1487 drawing->damage_begin = 0;
67f72973 1488 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1489
67f72973 1490 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1491 0, 0,
67f72973 1492 resourceview_data->drawing->width,
1493 resourceview_data->drawing->height);
9e01e6d4 1494 }
1495
1496 /* Update directly when scrolling */
67f72973 1497 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1498 TRUE);
1499
1500 return 0;
1501}
1502
1503gint traceset_notify(void *hook_data, void *call_data)
1504{
67f72973 1505 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1506 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1507
1508 if(unlikely(drawing->gc == NULL)) {
1509 return FALSE;
1510 }
1511 if(drawing->dotted_gc == NULL) {
1512 return FALSE;
1513 }
1514
67f72973 1515 drawing_clear(resourceview_data->drawing);
1516 processlist_clear(resourceview_data->process_list);
9e01e6d4 1517 gtk_widget_set_size_request(
67f72973 1518 resourceview_data->drawing->drawing_area,
1519 -1, processlist_get_height(resourceview_data->process_list));
1520 redraw_notify(resourceview_data, NULL);
9e01e6d4 1521
67f72973 1522 request_background_data(resourceview_data);
9e01e6d4 1523
1524 return FALSE;
1525}
1526
1527gint redraw_notify(void *hook_data, void *call_data)
1528{
67f72973 1529 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1530 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1531 GtkWidget *widget = drawing->drawing_area;
1532
1533 drawing->damage_begin = 0;
1534 drawing->damage_end = drawing->width;
1535
1536 /* fun feature, to be separated someday... */
67f72973 1537 drawing_clear(resourceview_data->drawing);
1538 processlist_clear(resourceview_data->process_list);
9e01e6d4 1539 gtk_widget_set_size_request(
67f72973 1540 resourceview_data->drawing->drawing_area,
1541 -1, processlist_get_height(resourceview_data->process_list));
9e01e6d4 1542 // Clear the images
67f72973 1543 rectangle_pixmap (resourceview_data->process_list,
9e01e6d4 1544 widget->style->black_gc,
1545 TRUE,
1546 0, 0,
1547 drawing->alloc_width,
1548 -1);
1549
1550 gtk_widget_queue_draw(drawing->drawing_area);
1551
1552 if(drawing->damage_begin < drawing->damage_end)
1553 {
1554 drawing_data_request(drawing,
1555 drawing->damage_begin,
1556 0,
1557 drawing->damage_end-drawing->damage_begin,
1558 drawing->height);
1559 }
1560
9e01e6d4 1561 return FALSE;
1562
1563}
1564
1565
1566gint continue_notify(void *hook_data, void *call_data)
1567{
67f72973 1568 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1569 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1570
1571 if(drawing->damage_begin < drawing->damage_end)
1572 {
1573 drawing_data_request(drawing,
1574 drawing->damage_begin,
1575 0,
1576 drawing->damage_end-drawing->damage_begin,
1577 drawing->height);
1578 }
1579
1580 return FALSE;
1581}
1582
1583
1584gint update_current_time_hook(void *hook_data, void *call_data)
1585{
67f72973 1586 ControlFlowData *resourceview_data = (ControlFlowData*)hook_data;
1587 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1588
1589 LttTime current_time = *((LttTime*)call_data);
1590
1591 TimeWindow time_window =
67f72973 1592 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 1593
1594 LttTime time_begin = time_window.start_time;
1595 LttTime width = time_window.time_width;
1596 LttTime half_width;
1597 {
1598 guint64 time_ll = ltt_time_to_uint64(width);
1599 time_ll = time_ll >> 1; /* divide by two */
1600 half_width = ltt_time_from_uint64(time_ll);
1601 }
1602 LttTime time_end = ltt_time_add(time_begin, width);
1603
1604 LttvTracesetContext * tsc =
67f72973 1605 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 1606
1607 LttTime trace_start = tsc->time_span.start_time;
1608 LttTime trace_end = tsc->time_span.end_time;
1609
1610 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1611 current_time.tv_nsec);
9e01e6d4 1612
1613 /* If current time is inside time interval, just move the highlight
1614 * bar */
1615
1616 /* Else, we have to change the time interval. We have to tell it
1617 * to the main window. */
1618 /* The time interval change will take care of placing the current
1619 * time at the center of the visible area, or nearest possible if we are
1620 * at one end of the trace. */
1621
1622
1623 if(ltt_time_compare(current_time, time_begin) < 0)
1624 {
1625 TimeWindow new_time_window;
1626
1627 if(ltt_time_compare(current_time,
1628 ltt_time_add(trace_start,half_width)) < 0)
1629 time_begin = trace_start;
1630 else
1631 time_begin = ltt_time_sub(current_time,half_width);
1632
1633 new_time_window.start_time = time_begin;
1634 new_time_window.time_width = width;
1635 new_time_window.time_width_double = ltt_time_to_double(width);
1636 new_time_window.end_time = ltt_time_add(time_begin, width);
1637
67f72973 1638 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1639 }
1640 else if(ltt_time_compare(current_time, time_end) > 0)
1641 {
1642 TimeWindow new_time_window;
1643
1644 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1645 time_begin = ltt_time_sub(trace_end,width);
1646 else
1647 time_begin = ltt_time_sub(current_time,half_width);
1648
1649 new_time_window.start_time = time_begin;
1650 new_time_window.time_width = width;
1651 new_time_window.time_width_double = ltt_time_to_double(width);
1652 new_time_window.end_time = ltt_time_add(time_begin, width);
1653
67f72973 1654 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1655
1656 }
67f72973 1657 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 1658
1659 /* Update directly when scrolling */
67f72973 1660 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1661 TRUE);
1662
1663 return 0;
1664}
1665
1666typedef struct _ClosureData {
1667 EventsRequest *events_request;
1668 LttvTracesetState *tss;
1669 LttTime end_time;
1670 guint x_end;
1671} ClosureData;
1672
58a9b31b 1673/* Draw line until end of the screen */
9e01e6d4 1674
1675void draw_closure(gpointer key, gpointer value, gpointer user_data)
1676{
67f72973 1677 ResourceUniqueNumeric *process_info = (ResourceUniqueNumeric*)key;
44ffb95f 1678 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1679 ClosureData *closure_data = (ClosureData*)user_data;
1680
1681 EventsRequest *events_request = closure_data->events_request;
67f72973 1682 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 1683
1684 LttvTracesetState *tss = closure_data->tss;
1685 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1686
1687 LttTime evtime = closure_data->end_time;
1688
1689 gboolean dodraw = TRUE;
1690
67f72973 1691 if(hashed_process_data->type == RV_RESOURCE_MACHINE)
1692 return;
1693
44ffb95f 1694 {
1695 /* For the process */
1696 /* First, check if the current process is in the state computation
1697 * process list. If it is there, that means we must add it right now and
1698 * draw items from the beginning of the read for it. If it is not
1699 * present, it's a new process and it was not present : it will
1700 * be added after the state update. */
1701#ifdef EXTRA_CHECK
1702 g_assert(lttv_traceset_number(tsc->ts) > 0);
1703#endif //EXTRA_CHECK
1704 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1705 LttvTraceState *ts = (LttvTraceState*)tc;
1706
67f72973 1707 /* Only draw for processes that are currently in the trace states */
44ffb95f 1708
67f72973 1709 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 1710#ifdef EXTRA_CHECK
67f72973 1711 /* Should be alike when background info is ready */
1712 if(resourceview_data->background_info_waiting==0)
44ffb95f 1713 g_assert(ltt_time_compare(process->creation_time,
1714 process_info->birth) == 0);
1715#endif //EXTRA_CHECK
1716
67f72973 1717 /* Now, the process is in the state hash and our own process hash.
1718 * We definitely can draw the items related to the ending state.
1719 */
1720
1721 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1722 evtime) <= 0))
1723 {
1724 TimeWindow time_window =
1725 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 1726
1727#ifdef EXTRA_CHECK
67f72973 1728 if(ltt_time_compare(evtime, time_window.start_time) == -1
1729 || ltt_time_compare(evtime, time_window.end_time) == 1)
1730 return;
44ffb95f 1731#endif //EXTRA_CHECK
67f72973 1732 Drawing_t *drawing = resourceview_data->drawing;
1733 guint width = drawing->width;
1734
1735 guint x = closure_data->x_end;
1736
1737 DrawContext draw_context;
1738
1739 /* Now create the drawing context that will be used to draw
1740 * items related to the last state. */
1741 draw_context.drawable = hashed_process_data->pixmap;
1742 draw_context.gc = drawing->gc;
1743 draw_context.pango_layout = drawing->pango_layout;
1744 draw_context.drawinfo.end.x = x;
1745
1746 draw_context.drawinfo.y.over = 1;
1747 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1748 draw_context.drawinfo.y.under = hashed_process_data->height;
1749
1750 draw_context.drawinfo.start.offset.over = 0;
1751 draw_context.drawinfo.start.offset.middle = 0;
1752 draw_context.drawinfo.start.offset.under = 0;
1753 draw_context.drawinfo.end.offset.over = 0;
1754 draw_context.drawinfo.end.offset.middle = 0;
1755 draw_context.drawinfo.end.offset.under = 0;
44ffb95f 1756#if 0
67f72973 1757 /* Jump over draw if we are at the same x position */
1758 if(x == hashed_process_data->x.over)
1759 {
1760 /* jump */
1761 } else {
1762 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1763 /* Draw the line */
1764 PropertiesLine prop_line = prepare_execmode_line(process);
1765 draw_line((void*)&prop_line, (void*)&draw_context);
44ffb95f 1766
67f72973 1767 hashed_process_data->x.over = x;
1768 }
44ffb95f 1769#endif //0
1770
67f72973 1771 if(unlikely(x == hashed_process_data->x.middle &&
1772 hashed_process_data->x.middle_used)) {
44ffb95f 1773#if 0 /* do not mark closure : not missing information */
67f72973 1774 if(hashed_process_data->x.middle_marked == FALSE) {
1775 /* Draw collision indicator */
1776 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1777 gdk_draw_point(drawing->pixmap,
1778 drawing->gc,
1779 x,
1780 y+(height/2)-3);
1781 hashed_process_data->x.middle_marked = TRUE;
1782 }
44ffb95f 1783#endif //0
67f72973 1784 /* Jump */
1785 } else {
1786 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1787 /* Draw the line */
1788 if(dodraw) {
1789 PropertiesLine prop_line;
1790 prop_line.line_width = STATE_LINE_WIDTH;
1791 prop_line.style = GDK_LINE_SOLID;
1792 prop_line.y = MIDDLE;
1793 if(hashed_process_data->type == RV_RESOURCE_CPU)
1794 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
1795 else if(hashed_process_data->type == RV_RESOURCE_IRQ)
1796 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
0305fe77 1797 else if(hashed_process_data->type == RV_RESOURCE_SOFT_IRQ)
1798 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[process_info->id]);
67f72973 1799 else if(hashed_process_data->type == RV_RESOURCE_BDEV) {
1800 gint devcode_gint = process_info->id;
1801 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1802 // the lookup may return null; bdev_set_line_color must act appropriately
1803 bdev_set_line_color(&prop_line, bdev);
44ffb95f 1804 }
67f72973 1805
1806 draw_line((void*)&prop_line, (void*)&draw_context);
1807 }
44ffb95f 1808
67f72973 1809 /* become the last x position */
1810 if(likely(x != hashed_process_data->x.middle)) {
1811 hashed_process_data->x.middle = x;
1812 /* but don't use the pixel */
1813 hashed_process_data->x.middle_used = FALSE;
44ffb95f 1814
67f72973 1815 /* Calculate the next good time */
1816 convert_pixels_to_time(width, x+1, time_window,
1817 &hashed_process_data->next_good_time);
44ffb95f 1818 }
1819 }
67f72973 1820 }
44ffb95f 1821 }
9e01e6d4 1822}
1823
1824int before_chunk(void *hook_data, void *call_data)
1825{
1826 EventsRequest *events_request = (EventsRequest*)hook_data;
1827 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1828 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
1829#if 0
67f72973 1830 /* Deactivate sort */
9e01e6d4 1831 gtk_tree_sortable_set_sort_column_id(
1832 GTK_TREE_SORTABLE(cfd->process_list->list_store),
1833 TRACE_COLUMN,
1834 GTK_SORT_ASCENDING);
1835#endif //0
1836 drawing_chunk_begin(events_request, tss);
1837
1838 return 0;
1839}
1840
1841int before_request(void *hook_data, void *call_data)
1842{
1843 EventsRequest *events_request = (EventsRequest*)hook_data;
1844 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1845
1846 drawing_data_request_begin(events_request, tss);
1847
1848 return 0;
1849}
1850
1851
1852/*
1853 * after request is necessary in addition of after chunk in order to draw
1854 * lines until the end of the screen. after chunk just draws lines until
1855 * the last event.
1856 *
1857 * for each process
1858 * draw closing line
1859 * expose
1860 */
1861int after_request(void *hook_data, void *call_data)
1862{
67f72973 1863 guint i;
1864 EventsRequest *events_request = (EventsRequest*)hook_data;
1865 ControlFlowData *resourceview_data = events_request->viewer_data;
1866 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1867
1868 ProcessList *process_list = resourceview_data->process_list;
1869 LttTime end_time = events_request->end_time;
1870
1871 ClosureData closure_data;
1872 closure_data.events_request = (EventsRequest*)hook_data;
1873 closure_data.tss = tss;
1874 closure_data.end_time = end_time;
1875
1876 TimeWindow time_window =
1877 lttvwindow_get_time_window(resourceview_data->tab);
1878 guint width = resourceview_data->drawing->width;
1879 convert_time_to_pixels(
1880 time_window,
1881 end_time,
1882 width,
1883 &closure_data.x_end);
1884
1885
1886 /* Draw last items */
1887 for(i=0; i<RV_RESOURCE_COUNT; i++) {
1888 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
1889 (void*)&closure_data);
1890 }
1891
1892 /* Request expose */
1893 drawing_request_expose(events_request, tss, end_time);
9e01e6d4 1894 return 0;
1895}
1896
1897/*
1898 * for each process
1899 * draw closing line
1900 * expose
1901 */
1902int after_chunk(void *hook_data, void *call_data)
1903{
1904 EventsRequest *events_request = (EventsRequest*)hook_data;
67f72973 1905 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 1906 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1907 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
1908 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
1909 LttTime end_time;
1910
67f72973 1911 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1912 guint i;
1913 LttvTraceset *traceset = tsc->ts;
1914 guint nb_trace = lttv_traceset_number(traceset);
1915
1916 /* Only execute when called for the first trace's events request */
1917 if(!process_list->current_hash_data) return;
1918
1919 for(i = 0 ; i < nb_trace ; i++) {
1920 g_free(process_list->current_hash_data[i]);
1921 }
1922 g_free(process_list->current_hash_data);
1923 process_list->current_hash_data = NULL;
1924
1925 if(tfc != NULL)
1926 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
1927 else /* end of traceset, or position now out of request : end */
1928 end_time = events_request->end_time;
1929
1930 ClosureData closure_data;
1931 closure_data.events_request = (EventsRequest*)hook_data;
1932 closure_data.tss = tss;
1933 closure_data.end_time = end_time;
1934
1935 TimeWindow time_window =
67f72973 1936 lttvwindow_get_time_window(resourceview_data->tab);
1937 guint width = resourceview_data->drawing->width;
9e01e6d4 1938 convert_time_to_pixels(
1939 time_window,
1940 end_time,
1941 width,
1942 &closure_data.x_end);
1943
1944 /* Draw last items */
67f72973 1945 for(i=0; i<RV_RESOURCE_COUNT; i++) {
1946 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 1947 (void*)&closure_data);
67f72973 1948 }
9e01e6d4 1949#if 0
1950 /* Reactivate sort */
1951 gtk_tree_sortable_set_sort_column_id(
67f72973 1952 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 1953 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1954 GTK_SORT_ASCENDING);
1955
67f72973 1956 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 1957 /* Request a full expose : drawing scrambled */
67f72973 1958 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 1959#endif //0
1960 /* Request expose (updates damages zone also) */
1961 drawing_request_expose(events_request, tss, end_time);
1962
1963 return 0;
1964}
1965
1966/* after_statedump_end
1967 *
1968 * @param hook_data ControlFlowData structure of the viewer.
1969 * @param call_data Event context.
1970 *
1971 * This function adds items to be drawn in a queue for each process.
1972 *
1973 */
1974int before_statedump_end(void *hook_data, void *call_data)
1975{
67f72973 1976 gint i;
1977
dd455fb8 1978 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1979 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 1980 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 1981
1982 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1983
1984 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1985
1986 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1987
1988 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
67f72973 1989 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1990
1991 LttEvent *e;
1992 e = ltt_tracefile_get_event(tfc->tf);
1993
67f72973 1994 LttvFilter *filter = resourceview_data->filter;
9e01e6d4 1995 if(filter != NULL && filter->head != NULL)
1996 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1997 tfc->t_context->t,tfc,NULL,NULL))
1998 return FALSE;
1999
2000 LttTime evtime = ltt_event_time(e);
2001
2002 ClosureData closure_data;
2003 closure_data.events_request = events_request;
2004 closure_data.tss = tss;
2005 closure_data.end_time = evtime;
2006
2007 TimeWindow time_window =
67f72973 2008 lttvwindow_get_time_window(resourceview_data->tab);
2009 guint width = resourceview_data->drawing->width;
9e01e6d4 2010 convert_time_to_pixels(
2011 time_window,
2012 evtime,
2013 width,
2014 &closure_data.x_end);
2015
2016 /* Draw last items */
67f72973 2017
2018 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2019 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2020 (void*)&closure_data);
67f72973 2021 }
9e01e6d4 2022#if 0
2023 /* Reactivate sort */
2024 gtk_tree_sortable_set_sort_column_id(
67f72973 2025 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2026 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2027 GTK_SORT_ASCENDING);
2028
67f72973 2029 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2030 /* Request a full expose : drawing scrambled */
67f72973 2031 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2032#endif //0
2033 /* Request expose (updates damages zone also) */
2034 drawing_request_expose(events_request, tss, evtime);
2035
2036 return 0;
2037}
This page took 0.134153 seconds and 4 git commands to generate.