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