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